UFO
CloudLiquidWater.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2021 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 
8 #include <iomanip>
9 #include <string>
10 
11 #include "eckit/exception/Exceptions.h"
12 
13 #include "ioda/ObsSpace.h"
14 
15 #include "oops/util/missingValues.h"
16 
18 #include "ufo/GeoVaLs.h"
20 #include "ufo/utils/Constants.h"
21 namespace ufo {
22 
23 static PredictorMaker<CloudLiquidWater>
24  makerFuncCloudLiquidWater_("cloud_liquid_water");
25 
26 // -----------------------------------------------------------------------------
27 
28 CloudLiquidWater::CloudLiquidWater(const Parameters_ & parameters, const oops::Variables & vars)
29  : PredictorBase(parameters, vars) {
30  // Initialize options
31  options_ = parameters;
32  const std::string &satellite = options_.satellite.value();
33 
34  // Currently the code is designed only for SSMIS brightness temperatures from
35  // channels 12 through 18, but a different satellite could use a different list of
36  // channels and frequencies requiring a different block of input checks.
37  if (satellite == "SSMIS") {
38  ASSERT(options_.ch19h.value() != boost::none && options_.ch19v.value() != boost::none &&
39  options_.ch22v.value() != boost::none && options_.ch37h.value() != boost::none &&
40  options_.ch37v.value() != boost::none && options_.ch91v.value() != boost::none &&
41  options_.ch91h.value() != boost::none);
42 
43  channels_ = {options_.ch19h.value().get(), options_.ch19v.value().get(),
44  options_.ch22v.value().get(), options_.ch37h.value().get(),
45  options_.ch37v.value().get(), options_.ch91v.value().get(),
46  options_.ch91h.value().get()};
47 
48  ASSERT(options_.ch19h.value().get() != 0 && options_.ch19v.value().get() != 0 &&
49  options_.ch22v.value().get() != 0 && options_.ch37h.value().get() != 0 &&
50  options_.ch37v.value().get() != 0 && options_.ch91v.value().get() != 0 &&
51  options_.ch91h.value().get() != 0 && channels_.size() == 7);
52 
53  } else {
54  std::string errString = "Currently only SSMIS satellite is supported.";
55  oops::Log::error() << errString;
56  throw eckit::BadValue(errString);
57  }
58 }
59 
60 // -----------------------------------------------------------------------------
61 
62 void CloudLiquidWater::compute(const ioda::ObsSpace & odb,
63  const GeoVaLs & geovals,
64  const ObsDiagnostics &,
65  ioda::ObsVector & out) const {
66  // Get required parameters
67  const std::string &vargrp = options_.varGroup.value();
68  const std::size_t nlocs = out.nlocs();
69  const std::size_t nvars = out.nvars();
70 
71  const float fmiss = util::missingValue(fmiss);
72  const double dmiss = util::missingValue(dmiss);
73 
74  // From the obs database, grab all the brightness temperatures of channels.
75  std::vector<float> bt19h(nlocs), bt19v(nlocs), bt22v(nlocs), bt37h(nlocs),
76  bt37v(nlocs), bt91v(nlocs), bt91h(nlocs);
77  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[0]), bt19h);
78  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[1]), bt19v);
79  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[2]), bt22v);
80  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[3]), bt37h);
81  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[4]), bt37v);
82  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[5]), bt91v);
83  odb.get_db(vargrp, "brightness_temperature_" + std::to_string(channels_[6]), bt91h);
84 
85  std::vector<float> szas(nlocs);
86  odb.get_db("MetaData", "sensor_zenith_angle", szas);
87 
88  std::vector<float> water_frac(nlocs, 0.0);
89  geovals.get(water_frac, "water_area_fraction");
90 
91  // Compute cloud liquid water amount
92  std::vector<float> clw(nlocs);
93  CLWRetMW_SSMIS::cloudLiquidWater(bt19h, bt19v, bt22v, bt37h, bt37v, bt91v, bt91h,
94  water_frac, clw);
95 
96  for (std::size_t iloc = 0; iloc < nlocs; ++iloc) {
97  for (std::size_t jvar = 0; jvar < nvars; ++jvar) {
98  float cossza = cos(Constants::deg2rad * szas[iloc]);
99  if (clw[iloc] == fmiss) {
100  out[iloc*nvars + jvar] = dmiss;
101  } else {
102  out[iloc*nvars + jvar] = static_cast<double>(clw[iloc]*cossza*cossza);
103  }
104  }
105  }
106 }
107 
108 // -----------------------------------------------------------------------------
109 
110 } // namespace ufo
static void cloudLiquidWater(const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, const std::vector< float > &, std::vector< float > &, std::vector< float > &)
CloudLiquidWaterParameters options_
std::vector< int > channels_
void compute(const ioda::ObsSpace &, const GeoVaLs &, const ObsDiagnostics &, ioda::ObsVector &) const override
compute the predictor
CloudLiquidWater(const Parameters_ &, const oops::Variables &)
Configuration parameters of the CloudLiquidWater predictor.
oops::OptionalParameter< int > ch91v
oops::OptionalParameter< int > ch22v
oops::RequiredParameter< std::string > satellite
We must specify a satellite reference name such as SSMIS to know which channels to expect.
oops::OptionalParameter< int > ch19h
oops::OptionalParameter< int > ch37v
oops::Parameter< std::string > varGroup
In case we need to override the ObsValue group name with another optional group name.
oops::OptionalParameter< int > ch19v
oops::OptionalParameter< int > ch91h
oops::OptionalParameter< int > ch37h
GeoVaLs: geophysical values at locations.
void get(std::vector< double > &, const std::string &var) const
Get 2D GeoVaLs for variable var (fails for 3D GeoVaLs)
Definition: GeoVaLs.cc:359
constexpr int clw
Definition: QCflags.h:28
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27
static PredictorMaker< CloudLiquidWater > makerFuncCloudLiquidWater_("cloud_liquid_water")
static constexpr double deg2rad
Definition: Constants.h:21