12 #include "ioda/ObsDataVector.h"
13 #include "oops/util/IntSetParser.h"
14 #include "oops/util/missingValues.h"
33 channels_.assign(chanset.begin(), chanset.end());
36 for (
size_t i = 0; i <
fields_.size(); ++i) {
44 invars_ +=
Variable(
"mass_content_of_cloud_liquid_water_in_atmosphere_layer@GeoVaLs");
45 invars_ +=
Variable(
"mass_content_of_cloud_ice_in_atmosphere_layer@GeoVaLs");
50 invars_ +=
Variable(
"specific_humidity_at_two_meters_above_surface@GeoVaLs");
62 ASSERT(out.nvars() == 1);
65 eckit::LocalConfiguration bMatrixConf;
71 eckit::LocalConfiguration rMatrixConf;
77 const std::string clw_name =
"mass_content_of_cloud_liquid_water_in_atmosphere_layer";
78 const std::string ciw_name =
"mass_content_of_cloud_ice_in_atmosphere_layer";
80 humidity_total(
nlocs);
84 std::vector<float> gv_pres_1(
nlocs), gv_pres_N(
nlocs);
85 in.
get(
Variable(
"air_pressure@GeoVaLs"), 0, gv_pres_1);
86 in.
get(
Variable(
"air_pressure@GeoVaLs"), np - 1, gv_pres_N);
88 ASSERT(gv_pres_1[0] !=
missing);
89 ASSERT(gv_pres_N[0] !=
missing);
90 bool p_ascending = (gv_pres_N[0] > gv_pres_1[0]);
93 std::vector<std::vector<std::vector<float>>>
94 jac_vec(
nlocs, std::vector<std::vector<float>>(nchans, std::vector<float>()));
95 for (
size_t ifield = 0; ifield <
fields_.size(); ++ifield) {
101 std::string jac_name =
"brightness_temperature_jacobian_"+
fields_[ifield]+
"@ObsDiag";
103 std::vector<float> jac_store(
nlocs);
104 for (
size_t ilev = 0; ilev < nlevs; ++ilev) {
105 const int level_gv = (p_ascending ? ilev : nlevs-ilev-1);
108 in.
get(
Variable(
"air_pressure@GeoVaLs"), level_gv, gv_pres);
109 in.
get(
Variable(
"air_temperature@GeoVaLs"), level_gv, gv_temp);
110 in.
get(
Variable(
"specific_humidity@GeoVaLs"), level_gv, gv_qgas);
111 in.
get(
Variable(clw_name+
"@GeoVaLs"), level_gv, gv_clw);
112 in.
get(
Variable(ciw_name+
"@GeoVaLs"), level_gv, gv_ciw);
113 std::vector<float> qsaturated(
nlocs);
115 static_cast<int>(
nlocs));
116 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
118 gv_qgas[iloc] = std::max(gv_qgas[iloc],
options_.
min_q.value());
119 gv_qgas[iloc] = std::min(gv_qgas[iloc], qsaturated[iloc]);
120 humidity_total[iloc] = gv_qgas[iloc] + gv_clw[iloc];
122 int qsplit_partition_mode = 1;
123 std::vector<float> qsplit_gas(
nlocs), qsplit_clw(
nlocs), qsplit_ciw(
nlocs);
125 gv_temp.data(), humidity_total.data(), qsplit_gas.data(),
126 qsplit_clw.data(), qsplit_ciw.data(), split_rain);
127 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
130 humidity_total[iloc] += gv_ciw[iloc];
132 humidity_total[iloc] = qsplit_gas[iloc] + qsplit_clw[iloc] + qsplit_ciw[iloc];
137 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
141 std::vector<float> jac_clw(
nlocs), jac_ciw(
nlocs);
146 std::vector<float> dq_dqtotal(
nlocs), dql_dqtotal(
nlocs), dqi_dqtotal(
nlocs);
147 int qsplit_derivative_mode = 2;
149 gv_temp.data(), humidity_total.data(), dq_dqtotal.data(),
150 dql_dqtotal.data(), dqi_dqtotal.data(), split_rain);
156 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
157 jac_store[iloc] *= dq_dqtotal[iloc];
158 jac_store[iloc] += jac_clw[iloc]*dql_dqtotal[iloc];
160 jac_store[iloc] += jac_ciw[iloc]*dqi_dqtotal[iloc];
162 jac_store[iloc] *= humidity_total[iloc];
166 if (
fields_[ifield] ==
"specific_humidity_at_two_meters_above_surface"
168 in.
get(
Variable(
"surface_pressure@GeoVaLs"), level_gv, gv_pres);
169 in.
get(
Variable(
"surface_temperature@GeoVaLs"), level_gv, gv_temp);
170 in.
get(
Variable(
"specific_humidity_at_two_meters_above_surface@GeoVaLs"),
172 std::vector<float> qsaturated(
nlocs);
174 static_cast<int>(
nlocs));
175 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
176 gv_qgas[iloc] = std::max(gv_qgas[iloc],
options_.
min_q.value());
177 gv_qgas[iloc] = std::min(gv_qgas[iloc], qsaturated[iloc]);
179 jac_store[iloc] *= gv_qgas[iloc];
183 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
184 jac_vec[iloc][ichan].push_back(jac_store[iloc]);
190 const size_t sizeB = staticB.
getsize();
191 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
192 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
193 ASSERT(jac_vec[iloc][ichan].size() == sizeB);
198 std::vector<std::vector<float>> departures(
nlocs, std::vector<float>(nchans));
199 std::vector<float> obsvalues(
nlocs);
200 std::vector<float> bgvalues(
nlocs);
201 std::vector<bool> is_out_of_bounds(
nlocs,
false);
202 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
206 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
207 departures[iloc][ichan] = obsvalues[iloc] - bgvalues[iloc];
210 is_out_of_bounds[iloc] =
true;
215 std::vector<float> latitude(
nlocs);
217 Eigen::MatrixXf Hmatrix(nchans, sizeB);
219 for (
size_t iloc = 0; iloc <
nlocs; ++iloc) {
220 if (is_out_of_bounds[iloc]) {
225 for (
size_t ichan = 0; ichan < nchans; ++ichan) {
226 Hmatrix.row(ichan) = Eigen::Map<Eigen::VectorXf>(jac_vec[iloc][ichan].data(), sizeB);
230 Eigen::Map<Eigen::VectorXf> dy(departures[iloc].data(), nchans);
234 staticB.
multiply(latitude[iloc], Hmatrix.transpose(), BHT);
235 Eigen::MatrixXf HBHT = Hmatrix*BHT;
236 Eigen::MatrixXf Scratch_matrix;
240 Eigen::LLT<Eigen::MatrixXf> decomposition(Scratch_matrix);
241 if (decomposition.info() == Eigen::NumericalIssue) {
242 oops::Log::warning() <<
243 "CloudCostFunction Scratch_matrix appears not to be positive definite" << std::endl;
247 Eigen::VectorXf Scratch_matrix2 = decomposition.solve(dy);
250 float Cost_final = 0.5*dy.transpose()*Scratch_matrix2;
251 Cost_final /=
static_cast<float>(nchans);
std::vector< std::string > fields_
std::vector< int > channels_
CloudCostFunctionParameters options_
const ufo::Variables & requiredVariables() const
geovals required to compute the function
void compute(const ObsFilterData &, ioda::ObsDataVector< float > &) const
compute the result of the function
CloudCostFunction(const eckit::LocalConfiguration &=eckit::LocalConfiguration())
oops::RequiredParameter< std::vector< std::string > > field_names
List of geovals describing fields required from the B-matrix.
oops::Parameter< bool > qtotal_split_rain
Include treatment of rain when splitting total humidity into constituent phases.
oops::Parameter< bool > qtotal_lnq_gkg
B-matrix file contains error covariances for ln(qtotal in units g/kg)
oops::Parameter< bool > reverse_Jacobian
Jacobian vertical ordering is reverse of geovals.
oops::Parameter< float > maxTb
Maximum bound for ObsValue brightness temperature.
oops::RequiredParameter< std::string > chanlist
Set of channels used in the calculation of the cost function.
oops::RequiredParameter< std::string > rmatrix_filepath
Path to location of file describing the R-matrix.
oops::Parameter< std::string > HofXGroup
Name of the H(x) group used in the cost function calculation.
oops::Parameter< float > maxCost
Maximum value for final cost returned by the ObsFunction.
oops::Parameter< float > min_q
Limit specific humidity to minimum value.
oops::RequiredParameter< std::string > bmatrix_filepath
Path to location of file describing the B-matrix.
oops::Parameter< float > minTb
Minimum bound for ObsValue brightness temperature.
oops::Parameter< bool > scattering_switch
Include gradient due to ice in brightness temperature total humidity Jacobian.
size_t getsize(void) const
Return bmatrix size (number of rows or columns of square matrix)
void multiply(const float, const Eigen::MatrixXf &, Eigen::MatrixXf &) const
Multiply input matrix by bmatrix array based on latitude.
void add(const std::vector< int > &, const Eigen::MatrixXf &, Eigen::MatrixXf &) const
Add r matrix variance onto input array.
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.
integer function nlocs(this)
Return the number of observational locations in this Locations object.
static ObsFunctionMaker< CloudCostFunction > makerCloudCostFunction_("CloudCostFunction")
void ufo_ops_satrad_qsatwat_f90(float *, const float *, const float *, const int &)
void ufo_ops_satrad_qsplit_f90(const int &, const int &, const float *, const float *, const float *, float *, float *, float *, const bool &)