20 #include "ioda/ObsDataVector.h"
21 #include "oops/util/IntSetParser.h"
22 #include "oops/util/missingValues.h"
28 static ObsFunctionMaker<CloudDetectMinResidualIR>
40 std::copy(channelset.begin(), channelset.end(), std::back_inserter(
channels_));
66 invars_ +=
Variable(
"average_surface_temperature_within_field_of_view@GeoVaLs");
99 std::vector<std::vector<float>> dbtdts(nchans, std::vector<float>(
nlocs));
100 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
101 in.
get(
Variable(
"brightness_temperature_jacobian_surface_temperature@ObsDiag",
106 std::vector<std::vector<std::vector<float>>>
107 dbtdt(nchans, std::vector<std::vector<float>>(nlevs, std::vector<float>(
nlocs)));
108 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
109 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
110 const int level = nlevs - ilev - 1;
111 in.
get(
Variable(
"brightness_temperature_jacobian_air_temperature@ObsDiag",
112 channels_)[ichan], level, dbtdt[ichan][ilev]);
117 std::vector<std::vector<std::vector<float>>>
118 tao(nchans, std::vector<std::vector<float>>(nlevs, std::vector<float>(
nlocs)));
119 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
120 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
121 const int level = nlevs - ilev - 1;
122 in.
get(
Variable(
"transmittances_of_atmosphere_layer@ObsDiag",
123 channels_)[ichan], level, tao[ichan][ilev]);
128 std::vector<float> values(
nlocs, 0.0);
129 std::vector<std::vector<float>> wfunc_pmaxlev(nchans, std::vector<float>(
nlocs));
130 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
131 in.
get(
Variable(
"pressure_level_at_peak_of_weightingfunction@ObsDiag",
133 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
134 wfunc_pmaxlev[ichan][iloc] = nlevs - values[iloc] + 1;
141 std::vector<int> qcflag(
nlocs, 0);
142 std::vector<std::vector<float>> varinv_use(nchans, std::vector<float>(
nlocs, 0.0));
143 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
146 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
147 if (flaggrp ==
"PreQC") values[iloc] ==
missing ? qcflag[iloc] = 100 : qcflag[iloc] = 0;
148 (qcflag[iloc] == 0) ? (values[iloc] = 1.0 / pow(values[iloc], 2)) : (values[iloc] = 0.0);
149 if (use_flag_clddet[ichan] > 0) varinv_use[ichan][iloc] = values[iloc];
154 std::vector<std::vector<float>> innovation(nchans, std::vector<float>(
nlocs));
155 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
158 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
159 innovation[ichan][iloc] = innovation[ichan][iloc] - values[iloc];
164 std::vector<std::vector<float>> obserr(nchans, std::vector<float>(
nlocs));
165 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
171 std::vector<float> tropprs(
nlocs);
172 in.
get(
Variable(
"tropopause_pressure@GeoVaLs"), tropprs);
175 std::vector<float> tsavg(
nlocs);
176 in.
get(
Variable(
"average_surface_temperature_within_field_of_view@GeoVaLs"), tsavg);
179 std::vector<float> water_frac(
nlocs);
180 std::vector<float> land_frac(
nlocs);
181 std::vector<float> ice_frac(
nlocs);
182 std::vector<float> snow_frac(
nlocs);
183 in.
get(
Variable(
"water_area_fraction@GeoVaLs"), water_frac);
184 in.
get(
Variable(
"land_area_fraction@GeoVaLs"), land_frac);
185 in.
get(
Variable(
"ice_area_fraction@GeoVaLs"), ice_frac);
186 in.
get(
Variable(
"surface_snow_area_fraction@GeoVaLs"), snow_frac);
189 std::vector<bool> land(
nlocs,
false);
190 std::vector<bool>
sea(
nlocs,
false);
191 std::vector<bool> ice(
nlocs,
false);
192 std::vector<bool> snow(
nlocs,
false);
193 std::vector<bool> mixed(
nlocs,
false);
194 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
195 sea[iloc] = water_frac[iloc] >= 0.99;
196 land[iloc] = land_frac[iloc] >= 0.99;
197 ice[iloc] = ice_frac[iloc] >= 0.99;
198 snow[iloc] = snow_frac[iloc] >= 0.99;
199 mixed[iloc] = (!
sea[iloc] && !land[iloc] && !ice[iloc] && !snow[iloc]);
203 std::vector<float> dtempf(
nlocs);
204 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
206 dtempf[iloc] = dtempf_in[0];
207 }
else if (land[iloc]) {
208 dtempf[iloc] = dtempf_in[1];
209 }
else if (ice[iloc]) {
210 dtempf[iloc] = dtempf_in[2];
211 }
else if (snow[iloc]) {
212 dtempf[iloc] = dtempf_in[3];
214 dtempf[iloc] = dtempf_in[4];
219 std::vector<std::vector<float>> prsl(nlevs, std::vector<float>(
nlocs));
220 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
221 const size_t level = nlevs - ilev - 1;
222 in.
get(
Variable(
"air_pressure@GeoVaLs"), level, prsl[ilev]);
226 std::vector<std::vector<float>> tair(nlevs, std::vector<float>(
nlocs));
227 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
228 const size_t level = nlevs - ilev - 1;
229 in.
get(
Variable(
"air_temperature@GeoVaLs"), level, tair[ilev]);
246 const float btmax = 550.f, btmin = 50.f;
247 for (
size_t iloc=0; iloc <
nlocs; ++iloc) {
252 float sum = 0.0, sum2 = 0.0, sum3 = 0.0;
255 std::vector<float> dbt(nchans);
256 for (
size_t ichan=0; ichan < nchans; ++ichan) {
257 if (varinv_use[ichan][iloc] > 0) {
258 sum3 = sum3 + innovation[ichan][iloc] * innovation[ichan][iloc] * varinv_use[ichan][iloc];
266 float cldprs = prsl[0][iloc] * 0.01;
269 for (
size_t k = 0 ; k < nlevs ; ++k) {
271 if (prsl[k][iloc] * 0.01 > tropprs[iloc] * 0.01) {
272 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
273 dbt[ichan] = (tair[k][iloc] - tsavg[iloc]) * dbtdts[ichan][iloc];
275 for (
size_t kk = 0; kk < k; ++kk) {
276 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
277 dbt[ichan] = dbt[ichan] + (tair[k][iloc] - tair[kk][iloc]) * dbtdt[ichan][kk][iloc];
282 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
283 if (varinv_use[ichan][iloc] > 0.0) {
284 sum = sum + innovation[ichan][iloc] * dbt[ichan] * varinv_use[ichan][iloc];
285 sum2 = sum2 + dbt[ichan] * dbt[ichan] * varinv_use[ichan][iloc];
288 if (fabs(sum2) < FLT_MIN) sum2 = copysign(1.0e-12, sum2);
289 cloudp = std::min(std::max((sum/sum2), 0.f), 1.f);
291 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
292 if (varinv_use[ichan][iloc] > 0.0) {
293 tmp = innovation[ichan][iloc] - cloudp * dbt[ichan];
294 sum = sum + tmp * tmp * varinv_use[ichan][iloc];
301 cldprs = prsl[k][iloc] * 0.01;
308 float tao_cld = -999.0;
309 for (
size_t ichan = 0; ichan < nchans; ++ichan) out[ichan][iloc] = 0;
311 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
313 tao_cld = tao[ichan][lcloud-1][iloc];
315 if (use_flag[ichan] < 0 && lcloud >= wfunc_pmaxlev[ichan][iloc]) out[ichan][iloc] = 1;
317 if (out[ichan][iloc] < 1 && tao_cld > 0.02) out[ichan][iloc] = 1;
326 float sum = 0.0, sum2 = 0.0;
329 const float dts_threshold = 3.0;
330 for (
size_t ichan=0; ichan < nchans; ++ichan) {
332 sum = sum + innovation[ichan][iloc] * dbtdts[ichan][iloc] * varinv_use[ichan][iloc];
333 sum2 = sum2 + dbtdts[ichan][iloc] * dbtdts[ichan][iloc] * varinv_use[ichan][iloc];
335 if (fabs(sum2) < FLT_MIN) sum2 = copysign(1.0e-12, sum2);
336 dts = std::fabs(sum / sum2);
338 if (
sea[iloc] ==
false) {
339 dts = std::min(dtempf[iloc], dts);
341 dts = std::min(dts_threshold, dts);
343 for (
size_t ichan=0; ichan < nchans; ++ichan) {
344 delta = std::max(0.05 * obserr[ichan][iloc], 0.02);
345 if (
std::abs(dts * dbtdts[ichan][iloc]) > delta) out[ichan][iloc] = 2;
~CloudDetectMinResidualIR()
CloudDetectMinResidualIRParameters options_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
CloudDetectMinResidualIR(const eckit::LocalConfiguration &)
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
std::vector< int > channels_
oops::Parameter< std::string > testQCflag
Name of the data group to which the QC flag is applied (default is QCflagsData)
oops::Parameter< std::string > testHofX
Name of the HofX group used to replace the default group (default is HofX)
oops::RequiredParameter< std::vector< int > > useflagChannel
Useflag (-1: not used; 0: monitoring; 1: used) for each channel in channelList.
oops::RequiredParameter< std::string > channelList
List of channels available for assimilation.
oops::Parameter< std::string > testObserr
Name of the data group to which the observation error is applied (default: ObsErrorData)
oops::RequiredParameter< std::vector< int > > useflagCloudDetect
Useflag (-1: not used; 1: used) indicating if the channel is used for cloud detection.
oops::RequiredParameter< std::vector< float > > obserrScaleFactorTsfc
ObsFilterData provides access to all data related to an ObsFilter.
size_t nlocs() const
Returns the number of locations in the associated ObsSpace.
size_t nlevs(const Variable &) const
Returns the number of levels in the specified variable.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
real(kind_real), parameter, public sea
integer function nlocs(this)
Return the number of observational locations in this Locations object.
static ObsFunctionMaker< CloudDetectMinResidualIR > makerCloudDetectMinResidualIR_("CloudDetectMinResidualIR")
util::Duration abs(const util::Duration &duration)