1 /*
2 This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
3
4 Copyright (C) 2006 Brockmann Consult
5
6 Author: Ralf Quast
7
8 */
9
10 // clang-format off
11 /*
12 MODULE OPERATOR INDEX DESCRIPTION
13
14 EcaCfd eca_cfd CFD maximum number of consecutive frost days
15 EcaCsu eca_csu CSU maximum number of consecutive summer days
16 EcaCwdi eca_cwdi CWDI cold wave duration index
17 EcaCwfi eca_cwfi CWFI number of cold-spell days
18 EcaEtr eca_etr ETR intra-period extreme temperature range
19 EcaFd eca_fd FD number of frost days
20 EcaGsl eca_gsl GSL growing season length
21 EcaHd eca_hd HD heating degree days
22 EcaHwdi eca_hwdi HWDI heat wave duration index
23 EcaHwfi eca_hwfi HWFI number of warm-spell days
24 EcaId eca_id ID number of ice days
25 EcaSu eca_su SU number of summer days
26 EcaTg10p eca_tg10p TG10p percent of time TX < 10th percentile of daily mean temperature
27 EcaTg90p eca_tg90p TG90p percent of time TX > 90th percentile of daily mean temperature
28 EcaTn10p eca_tn10p TN10p percent of time TX < 10th percentile of daily minimum temperature
29 EcaTn90p eca_tn90p TN90p percent of time TX > 90th percentile of daily minimum temperature
30 EcaTr eca_tr TR number of tropical nights
31 EcaTx10p eca_tx10p TX10p percent of time TX < 10th percentile of daily maximum temperature
32 EcaTx90p eca_tx90p TX90p percent of time TX > 90th percentile of daily maximum temperature
33
34 EcaCdd eca_cdd CDD maximum number of consecutive dry days
35 EcaCwd eca_cwd CWD maximum number of consecutive wet days
36 EcaR10mm eca_r10mm R10mm number of days with precipitation >= 10 mm
37 EcaR20mm eca_r20mm R20mm number of days with precipitation >= 20 mm
38 EcaR75p eca_r75p R75p Percent of time RR > 75th percentile of daily precipitation amount
39 EcaR75ptot eca_r75ptot R75pTOT Percentage of annual total precipitation due to events with RR > 75th percentile of daily precipitation amount
40 EcaR90p eca_r90p R90p Percent of time RR > 90th percentile of daily precipitation amount
41 EcaR90ptot eca_r90ptot R90pTOT Percentage of annual total precipitation due to events with RR > 90th percentile of daily precipitation amount
42 EcaR95p eca_r95p R95p Percent of time RR > 95th percentile of daily precipitation amount
43 EcaR95ptot eca_r95ptot R95pTOT Percentage of annual total precipitation due to events with RR > 95th percentile of daily precipitation amount
44 EcaR99p eca_r99p R99p Percent of time RR > 75th percentile of daily precipitation amount
45 EcaR99ptot eca_r99ptot R99pTOT Percentage of annual total precipitation due to events with RR > 99th percentile of daily precipitation amount
46 EcaRr1 eca_rr1 RR1 number of wet days
47 EcaSdii eca_sdii SDII simple daily intensity index
48
49 Fdns fdns frost days without surface snow
50
51 Strwin strwin number of strong-wind days
52 Strbre strbre number of strong-breeze days
53 Strgal strgal number of strong-gale days
54 Hurr hurr number of hurricane days
55 */
56 // clang-format on
57
58 #include "process_int.h"
59 #include "cdo_options.h"
60 #include "param_conversion.h"
61 #include "ecacore.h"
62 #include "ecautil.h"
63 #include "util_date.h"
64 #include "pmlist.h"
65
66 #define TO_DEG_CELSIUS(x) ((x) -273.15)
67 #define TO_KELVIN(x) ((x) + 273.15)
68
69 constexpr int ECA_refdate = 19550101;
70 constexpr int ETC_refdate = 18500101;
71
72 // clang-format off
73
74 static const char CFD_NAME[] = "consecutive_frost_days_index_per_time_period";
75 static const char CFD_LONGNAME[] = "Consecutive frost days index is the greatest number of consecutive frost days in a given time period. Frost days is the number of days where minimum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
76 //static const char CFD_UNITS[] = "No.";
77 static const char CFD_NAME2[] = "number_of_cfd_periods_with_more_than_%ddays_per_time_period";
78 static const char CFD_LONGNAME2[] = "Number of cfd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
79 static const char CFD_UNITS2[] = "No.";
80
81 static const char CSU_NAME[] = "consecutive_summer_days_index_per_time_period";
82 static const char CSU_LONGNAME[] = "Consecutive summer days index is the greatest number of consecutive summer days in a given time period. Summer days is the number of days where maximum of temperature is above 25 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
83 //static const char CSU_UNITS[] = "No.";
84 static const char CSU_NAME2[] = "number_of_csu_periods_with_more_than_%ddays_per_time_period";
85 static const char CSU_LONGNAME2[] = "Number of csu periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
86 static const char CSU_UNITS2[] = "No.";
87
88 static const char CWDI_NAME[] = "cold_wave_duration_index_wrt_mean_of_reference_period";
89 static const char CWDI_LONGNAME[] = "This is the number of days per time period where in intervals of at least %d consecutive days the daily minimum temperature is more than %1.0f degrees below a reference value. The reference value is calculated as the mean of minimum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
90 static const char CWDI_UNITS[] = "No.";
91 static const char CWDI_NAME2[] = "cold_waves_per_time_period";
92 static const char CWDI_LONGNAME2[] = "Number of cold waves per time period. The time period should be defined by the bounds of the time coordinate.";
93 static const char CWDI_UNITS2[] = "No.";
94
95 static const char CWFI_NAME[] = "cold_spell_days_index_wrt_10th_percentile_of_reference_period";
96 static const char CWFI_NAME_ET[] = "csdiETCCDI";
97 static const char CWFI_LONGNAME[] = "This is the number of days per time period where in intervals of at least %d consecutive days the daily mean temperature is below a reference value. The reference value is calculated as the 10th percentile of daily mean temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
98 static const char CWFI_LONGNAME_ET[] = "Cold Spell Duration Index";
99 static const char CWFI_UNITS[] = "No.";
100 static const char CWFI_UNITS_ET[] = "days";
101 static const char CWFI_NAME2[] = "cold_spell_periods_per_time_period";
102 static const char CWFI_LONGNAME2[] = "Number of cold spell periods per time period. The time period should be defined by the bounds of the time coordinate.";
103 static const char CWFI_UNITS2[] = "No.";
104
105 static const char ETR_NAME[] = "intra_period_extreme_temperature_range";
106 static const char ETR_LONGNAME[] = "Difference between the absolute extreme temperatures in observation period. The time period should be defined by the bounds of the time coordinate.";
107 //static const char ETR_UNITS[] = "K";
108
109 static const char FD_NAME[] = "frost_days_index_per_time_period";
110 static const char FD_NAME_ET[] = "fdETCCDI";
111 static const char FD_LONGNAME[] = "Frost days index is the number of days where minimum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
112 static const char FD_LONGNAME_ET[] = "Number of Frost Days";
113 //static const char FD_UNITS[] = "No.";
114 static const char FD_UNITS_ET[] = "days";
115
116 static const char GSL_NAME[] = "thermal_growing_season_length";
117 static const char GSL_LONGNAME[] = "Counted are the number of days per calendar year between the first occurrence of at least %d consecutive days where the daily mean temperature is above %1.0f degree Celsius and the first occurrence of at least %d consecutive days after 1st of July where the daily mean temperature is below %1.0f degree Celsius. The time period should be defined by the bounds of the time coordinate.";
118 static const char GSL_UNITS[] = "No.";
119 static const char GSL_NAME2[] = "day_of_year_of_growing_season_start";
120 static const char GSL_LONGNAME2[] = "Day of year of growing season start. The time period should be defined by the bounds of the time coordinate.";
121 static const char GSL_UNITS2[] = "No.";
122
123 static const char HD_NAME[] = "heating_degree_days_per_time_period";
124 static const char HD_LONGNAME[] = "Heating degree days relates the outside temperature with the room temperature during the heating period. It is the sum of the difference between room temperature X and daily mean temperature Y on days where Y is below a given constant A. X is 20 degree Celsius and A is 15 degree Celsius according to VDI guidelines. According to ECAD both X and A are 17 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
125 static const char HD_UNITS[] = "No.";
126
127 static const char HWDI_NAME[] = "heat_wave_duration_index_wrt_mean_of_reference_period";
128 static const char HWDI_LONGNAME[] = "This is the number of days per time period where in intervals of at least %d consecutive days the daily maximum temperature is more than %1.0f degrees above a reference value. The reference value is calculated as the mean of maximum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
129 static const char HWDI_UNITS[] = "No.";
130 static const char HWDI_NAME2[] = "heat_waves_per_time_period";
131 static const char HWDI_LONGNAME2[] = "Number of heat waves per time period. The time period should be defined by the bounds of the time coordinate.";
132 static const char HWDI_UNITS2[] = "No.";
133
134 static const char HWFI_NAME[] = "warm_spell_days_index_wrt_90th_percentile_of_reference_period";
135 static const char HWFI_NAME_ET[] = "wsdiETCCDI";
136 static const char HWFI_LONGNAME[] = "This is the number of days per time period where in intervals of at least %d consecutive days the daily mean temperature is above a reference value. The reference value is calculated as the 90th percentile of daily mean temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
137 static const char HWFI_LONGNAME_ET[] = "Warm Spell Duration Index";
138 static const char HWFI_UNITS[] = "No.";
139 static const char HWFI_UNITS_ET[] = "days";
140 static const char HWFI_NAME2[] = "warm_spell_periods_per_time_period";
141 static const char HWFI_LONGNAME2[] = "Number of warm spell periods per time period. The time period should be defined by the bounds of the time coordinate.";
142 static const char HWFI_UNITS2[] = "No.";
143
144 static const char ID_NAME[] = "ice_days_index_per_time_period";
145 static const char ID_NAME_ET[] = "idETCCDI";
146 static const char ID_LONGNAME[] = "Ice days index is the number of days where maximum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
147 static const char ID_LONGNAME_ET[] = "Number of Icing Days";
148 static const char ID_UNITS[] = "No.";
149 static const char ID_UNITS_ET[] = "days";
150
151 static const char SU_NAME[] = "summer_days_index_per_time_period";
152 static const char SU_NAME_ET[] = "suETCCDI";
153 static const char SU_LONGNAME[] = "Summer days index is the number of days where maximum of temperature is above %1.0f degree Celsius. The time period should be defined by the bounds of the time coordinate.";
154 static const char SU_LONGNAME_ET[] = "Number of Summer Days";
155 //static const char SU_UNITS[] = "No.";
156 static const char SU_UNITS_ET[] = "days";
157
158 static const char TG10P_NAME[] = "cold_days_percent_wrt_10th_percentile_of_reference_period";
159 static const char TG10P_LONGNAME[] = "This is the percent of time per time period where daily mean temperature is below a reference value. The reference value is calculated as the 10th percentile of daily mean temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
160 static const char TG10P_UNITS[] = "Percent";
161
162 static const char TG90P_NAME[] = "warm_days_percent_wrt_90th_percentile_of_reference_period";
163 static const char TG90P_LONGNAME[] = "This is the percent of time per time period where daily mean temperature is above a reference value. The reference value is calculated as the 90th percentile of daily mean temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
164 static const char TG90P_UNITS[] = "Percent";
165
166 static const char TN10P_NAME[] = "cold_nights_percent_wrt_10th_percentile_of_reference_period";
167 static const char TN10P_LONGNAME[] = "This is the percent of time per time period where daily minimum temperature is below a reference value. The reference value is calculated as the 10th percentile of daily minimum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
168 static const char TN10P_UNITS[] = "Percent";
169
170 static const char TN90P_NAME[] = "warm_nights_percent_wrt_90th_percentile_of_reference_period";
171 static const char TN90P_LONGNAME[] = "This is the percent of time per time period where daily minimum temperature is above a reference value. The reference value is calculated as the 90th percentile of daily minimum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
172 static const char TN90P_UNITS[] = "Percent";
173
174 static const char TR_NAME[] = "tropical_nights_index_per_time_period";
175 static const char TR_NAME_ET[] = "trETCCDI";
176 static const char TR_LONGNAME[] = "Tropical nights index is the number of days where minimum of temperature is above %1.0f degree Celsius. The time period should be defined by the bounds of the time coordinate.";
177 static const char TR_LONGNAME_ET[] = "Number of Tropical Nights";
178 static const char TR_UNITS[] = "No.";
179 static const char TR_UNITS_ET[] = "days";
180
181 static const char TX10P_NAME[] = "very_cold_days_percent_wrt_10th_percentile_of_reference_period";
182 static const char TX10P_LONGNAME[] = "This is the percent of time per time period where daily maximum temperature is below a reference value. The reference value is calculated as the 10th percentile of daily maximum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
183 static const char TX10P_UNITS[] = "Percent";
184
185 static const char TX90P_NAME[] = "very_warm_days_percent_wrt_90th_percentile_of_reference_period";
186 static const char TX90P_LONGNAME[] = "This is the percent of time per time period where daily maximum temperature is above a reference value. The reference value is calculated as the 90th percentile of daily maximum temperatures of a five day window centred on each calendar day of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
187 static const char TX90P_UNITS[] = "Percent";
188
189 static const char CDD_NAME[] = "consecutive_dry_days_index_per_time_period";
190 static const char CDD_NAME_ET[] = "cddETCCDI";
191 static const char CDD_LONGNAME[] = "Consecutive dry days is the greatest number of consecutive days per time period with daily precipitation amount below %g mm. The time period should be defined by the bounds of the time coordinate.";
192 static const char CDD_LONGNAME_ET[] = "Maximum Number of Consecutive Days with Less Than 1mm of Precipitation [days]";
193 static const char CDD_UNITS[] = "No.";
194 static const char CDD_UNITS_ET[] = "days";
195 static const char CDD_NAME2[] = "number_of_cdd_periods_with_more_than_%ddays_per_time_period";
196 static const char CDD_LONGNAME2[] = "Number of cdd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
197 static const char CDD_UNITS2[] = "No.";
198
199 static const char CWD_NAME[] = "consecutive_wet_days_index_per_time_period";
200 static const char CWD_NAME_ET[] = "cwdETCCDI";
201 static const char CWD_LONGNAME[] = "Consecutive wet days is the greatest number of consecutive days per time period with daily precipitation above %g mm. The time period should be defined by the bounds of the time coordinate.";
202 static const char CWD_LONGNAME_ET[] = "Maximum Number of Consecutive Days with At Least 1mm of Precipitation";
203 static const char CWD_UNITS[] = "No.";
204 static const char CWD_UNITS_ET[] = "days";
205 static const char CWD_NAME2[] = "number_of_cwd_periods_with_more_than_%ddays_per_time_period";
206 static const char CWD_LONGNAME2[] = "Number of cwd periods in given time period with more than %d days. The time period should be defined by the bounds of the time coordinate.";
207 static const char CWD_UNITS2[] = "No.";
208
209 static const char PD_NAME[] = "precipitation_days_index_per_time_period";
210 static const char PD_NAME_ET[] = "r1mmETCCDI";
211 static const char PD_LONGNAME[] = "precipitation days is the number of days per time period with daily precipitation sum exceeding %g mm. The time period should be defined by the bounds of the time coordinate.";
212 static const char PD_LONGNAME_ET[] = "Count of Days with At Least 1mm of Precipitation";
213 static const char PD_UNITS[] = "No.";
214 static const char PD_UNITS_ET[] = "days";
215
216 static const char R10MM_NAME[] = "heavy_precipitation_days_index_per_time_period";
217 static const char R10MM_NAME_ET[] = "r10mmETCCDI";
218 static const char R10MM_LONGNAME[] = "Heavy precipitation days is the number of days per time period with daily precipitation sum exceeding 10 mm. The time period should be defined by the bounds of the time coordinate.";
219 static const char R10MM_LONGNAME_ET[]= "Count of Days with At Least 10mm of Precipitation";
220 static const char R10MM_UNITS[] = "No.";
221 static const char R10MM_UNITS_ET[] = "days";
222
223 static const char R20MM_NAME[] = "very_heavy_precipitation_days_index_per_time_period";
224 static const char R20MM_NAME_ET[] = "r20mmETCCDI";
225 static const char R20MM_LONGNAME[] = "Very heavy precipitation days is the number of days with daily precipitation sum exceeding 20 mm. The time period should be defined by the bounds of the time coordinate.";
226 static const char R20MM_LONGNAME_ET[]= "Count of Days with At Least 20mm of Precipitation";
227 static const char R20MM_UNITS[] = "No.";
228 static const char R20MM_UNITS_ET[] = "days";
229
230 static const char R75P_NAME[] = "moderate_wet_days_wrt_75th_percentile_of_reference_period";
231 static const char R75P_LONGNAME[] = "This is the percent of time per time period of wet days (daily sum at least 1 mm / day) where daily precipitation amount of a wet day is above a reference value. The reference value is calculated as the 75th percentile of all wet days of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
232 static const char R75P_UNITS[] = "Percent";
233
234 static const char R75PTOT_NAME[] = "precipitation_percent_due_to_R75p_days";
235 static const char R75PTOT_LONGNAME[] = "Percentage of total precipitation amount per time period due to moderate_wet_days_wrt_75th_percentile_of_reference_period. The time period should be defined by the bounds of the time coordinate.";
236 static const char R75PTOT_UNITS[] = "Percent";
237
238 static const char R90P_NAME[] = "wet_days_wrt_90th_percentile_of_reference_period";
239 static const char R90P_LONGNAME[] = "This is the percent of time per time period of wet days (daily sum at least 1 mm / day) where daily precipitation amount of a wet day is above a reference value. The reference value is calculated as the 90th percentile of all wet days of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
240 static const char R90P_UNITS[] = "Percent";
241
242 static const char R90PTOT_NAME[] = "precipitation_percent_due_to_R90p_days";
243 static const char R90PTOT_LONGNAME[] = "Percentage of total precipitation amount per time period due towet_days_wrt_90th_percentile_of_reference_period. The time period should be defined by the bounds of the time coordinate.";
244 static const char R90PTOT_UNITS[] = "Percent";
245
246 static const char R95P_NAME[] = "very_wet_days_wrt_95th_percentile_of_reference_period";
247 static const char R95P_LONGNAME[] = "This is the percent of time per time period of wet days (daily sum at least 1 mm / day) where daily precipitation amount of a wet day is above a reference value. The reference value is calculated as the 95th percentile of all wet days of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
248 static const char R95P_UNITS[] = "Percent";
249
250 static const char R95PTOT_NAME[] = "precipitation_percent_due_to_R95p_days";
251 static const char R95PTOT_LONGNAME[] = "Percentage of total precipitation amount per time period due to very_wet_days_wrt_95th_percentile_of_reference_period. The time period should be defined by the bounds of the time coordinate.";
252 static const char R95PTOT_UNITS[] = "Percent";
253
254 static const char R99P_NAME[] = "extremely_wet_days_wrt_99th_percentile_of_reference_period";
255 static const char R99P_LONGNAME[] = "This is the percent of time per time period of wet days (daily sum at least 1 mm / day) where daily precipitation amount of a wet day is above a reference value. The reference value is calculated as the 99th percentile of all wet days of a given 30 year climate reference period. The time period should be defined by the bounds of the time coordinate.";
256 static const char R99P_UNITS[] = "Percent";
257
258 static const char R99PTOT_NAME[] = "precipitation_percent_due_to_R99p_days";
259 static const char R99PTOT_LONGNAME[] = "percentage of total precipitation amount per time period due to extremely_wet_days_wrt_99th_percentile_of_reference_period. The time period should be defined by the bounds of the time coordinate.";
260 //static const char R99PTOT_UNITS[] = "Percent";
261
262 static const char RR1_NAME[] = "wet_days_index_per_time_period";
263 static const char RR1_LONGNAME[] = "Wet days index is the number of days per time period with daily precipitation of at least %g mm. The time period should be defined by the bounds of the time coordinate.";
264 static const char RR1_UNITS[] = "No.";
265
266 static const char RX1DAY_NAME[] = "highest_one_day_precipitation_amount_per_time_period";
267 static const char RX1DAY_NAME_ET[] = "rx1dayETCCDI";
268 static const char RX1DAY_LONGNAME[] = "Highest one day precipitation is the maximum of one day precipitation amount in a given time period. The time period should be defined by the bounds of the time coordinate.";
269 static const char RX1DAY_LONGNAME_ET[]= "Maximum 1-day Precipitation";
270 static const char RX1DAY_UNITS[] = "mm per day";
271 static const char RX1DAY_UNITS_ET[] = "mm";
272
273 static const char RX5DAY_NAME[] = "highest_five_day_precipitation_amount_per_time_period";
274 static const char RX5DAY_NAME_ET[] = "rx5dayETCCDI";
275 static const char RX5DAY_LONGNAME[] = "Highest precipitation amount for five day interval (including the calendar day as the last day). The time period should be defined by the bounds of the time coordinate.";
276 static const char RX5DAY_LONGNAME_ET[]= "Maximum Consecutive 5-day Precipitation";
277 static const char RX5DAY_UNITS[] = "mm per 5 day";
278 static const char RX5DAY_UNITS_ET[] = "mm";
279 static const char RX5DAY_NAME2[] = "number_of_5day_heavy_precipitation_periods_per_time_period";
280 static const char RX5DAY_LONGNAME2[] = "Number of 5day periods in given time period with precipitation amount exceeding %1.0f mm / 5 days. The time period should be defined by the bounds of the time coordinate.";
281 static const char RX5DAY_UNITS2[] = "No.";
282
283 static const char SDII_NAME[] = "simple_daily_intensity_index_per_time_period";
284 static const char SDII_NAME_ET[] = "sdiiETCCDI";
285 static const char SDII_LONGNAME[] = "Simple daily intensity index is the mean of precipitation amount on wet days. A wet day is a day with precipitation sum of at least %g mm. The time period should be defined by the bounds of the time coordinate.";
286 static const char SDII_LONGNAME_ET[] = "Simple Precipitation Intensity Index";
287 static const char SDII_UNITS[] = "mm";
288 static const char SDII_UNITS_ET[] = "mm d-1";
289
290 static const char FDNS_NAME[] = "frost_days_where_no_snow_index_per_time_period";
291 static const char FDNS_LONGNAME[] = "Frost days where no snow index is the number of days without snowcover and where the minimum of temperature is below 0 degree Celsius. The time period should be defined by the bounds of the time coordinate.";
292 static const char FDNS_UNITS[] = "No.";
293
294 static const char STRWIN_NAME[] = "strong_wind_days_index_per_time_period";
295 static const char STRWIN_LONGNAME[] = "Strong wind days index is the number of days per time period where maximum wind speed is above %1.0f m/s. The time period should be defined by the bounds of the time coordinate.";
296 static const char STRWIN_UNITS[] = "No.";
297 static const char STRWIN_NAME2[] = "consecutive_strong_wind_days_index_per_time_period";
298 static const char STRWIN_LONGNAME2[] = "Greatest number of consecutive strong wind days per time period. The time period should be defined by the bounds of the time coordinate.";
299 static const char STRWIN_UNITS2[] = "No.";
300
301 static const char STRBRE_NAME[] = "strong_breeze_days_index_per_time_period";
302 static const char STRBRE_LONGNAME[] = "Strong breeze days index is the number of days per time period where maximum wind speed is above 10.5 m/s. The time period should be defined by the bounds of the time coordinate.";
303 static const char STRBRE_NAME2[] = "consecutive_strong_breeze_days_index_per_time_period";
304 static const char STRBRE_LONGNAME2[] = "Greatest number of consecutive strong breeze days per time period. The time period should be defined by the bounds of the time coordinate.";
305
306 //static const char STRGAL_NAME[] = "strong_gale_days_index_per_time_period";
307 //static const char STRGAL_LONGNAME[] = "Strong gale days index is the number of days per time period where maximum wind speed is above 20.5 m/s. The time period should be defined by the bounds of the time coordinate.";
308 //static const char STRGAL_NAME2[] = "consecutive_strong_gale_days_index_per_time_period";
309 //static const char STRGAL_LONGNAME2[] = "Greatest number of consecutive strong gale days per time period. The time period should be defined by the bounds of the time coordinate.";
310
311 static const char HURR_NAME[] = "hurricane_days_index_per_time_period";
312 static const char HURR_LONGNAME[] = "Hurricane days index is the number of days per time period where maximum wind speed is above 32.5 m/s. The time period should be defined by the bounds of the time coordinate.";
313 static const char HURR_NAME2[] = "consecutive_hurricane_days_index_per_time_period";
314 static const char HURR_LONGNAME2[] = "Greatest number of consecutive hurricane days per time period. The time period should be defined by the bounds of the time coordinate.";
315
316 // clang-format on
317
318 /* ECA temperature indices */
319
320 static int
addWithFrequency(const std::vector<std::string> & params,const char * operatorName,size_t defaultDays)321 addWithFrequency(const std::vector<std::string> ¶ms, const char *operatorName, size_t defaultDays)
322 {
323 int opID = 0;
324
325 KVList kvlist;
326 if (kvlist.parse_arguments(1, params) != 0) cdo_abort("Argument parse error!");
327 auto kv = kvlist.search("freq");
328 if (kv && kv->nvalues > 0)
329 {
330 if (kv->values[0] == "month")
331 opID = cdo_operator_add(operatorName, 0, 8, nullptr);
332 else if (kv->values[0] == "year")
333 opID = cdo_operator_add(operatorName, 0, 10, nullptr);
334 else
335 cdo_abort("Frequency '%s' unknown.", kv->values[0]);
336 }
337 else
338 opID = cdo_operator_add(operatorName, 0, defaultDays, nullptr);
339
340 return opID;
341 }
342
343 void *
EcaCfd(void * process)344 EcaCfd(void *process)
345 {
346 int ndays = 5;
347
348 cdo_initialize(process);
349
350 if (cdo_operator_argc() > 2) cdo_abort("Too many arguments!");
351 if (cdo_operator_argc() > 1)
352 {
353 auto params = cdo_get_oper_argv();
354 params = std::vector<std::string>(params.begin() + 1, params.end());
355 addWithFrequency(params, "eca_cfd", 31);
356 }
357 else
358 {
359 if (cdo_operator_argc() > 0) ndays = parameter_to_int(cdo_operator_argv(0));
360 cdo_operator_add("eca_cfd", 0, 31, nullptr);
361 }
362
363 char cfd_longname2[1024];
364 char cfd_name2[1024];
365 sprintf(cfd_longname2, CFD_LONGNAME2, ndays);
366 sprintf(cfd_name2, CFD_NAME2, ndays);
367
368 ECA_REQUEST_1 request;
369
370 request.var1.name = CFD_NAME;
371 request.var1.longname = CFD_LONGNAME;
372 request.var1.refdate = ECA_refdate;
373 request.var1.f1 = vfarselltc;
374 request.var1.f1arg = TO_KELVIN(0.0);
375 request.var1.f2 = vfarnum2;
376 request.var1.f3 = field2_max;
377 request.var2.name = cfd_name2;
378 request.var2.longname = cfd_longname2;
379 request.var2.units = CFD_UNITS2;
380 request.var2.h1 = vfarseleqc;
381 request.var2.h1arg = ndays + 1;
382 request.var2.h3 = vfarnum;
383
384 eca1(request);
385
386 cdo_finish();
387
388 return 0;
389 }
390
391 void *
EcaCsu(void * process)392 EcaCsu(void *process)
393 {
394 double argT = 25.0;
395 int ndays = 5;
396
397 cdo_initialize(process);
398
399 if (cdo_operator_argc() > 3) cdo_abort("Too many arguments!");
400 if (cdo_operator_argc() > 2)
401 {
402 auto params = cdo_get_oper_argv();
403 params = std::vector<std::string>(params.begin() + 2, params.end());
404 addWithFrequency(params, "eca_csu", 31);
405 }
406 else if (cdo_operator_argc() > 0)
407 {
408 cdo_operator_add("eca_csu", 0, 31, nullptr);
409 argT = parameter_to_double(cdo_operator_argv(0));
410 if (cdo_operator_argc() == 2) ndays = parameter_to_int(cdo_operator_argv(1));
411 }
412 else
413 cdo_operator_add("eca_csu", 0, 31, nullptr);
414
415 char csu_longname2[1024];
416 char csu_name2[1024];
417 sprintf(csu_longname2, CSU_LONGNAME2, ndays);
418 sprintf(csu_name2, CSU_NAME2, ndays);
419
420 ECA_REQUEST_1 request;
421
422 request.var1.name = CSU_NAME;
423 request.var1.longname = CSU_LONGNAME;
424 request.var1.refdate = ECA_refdate;
425 request.var1.f1 = vfarselgtc;
426 request.var1.f1arg = TO_KELVIN(argT);
427 request.var1.f2 = vfarnum2;
428 request.var1.f3 = field2_max;
429 request.var2.name = csu_name2;
430 request.var2.longname = csu_longname2;
431 request.var2.units = CSU_UNITS2;
432 request.var2.h1 = vfarseleqc;
433 request.var2.h1arg = ndays + 1;
434 request.var2.h3 = vfarnum;
435
436 eca1(request);
437
438 cdo_finish();
439
440 return 0;
441 }
442
443 void *
EcaCwdi(void * process)444 EcaCwdi(void *process)
445 {
446 int argN = 6;
447 double argT = 5.0;
448
449 cdo_initialize(process);
450
451 if (cdo_operator_argc() > 2)
452 {
453 auto params = cdo_get_oper_argv();
454 params = std::vector<std::string>(params.begin() + 2, params.end());
455 addWithFrequency(params, "eca_cwdi", 31);
456 argT = parameter_to_double(cdo_operator_argv(1));
457 argN = parameter_to_int(cdo_operator_argv(0));
458 }
459 else
460 {
461 if (cdo_operator_argc() > 1)
462 argT = parameter_to_double(cdo_operator_argv(1));
463 else if (cdo_operator_argc() > 0)
464 argN = parameter_to_int(cdo_operator_argv(0));
465 cdo_operator_add("eca_cwdi", 0, 31, nullptr);
466 }
467
468 char longname[sizeof(CWDI_LONGNAME) + 80];
469 sprintf(longname, CWDI_LONGNAME, argN, argT);
470
471 ECA_REQUEST_2 request;
472
473 request.var1.name = CWDI_NAME;
474 request.var1.longname = longname;
475 request.var1.refdate = ECA_refdate;
476 request.var1.units = CWDI_UNITS;
477 request.var1.f2 = fieldc_sub;
478 request.var1.f2arg = argT;
479 request.var1.f3 = vfarsellt;
480 request.var1.f4 = vfarnum2;
481 request.var1.f5 = vfarnum3;
482 request.var1.f5arg = argN;
483 request.var2.name = CWDI_NAME2;
484 request.var2.longname = CWDI_LONGNAME2;
485 request.var2.units = CWDI_UNITS2;
486 request.var2.h1 = vfarseleqc;
487 request.var2.h1arg = argN;
488 request.var2.h2 = vfarnum;
489
490 eca2(request);
491
492 cdo_finish();
493
494 return 0;
495 }
496
497 void *
EcaCwfi(void * process)498 EcaCwfi(void *process)
499 {
500 int argN = 6;
501
502 cdo_initialize(process);
503
504 int OPID_ECA = 0, OPID_ETC = 0;
505 if (cdo_operator_argc() > 1)
506 {
507 auto params = cdo_get_oper_argv();
508 params = std::vector<std::string>(params.begin() + 1, params.end());
509 OPID_ECA = addWithFrequency(params, "eca_cwfi", 31);
510 OPID_ETC = addWithFrequency(params, "etccdi_csdi", 10);
511 argN = parameter_to_int(cdo_operator_argv(0));
512 }
513 else
514 {
515 if (cdo_operator_argc() > 0) argN = parameter_to_int(cdo_operator_argv(0));
516 OPID_ECA = cdo_operator_add("eca_cwfi", 0, 31, nullptr);
517 OPID_ETC = cdo_operator_add("etccdi_csdi", 0, 10, nullptr);
518 }
519
520 char longname[sizeof(CWFI_LONGNAME) + 40];
521 sprintf(longname, CWFI_LONGNAME, argN);
522
523 ECA_REQUEST_2 request;
524
525 if (OPID_ECA == cdo_operator_id())
526 {
527 request.var1.name = CWFI_NAME;
528 request.var1.longname = longname;
529 request.var1.units = CWFI_UNITS;
530 request.var1.refdate = ECA_refdate;
531 }
532 else if (OPID_ETC == cdo_operator_id())
533 {
534 request.var1.name = CWFI_NAME_ET;
535 request.var1.longname = CWFI_LONGNAME_ET;
536 request.var1.units = CWFI_UNITS_ET;
537 request.var1.refdate = ETC_refdate;
538 }
539
540 request.var1.f3 = vfarsellt;
541 request.var1.f4 = vfarnum2;
542 request.var1.f5 = vfarnum3;
543 request.var1.f5arg = argN;
544 request.var2.name = CWFI_NAME2;
545 request.var2.longname = CWFI_LONGNAME2;
546 request.var2.units = CWFI_UNITS2;
547 request.var2.h1 = vfarseleqc;
548 request.var2.h1arg = argN;
549 request.var2.h2 = vfarnum;
550
551 eca2(request);
552
553 cdo_finish();
554
555 return 0;
556 }
557
558 void *
EcaEtr(void * process)559 EcaEtr(void *process)
560 {
561 cdo_initialize(process);
562
563 cdo_operator_add("eca_etr", 0, 31, nullptr);
564
565 ECA_REQUEST_3 request;
566
567 request.name = ETR_NAME;
568 request.longname = ETR_LONGNAME;
569 request.refdate = ECA_refdate;
570 request.f1 = field2_max;
571 request.f2 = field2_min;
572 request.f3 = field2_sub;
573
574 eca3(request);
575 cdo_finish();
576
577 return 0;
578 }
579
580 void *
EcaFd(void * process)581 EcaFd(void *process)
582 {
583 cdo_initialize(process);
584
585 int OPID_ECA = 0, OPID_ETC = 0;
586 if (cdo_operator_argc() > 0)
587 {
588 auto params = cdo_get_oper_argv();
589 OPID_ECA = addWithFrequency(params, "eca_fd", 31);
590 OPID_ETC = addWithFrequency(params, "etccdi_fd", 10);
591 }
592 else
593 {
594 OPID_ECA = cdo_operator_add("eca_fd", 0, 31, nullptr);
595 OPID_ETC = cdo_operator_add("etccdi_fd", 0, 10, nullptr);
596 }
597
598 ECA_REQUEST_1 request;
599
600 if (OPID_ECA == cdo_operator_id())
601 {
602 request.var1.name = FD_NAME;
603 request.var1.longname = FD_LONGNAME;
604 request.var1.refdate = ECA_refdate;
605 }
606 else if (OPID_ETC == cdo_operator_id())
607 {
608 request.var1.name = FD_NAME_ET;
609 request.var1.longname = FD_LONGNAME_ET;
610 request.var1.units = FD_UNITS_ET;
611 request.var1.refdate = ETC_refdate;
612 }
613
614 request.var1.f1 = vfarselltc;
615 request.var1.f1arg = TO_KELVIN(0.0);
616 request.var1.f2 = vfarnum;
617
618 eca1(request);
619
620 cdo_finish();
621
622 return 0;
623 }
624
625 /*
626 * Definition of GSL: (Thermal) Growing Season Length start at the first span
627 * of at least 6 (argN) days with T > 5.0°C (argT) in first half of the year
628 * and ends at the first span of ar least 6 (argN) days with T < 5.0°C (argT)
629 * in the second half.
630 * ATTENTION: Year of the northern hemisphere starts in january to
631 * december, whereas for the southern hemisphere is goes from july to june!
632 * Hence, at least 18 Month of data is needed for computing the gsl of the whole earth.
633 */
634 void *
EcaGsl(void * process)635 EcaGsl(void *process)
636 {
637 int argN = 6;
638 double argT = 5.0;
639 double minLandFraction = 0.5;
640
641 cdo_initialize(process);
642 cdo_operator_add("eca_gsl", 0, 10, nullptr);
643
644 if (cdo_operator_argc() > 0) argN = parameter_to_int(cdo_operator_argv(0));
645 if (cdo_operator_argc() > 1) argT = parameter_to_double(cdo_operator_argv(1));
646 if (cdo_operator_argc() > 2) minLandFraction = parameter_to_double(cdo_operator_argv(2));
647
648 char longname[sizeof(GSL_LONGNAME) + 160];
649 sprintf(longname, GSL_LONGNAME, argN, argT, argN, argT);
650
651 ECA_REQUEST_4 request;
652
653 request.name = GSL_NAME;
654 request.longname = longname;
655 request.units = GSL_UNITS;
656 request.name2 = GSL_NAME2;
657 request.longname2 = GSL_LONGNAME2;
658 request.units2 = GSL_UNITS2;
659 request.s1 = vfarselgtc;
660 request.s1arg = TO_KELVIN(argT);
661 request.s2 = vfarselltc;
662 request.s2arg = TO_KELVIN(argT);
663 request.s3 = vfarselgec;
664 request.s3arg = minLandFraction;
665 request.consecutiveDays = argN;
666
667 eca4(request);
668
669 cdo_finish();
670
671 return 0;
672 }
673
674 void *
EcaHd(void * process)675 EcaHd(void *process)
676 {
677 double argX = 17.0;
678 double argA = 17.0;
679
680 cdo_initialize(process);
681
682 cdo_operator_add("eca_hd", 0, 31, nullptr);
683
684 if (cdo_operator_argc() > 0)
685 {
686 argX = parameter_to_double(cdo_operator_argv(0));
687 argA = argX;
688 }
689 if (cdo_operator_argc() > 1) argA = parameter_to_double(cdo_operator_argv(1));
690
691 ECA_REQUEST_1 request;
692
693 request.var1.name = HD_NAME;
694 request.var1.longname = HD_LONGNAME;
695 request.var1.refdate = ECA_refdate;
696 request.var1.units = HD_UNITS;
697 request.var1.f1 = vfarselltc;
698 request.var1.f1arg = TO_KELVIN(argA);
699 request.var1.f2 = field2_sum;
700 request.var1.mulc = -1.0;
701 request.var1.addc = TO_KELVIN(argX);
702
703 eca1(request);
704
705 cdo_finish();
706
707 return 0;
708 }
709
710 void *
EcaHwdi(void * process)711 EcaHwdi(void *process)
712 {
713 int argN = 6;
714 double argT = 5.0;
715
716 cdo_initialize(process);
717
718 if (cdo_operator_argc() > 2)
719 {
720 auto params = cdo_get_oper_argv();
721 params = std::vector<std::string>(params.begin() + 2, params.end());
722 addWithFrequency(params, "eca_hwdi", 31);
723 argN = parameter_to_int(cdo_operator_argv(0));
724 argT = parameter_to_double(cdo_operator_argv(1));
725 }
726 else
727 {
728 if (cdo_operator_argc() > 0) argN = parameter_to_int(cdo_operator_argv(0));
729 if (cdo_operator_argc() > 1) argT = parameter_to_double(cdo_operator_argv(1));
730 cdo_operator_add("eca_hwdi", 0, 31, nullptr);
731 }
732
733 char longname[sizeof(HWDI_LONGNAME) + 80];
734 sprintf(longname, HWDI_LONGNAME, argN, argT);
735
736 ECA_REQUEST_2 request;
737
738 request.var1.name = HWDI_NAME;
739 request.var1.longname = longname;
740 request.var1.refdate = ECA_refdate;
741 request.var1.units = HWDI_UNITS;
742 request.var1.f2 = fieldc_add;
743 request.var1.f2arg = argT;
744 request.var1.f3 = vfarselgt;
745 request.var1.f4 = vfarnum2;
746 request.var1.f5 = vfarnum3;
747 request.var1.f5arg = argN;
748 request.var2.name = HWDI_NAME2;
749 request.var2.longname = HWDI_LONGNAME2;
750 request.var2.units = HWDI_UNITS2;
751 request.var2.h1 = vfarseleqc;
752 request.var2.h1arg = argN;
753 request.var2.h2 = vfarnum;
754
755 eca2(request);
756
757 cdo_finish();
758
759 return 0;
760 }
761
762 void *
EcaHwfi(void * process)763 EcaHwfi(void *process)
764 {
765 int argN = 6;
766
767 cdo_initialize(process);
768
769 int OPID_ECA = 0, OPID_ETC = 0;
770 if (cdo_operator_argc() > 1)
771 {
772 auto params = cdo_get_oper_argv();
773 params = std::vector<std::string>(params.begin() + 1, params.end());
774 OPID_ECA = addWithFrequency(params, "eca_hwfi", 31);
775 OPID_ETC = addWithFrequency(params, "etccdi_wsdi", 10);
776 argN = parameter_to_int(cdo_operator_argv(0));
777 }
778 else
779 {
780 if (cdo_operator_argc() > 0) argN = parameter_to_int(cdo_operator_argv(0));
781 OPID_ECA = cdo_operator_add("eca_hwfi", 0, 31, nullptr);
782 OPID_ETC = cdo_operator_add("etccdi_wsdi", 0, 10, nullptr);
783 }
784
785 char longname[sizeof(HWFI_LONGNAME) + 40];
786 sprintf(longname, HWFI_LONGNAME, argN);
787
788 ECA_REQUEST_2 request;
789
790 if (OPID_ECA == cdo_operator_id())
791 {
792 request.var1.name = HWFI_NAME;
793 request.var1.longname = longname;
794 request.var1.units = HWFI_UNITS;
795 request.var1.refdate = ECA_refdate;
796 }
797 else if (OPID_ETC == cdo_operator_id())
798 {
799 request.var1.name = HWFI_NAME_ET;
800 request.var1.longname = HWFI_LONGNAME_ET;
801 request.var1.units = HWFI_UNITS_ET;
802 request.var1.refdate = ETC_refdate;
803 }
804
805 request.var1.f3 = vfarselgt;
806 request.var1.f4 = vfarnum2;
807 request.var1.f5 = vfarnum3;
808 request.var1.f5arg = argN;
809 request.var2.name = HWFI_NAME2;
810 request.var2.longname = HWFI_LONGNAME2;
811 request.var2.units = HWFI_UNITS2;
812 request.var2.h1 = vfarseleqc;
813 request.var2.h1arg = argN;
814 request.var2.h2 = vfarnum;
815
816 eca2(request);
817
818 cdo_finish();
819
820 return 0;
821 }
822
823 void *
EcaId(void * process)824 EcaId(void *process)
825 {
826 cdo_initialize(process);
827
828 int OPID_ECA = 0, OPID_ETC = 0;
829 if (cdo_operator_argc() > 0)
830 {
831 auto params = cdo_get_oper_argv();
832 OPID_ECA = addWithFrequency(params, "eca_id", 31);
833 OPID_ETC = addWithFrequency(params, "etccdi_id", 10);
834 }
835 else
836 {
837 OPID_ETC = cdo_operator_add("etccdi_id", 0, 10, nullptr);
838 OPID_ECA = cdo_operator_add("eca_id", 0, 31, nullptr);
839 }
840
841 ECA_REQUEST_1 request;
842
843 if (OPID_ECA == cdo_operator_id())
844 {
845 request.var1.name = ID_NAME;
846 request.var1.longname = ID_LONGNAME;
847 request.var1.units = ID_UNITS;
848 }
849 else if (OPID_ETC == cdo_operator_id())
850 {
851 request.var1.name = ID_NAME_ET;
852 request.var1.longname = ID_LONGNAME_ET;
853 request.var1.units = ID_UNITS_ET;
854 }
855
856 request.var1.f1 = vfarselltc;
857 request.var1.f1arg = TO_KELVIN(0.0);
858 request.var1.f2 = vfarnum;
859
860 eca1(request);
861
862 cdo_finish();
863
864 return 0;
865 }
866
867 void *
EcaSu(void * process)868 EcaSu(void *process)
869 {
870 double argT = 25.0;
871
872 cdo_initialize(process);
873
874 int OPID_ECA = 0, OPID_ETC = 0;
875 if (cdo_operator_argc() > 0) argT = parameter_to_double(cdo_operator_argv(0));
876 if (cdo_operator_argc() > 1)
877 {
878 auto params = cdo_get_oper_argv();
879 params = std::vector<std::string>(params.begin() + 1, params.end());
880 OPID_ECA = addWithFrequency(params, "eca_su", 31);
881 OPID_ETC = addWithFrequency(params, "etccdi_su", 10);
882 }
883 else
884 {
885 OPID_ETC = cdo_operator_add("etccdi_su", 0, 10, nullptr);
886 OPID_ECA = cdo_operator_add("eca_su", 0, 31, nullptr);
887 }
888
889 char longname[sizeof(SU_LONGNAME) + 40];
890 sprintf(longname, SU_LONGNAME, argT);
891
892 ECA_REQUEST_1 request;
893
894 if (OPID_ECA == cdo_operator_id())
895 {
896 request.var1.name = SU_NAME;
897 request.var1.longname = longname;
898 request.var1.refdate = ECA_refdate;
899 }
900 else if (OPID_ETC == cdo_operator_id())
901 {
902 request.var1.name = SU_NAME_ET;
903 request.var1.longname = SU_LONGNAME_ET;
904 request.var1.units = SU_UNITS_ET;
905 request.var1.refdate = ETC_refdate;
906 }
907
908 request.var1.f1 = vfarselgtc;
909 request.var1.f1arg = TO_KELVIN(argT);
910 request.var1.f2 = vfarnum;
911
912 eca1(request);
913
914 cdo_finish();
915
916 return 0;
917 }
918
919 void *
EcaTg10p(void * process)920 EcaTg10p(void *process)
921 {
922 cdo_initialize(process);
923
924 cdo_operator_add("eca_tg10p", 0, 31, nullptr);
925
926 ECA_REQUEST_2 request;
927
928 request.var1.name = TG10P_NAME;
929 request.var1.longname = TG10P_LONGNAME;
930 request.var1.refdate = ECA_refdate;
931 request.var1.units = TG10P_UNITS;
932 request.var1.f3 = vfarsellt;
933 request.var1.f4 = vfarnum;
934 request.var1.epilog = PERCENT_OF_TIME;
935
936 eca2(request);
937
938 cdo_finish();
939
940 return 0;
941 }
942
943 void *
EcaTg90p(void * process)944 EcaTg90p(void *process)
945 {
946 cdo_initialize(process);
947
948 cdo_operator_add("eca_tg90p", 0, 31, nullptr);
949
950 ECA_REQUEST_2 request;
951
952 request.var1.name = TG90P_NAME;
953 request.var1.longname = TG90P_LONGNAME;
954 request.var1.refdate = ECA_refdate;
955 request.var1.units = TG90P_UNITS;
956 request.var1.f3 = vfarselgt;
957 request.var1.f4 = vfarnum;
958 request.var1.epilog = PERCENT_OF_TIME;
959
960 eca2(request);
961
962 cdo_finish();
963
964 return 0;
965 }
966
967 void *
EcaTn10p(void * process)968 EcaTn10p(void *process)
969 {
970 cdo_initialize(process);
971
972 cdo_operator_add("eca_tn10p", 0, 31, nullptr);
973
974 ECA_REQUEST_2 request;
975
976 request.var1.name = TN10P_NAME;
977 request.var1.longname = TN10P_LONGNAME;
978 request.var1.refdate = ECA_refdate;
979 request.var1.units = TN10P_UNITS;
980 request.var1.f3 = vfarsellt;
981 request.var1.f4 = vfarnum;
982 request.var1.epilog = PERCENT_OF_TIME;
983
984 eca2(request);
985
986 cdo_finish();
987
988 return 0;
989 }
990
991 void *
EcaTn90p(void * process)992 EcaTn90p(void *process)
993 {
994 cdo_initialize(process);
995
996 cdo_operator_add("eca_tn90p", 0, 31, nullptr);
997
998 ECA_REQUEST_2 request;
999
1000 request.var1.name = TN90P_NAME;
1001 request.var1.longname = TN90P_LONGNAME;
1002 request.var1.refdate = ECA_refdate;
1003 request.var1.units = TN90P_UNITS;
1004 request.var1.f3 = vfarselgt;
1005 request.var1.f4 = vfarnum;
1006 request.var1.epilog = PERCENT_OF_TIME;
1007
1008 eca2(request);
1009
1010 cdo_finish();
1011
1012 return 0;
1013 }
1014
1015 void *
EcaTr(void * process)1016 EcaTr(void *process)
1017 {
1018 double argT = 20.0;
1019
1020 cdo_initialize(process);
1021
1022 int OPID_ECA = 0, OPID_ETC = 0;
1023 if (cdo_operator_argc() > 0) argT = parameter_to_double(cdo_operator_argv(0));
1024 if (cdo_operator_argc() > 1)
1025 {
1026 auto params = cdo_get_oper_argv();
1027 params = std::vector<std::string>(params.begin() + 1, params.end());
1028 OPID_ECA = addWithFrequency(params, "eca_tr", 31);
1029 OPID_ETC = addWithFrequency(params, "etccdi_tr", 10);
1030 }
1031 else
1032 {
1033 OPID_ETC = cdo_operator_add("etccdi_tr", 0, 10, nullptr);
1034 OPID_ECA = cdo_operator_add("eca_tr", 0, 31, nullptr);
1035 }
1036
1037 char tr_longname[1024];
1038 sprintf(tr_longname, TR_LONGNAME, argT);
1039
1040 ECA_REQUEST_1 request;
1041
1042 if (OPID_ECA == cdo_operator_id())
1043 {
1044 request.var1.name = TR_NAME;
1045 request.var1.longname = tr_longname;
1046 request.var1.units = TR_UNITS;
1047 request.var1.refdate = ECA_refdate;
1048 }
1049 else if (OPID_ETC == cdo_operator_id())
1050 {
1051 request.var1.name = TR_NAME_ET;
1052 request.var1.longname = TR_LONGNAME_ET;
1053 request.var1.units = TR_UNITS_ET;
1054 request.var1.refdate = ETC_refdate;
1055 }
1056
1057 request.var1.f1 = vfarselgtc;
1058 request.var1.f1arg = TO_KELVIN(argT);
1059 request.var1.f2 = vfarnum;
1060
1061 eca1(request);
1062
1063 cdo_finish();
1064
1065 return 0;
1066 }
1067
1068 void *
EcaTx10p(void * process)1069 EcaTx10p(void *process)
1070 {
1071 cdo_initialize(process);
1072
1073 cdo_operator_add("eca_tx10p", 0, 31, nullptr);
1074
1075 ECA_REQUEST_2 request;
1076
1077 request.var1.name = TX10P_NAME;
1078 request.var1.longname = TX10P_LONGNAME;
1079 request.var1.refdate = ECA_refdate;
1080 request.var1.units = TX10P_UNITS;
1081 request.var1.f3 = vfarsellt;
1082 request.var1.f4 = vfarnum;
1083 request.var1.epilog = PERCENT_OF_TIME;
1084
1085 eca2(request);
1086
1087 cdo_finish();
1088
1089 return 0;
1090 }
1091
1092 void *
EcaTx90p(void * process)1093 EcaTx90p(void *process)
1094 {
1095 cdo_initialize(process);
1096 if (cdo_operator_argc() > 0)
1097 {
1098 if ('m' == cdo_operator_argv(0)[0])
1099 cdo_operator_add("eca_tx90p", 0, 8, nullptr); /* monthly mode */
1100 else
1101 cdo_warning("Parameter value '%s' is invalid. The only valid value is "
1102 "'m' indicating monthly mode. Operating in yearly mode now.",
1103 cdo_operator_argv(0));
1104 }
1105 else
1106 cdo_operator_add("eca_tx90p", 0, 31, nullptr);
1107
1108 ECA_REQUEST_2 request;
1109
1110 request.var1.name = TX90P_NAME;
1111 request.var1.longname = TX90P_LONGNAME;
1112 request.var1.refdate = ECA_refdate;
1113 request.var1.units = TX90P_UNITS;
1114 request.var1.f3 = vfarselgt;
1115 request.var1.f4 = vfarnum;
1116 request.var1.epilog = PERCENT_OF_TIME;
1117
1118 eca2(request);
1119
1120 cdo_finish();
1121
1122 return 0;
1123 }
1124
1125 // ECA precipitation indices
1126
1127 void *
EcaCdd(void * process)1128 EcaCdd(void *process)
1129 {
1130 double threshold = 1;
1131 int ndays = 5;
1132
1133 cdo_initialize(process);
1134
1135 int OPID_ECA = 0, OPID_ETC = 0;
1136 if (cdo_operator_argc() > 3)
1137 cdo_abort("Too many arguments!");
1138 else if (cdo_operator_argc() > 2)
1139 {
1140 auto params = cdo_get_oper_argv();
1141 params = std::vector<std::string>(params.begin() + 2, params.end());
1142 OPID_ECA = addWithFrequency(params, "eca_cdd", 31);
1143 OPID_ETC = addWithFrequency(params, "etccdi_cdd", 10);
1144 }
1145 else if (cdo_operator_argc() > 0)
1146 {
1147 threshold = parameter_to_double(cdo_operator_argv(0));
1148 if (cdo_operator_argc() == 2) ndays = parameter_to_int(cdo_operator_argv(1));
1149 OPID_ECA = cdo_operator_add("eca_cdd", 0, 31, nullptr);
1150 OPID_ETC = cdo_operator_add("etccdi_cdd", 0, 10, nullptr);
1151 }
1152 else
1153 {
1154 OPID_ECA = cdo_operator_add("eca_cdd", 0, 31, nullptr);
1155 OPID_ETC = cdo_operator_add("etccdi_cdd", 0, 10, nullptr);
1156 }
1157
1158 char cdd_longname[1024];
1159 char cdd_longname2[1024];
1160 char cdd_name2[1024];
1161 sprintf(cdd_longname, CDD_LONGNAME, threshold);
1162 sprintf(cdd_longname2, CDD_LONGNAME2, ndays);
1163 sprintf(cdd_name2, CDD_NAME2, ndays);
1164
1165 ECA_REQUEST_1 request;
1166
1167 if (OPID_ECA == cdo_operator_id())
1168 {
1169 request.var1.name = CDD_NAME;
1170 request.var1.longname = cdd_longname;
1171 request.var1.units = CDD_UNITS;
1172 request.var1.refdate = ECA_refdate;
1173 }
1174 else if (OPID_ETC == cdo_operator_id())
1175 {
1176 request.var1.name = CDD_NAME_ET;
1177 request.var1.longname = CDD_LONGNAME_ET;
1178 request.var1.units = CDD_UNITS_ET;
1179 request.var1.refdate = ETC_refdate;
1180 }
1181
1182 request.var1.f1 = vfarselltc;
1183 request.var1.f1arg = threshold;
1184 request.var1.f2 = vfarnum2;
1185 request.var1.f3 = field2_max;
1186 request.var2.name = cdd_name2;
1187 request.var2.longname = cdd_longname2;
1188 request.var2.units = CDD_UNITS2;
1189 request.var2.h1 = vfarseleqc;
1190 request.var2.h1arg = ndays + 1;
1191 request.var2.h3 = vfarnum;
1192
1193 eca1(request);
1194
1195 cdo_finish();
1196
1197 return 0;
1198 }
1199
1200 void *
EcaCwd(void * process)1201 EcaCwd(void *process)
1202 {
1203 double threshold = 1;
1204 int ndays = 5;
1205
1206 cdo_initialize(process);
1207
1208 int OPID_ECA = 0, OPID_ETC = 0;
1209
1210 if (cdo_operator_argc() > 3)
1211 cdo_abort("Too many arguments!");
1212 else if (cdo_operator_argc() > 2)
1213 {
1214 auto params = cdo_get_oper_argv();
1215 params = std::vector<std::string>(params.begin() + 2, params.end());
1216 OPID_ECA = addWithFrequency(params, "eca_cwd", 31);
1217 OPID_ETC = addWithFrequency(params, "etccdi_cwd", 10);
1218 }
1219 else if (cdo_operator_argc() > 0)
1220 {
1221 threshold = parameter_to_double(cdo_operator_argv(0));
1222 if (cdo_operator_argc() == 2) ndays = parameter_to_int(cdo_operator_argv(1));
1223 OPID_ECA = cdo_operator_add("eca_cwd", 0, 31, nullptr);
1224 OPID_ETC = cdo_operator_add("etccdi_cwd", 0, 10, nullptr);
1225 }
1226 else
1227 {
1228 OPID_ECA = cdo_operator_add("eca_cwd", 0, 31, nullptr);
1229 OPID_ETC = cdo_operator_add("etccdi_cwd", 0, 10, nullptr);
1230 }
1231
1232 char cwd_longname[1024];
1233 char cwd_longname2[1024];
1234 char cwd_name2[1024];
1235 sprintf(cwd_longname, CWD_LONGNAME, threshold);
1236 sprintf(cwd_longname2, CWD_LONGNAME2, ndays);
1237 sprintf(cwd_name2, CWD_NAME2, ndays);
1238
1239 ECA_REQUEST_1 request;
1240
1241 if (OPID_ECA == cdo_operator_id())
1242 {
1243 request.var1.name = CWD_NAME;
1244 request.var1.longname = cwd_longname;
1245 request.var1.units = CWD_UNITS;
1246 request.var1.refdate = ECA_refdate;
1247 }
1248 else if (OPID_ETC == cdo_operator_id())
1249 {
1250 request.var1.name = CWD_NAME_ET;
1251 request.var1.longname = CWD_LONGNAME_ET;
1252 request.var1.units = CWD_UNITS_ET;
1253 request.var1.refdate = ETC_refdate;
1254 }
1255 request.var1.f1 = vfarselgec;
1256 request.var1.f1arg = threshold;
1257 request.var1.f2 = vfarnum2;
1258 request.var1.f3 = field2_max;
1259 request.var2.name = cwd_name2;
1260 request.var2.longname = cwd_longname2;
1261 request.var2.units = CWD_UNITS2;
1262 request.var2.h1 = vfarseleqc;
1263 request.var2.h1arg = ndays + 1;
1264 request.var2.h3 = vfarnum;
1265
1266 eca1(request);
1267
1268 cdo_finish();
1269
1270 return 0;
1271 }
1272
1273 void *
EcaPd(void * process)1274 EcaPd(void *process)
1275 {
1276 char lnamebuffer[1024];
1277 double threshold = 0;
1278 ECA_REQUEST_1 request;
1279
1280 cdo_initialize(process);
1281
1282 int datelenOp = 31;
1283 if (cdo_operator_argc() > 0)
1284 {
1285 auto params = cdo_get_oper_argv();
1286 KVList kvlist;
1287 if (strstr(cdo_operator_argv(0).c_str(), "=") || cdo_operator_argc() > 1)
1288 {
1289 if (cdo_operator_argc() > 1) params = std::vector<std::string>(params.begin() + 1, params.end());
1290 if (kvlist.parse_arguments(1, params) != 0) cdo_abort("Argument parse error!");
1291 auto kv = kvlist.search("freq");
1292 if (kv && kv->nvalues > 0)
1293 {
1294 if (kv->values[0] == "month")
1295 datelenOp = 8;
1296 else if (kv->values[0] == "year")
1297 datelenOp = 10;
1298 }
1299 }
1300 }
1301
1302 // clang-format off
1303 const auto ECA_PD = cdo_operator_add("eca_pd", 0, datelenOp, nullptr);
1304 const auto ETCCDI_PD = cdo_operator_add("etccdi_r1mm", 0, datelenOp, nullptr);
1305 const auto ECA_R10MM = cdo_operator_add("eca_r10mm", 0, datelenOp, nullptr);
1306 const auto ETCCDI_R10MM = cdo_operator_add("etccdi_r10mm", 0, datelenOp, nullptr);
1307 const auto ECA_R20MM = cdo_operator_add("eca_r20mm", 0, datelenOp, nullptr);
1308 const auto ETCCDI_R20MM = cdo_operator_add("etccdi_r20mm", 0, datelenOp, nullptr);
1309 // clang-format on
1310
1311 const auto operatorID = cdo_operator_id();
1312
1313 if (operatorID == ECA_PD || operatorID == ETCCDI_PD)
1314 {
1315 if (operatorID == ECA_PD)
1316 {
1317 operator_input_arg("daily precipitation amount threshold in [mm]");
1318
1319 if (cdo_operator_argc() < 1) cdo_abort("Too few arguments!");
1320 if (cdo_operator_argc() > 2) cdo_abort("Too many arguments!");
1321 threshold = parameter_to_double(cdo_operator_argv(0));
1322 sprintf(lnamebuffer, PD_LONGNAME, threshold);
1323 request.var1.name = PD_NAME;
1324 request.var1.longname = lnamebuffer;
1325 request.var1.units = PD_UNITS;
1326 }
1327 else
1328 {
1329 threshold = 1;
1330 request.var1.name = PD_NAME_ET;
1331 request.var1.longname = PD_LONGNAME_ET;
1332 request.var1.units = PD_UNITS_ET;
1333 }
1334 if (threshold < 0) cdo_abort("Parameter out of range: threshold = %g", threshold);
1335 }
1336 else if (operatorID == ECA_R10MM || operatorID == ETCCDI_R10MM)
1337 {
1338 threshold = 10;
1339 if (operatorID == ECA_R10MM)
1340 {
1341 request.var1.name = R10MM_NAME;
1342 request.var1.longname = R10MM_LONGNAME;
1343 request.var1.units = R10MM_UNITS;
1344 request.var1.refdate = ECA_refdate;
1345 }
1346 else
1347 {
1348 request.var1.name = R10MM_NAME_ET;
1349 request.var1.longname = R10MM_LONGNAME_ET;
1350 request.var1.units = R10MM_UNITS_ET;
1351 request.var1.refdate = ETC_refdate;
1352 }
1353 }
1354 else if (operatorID == ECA_R20MM || operatorID == ETCCDI_R20MM)
1355 {
1356 threshold = 20;
1357 if (operatorID == ECA_R20MM)
1358 {
1359 request.var1.name = R20MM_NAME;
1360 request.var1.longname = R20MM_LONGNAME;
1361 request.var1.units = R20MM_UNITS;
1362 request.var1.refdate = ECA_refdate;
1363 }
1364 else
1365 {
1366 request.var1.name = R20MM_NAME_ET;
1367 request.var1.longname = R20MM_LONGNAME_ET;
1368 request.var1.units = R20MM_UNITS_ET;
1369 request.var1.refdate = ETC_refdate;
1370 }
1371 }
1372
1373 if (Options::cdoVerbose) cdo_print("threshold = %g", threshold);
1374
1375 request.var1.f1 = vfarselgec;
1376 request.var1.f1arg = threshold;
1377 request.var1.f2 = vfarnum;
1378
1379 eca1(request);
1380
1381 cdo_finish();
1382
1383 return 0;
1384 }
1385
1386 void *
EcaR75p(void * process)1387 EcaR75p(void *process)
1388 {
1389 cdo_initialize(process);
1390
1391 cdo_operator_add("eca_r75p", 0, 31, nullptr);
1392
1393 ECA_REQUEST_2 request;
1394
1395 request.var1.name = R75P_NAME;
1396 request.var1.longname = R75P_LONGNAME;
1397 request.var1.refdate = ECA_refdate;
1398 request.var1.units = R75P_UNITS;
1399 request.var1.f1 = vfarselgec;
1400 request.var1.f3 = vfarselgt;
1401 request.var1.f4 = vfarnum;
1402 request.var1.epilog = PERCENT_OF_TIME;
1403
1404 eca2(request);
1405
1406 cdo_finish();
1407
1408 return 0;
1409 }
1410
1411 void *
EcaR75ptot(void * process)1412 EcaR75ptot(void *process)
1413 {
1414 cdo_initialize(process);
1415
1416 cdo_operator_add("eca_r75ptot", 0, 31, nullptr);
1417
1418 ECA_REQUEST_2 request;
1419
1420 request.var1.name = R75PTOT_NAME;
1421 request.var1.longname = R75PTOT_LONGNAME;
1422 request.var1.refdate = ECA_refdate;
1423 request.var1.units = R75PTOT_UNITS;
1424 request.var1.f1 = vfarselgec;
1425 request.var1.f3 = vfarselgt;
1426 request.var1.f4 = field2_sum;
1427 request.var1.epilog = PERCENT_OF_TOTAL_AMOUNT;
1428
1429 eca2(request);
1430
1431 cdo_finish();
1432
1433 return 0;
1434 }
1435
1436 void *
EcaR90p(void * process)1437 EcaR90p(void *process)
1438 {
1439 cdo_initialize(process);
1440
1441 cdo_operator_add("eca_r90p", 0, 31, nullptr);
1442
1443 ECA_REQUEST_2 request;
1444
1445 request.var1.name = R90P_NAME;
1446 request.var1.longname = R90P_LONGNAME;
1447 request.var1.refdate = ECA_refdate;
1448 request.var1.units = R90P_UNITS;
1449 request.var1.f1 = vfarselgec;
1450 request.var1.f3 = vfarselgt;
1451 request.var1.f4 = vfarnum;
1452 request.var1.epilog = PERCENT_OF_TIME;
1453
1454 eca2(request);
1455
1456 cdo_finish();
1457
1458 return 0;
1459 }
1460
1461 void *
EcaR90ptot(void * process)1462 EcaR90ptot(void *process)
1463 {
1464 cdo_initialize(process);
1465
1466 cdo_operator_add("eca_r90ptot", 0, 31, nullptr);
1467
1468 ECA_REQUEST_2 request;
1469
1470 request.var1.name = R90PTOT_NAME;
1471 request.var1.longname = R90PTOT_LONGNAME;
1472 request.var1.refdate = ECA_refdate;
1473 request.var1.units = R90PTOT_UNITS;
1474 request.var1.f1 = vfarselgec;
1475 request.var1.f3 = vfarselgt;
1476 request.var1.f4 = field2_sum;
1477 request.var1.epilog = PERCENT_OF_TOTAL_AMOUNT;
1478
1479 eca2(request);
1480
1481 cdo_finish();
1482
1483 return 0;
1484 }
1485
1486 void *
EcaR95p(void * process)1487 EcaR95p(void *process)
1488 {
1489 cdo_initialize(process);
1490
1491 cdo_operator_add("eca_r95p", 0, 31, nullptr);
1492
1493 ECA_REQUEST_2 request;
1494
1495 request.var1.name = R95P_NAME;
1496 request.var1.longname = R95P_LONGNAME;
1497 request.var1.refdate = ECA_refdate;
1498 request.var1.units = R95P_UNITS;
1499 request.var1.f1 = vfarselgec;
1500 request.var1.f3 = vfarselgt;
1501 request.var1.f4 = vfarnum;
1502 request.var1.epilog = PERCENT_OF_TIME;
1503
1504 eca2(request);
1505
1506 cdo_finish();
1507
1508 return 0;
1509 }
1510
1511 void *
EcaR95ptot(void * process)1512 EcaR95ptot(void *process)
1513 {
1514 cdo_initialize(process);
1515
1516 cdo_operator_add("eca_r95ptot", 0, 31, nullptr);
1517
1518 ECA_REQUEST_2 request;
1519
1520 request.var1.name = R95PTOT_NAME;
1521 request.var1.longname = R95PTOT_LONGNAME;
1522 request.var1.refdate = ECA_refdate;
1523 request.var1.units = R95PTOT_UNITS;
1524 request.var1.f1 = vfarselgec;
1525 request.var1.f3 = vfarselgt;
1526 request.var1.f4 = field2_sum;
1527 request.var1.epilog = PERCENT_OF_TOTAL_AMOUNT;
1528
1529 eca2(request);
1530
1531 cdo_finish();
1532
1533 return 0;
1534 }
1535
1536 void *
EcaR99p(void * process)1537 EcaR99p(void *process)
1538 {
1539 cdo_initialize(process);
1540
1541 cdo_operator_add("eca_r99p", 0, 31, nullptr);
1542
1543 ECA_REQUEST_2 request;
1544
1545 request.var1.name = R99P_NAME;
1546 request.var1.longname = R99P_LONGNAME;
1547 request.var1.refdate = ECA_refdate;
1548 request.var1.units = R99P_UNITS;
1549 request.var1.f1 = vfarselgec;
1550 request.var1.f3 = vfarselgt;
1551 request.var1.f4 = vfarnum;
1552 request.var1.epilog = PERCENT_OF_TIME;
1553
1554 eca2(request);
1555
1556 cdo_finish();
1557
1558 return 0;
1559 }
1560
1561 void *
EcaR99ptot(void * process)1562 EcaR99ptot(void *process)
1563 {
1564 cdo_initialize(process);
1565
1566 cdo_operator_add("eca_r99ptot", 0, 31, nullptr);
1567
1568 ECA_REQUEST_2 request;
1569
1570 request.var1.name = R99PTOT_NAME;
1571 request.var1.longname = R99PTOT_LONGNAME;
1572 request.var1.refdate = ECA_refdate;
1573 request.var1.f1 = vfarselgec;
1574 request.var1.f3 = vfarselgt;
1575 request.var1.f4 = field2_sum;
1576 request.var1.epilog = PERCENT_OF_TOTAL_AMOUNT;
1577
1578 eca2(request);
1579
1580 cdo_finish();
1581
1582 return 0;
1583 }
1584
1585 void *
EcaRr1(void * process)1586 EcaRr1(void *process)
1587 {
1588 double threshold = 1;
1589
1590 cdo_initialize(process);
1591
1592 if (cdo_operator_argc() > 2)
1593 cdo_abort("Too many arguments!");
1594 else if (cdo_operator_argc() > 1)
1595 {
1596 auto params = cdo_get_oper_argv();
1597 params = std::vector<std::string>(params.begin() + 1, params.end());
1598 addWithFrequency(params, "eca_rr1", 31);
1599 }
1600 else
1601 {
1602 if (cdo_operator_argc() == 1) threshold = parameter_to_double(cdo_operator_argv(0));
1603 cdo_operator_add("eca_rr1", 0, 31, nullptr);
1604 }
1605
1606 char lnamebuffer[1024];
1607 sprintf(lnamebuffer, RR1_LONGNAME, threshold);
1608
1609 ECA_REQUEST_1 request;
1610
1611 request.var1.name = RR1_NAME;
1612 request.var1.longname = lnamebuffer;
1613 request.var1.units = RR1_UNITS;
1614 request.var1.f1 = vfarselgec;
1615 request.var1.f1arg = threshold;
1616 request.var1.f2 = vfarnum;
1617
1618 eca1(request);
1619
1620 cdo_finish();
1621
1622 return 0;
1623 }
1624
1625 void *
EcaRx1day(void * process)1626 EcaRx1day(void *process)
1627 {
1628 cdo_initialize(process);
1629
1630 int OPID_ECA = 0, OPID_ETC = 0;
1631
1632 if (cdo_operator_argc() > 0)
1633 {
1634 auto params = cdo_get_oper_argv();
1635 OPID_ECA = addWithFrequency(params, "eca_rx1day", 31);
1636 OPID_ETC = addWithFrequency(params, "etccdi_rx1day", 10);
1637 }
1638 else
1639 {
1640 OPID_ECA = cdo_operator_add("eca_rx1day", 0, 31, nullptr);
1641 OPID_ETC = cdo_operator_add("etccdi_rx1day", 0, 10, nullptr);
1642 }
1643
1644 ECA_REQUEST_1 request;
1645
1646 if (OPID_ECA == cdo_operator_id())
1647 {
1648 request.var1.name = RX1DAY_NAME;
1649 request.var1.longname = RX1DAY_LONGNAME;
1650 request.var1.units = RX1DAY_UNITS;
1651 request.var1.refdate = ECA_refdate;
1652 }
1653 else if (OPID_ETC == cdo_operator_id())
1654 {
1655 request.var1.name = RX1DAY_NAME_ET;
1656 request.var1.longname = RX1DAY_LONGNAME_ET;
1657 request.var1.units = RX1DAY_UNITS_ET;
1658 request.var1.refdate = ETC_refdate;
1659 }
1660 request.var1.f2 = field2_max;
1661
1662 eca1(request);
1663
1664 cdo_finish();
1665
1666 return 0;
1667 }
1668
1669 void *
EcaRx5day(void * process)1670 EcaRx5day(void *process)
1671 {
1672 double argX = 50.0;
1673
1674 cdo_initialize(process);
1675
1676 int OPID_ECA = 0, OPID_ETC = 0;
1677 if (cdo_operator_argc() > 0)
1678 {
1679 argX = parameter_to_double(cdo_operator_argv(0));
1680 if (cdo_operator_argc() > 1)
1681 {
1682 auto params = cdo_get_oper_argv();
1683 params = std::vector<std::string>(params.begin() + 1, params.end());
1684 OPID_ECA = addWithFrequency(params, "eca_rx5day", 31);
1685 OPID_ETC = addWithFrequency(params, "etccdi_rx5day", 10);
1686 }
1687 else
1688 {
1689 OPID_ECA = cdo_operator_add("eca_rx5day", 0, 31, nullptr);
1690 OPID_ETC = cdo_operator_add("etccdi_rx5day", 0, 10, nullptr);
1691 }
1692 }
1693 else
1694 {
1695 OPID_ECA = cdo_operator_add("eca_rx5day", 0, 31, nullptr);
1696 OPID_ETC = cdo_operator_add("etccdi_rx5day", 0, 10, nullptr);
1697 }
1698
1699 char longname[sizeof(RX5DAY_LONGNAME2) + 40];
1700 sprintf(longname, RX5DAY_LONGNAME2, argX);
1701
1702 ECA_REQUEST_1 request;
1703
1704 if (OPID_ECA == cdo_operator_id())
1705 {
1706 request.var1.name = RX5DAY_NAME;
1707 request.var1.longname = RX5DAY_LONGNAME;
1708 request.var1.units = RX5DAY_UNITS;
1709 request.var1.refdate = ECA_refdate;
1710 }
1711 else if (OPID_ETC == cdo_operator_id())
1712 {
1713 request.var1.name = RX5DAY_NAME_ET;
1714 request.var1.longname = RX5DAY_LONGNAME_ET;
1715 request.var1.units = RX5DAY_UNITS_ET;
1716 request.var1.refdate = ETC_refdate;
1717 }
1718 request.var1.f2 = field2_max;
1719 request.var2.name = RX5DAY_NAME2;
1720 request.var2.longname = longname;
1721 request.var2.units = RX5DAY_UNITS2;
1722 request.var2.h1 = vfarselgec;
1723 request.var2.h1arg = argX;
1724 request.var2.h2 = vfarnum;
1725
1726 eca1(request);
1727
1728 cdo_finish();
1729
1730 return 0;
1731 }
1732
1733 void *
EcaSdii(void * process)1734 EcaSdii(void *process)
1735 {
1736 ECA_REQUEST_1 request;
1737 char lnamebuffer[1024];
1738 double threshold = 1;
1739
1740 cdo_initialize(process);
1741 int OPID_ECA = 0, OPID_ETC = 0;
1742
1743 if (cdo_operator_argc() > 2)
1744 cdo_abort("Too many arguments!");
1745 else if (cdo_operator_argc() > 1)
1746 {
1747 auto params = cdo_get_oper_argv();
1748 params = std::vector<std::string>(params.begin() + 1, params.end());
1749 OPID_ECA = addWithFrequency(params, "eca_sdii", 31);
1750 OPID_ETC = addWithFrequency(params, "etccdi_sdii", 10);
1751 }
1752 else
1753 {
1754 OPID_ECA = cdo_operator_add("eca_sdii", 0, 31, nullptr);
1755 OPID_ETC = cdo_operator_add("etccdi_sdii", 0, 31, nullptr);
1756 if (cdo_operator_argc() == 1) threshold = parameter_to_double(cdo_operator_argv(0));
1757 }
1758
1759 sprintf(lnamebuffer, SDII_LONGNAME, threshold);
1760 if (OPID_ECA == cdo_operator_id())
1761 {
1762 request.var1.name = SDII_NAME;
1763 request.var1.longname = lnamebuffer;
1764 request.var1.units = SDII_UNITS;
1765 }
1766 else if (OPID_ETC == cdo_operator_id())
1767 {
1768 request.var1.name = SDII_NAME_ET;
1769 request.var1.longname = SDII_LONGNAME_ET;
1770 request.var1.units = SDII_UNITS_ET;
1771 }
1772
1773 request.var1.f1 = vfarselgec;
1774 request.var1.f1arg = threshold;
1775 request.var1.f2 = field2_sum;
1776 request.var1.epilog = MEAN;
1777
1778 eca1(request);
1779 cdo_finish();
1780
1781 return 0;
1782 }
1783
1784 void *
Fdns(void * process)1785 Fdns(void *process)
1786 {
1787 ECA_REQUEST_2 request;
1788
1789 cdo_initialize(process);
1790 cdo_operator_add("fdns", 0, 31, nullptr);
1791
1792 request.var1.name = FDNS_NAME;
1793 request.var1.longname = FDNS_LONGNAME;
1794 request.var1.refdate = ECA_refdate;
1795 request.var1.units = FDNS_UNITS;
1796 request.var1.f1 = vfarsellec;
1797 request.var1.f1arg = TO_KELVIN(0.0);
1798 request.var1.f2 = vfarsellec;
1799 request.var1.f2arg = 0.01;
1800 request.var1.f3 = field2_add; // any f with f(a, b) = miss, if a = miss or b = miss will do here
1801 request.var1.f4 = vfarnum;
1802
1803 eca2(request);
1804
1805 cdo_finish();
1806
1807 return 0;
1808 }
1809
1810 void *
Strwin(void * process)1811 Strwin(void *process)
1812 {
1813 double maxWind = 10.5;
1814
1815 cdo_initialize(process);
1816
1817 if (cdo_operator_argc() > 2)
1818 cdo_abort("Too many arguments!");
1819 else if (cdo_operator_argc() > 1)
1820 {
1821 auto params = cdo_get_oper_argv();
1822 params = std::vector<std::string>(params.begin() + 1, params.end());
1823 addWithFrequency(params, "strwin", 31);
1824 }
1825 else
1826 {
1827 if (cdo_operator_argc() > 0) maxWind = parameter_to_double(cdo_operator_argv(0));
1828 cdo_operator_add("strwin", 0, 31, nullptr);
1829 }
1830
1831 char longname[sizeof(STRWIN_LONGNAME) + 40];
1832 sprintf(longname, STRWIN_LONGNAME, maxWind);
1833
1834 ECA_REQUEST_1 request;
1835
1836 request.var1.name = STRWIN_NAME;
1837 request.var1.longname = longname;
1838 request.var1.refdate = ECA_refdate;
1839 request.var1.units = STRWIN_UNITS;
1840 request.var1.f1 = vfarselgec;
1841 request.var1.f1arg = maxWind;
1842 request.var1.f2 = vfarnum;
1843 request.var2.name = STRWIN_NAME2;
1844 request.var2.longname = STRWIN_LONGNAME2;
1845 request.var2.units = STRWIN_UNITS2;
1846 request.var2.h1 = vfarselgec;
1847 request.var2.h1arg = maxWind;
1848 request.var2.h2 = vfarnum2;
1849 request.var2.h3 = field2_max;
1850
1851 eca1(request);
1852
1853 cdo_finish();
1854
1855 return 0;
1856 }
1857
1858 void *
Strbre(void * process)1859 Strbre(void *process)
1860 {
1861 static const double maxWind = 10.5;
1862 ECA_REQUEST_1 request;
1863
1864 cdo_initialize(process);
1865 if (cdo_operator_argc() > 0)
1866 {
1867 auto params = cdo_get_oper_argv();
1868 addWithFrequency(params, "strbre", 31);
1869 }
1870 else
1871 cdo_operator_add("strbre", 0, 31, nullptr);
1872
1873 request.var1.name = STRBRE_NAME;
1874 request.var1.longname = STRBRE_LONGNAME;
1875 request.var1.refdate = ECA_refdate;
1876 request.var1.units = STRWIN_UNITS;
1877 request.var1.f1 = vfarselgec;
1878 request.var1.f1arg = maxWind;
1879 request.var1.f2 = vfarnum;
1880 request.var2.name = STRBRE_NAME2;
1881 request.var2.longname = STRBRE_LONGNAME2;
1882 request.var2.units = STRWIN_UNITS2;
1883 request.var2.h1 = vfarselgec;
1884 request.var2.h1arg = maxWind;
1885 request.var2.h2 = vfarnum2;
1886 request.var2.h3 = field2_max;
1887
1888 eca1(request);
1889 cdo_finish();
1890
1891 return 0;
1892 }
1893
1894 void *
Strgal(void * process)1895 Strgal(void *process)
1896 {
1897 static const double maxWind = 20.5;
1898 ECA_REQUEST_1 request;
1899
1900 cdo_initialize(process);
1901 if (cdo_operator_argc() > 0)
1902 {
1903 auto params = cdo_get_oper_argv();
1904 addWithFrequency(params, "strgal", 31);
1905 }
1906 else
1907 cdo_operator_add("strgal", 0, 31, nullptr);
1908
1909 request.var1.name = STRBRE_NAME;
1910 request.var1.longname = STRBRE_LONGNAME;
1911 request.var1.refdate = ECA_refdate;
1912 request.var1.units = STRWIN_UNITS;
1913 request.var1.f1 = vfarselgec;
1914 request.var1.f1arg = maxWind;
1915 request.var1.f2 = vfarnum;
1916 request.var2.name = STRBRE_NAME2;
1917 request.var2.longname = STRBRE_LONGNAME2;
1918 request.var2.units = STRWIN_UNITS2;
1919 request.var2.h1 = vfarselgec;
1920 request.var2.h1arg = maxWind;
1921 request.var2.h2 = vfarnum2;
1922 request.var2.h3 = field2_max;
1923
1924 eca1(request);
1925 cdo_finish();
1926
1927 return 0;
1928 }
1929
1930 void *
Hurr(void * process)1931 Hurr(void *process)
1932 {
1933 static const double maxWind = 32.5;
1934 ECA_REQUEST_1 request;
1935
1936 cdo_initialize(process);
1937 if (cdo_operator_argc() > 0)
1938 {
1939 auto params = cdo_get_oper_argv();
1940 addWithFrequency(params, "hurr", 31);
1941 }
1942 else
1943 cdo_operator_add("hurr", 0, 31, nullptr);
1944
1945 request.var1.name = HURR_NAME;
1946 request.var1.longname = HURR_LONGNAME;
1947 request.var1.refdate = ECA_refdate;
1948 request.var1.units = STRWIN_UNITS;
1949 request.var1.f1 = vfarselgec;
1950 request.var1.f1arg = maxWind;
1951 request.var1.f2 = vfarnum;
1952 request.var2.name = HURR_NAME2;
1953 request.var2.longname = HURR_LONGNAME2;
1954 request.var2.units = STRWIN_UNITS2;
1955 request.var2.h1 = vfarselgec;
1956 request.var2.h1arg = maxWind;
1957 request.var2.h2 = vfarnum2;
1958 request.var2.h3 = field2_max;
1959
1960 eca1(request);
1961
1962 cdo_finish();
1963
1964 return 0;
1965 }
1966