1 /*
2   This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
3 
4   Author: Uwe Schulzweida
5 
6 */
7 #ifndef FIELD_H
8 #define FIELD_H
9 
10 #include <cstdio>
11 #include "varray.h"
12 #include "cdo_options.h"
13 #include "cdo_vlist.h"
14 #include "compare.h"
15 
16 enum FieldFunc
17 {
18   FieldFunc_Min = 100,
19   FieldFunc_Max,
20   FieldFunc_Range,
21   FieldFunc_Sum,
22   FieldFunc_Avg,
23   FieldFunc_Mean,
24   FieldFunc_Var,
25   FieldFunc_Var1,
26   FieldFunc_Std,
27   FieldFunc_Std1,
28   FieldFunc_Skew,
29   FieldFunc_Kurt,
30   FieldFunc_Median,
31   FieldFunc_Pctl,
32 
33   FieldFunc_Cor,
34   FieldFunc_Covar,
35   FieldFunc_Avgw,
36   FieldFunc_Meanw,
37   FieldFunc_Stdw,
38   FieldFunc_Std1w,
39   FieldFunc_Varw,
40   FieldFunc_Var1w,
41   FieldFunc_Minidx,
42   FieldFunc_Maxidx,
43   FieldFunc_Rmsd,
44 
45   FieldFunc_Add,
46   FieldFunc_Sub,
47   FieldFunc_Mul,
48   FieldFunc_Div,
49   FieldFunc_Mod,
50 
51   FieldFunc_Atan2,
52   FieldFunc_Setmiss,
53 };
54 
55 double var_to_std(double rvar, double missval);
56 
57 enum field_flag
58 {
59   FIELD_VEC = 2,  // allocated memory
60   FIELD_FLT = 4,  // 32-bit float
61   FIELD_DBL = 8,  // 64-bit float
62   FIELD_NAT = 16, // native: 32-bit float for 32-bit float data, otherweise 64-bit float
63 };
64 
65 class // Field
66 #ifdef WARN_UNUSED
67 [[gnu::warn_unused]]
68 #endif
69 Field
70 {
71 public:
72   int fpeRaised = 0;
73   int nwpv = 1;         // number of words per value; real:1  complex:2
74   int grid = -1;
75   MemType memType = MemType::Native;  // MemType::Float or MemType::Double
76 
77   size_t gridsize = 0;
78   size_t size = 0;
79   size_t nsamp = 0;
80 
81   size_t nmiss = 0;
82   double missval = 0;
83 
84   Varray<float> vec_f;
85   Varray<double> vec_d;
86   Varray<double> weightv;
87 
Field()88   Field() {}
89   void init(const CdoVar &var);
90   void resize(size_t count);
91   void resize(size_t count, double value);
92   void resizef(size_t count);
93   void resizef(size_t count, float value);
94   bool empty() const;
95   void check_gridsize() const;
96 
hasData()97   bool hasData() const
98   {
99     return (memType == MemType::Float) ? !vec_f.empty() : !vec_d.empty();
100   }
101 
102 private:
103   size_t m_count = 0;
104 };
105 
106 class // Field3D
107 #ifdef WARN_UNUSED
108 [[gnu::warn_unused]]
109 #endif
110 Field3D : public Field
111 {
112 public:
113   size_t nlevels = 0;
114 
Field3D()115   Field3D() {}
116   void init(const CdoVar &var);
117 };
118 
119 struct RecordInfo
120 {
121   int varID = 0;
122   int levelID = 0;
123   bool lconst = false;
124 };
125 
126 using FieldVector = std::vector<Field>;
127 using FieldVector2D = std::vector<FieldVector>;
128 using FieldVector3D = std::vector<FieldVector2D>;
129 
130 using Field3DVector = std::vector<Field3D>;
131 
132 void field_fill(Field &field, double value);
133 void field_copy(const Field &field_src, Field &field_tgt);
134 void field_copy(const Field3D &field_src, Field3D &field_tgt);
135 void field_copy(const Field3D &field_src, int levelID, Field &field_tgt);
136 void field_add(Field &field1, const Field3D &field2, int levelID);
137 size_t field_num_miss(const Field &field);
138 size_t field_num_mv(Field &field);
139 MinMax field_min_max(const Field &field);
140 
141 template <class UnaryOperation>
field_transform(const Field & fieldIn,Field & fieldOut,UnaryOperation unary_op)142 void field_transform(const Field &fieldIn, Field &fieldOut, UnaryOperation unary_op)
143 {
144   if (fieldIn.memType == MemType::Float && fieldOut.memType == MemType::Float)
145     varray_transform(fieldIn.vec_f, fieldOut.vec_f, unary_op);
146   else
147     varray_transform(fieldIn.vec_d, fieldOut.vec_d, unary_op);
148 }
149 
150 // fieldmem.cc
151 void fields_from_vlist(int vlistID, FieldVector2D &field2D);
152 void fields_from_vlist(int vlistID, FieldVector2D &field2D, int ptype);
153 void fields_from_vlist(int vlistID, FieldVector2D &field2D, int ptype, double fillValue);
154 
155 // field.cc
156 double field_function(const Field &field, int function);
157 double field_min(const Field &field);
158 double field_max(const Field &field);
159 double field_sum(const Field &field);
160 double field_mean(const Field &field);
161 double field_meanw(const Field &field);
162 double field_avg(const Field &field);
163 double field_avgw(const Field &field);
164 double field_std(const Field &field);
165 double field_std1(const Field &field);
166 double field_var(const Field &field);
167 double field_var1(const Field &field);
168 double field_stdw(const Field &field);
169 double field_std1w(const Field &field);
170 double field_varw(const Field &field);
171 double field_var1w(const Field &field);
172 
173 // ENS validation
174 double field_rank(Field &field);
175 
176 double field_pctl(Field &field, double pn);
177 
178 // field_zonal.cc
179 void zonal_function(const Field &field1, Field &field2, int function);
180 void zonal_min(const Field &field1, Field &field2);
181 void zonal_max(const Field &field1, Field &field2);
182 void zonal_range(const Field &field1, Field &field2);
183 void zonal_sum(const Field &field1, Field &field2);
184 void zonal_avg(const Field &field1, Field &field2);
185 void zonal_mean(const Field &field1, Field &field2);
186 void zonal_std(const Field &field1, Field &field2);
187 void zonal_std1(const Field &field1, Field &field2);
188 void zonal_var(const Field &field1, Field &field2);
189 void zonal_var1(const Field &field1, Field &field2);
190 void zonal_median(const Field &field1, Field &field2);
191 void zonal_pctl(const Field &field1, Field &field2, double pn);
192 
193 // field_meridional.cc
194 void meridional_function(const Field &field1, Field &field2, int function);
195 void meridional_pctl(const Field &field1, Field &field2, double pn);
196 
197 void field_rms(const Field &field1, const Field &field2, Field &field3);
198 
199 // fieldc.cc
200 void fieldc_function(Field &field, double rconst, int function);
201 void fieldc_mul(Field &field, double rconst);
202 void fieldc_div(Field &field, double rconst);
203 void fieldc_add(Field &field, double rconst);
204 void fieldc_sub(Field &field, double rconst);
205 void fieldc_min(Field &field, double rconst);
206 void fieldc_max(Field &field, double rconst);
207 void fieldc_mod(Field &field, double divisor);
208 
209 // fieldc_complex.cc
210 void fieldc_function_complex(Field &field, const double rconstcplx[2], int function);
211 
212 // field2.cc
213 void field2_function(Field &field1, const Field &field2, int function);
214 
215 void field2_add(Field &field1, const Field &field2);
216 void field2_sum(Field &field1, const Field &field2);
217 void field2_sub(Field &field1, const Field &field2);
218 void field2_mul(Field &field1, const Field &field2);
219 void field2_div(Field &field1, const Field &field2);
220 void field2_min(Field &field1, const Field &field2);
221 void field2_max(Field &field1, const Field &field2);
222 void field2_atan2(Field &field1, const Field &field2);
223 
224 void field2_sumq(Field &field1, const Field &field2);
225 void field2_sumw(Field &field1, const Field &field2, double w);
226 void field2_sumqw(Field &field1, const Field &field2, double w);
227 void field2_sumtr(Field &field1, const Field &field2, double refval);
228 void field2_vinit(Field &field1, const Field &field2);
229 void field2_vincr(Field &field1, const Field &field2);
230 
231 void field2_sumsumq(Field &field1, Field &field2, const Field &field3);
232 void field2_maxmin(Field &field1, Field &field2, const Field &field3);
233 void field2_minidx(Field &field1, Field &field2, const Field &field3, int idx);
234 void field2_maxidx(Field &field1, Field &field2, const Field &field3, int idx);
235 void field2_var(Field &field1, const Field &field2, const Field &field3, int divisor);
236 void field2_std(Field &field1, const Field &field2, const Field &field3, int divisor);
237 void fieldc_var(Field &field1, const Field &field2, int nsets, int divisor);
238 void fieldc_std(Field &field1, const Field &field2, int nsets, int divisor);
239 void field2_moq(Field &field1, const Field &field2);
240 void field2_moqw(Field &field1, const Field &field2, double w);
241 
242 void field2_count(Field &field1, const Field &field2);
243 
244 // field2_complex.cc
245 void field2_function_complex(Field &field1, const Field &field2, int function);
246 
247 #endif /* FIELD_H */
248