12 #include "eckit/exception/Exceptions.h"
14 #include "oops/util/CompareNVectors.h"
15 #include "oops/util/Logger.h"
16 #include "oops/util/missingValues.h"
17 #include "oops/util/PropertiesOfNVectors.h"
25 const std::vector <float> &valuesIn,
26 const std::vector <float> &coordIn,
27 const std::vector <float> &bigGap,
28 const std::vector <float> &coordOut,
31 std::vector <int> &flagsOut,
32 std::vector <float> &valuesOut,
34 std::vector <float> *coordMax,
35 std::vector <float> *coordMin)
37 const float missingValueFloat = util::missingValue(missingValueFloat);
38 const size_t numRepLev = coordIn.size();
39 const size_t numInterp = coordOut.size();
41 numInterp : numInterp - 1;
44 const bool Ascending = coordOut[0] < coordOut[numInterp - 1];
47 std::vector <float> ZIn = coordIn;
48 std::vector <float> ZOut = coordOut;
52 std::transform(ZIn.begin(), ZIn.end(), ZIn.begin(),
53 std::bind(std::multiplies<float>(), std::placeholders::_1, -1));
54 std::transform(ZOut.begin(), ZOut.end(), ZOut.begin(),
55 std::bind(std::multiplies<float>(), std::placeholders::_1, -1));
60 if (coordMin) coordMin->assign(numOut, missingValueFloat);
61 if (coordMax) coordMax->assign(numOut, missingValueFloat);
66 std::vector <float> valuesInterp(numInterp, missingValueFloat);
68 std::vector <size_t> idxUsefulLevels;
70 std::vector <bool> bigGapWithPreviousLevel(numRepLev + 1,
false);
73 for (
size_t JLev = 0; JLev < numRepLev; ++JLev) {
75 if (valuesIn[JLev] == missingValueFloat ||
79 if (idxUsefulLevels.size() > 0 && ZIn[JLevP] == ZIn[JLev])
continue;
81 if (idxUsefulLevels.size() == 0) {
83 bigGapWithPreviousLevel[idxUsefulLevels.size()] =
true;
84 }
else if (ZIn[JLevP] - ZIn[JLev] > std::max(bigGap[JLevP], bigGap[JLev])) {
87 bigGapWithPreviousLevel[idxUsefulLevels.size()] =
true;
90 idxUsefulLevels.push_back(JLev);
96 std::vector <int> flagsInterp(numInterp, 0);
99 for (
size_t MLev = 0; MLev < numInterp; ++MLev) {
101 const double ZMLev = ZOut[MLev];
104 while (JLev != idxUsefulLevels.size() && ZIn[idxUsefulLevels[JLev]] >= ZMLev)
110 if (JLev == 0 || JLev == idxUsefulLevels.size()) {
112 }
else if (!bigGapWithPreviousLevel[JLev]) {
114 const size_t J1 = idxUsefulLevels[JLev - 1];
115 const size_t J2 = idxUsefulLevels[JLev];
117 const double Interp_factor = (ZMLev - ZIn[J1]) / (ZIn[J2] - ZIn[J1]);
119 valuesInterp[MLev] = valuesIn[J1] + (valuesIn[J2] - valuesIn[J1]) * Interp_factor;
120 flagsInterp[MLev] = flagsIn[J1] | flagsIn[J2];
131 if (valuesInterp[MLev - 1] != missingValueFloat &&
132 valuesInterp[MLev] != missingValueFloat) {
134 valuesInterp[MLev - 1] = (valuesInterp[MLev - 1] + valuesInterp[MLev]) * 0.5;
135 flagsInterp[MLev - 1] |= flagsInterp[MLev];
136 if (coordMax) (*coordMax)[MLev - 1] = ZOut[MLev - 1];
137 if (coordMin) (*coordMin)[MLev - 1] = ZOut[MLev];
152 size_t J2 = idxUsefulLevels[JLevP];
153 if (valuesInterp[MLev - 1] != missingValueFloat) {
154 const double DZ = ZOut[MLev - 1] - ZIn[J2];
155 valuesInterp[MLev - 1] = (valuesInterp[MLev - 1] + valuesIn[J2]) * DZ;
157 if (coordMax) (*coordMax)[MLev - 1] = ZOut[MLev - 1];
159 valuesInterp[MLev - 1] = 0.0;
160 if (coordMax) (*coordMax)[MLev - 1] = ZIn[J2];
165 size_t J1 = idxUsefulLevels[JLev - 1];
166 if (valuesInterp[MLev] != missingValueFloat) {
167 const double DZ = ZIn[J1] - ZOut[MLev];
168 valuesInterp[MLev - 1] += (valuesInterp[MLev] + valuesIn[J1]) * DZ;
170 flagsInterp[MLev - 1] |= flagsInterp[MLev];
171 if (coordMin) (*coordMin)[MLev - 1] = ZOut[MLev];
173 if (coordMin) (*coordMin)[MLev - 1] = ZIn[J1];
178 for (
size_t J = JLevP + 1; J < JLev; ++J) {
179 J1 = idxUsefulLevels[J - 1];
180 J2 = idxUsefulLevels[J];
181 const double DZ = ZIn[J1] - ZIn[J2];
182 valuesInterp[MLev - 1] += (valuesIn[J1] + valuesIn[J2]) * DZ;
184 flagsInterp[MLev - 1] |= flagsIn[J1];
186 J1 = idxUsefulLevels[JLev - 1];
187 flagsInterp[MLev - 1] |= flagsIn[J1];
192 const double DZMod = ZOut[MLev - 1] - ZOut[MLev];
195 if (DZSum > DZFrac * DZMod) {
197 if (DZSum <= 0.995 * DZMod)
201 valuesInterp[MLev - 1] *= 0.5 / DZSum;
203 valuesInterp[MLev - 1] = missingValueFloat;
209 if (Ascending && coordMin && coordMax &&
210 (*coordMax)[MLev - 1] != missingValueFloat &&
211 (*coordMin)[MLev - 1] != missingValueFloat) {
212 (*coordMax)[MLev - 1] *= -1;
213 (*coordMin)[MLev - 1] *= -1;
214 std::swap((*coordMax)[MLev - 1], (*coordMin)[MLev - 1]);
219 flagsOut = {flagsInterp.begin(), flagsInterp.begin() + numOut};
220 valuesOut = {valuesInterp.begin(), valuesInterp.begin() + numOut};
@ PartialLayerFlag
Partial Layer Vert Average.
@ FinalRejectFlag
Final QC flag.
void calculateVerticalAverage(const std::vector< int > &flagsIn, const std::vector< float > &valuesIn, const std::vector< float > &coordIn, const std::vector< float > &bigGap, const std::vector< float > &coordOut, float DZFrac, ProfileAveraging::Method method, std::vector< int > &flagsOut, std::vector< float > &valuesOut, int &numGaps, std::vector< float > *coordMax, std::vector< float > *coordMin)
Profile vertical averaging onto model levels.