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
8 #include <cdi.h>
9
10 #include "process_int.h"
11 #include "util_string.h"
12 #include "cdo_options.h"
13
14 void *
Deltime(void * process)15 Deltime(void *process)
16 {
17 bool copytimestep;
18 int year, month, day;
19 int dday, dmon;
20 const char *cmons[] = { "", "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" };
21
22 cdo_initialize(process);
23
24 const auto dataIsUnchanged = data_is_unchanged();
25
26 // clang-format off
27 const auto DELDAY = cdo_operator_add("delday", 0, 0, nullptr);
28 const auto DEL29FEB = cdo_operator_add("del29feb", 0, 0, nullptr);
29 // clang-format on
30
31 (void) (DELDAY); // CDO_UNUSED
32
33 const auto operatorID = cdo_operator_id();
34
35 if (operatorID == DEL29FEB)
36 {
37 dday = 29;
38 dmon = 2;
39 operator_check_argc(0);
40 }
41 else
42 {
43 int nsel = cdo_operator_argc();
44 if (nsel < 1) cdo_abort("Too few arguments!");
45 if (nsel > 1) cdo_abort("Too many arguments!");
46 const char *sarg = cdo_operator_argv(0).c_str();
47 dday = atoi(sarg);
48 dmon = 0;
49 while (isdigit(*sarg)) sarg++;
50 if (isalpha(*sarg))
51 {
52 char smon[32];
53 strncpy(smon, sarg, sizeof(smon) - 1);
54 smon[sizeof(smon) - 1] = 0;
55 cstr_to_lower_case(smon);
56 int im;
57 for (im = 0; im < 12; ++im)
58 if (memcmp(smon, cmons[im + 1], 3) == 0) break;
59
60 if (im < 12) dmon = im + 1;
61 }
62 }
63
64 if (Options::cdoVerbose) cdo_print("delete day %d%s", dday, cmons[dmon]);
65
66 const auto streamID1 = cdo_open_read(0);
67
68 const auto vlistID1 = cdo_stream_inq_vlist(streamID1);
69 const auto vlistID2 = vlistDuplicate(vlistID1);
70
71 const auto taxisID1 = vlistInqTaxis(vlistID1);
72 const auto taxisID2 = taxisDuplicate(taxisID1);
73 taxisDefCalendar(taxisID2, CALENDAR_365DAYS);
74 vlistDefTaxis(vlistID2, taxisID2);
75
76 const auto streamID2 = cdo_open_write(1);
77 cdo_def_vlist(streamID2, vlistID2);
78
79 Field field;
80
81 VarList varList1;
82 varListInit(varList1, vlistID1);
83
84 int nfound = 0;
85 int tsID = 0;
86 int tsID2 = 0;
87 while (true)
88 {
89 const auto nrecs = cdo_stream_inq_timestep(streamID1, tsID);
90 if (nrecs == 0) break;
91
92 const auto vdate = taxisInqVdate(taxisID1);
93 // vtime = taxisInqVtime(taxisID1);
94
95 cdiDecodeDate(vdate, &year, &month, &day);
96
97 if (day == dday && (month == dmon || dmon == 0))
98 {
99 nfound++;
100 copytimestep = false;
101 if (Options::cdoVerbose) cdo_print("Delete %4.4d-%2.2d-%2.2d at timestep %d", year, month, day, tsID + 1);
102 }
103 else
104 copytimestep = true;
105
106 if (copytimestep)
107 {
108 cdo_taxis_copy_timestep(taxisID2, taxisID1);
109 cdo_def_timestep(streamID2, tsID2++);
110
111 for (int recID = 0; recID < nrecs; recID++)
112 {
113 int varID, levelID;
114 cdo_inq_record(streamID1, &varID, &levelID);
115 cdo_def_record(streamID2, varID, levelID);
116 if (dataIsUnchanged)
117 {
118 cdo_copy_record(streamID2, streamID1);
119 }
120 else
121 {
122 field.init(varList1[varID]);
123 cdo_read_record(streamID1, field);
124 cdo_write_record(streamID2, field);
125 }
126 }
127 }
128
129 tsID++;
130 }
131
132 cdo_stream_close(streamID2);
133 cdo_stream_close(streamID1);
134
135 if (nfound == 0) cdo_warning("Day %d%s not found!", dday, cmons[dmon]);
136
137 vlistDestroy(vlistID2);
138
139 cdo_finish();
140
141 return nullptr;
142 }
143