UFO
ObsProfileAverageTLAD.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2021 UK Met Office
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 <iomanip>
11 #include <ostream>
12 #include <vector>
13 
14 #include "ioda/ObsVector.h"
15 
16 #include "oops/base/Variables.h"
17 #include "oops/util/Logger.h"
18 #include "oops/util/missingValues.h"
19 
20 #include "ufo/GeoVaLs.h"
21 #include "ufo/ObsDiagnostics.h"
22 
23 namespace ufo {
24 
25 // -----------------------------------------------------------------------------
27 // -----------------------------------------------------------------------------
28 
30  const eckit::Configuration & config)
31  : LinearObsOperatorBase(odb), odb_(odb), data_(odb, config)
32 {
33  oops::Log::trace() << "ObsProfileAverageTLAD constructed" << std::endl;
34 }
35 
36 // -----------------------------------------------------------------------------
37 
39  oops::Log::trace() << "ObsProfileAverageTLAD destructed" << std::endl;
40 }
41 
42 // -----------------------------------------------------------------------------
43 
45  // The initial trajectory is used to determine the slant path locations.
46  data_.cacheGeoVaLs(geovals);
47  oops::Log::trace() << "ObsProfileAverageTLAD: trajectory set" << std::endl;
48 }
49 
50 // -----------------------------------------------------------------------------
51 
52 void ObsProfileAverageTLAD::simulateObsTL(const GeoVaLs & dx, ioda::ObsVector & dy) const {
53  oops::Log::trace() << "ObsProfileAverageTLAD: simulateObsTL started" << std::endl;
54 
55  // Get correspondence between record numbers and indices in the total sample.
56  const std::vector<std::size_t> &recnums = odb_.recidx_all_recnums();
57 
58  // Number of profiles in the original ObsSpace.
59  const std::size_t nprofs = recnums.size() / 2;
60 
61  // Loop over profiles.
62  for (std::size_t jprof = 0; jprof < nprofs; ++jprof) {
63  const std::vector<std::size_t> &locsOriginal = odb_.recidx_vector(recnums[jprof]);
64  const std::vector<std::size_t> &locsExtended = odb_.recidx_vector(recnums[jprof + nprofs]);
65 
66  // Retrieve slant path locations.
67  const std::vector<std::size_t>& slant_path_location =
68  data_.getSlantPathLocations(locsOriginal, locsExtended);
69 
70  for (int jvar : data_.operatorVarIndices()) {
71  const auto& variable = dy.varnames().variables()[jvar];
72  const std::size_t nlevs_var = dx.nlevs(variable);
73  std::vector<double> var_gv(nlevs_var);
74  for (std::size_t mlev = 0; mlev < nlevs_var; ++mlev) {
75  const std::size_t jloc = slant_path_location[mlev];
76  dx.getAtLocation(var_gv, variable, jloc);
77  dy[locsExtended[mlev] * dy.nvars() + jvar] = var_gv[mlev];
78  }
79  }
80  }
81 
82  oops::Log::trace() << "ObsProfileAverageTLAD: simulateObsTL finished" << std::endl;
83 }
84 
85 // -----------------------------------------------------------------------------
86 
87 void ObsProfileAverageTLAD::simulateObsAD(GeoVaLs & dx, const ioda::ObsVector & dy) const {
88  oops::Log::trace() << "ObsProfileAverageTLAD: simulateObsAD started" << std::endl;
89 
90  const double missing = util::missingValue(missing);
91 
92  // Get correspondence between record numbers and indices in the total sample.
93  const std::vector<std::size_t> &recnums = odb_.recidx_all_recnums();
94 
95  // Number of profiles in the original ObsSpace.
96  const std::size_t nprofs = recnums.size() / 2;
97 
98  // Loop over profiles.
99  for (std::size_t jprof = 0; jprof < nprofs; ++jprof) {
100  const std::vector<std::size_t> &locsOriginal = odb_.recidx_vector(recnums[jprof]);
101  const std::vector<std::size_t> &locsExtended = odb_.recidx_vector(recnums[jprof + nprofs]);
102 
103  // Retrieve slant path locations.
104  const std::vector<std::size_t>& slant_path_location =
105  data_.getSlantPathLocations(locsOriginal, locsExtended);
106 
107  for (int jvar : data_.operatorVarIndices()) {
108  const auto& variable = dy.varnames().variables()[jvar];
109  const std::size_t nlevs_var = dx.nlevs(variable);
110  std::vector<double> var_gv(nlevs_var);
111  for (std::size_t mlev = 0; mlev < nlevs_var; ++mlev) {
112  const std::size_t jloc = slant_path_location[mlev];
113  // Get the current value of dx.
114  dx.getAtLocation(var_gv, variable, jloc);
115  const std::size_t idx = locsExtended[mlev] * dy.nvars() + jvar;
116  if (dy[idx] != missing)
117  var_gv[mlev] += dy[idx];
118  // Store the new value of dx.
119  dx.putAtLocation(var_gv, variable, jloc);
120  }
121  }
122  }
123 
124  oops::Log::trace() << "ObsProfileAverageTLAD: simulateObsAD finished" << std::endl;
125 }
126 
127 // -----------------------------------------------------------------------------
128 
129 void ObsProfileAverageTLAD::print(std::ostream & os) const {
130  os << "ObsProfileAverageTLAD operator" << std::endl;
131 }
132 
133 // -----------------------------------------------------------------------------
134 
135 } // namespace ufo
GeoVaLs: geophysical values at locations.
size_t nlevs(const std::string &var) const
Return number of levels for a specified variable.
Definition: GeoVaLs.cc:310
void putAtLocation(const std::vector< double > &vals, const std::string &var, const int loc) const
Put GeoVaLs for double variable var at location loc.
Definition: GeoVaLs.cc:451
void getAtLocation(std::vector< double > &, const std::string &, const int) const
Get GeoVaLs at a specified location.
Definition: GeoVaLs.cc:380
std::vector< std::size_t > getSlantPathLocations(const std::vector< std::size_t > &locsOriginal, const std::vector< std::size_t > &locsExtended) const
void cacheGeoVaLs(const GeoVaLs &gv) const
Cache the initial values of the GeoVaLs.
const std::vector< int > & operatorVarIndices() const
Return operator variable indices for the operator.
ObsProfileAverageData data_
Data handler for the ProfileAverage operator and TL/AD code.
void setTrajectory(const GeoVaLs &, ObsDiagnostics &) override
Obs Operator.
ObsProfileAverageTLAD(const ioda::ObsSpace &, const eckit::Configuration &)
void print(std::ostream &) const override
void simulateObsTL(const GeoVaLs &, ioda::ObsVector &) const override
const ioda::ObsSpace & odb_
ObsSpace.
void simulateObsAD(GeoVaLs &, const ioda::ObsVector &) const override
constexpr int missing
Definition: QCflags.h:20
Definition: RunCRTM.h:27
static ObsOperatorMaker< ObsProfileAverage > obsProfileAverageMaker_("ProfileAverage")