UFO
Cal_ProfileHorizontalDrift.cc
Go to the documentation of this file.
1 /*
2  * (C) Crown copyright 2021, 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 #include "ufo/utils/Constants.h"
10 
11 namespace ufo {
12 
13 /************************************************************************************/
14 // Cal_ProfileHorizontalDrift
15 /************************************************************************************/
16 
17 static TransformMaker<Cal_ProfileHorizontalDrift>
18 makerCal_ProfileHorizontalDrift_("ProfileHorizontalDrift");
19 
21 (const VariableTransformsParameters &options,
22  const ObsFilterData &data,
23  const std::shared_ptr<ioda::ObsDataVector<int>> &flags)
24  : TransformBase(options, data, flags) {}
25 
26 /************************************************************************************/
27 
28 void Cal_ProfileHorizontalDrift::runTransform(const std::vector<bool> &apply) {
29  oops::Log::trace() << " --> Compute horizontal drift lat/lon/time" << std::endl;
30  oops::Log::trace() << " --> method: " << method() << std::endl;
31 
32  // Ensure observations have been grouped into profiles.
33  if (obsdb_.obs_group_vars().empty())
34  throw eckit::UserError("Group variables configuration is empty", Here());
35 
36  // Ensure observations have been sorted by air pressure in descending order.
37  if (obsdb_.obs_sort_var() != "air_pressure")
38  throw eckit::UserError("Sort variable must be air_pressure", Here());
39  if (obsdb_.obs_sort_order() != "descending")
40  throw eckit::UserError("Profiles must be sorted in descending order", Here());
41 
42  // Obtain values from ObsSpace.
43  std::vector<float> latitude_in, longitude_in, wind_speed, wind_from_direction, height;
44  std::vector<util::DateTime> datetime_in;
45  getObservation("MetaData", "latitude", latitude_in, true);
46  getObservation("MetaData", "longitude", longitude_in, true);
47  getObservation("MetaData", "datetime", datetime_in, true);
48  getObservation("ObsValue", "geopotential_height", height, true);
49  getObservation("ObsValue", "wind_speed", wind_speed, true);
50  getObservation("ObsValue", "wind_from_direction", wind_from_direction, true);
51 
52  if (!oops::allVectorsSameNonZeroSize(latitude_in, longitude_in, datetime_in,
53  height, wind_speed, wind_from_direction)) {
54  oops::Log::warning() << "Vector sizes: "
55  << oops::listOfVectorSizes(latitude_in, longitude_in, datetime_in,
56  height, wind_speed, wind_from_direction)
57  << std::endl;
58  throw eckit::BadValue("At least one vector is the wrong size", Here());
59  }
60 
61  // Number of locations in the ObsSpace.
62  const size_t nlocs = obsdb_.nlocs();
63 
64  // Output values are initialised to input values.
65  std::vector<float> latitude_out = latitude_in;
66  std::vector<float> longitude_out = longitude_in;
67  std::vector<util::DateTime> datetime_out = datetime_in;
68 
69  // Get correspondence between record numbers and indices in the total sample.
70  const std::vector<size_t> &recnums = obsdb_.recidx_all_recnums();
71 
72  // Number of profiles in the ObsSpace.
73  const size_t nprofs = recnums.size();
74 
75  // Perform drift calculation for each profile in the sample.
76  for (size_t jprof = 0; jprof < nprofs; ++jprof) {
77  const std::vector<size_t> &locs = obsdb_.recidx_vector(recnums[jprof]);
78  formulas::horizontalDrift(locs, apply,
79  latitude_in, longitude_in, datetime_in,
80  height, wind_speed, wind_from_direction,
81  latitude_out, longitude_out, datetime_out);
82  }
83 
84  // Save output values.
85  obsdb_.put_db("DerivedMetaData", "latitude", latitude_out);
86  obsdb_.put_db("DerivedMetaData", "longitude", longitude_out);
87  obsdb_.put_db("DerivedMetaData", "datetime", datetime_out);
88 }
89 } // namespace ufo
90 
void runTransform(const std::vector< bool > &apply) override
Run variable conversion.
Cal_ProfileHorizontalDrift(const VariableTransformsParameters &options, const ObsFilterData &data, const std::shared_ptr< ioda::ObsDataVector< int >> &flags)
ObsFilterData provides access to all data related to an ObsFilter.
Base class for variable conversion.
Definition: TransformBase.h:53
formulas::MethodFormulation method() const
subclasses to access Method and formualtion used for the calculation
ioda::ObsSpace & obsdb_
Observation space.
void getObservation(const std::string &originalTag, const std::string &varName, std::vector< T > &obsVector, bool require=false) const
templated function for float, int data types
Definition: TransformBase.h:94
Options controlling the operation of the variablestansform filter.
void horizontalDrift(const std::vector< size_t > &locs, const std::vector< bool > &apply, const std::vector< float > &lat_in, const std::vector< float > &lon_in, const std::vector< util::DateTime > &time_in, const std::vector< float > &height, const std::vector< float > &windspd, const std::vector< float > &winddir, std::vector< float > &lat_out, std::vector< float > &lon_out, std::vector< util::DateTime > &time_out, MethodFormulation formulation)
Compute horizontal drift latitude, longitude and time for an atmospheric profile.
Definition: Formulas.cc:381
integer function nlocs(this)
Return the number of observational locations in this Locations object.
Definition: RunCRTM.h:27
static TransformMaker< Cal_ProfileHorizontalDrift > makerCal_ProfileHorizontalDrift_("ProfileHorizontalDrift")