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 "cdo_zaxis.h"
12 #include "param_conversion.h"
13 #include "cdi_lockedIO.h"
14
15 void *
Seloperator(void * process)16 Seloperator(void *process)
17 {
18 int varID, levelID;
19 bool selfound = false;
20
21 cdo_initialize(process);
22
23 const auto dataIsUnchanged = data_is_unchanged();
24
25 operator_input_arg("code, ltype, level");
26
27 const auto scode = parameter_to_int(cdo_operator_argv(0));
28 const auto sltype = parameter_to_int(cdo_operator_argv(1));
29
30 const auto slevel = (cdo_operator_argc() == 3) ? parameter_to_double(cdo_operator_argv(2)) : 0.0;
31
32 const auto streamID1 = cdo_open_read(0);
33 const auto vlistID1 = cdo_stream_inq_vlist(streamID1);
34
35 const auto nvars = vlistNvars(vlistID1);
36 for (varID = 0; varID < nvars; varID++)
37 {
38 const auto code = vlistInqVarCode(vlistID1, varID);
39 const auto zaxisID = vlistInqVarZaxis(vlistID1, varID);
40 const auto nlevels = zaxisInqSize(zaxisID);
41 const auto ltype = zaxis_to_ltype(zaxisID);
42
43 for (int levID = 0; levID < nlevels; levID++)
44 {
45 const auto level = cdo_zaxis_inq_level(zaxisID, levID);
46 const auto sellevel = (cdo_operator_argc() == 3) ? IS_EQUAL(level, slevel) : true;
47 const auto selcode = (scode == -1 || scode == code);
48 const auto selltype = (sltype == -1 || sltype == ltype);
49
50 if (selcode && selltype && sellevel)
51 {
52 vlistDefFlag(vlistID1, varID, levID, true);
53 selfound = true;
54 }
55 }
56 }
57
58 if (!selfound) cdo_warning("Code %d, ltype %d, level %g not found!", scode, sltype, slevel);
59
60 const auto vlistID2 = vlistCreate();
61 cdo_vlist_copy_flag(vlistID2, vlistID1);
62 vlistDefNtsteps(vlistID2, vlistNtsteps(vlistID1));
63
64 const auto taxisID1 = vlistInqTaxis(vlistID1);
65 const auto taxisID2 = taxisDuplicate(taxisID1);
66 vlistDefTaxis(vlistID2, taxisID2);
67
68 const auto streamID2 = cdo_open_write(1);
69 cdo_def_vlist(streamID2, vlistID2);
70
71 Field field;
72
73 VarList varList1;
74 varListInit(varList1, vlistID1);
75
76 int tsID = 0;
77 while (true)
78 {
79 const auto nrecs = cdo_stream_inq_timestep(streamID1, tsID);
80 if (nrecs == 0) break;
81
82 cdo_taxis_copy_timestep(taxisID2, taxisID1);
83 cdo_def_timestep(streamID2, tsID);
84
85 for (int recID = 0; recID < nrecs; recID++)
86 {
87 cdo_inq_record(streamID1, &varID, &levelID);
88 if (vlistInqFlag(vlistID1, varID, levelID) == true)
89 {
90 const auto varID2 = vlistFindVar(vlistID2, varID);
91 const auto levelID2 = vlistFindLevel(vlistID2, varID, levelID);
92 cdo_def_record(streamID2, varID2, levelID2);
93
94 if (dataIsUnchanged)
95 {
96 cdo_copy_record(streamID2, streamID1);
97 }
98 else
99 {
100 field.init(varList1[varID]);
101 cdo_read_record(streamID1, field);
102 cdo_write_record(streamID2, field);
103 }
104 }
105 }
106
107 tsID++;
108 }
109
110 cdo_stream_close(streamID1);
111 cdo_stream_close(streamID2);
112
113 vlistDestroy(vlistID2);
114
115 cdo_finish();
116
117 return nullptr;
118 }
119