UFO
ObsBiasOperator.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 "ufo/ObsBiasOperator.h"
9 
10 #include <string>
11 #include <vector>
12 
13 #include "ioda/ObsVector.h"
14 
15 #include "oops/util/Logger.h"
16 #include "oops/util/missingValues.h"
17 
18 #include "ufo/ObsBias.h"
19 #include "ufo/ObsDiagnostics.h"
20 
21 namespace ufo {
22 
23 // -----------------------------------------------------------------------------
24 
25 ObsBiasOperator::ObsBiasOperator(ioda::ObsSpace & odb)
26  : odb_(odb) {
27  oops::Log::trace() << "ObsBiasOperator::create done." << std::endl;
28 }
29 
30 // -----------------------------------------------------------------------------
31 
32 void ObsBiasOperator::computeObsBias(const GeoVaLs & geovals, ioda::ObsVector & ybias,
33  const ObsBias & biascoeffs, ObsDiagnostics & ydiags) const {
34  oops::Log::trace() << "ObsBiasOperator::computeObsBias starting" << std::endl;
35 
36  const double missing = util::missingValue(missing);
37  const Predictors & predictors = biascoeffs.predictors();
38  const std::size_t npreds = predictors.size();
39  std::vector<ioda::ObsVector> predData(npreds, ioda::ObsVector(odb_));
40  for (std::size_t p = 0; p < npreds; ++p) {
41  predictors[p]->compute(odb_, geovals, ydiags, predData[p]);
42  predData[p].save(predictors[p]->name() + "Predictor");
43  }
44 
45  const oops::Variables &correctedVars = biascoeffs.correctedVars();
46  // At present we can label predictors with either the channel number or the variable name, but not
47  // both. So if there are multiple channels, make sure there's only one (multi-channel) variable.
48  ASSERT(correctedVars.channels().empty() ||
49  correctedVars.variables().size() == correctedVars.channels().size());
50 
51  const std::size_t nlocs = ybias.nlocs();
52  const std::size_t nvars = ybias.nvars();
53 
54  ybias.zero();
55 
56  /* ybias memory layout (nlocs X nvars)
57  * ch1 ch2 ch3 ch4
58  * Loc --------------------------
59  * 0 | 0 1 2 3
60  * 1 | 4 5 6 7
61  * 2 | 8 9 10 11
62  * 3 |12 13 14 15
63  * 4 |16 17 18 19
64  * ...|
65  */
66 
67  std::vector<double> biasTerm(nlocs);
68  // For each channel: ( nlocs X 1 ) = ( nlocs X npreds ) * ( npreds X 1 )
69  for (std::size_t jvar = 0; jvar < nvars; ++jvar) {
70  std::string predictorSuffix;
71  if (correctedVars.channels().empty())
72  predictorSuffix = correctedVars[jvar];
73  else
74  predictorSuffix = std::to_string(correctedVars.channels()[jvar]);
75 
76  for (std::size_t jp = 0; jp < npreds; ++jp) {
77  // axpy
78  const double beta = biascoeffs(jp, jvar);
79  for (std::size_t jl = 0; jl < nlocs; ++jl) {
80  if (predData[jp][jl*nvars+jvar] != missing) {
81  biasTerm[jl] = predData[jp][jl*nvars+jvar] * beta;
82  ybias[jl*nvars+jvar] += biasTerm[jl];
83  }
84  }
85  // Save ObsBiasOperatorTerms (bias_coeff * predictor) for QC
86  const std::string varname = predictors[jp]->name() + "_" + predictorSuffix;
87  if (ydiags.has(varname)) {
88  ydiags.allocate(1, oops::Variables({varname}));
89  ydiags.save(biasTerm, varname, 0);
90  } else {
91  oops::Log::error() << varname << " is not reserved in ydiags !" << std::endl;
92  ABORT("ObsBiasOperatorTerm variable is not reserved in ydiags");
93  }
94  }
95  }
96 
97  oops::Log::trace() << "ObsBiasOperator::computeObsBiasOperator done." << std::endl;
98 }
99 
100 // -----------------------------------------------------------------------------
101 
102 void ObsBiasOperator::print(std::ostream & os) const {
103  os << "ObsBiasOperator: linear combination of the predictors." << std::endl;
104 }
105 
106 // -----------------------------------------------------------------------------
107 
108 } // namespace ufo
GeoVaLs: geophysical values at locations.
const oops::Variables & correctedVars() const
Return the list of bias-corrected variables.
const Predictors & predictors() const
Return a reference to the vector of all (static and variable) predictors.
void print(std::ostream &) const override
Print details (used for logging)
void computeObsBias(const GeoVaLs &, ioda::ObsVector &, const ObsBias &, ObsDiagnostics &) const
Compute bias correction.
ObsBiasOperator(ioda::ObsSpace &)
ioda::ObsSpace & odb_
ObsSpace used for computing predictors.
void allocate(const int nlev, const oops::Variables &vars)
Allocate diagnostics for variables vars with nlev number of levels.
bool has(const std::string &var) const
void save(const std::vector< double > &, const std::string &, const int)
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
std::vector< std::shared_ptr< PredictorBase > > Predictors
Definition: PredictorBase.h:92