OOPS
ObsSpaceQG.cc
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2009-2016 ECMWF.
3  * (C) Copyright 2017-2019 UCAR.
4  *
5  * This software is licensed under the terms of the Apache Licence Version 2.0
6  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
7  * In applying this licence, ECMWF does not waive the privileges and immunities
8  * granted to it by virtue of its status as an intergovernmental organisation nor
9  * does it submit to any jurisdiction.
10  */
11 
12 #include "model/ObsSpaceQG.h"
13 
14 #include <map>
15 #include <string>
16 #include <utility>
17 
18 #include "atlas/array.h"
19 #include "atlas/field.h"
20 #include "eckit/config/Configuration.h"
21 #include "eckit/exception/Exceptions.h"
22 #include "eckit/geometry/Sphere.h"
23 
24 #include "oops/util/abor1_cpp.h"
25 #include "oops/util/DateTime.h"
26 #include "oops/util/Duration.h"
27 #include "oops/util/Logger.h"
28 
29 #include "model/ObsVecQG.h"
30 
31 using atlas::array::make_view;
32 
33 namespace qg {
34 // -----------------------------------------------------------------------------
35 // initialization for the static map
36 std::map < std::string, F90odb > ObsSpaceQG::theObsFileRegister_;
38 
39 // -----------------------------------------------------------------------------
40 
41 ObsSpaceQG::ObsSpaceQG(const eckit::Configuration & config, const eckit::mpi::Comm & comm,
42  const util::DateTime & bgn, const util::DateTime & end,
43  const eckit::mpi::Comm & timeComm)
44  : oops::ObsSpaceBase(config, comm, bgn, end), obsname_(config.getString("obs type")),
45  winbgn_(bgn), winend_(end), obsvars_(), isLocal_(false), comm_(comm)
46 {
47  typedef std::map< std::string, F90odb >::iterator otiter;
48 
49  eckit::LocalConfiguration fileconf(config);
50  std::string ofin("-");
51  if (config.has("obsdatain")) {
52  ofin = config.getString("obsdatain.obsfile");
53  }
54  std::string ofout("-");
55  if (config.has("obsdataout")) {
56  ofout = config.getString("obsdataout.obsfile");
57  if (timeComm.size() > 1) {
58  std::ostringstream ss;
59  ss << "_" << timeComm.rank();
60  std::size_t found = ofout.find_last_of(".");
61  if (found == std::string::npos) found = ofout.length();
62  std::string fileout = ofout.insert(found, ss.str());
63  fileconf.set("obsdataout.obsfile", fileout);
64  }
65  }
66  oops::Log::trace() << "ObsSpaceQG: Obs files are: " << ofin << " and " << ofout << std::endl;
67  std::string ref = ofin + ofout;
68  if (ref == "--") {
69  ABORT("Underspecified observation files.");
70  }
71 
72  otiter it = theObsFileRegister_.find(ref);
73  if ( it == theObsFileRegister_.end() ) {
74  // Open new file
75  oops::Log::trace() << "ObsSpaceQG::getHelper: " << "Opening " << ref << std::endl;
76  qg_obsdb_setup_f90(key_, fileconf, bgn, end);
78  } else {
79  // File already open
80  oops::Log::trace() << "ObsSpaceQG::getHelper: " << ref << " already opened." << std::endl;
81  key_ = it->second;
82  }
84 
85  // Set variables simulated for different obstypes
86  if (obsname_ == "Stream") obsvars_.push_back("Stream");
87  if (obsname_ == "WSpeed") obsvars_.push_back("WSpeed");
88  if (obsname_ == "Wind") {
89  obsvars_.push_back("Uwind");
90  obsvars_.push_back("Vwind");
91  }
92 
93  // Generate locations etc... if required
94  if (config.has("generate")) {
95  const eckit::LocalConfiguration gconf(config, "generate");
96  const util::Duration first(gconf.getString("begin"));
97  const util::DateTime start(winbgn_ + first);
98  const util::Duration freq(gconf.getString("obs_period"));
99  int nobstimes = 0;
100  util::DateTime now(start);
101  while (now <= winend_) {
102  ++nobstimes;
103  now += freq;
104  }
105  int iobs;
106  qg_obsdb_generate_f90(key_, obsname_.size(), obsname_.c_str(), gconf,
107  start, freq, nobstimes, iobs);
108  }
109 }
110 
111 // -----------------------------------------------------------------------------
112 
114  const eckit::geometry::Point2 & refPoint,
115  const eckit::Configuration & conf)
116  : oops::ObsSpaceBase(eckit::LocalConfiguration(), obsdb.comm_,
117  obsdb.windowStart(), obsdb.windowEnd()),
118  key_(obsdb.key_), obsname_(obsdb.obsname_),
119  winbgn_(obsdb.winbgn_), winend_(obsdb.winend_), obsvars_(obsdb.obsvars_),
120  localobs_(), isLocal_(true), comm_(obsdb.comm_)
121 {
122  oops::Log::trace() << "ObsSpaceQG for LocalObs starting" << std::endl;
123  const double dist = conf.getDouble("lengthscale");
124 
125  // get locations of all obs
126  std::unique_ptr<LocationsQG> locs = locations(winbgn_, winend_);
127 
128  atlas::Field field_lonlat = locs->lonlat();
129  auto lonlat = make_view<double, 2>(field_lonlat);
130 
131  for (int jj = 0; jj < locs->size(); ++jj) {
132  eckit::geometry::Point2 obsPoint(lonlat(jj, 0), lonlat(jj, 1));
133  double localDist = eckit::geometry::Sphere::distance(6.371e6, refPoint, obsPoint);
134  if (localDist < dist) localobs_.push_back(jj);
135  }
136 
137  oops::Log::trace() << "ObsSpaceQG for LocalObs done" << std::endl;
138 }
139 
140 // -----------------------------------------------------------------------------
141 
143  if ( !isLocal_ ) {
144  ASSERT(theObsFileCount_ > 0);
146  if (theObsFileCount_ == 0) {
147  theObsFileRegister_.clear();
149  }
150  }
151 }
152 
153 // -----------------------------------------------------------------------------
154 
155 void ObsSpaceQG::getdb(const std::string & col, int & keyData) const {
156  if ( isLocal_ ) {
157  qg_obsdb_get_local_f90(key_, obsname_.size(), obsname_.c_str(), col.size(),
158  col.c_str(), localobs_.size(), localobs_.data(), keyData);
159  } else {
160  qg_obsdb_get_f90(key_, obsname_.size(), obsname_.c_str(), col.size(), col.c_str(), keyData);
161  }
162 }
163 
164 // -----------------------------------------------------------------------------
165 
166 void ObsSpaceQG::putdb(const std::string & col, const int & keyData) const {
167  // not implemented for local ObsSpace
168  ASSERT(isLocal_ == false);
169  qg_obsdb_put_f90(key_, obsname_.size(), obsname_.c_str(), col.size(), col.c_str(), keyData);
170 }
171 
172 // -----------------------------------------------------------------------------
173 
174 bool ObsSpaceQG::has(const std::string & col) const {
175  int ii;
176  qg_obsdb_has_f90(key_, obsname_.size(), obsname_.c_str(), col.size(), col.c_str(), ii);
177  return ii;
178 }
179 
180 // -----------------------------------------------------------------------------
181 
182 std::unique_ptr<LocationsQG> ObsSpaceQG::locations(const util::DateTime & t1,
183  const util::DateTime & t2) const {
184  atlas::FieldSet fields;
185  std::vector<util::DateTime> times;
186  qg_obsdb_locations_f90(key_, obsname_.size(), obsname_.c_str(), t1, t2,
187  fields.get(), times);
188  return std::unique_ptr<LocationsQG>(new LocationsQG(fields, std::move(times)));
189 }
190 
191 // -----------------------------------------------------------------------------
192 
193 void ObsSpaceQG::printJo(const ObsVecQG & dy, const ObsVecQG & grad) const {
194  oops::Log::info() << "ObsSpaceQG::printJo not implemented" << std::endl;
195 }
196 
197 // -----------------------------------------------------------------------------
198 
199 int ObsSpaceQG::nobs() const {
200  if ( isLocal_ ) {
201  return localobs_.size();
202  } else {
203  int iobs;
204  qg_obsdb_nobs_f90(key_, obsname_.size(), obsname_.c_str(), iobs);
205  return iobs;
206  }
207 }
208 // -----------------------------------------------------------------------------
209 
210 void ObsSpaceQG::print(std::ostream & os) const {
211  os << "ObsSpace for " << obsname_ << ", " << this->nobs() << " obs" << std::endl;
212 }
213 
214 // -----------------------------------------------------------------------------
215 
216 } // namespace qg
qg::qg_obsdb_delete_f90
void qg_obsdb_delete_f90(F90odb &)
qg::qg_obsdb_get_f90
void qg_obsdb_get_f90(const F90odb &, const int &, const char *, const int &, const char *, const F90ovec &)
qg::ObsSpaceQG::obsvars_
oops::Variables obsvars_
Definition: ObsSpaceQG.h:90
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
qg::ObsSpaceQG::key_
F90odb key_
Definition: ObsSpaceQG.h:86
ObsSpaceQG.h
qg
The namespace for the qg model.
Definition: qg/model/AnalyticInit.cc:13
qg::qg_obsdb_locations_f90
void qg_obsdb_locations_f90(const F90odb &, const int &, const char *, const util::DateTime &, const util::DateTime &, atlas::field::FieldSetImpl *, std::vector< util::DateTime > &)
qg::qg_obsdb_generate_f90
void qg_obsdb_generate_f90(const F90odb &, const int &, const char *, const eckit::Configuration &, const util::DateTime &, const util::Duration &, const int &, int &)
qg::qg_obsdb_put_f90
void qg_obsdb_put_f90(const F90odb &, const int &, const char *, const int &, const char *, const F90ovec &)
qg::ObsSpaceQG::theObsFileCount_
static int theObsFileCount_
Definition: ObsSpaceQG.h:97
qg::ObsSpaceQG::localobs_
std::vector< int > localobs_
Definition: ObsSpaceQG.h:91
qg::ObsSpaceQG
ObsSpace for QG model.
Definition: ObsSpaceQG.h:44
qg::ObsSpaceQG::winend_
const util::DateTime winend_
Definition: ObsSpaceQG.h:89
qg::LocationsQG
LocationsQG class to handle locations for QG model.
Definition: LocationsQG.h:36
qg::ObsSpaceQG::nobs
int nobs() const
return number of observations (unique locations)
Definition: ObsSpaceQG.cc:199
qg::qg_obsdb_has_f90
void qg_obsdb_has_f90(const F90odb &, const int &, const char *, const int &, const char *, int &)
ObsVecQG.h
eckit
Definition: FieldL95.h:22
qg::ObsSpaceQG::ObsSpaceQG
ObsSpaceQG(const eckit::Configuration &, const eckit::mpi::Comm &, const util::DateTime &, const util::DateTime &, const eckit::mpi::Comm &)
create full ObsSpace (read or generate data)
Definition: ObsSpaceQG.cc:41
qg::ObsSpaceQG::printJo
void printJo(const ObsVecQG &, const ObsVecQG &) const
Definition: ObsSpaceQG.cc:193
qg::ObsVecQG
ObsVecQG class to handle vectors in observation space for QG model.
Definition: ObsVecQG.h:34
qg::ObsSpaceQG::print
void print(std::ostream &) const
Definition: ObsSpaceQG.cc:210
qg::ObsSpaceQG::theObsFileRegister_
static std::map< std::string, F90odb > theObsFileRegister_
Definition: ObsSpaceQG.h:96
qg::ObsSpaceQG::winbgn_
const util::DateTime winbgn_
Definition: ObsSpaceQG.h:88
oops::Variables::push_back
void push_back(const std::string &)
Definition: oops/base/Variables.cc:145
qg::ObsSpaceQG::isLocal_
bool isLocal_
Definition: ObsSpaceQG.h:92
qg::qg_obsdb_get_local_f90
void qg_obsdb_get_local_f90(const F90odb &, const int &, const char *, const int &, const char *, const int &, const int *, const F90ovec &)
qg::ObsSpaceQG::getdb
void getdb(const std::string &, int &) const
read data or metadata
Definition: ObsSpaceQG.cc:155
qg::ObsSpaceQG::has
bool has(const std::string &col) const
check if variable is in ObsSpace
Definition: ObsSpaceQG.cc:174
qg::ObsSpaceQG::locations
std::unique_ptr< LocationsQG > locations(const util::DateTime &t1, const util::DateTime &t2) const
create locations between times (t1, t2]
Definition: ObsSpaceQG.cc:182
qg::qg_obsdb_setup_f90
void qg_obsdb_setup_f90(F90odb &, const eckit::Configuration &, const util::DateTime &, const util::DateTime &)
qg::ObsSpaceQG::~ObsSpaceQG
~ObsSpaceQG()
Definition: ObsSpaceQG.cc:142
qg::ObsSpaceQG::obsname_
const std::string obsname_
Definition: ObsSpaceQG.h:87
qg::qg_obsdb_nobs_f90
void qg_obsdb_nobs_f90(const F90odb &, const int &, const char *, int &)
qg::ObsSpaceQG::putdb
void putdb(const std::string &, const int &) const
save data or metadata
Definition: ObsSpaceQG.cc:166