UFO
ObsErrorBoundMW.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2020 UCAR
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
9 
10 #include <algorithm>
11 #include <cmath>
12 #include <iomanip>
13 #include <iostream>
14 #include <set>
15 #include <string>
16 #include <vector>
17 
18 #include "ioda/ObsDataVector.h"
19 #include "oops/util/IntSetParser.h"
20 #include "oops/util/missingValues.h"
24 #include "ufo/filters/Variable.h"
25 #include "ufo/utils/Constants.h"
26 #include "ufo/utils/StringUtils.h"
27 
28 namespace ufo {
29 
31 
32 // -----------------------------------------------------------------------------
33 
34 ObsErrorBoundMW::ObsErrorBoundMW(const eckit::LocalConfiguration & conf)
35  : invars_() {
36  // Check options
37  options_.deserialize(conf);
38 
39  // Get sensor information from options
40  const std::string &sensor = options_.sensor.value();
41 
42  // Get instrument and satellite from sensor
43  std::string inst, sat;
44  splitInstSat(sensor, inst, sat);
45  ASSERT(inst == "amsua" || inst == "atms");
46 
47  // Get channels from options
48  std::set<int> channelset = oops::parseIntSet(options_.channelList);
49  std::copy(channelset.begin(), channelset.end(), std::back_inserter(channels_));
50  ASSERT(channels_.size() > 0);
51 
52  // Get test groups from options
53  const std::string &errgrp = options_.testObserr.value();
54  const std::string &flaggrp = options_.testQCflag.value();
55 
56  // Include list of required data from ObsSpace
57  invars_ += Variable("brightness_temperature@"+flaggrp, channels_);
58  invars_ += Variable("brightness_temperature@"+errgrp, channels_);
59  invars_ += Variable("brightness_temperature@ObsError", channels_);
60 
61  // Include list of required data from GeoVaLs
62  invars_ += Variable("water_area_fraction@GeoVaLs");
63 
64  const Variable &obserrlat = options_.obserrBoundLat.value();
65  invars_ += obserrlat;
66 
67  const Variable &obserrtaotop = options_.obserrBoundTransmittop.value();
68  invars_ += obserrtaotop;
69 
70  const Variable &obserrtopo = options_.obserrBoundTopo.value();
71  invars_ += obserrtopo;
72 
73  const Variable &obserr = options_.obserrFunction.value();
74  invars_ += obserr;
75 }
76 
77 // -----------------------------------------------------------------------------
78 
80 
81 // -----------------------------------------------------------------------------
82 
84  ioda::ObsDataVector<float> & out) const {
85  // Get sensor information from options
86  const std::string &sensor = options_.sensor.value();
87 
88  // Get instrument and satellite from sensor
89  std::string inst, sat;
90  splitInstSat(sensor, inst, sat);
91  ASSERT(inst == "amsua" || inst == "atms");
92 
93  // Get dimensions
94  size_t nlocs = in.nlocs();
95  size_t nchans = channels_.size();
96 
97  // Get observation error bounds from options
98  const std::vector<float> &obserr_bound_max = options_.obserrBoundMax.value();
99 
100  // Get area fraction of each surface type
101  std::vector<float> water_frac(nlocs);
102  in.get(Variable("water_area_fraction@GeoVaLs"), water_frac);
103 
104  // Get error factor from ObsFunction
105  const Variable &obserrlat = options_.obserrBoundLat.value();
106  ioda::ObsDataVector<float> errflat(in.obsspace(), obserrlat.toOopsVariables());
107  in.get(obserrlat, errflat);
108 
109  // Get error factor from ObsFunction
110  const Variable &obserrtaotop = options_.obserrBoundTransmittop.value();
111  ioda::ObsDataVector<float> errftaotop(in.obsspace(), obserrtaotop.toOopsVariables());
112  in.get(obserrtaotop, errftaotop);
113 
114  // Get error factor from ObsFunction
115  const Variable &obserrtopo = options_.obserrBoundTopo.value();
116  ioda::ObsDataVector<float> errftopo(in.obsspace(), obserrtopo.toOopsVariables());
117  in.get(obserrtopo, errftopo);
118 
119  // Get all-sky observation error from ObsFunction
120  const Variable &obserrvar = options_.obserrFunction.value();
121  ioda::ObsDataVector<float> obserr(in.obsspace(), obserrvar.toOopsVariables());
122  in.get(obserrvar, obserr);
123 
124  // Set channel numbers
125  int ich238, ich314, ich503, ich528, ich536, ich544, ich549, ich890;
126  if (inst == "amsua") {
127  ich238 = 1, ich314 = 2, ich503 = 3, ich528 = 4, ich536 = 5;
128  ich544 = 6, ich549 = 7, ich890 = 15;
129  } else if (inst == "atms") {
130  ich238 = 1, ich314 = 2, ich503 = 3, ich528 = 5, ich536 = 6;
131  ich544 = 7, ich549 = 8, ich890 = 16;
132  }
133 
134  // Output integrated error bound for gross check
135  std::vector<float> obserrdata(nlocs);
136  std::vector<int> qcflagdata(nlocs);
137  const std::string &errgrp = options_.testObserr.value();
138  const std::string &flaggrp = options_.testQCflag.value();
139  const float missing = util::missingValue(missing);
140  float varinv = 0.0;
141  for (size_t ichan = 0; ichan < nchans; ++ichan) {
142  int channel = ichan + 1;
143  in.get(Variable("brightness_temperature@"+flaggrp, channels_)[ichan], qcflagdata);
144  in.get(Variable("brightness_temperature@"+errgrp, channels_)[ichan], obserrdata);
145  for (size_t iloc = 0; iloc < nlocs; ++iloc) {
146  if (flaggrp == "PreQC") obserrdata[iloc] == missing ? qcflagdata[iloc] = 100
147  : qcflagdata[iloc] = 0;
148  (qcflagdata[iloc] == 0) ? (varinv = 1.0 / pow(obserrdata[iloc], 2)) : (varinv = 0.0);
149  out[ichan][iloc] = obserr[ichan][iloc];
150  if (varinv > 0.0) {
151  if (water_frac[iloc] > 0.99) {
152  if (inst == "amsua") {
153  if (channel <= ich536 || channel == ich890) {
154  out[ichan][iloc] = 3.0 * obserr[ichan][iloc]
155  * (1.0 / pow(errflat[0][iloc], 2))
156  * (1.0 / pow(errftaotop[ichan][iloc], 2))
157  * (1.0 / pow(errftopo[ichan][iloc], 2));
158  } else {
159  out[ichan][iloc] = std::fmin((3.0 * obserr[ichan][iloc]
160  * (1.0 / pow(errflat[0][iloc], 2))
161  * (1.0 / pow(errftaotop[ichan][iloc], 2))
162  * (1.0 / pow(errftopo[ichan][iloc], 2))),
163  obserr_bound_max[ichan]);
164  }
165  }
166  if (inst == "atms") {
167  if (channel <= ich536 || channel >= ich890) {
168  out[ichan][iloc] = std::fmin((3.0 * obserr[ichan][iloc]
169  * (1.0 / pow(errflat[0][iloc], 2))
170  * (1.0 / pow(errftaotop[ichan][iloc], 2))
171  * (1.0 / pow(errftopo[ichan][iloc], 2))), 10.0);
172  } else {
173  out[ichan][iloc] = std::fmin((3.0 * obserr[ichan][iloc]
174  * (1.0 / pow(errflat[0][iloc], 2))
175  * (1.0 / pow(errftaotop[ichan][iloc], 2))
176  * (1.0 / pow(errftopo[ichan][iloc], 2))),
177  obserr_bound_max[ichan]);
178  }
179  }
180  } else {
181  out[ichan][iloc] = std::fmin((3.0 * obserr[ichan][iloc]
182  * (1.0 / pow(errflat[0][iloc], 2))
183  * (1.0 / pow(errftaotop[ichan][iloc], 2))
184  * (1.0 / pow(errftopo[ichan][iloc], 2))),
185  obserr_bound_max[ichan]);
186  }
187  }
188  }
189  }
190 }
191 
192 // -----------------------------------------------------------------------------
193 
195  return invars_;
196 }
197 
198 // -----------------------------------------------------------------------------
199 
200 } // namespace ufo
ObsErrorBoundMWParameters options_
std::vector< int > channels_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
ufo::Variables invars_
ObsErrorBoundMW(const eckit::LocalConfiguration &)
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
oops::RequiredParameter< Variable > obserrBoundTopo
Function to set the observation bound based on terrain height.
oops::RequiredParameter< std::string > channelList
List of channels available for assimilation.
oops::RequiredParameter< Variable > obserrBoundLat
Function to set the observation bound based on latitude.
oops::RequiredParameter< Variable > obserrBoundTransmittop
Function to set the observation bound based on transmittance at model top.
oops::RequiredParameter< std::string > sensor
Name of the sensor for which the observation error factor applies.
oops::Parameter< std::string > testObserr
Name of the data group to which the observation error is applied (default: ObsErrorData)
oops::RequiredParameter< Variable > obserrFunction
Function to estimate observation error based on symmetric cloud amount.
oops::Parameter< std::string > testQCflag
Name of the data group to which the QC flag is applied (default is QCflagsData)
oops::RequiredParameter< std::vector< float > > obserrBoundMax
The maximum value of the observation error bound for each channel in channelList.
ObsFilterData provides access to all data related to an ObsFilter.
size_t nlocs() const
Returns the number of locations in the associated ObsSpace.
ioda::ObsSpace & obsspace() const
Returns reference to ObsSpace associated with ObsFilterData.
void get(const Variable &varname, std::vector< float > &values) const
Fills a std::vector with values of the specified variable.
oops::Variables toOopsVariables() const
Definition: Variable.cc:139
constexpr int missing
Definition: QCflags.h:20
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27
static ObsFunctionMaker< ObsErrorBoundMW > makerObsErrorBoundMW_("ObsErrorBoundMW")
void splitInstSat(const std::string &instsat, std::string &inst, std::string &sat)
Definition: StringUtils.cc:51