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