17 #include "ioda/distribution/Accumulator.h"
18 #include "ioda/Engines/Factory.h"
19 #include "ioda/Layout.h"
20 #include "ioda/ObsGroup.h"
21 #include "ioda/ObsSpace.h"
22 #include "ioda/ObsVector.h"
24 #include "oops/util/IntSetParser.h"
25 #include "oops/util/Logger.h"
26 #include "oops/util/Random.h"
28 #include "ufo/ObsBias.h"
39 : odb_(odb), prednames_(0), vars_(odb.obsvariables()), variances_(),
41 ht_rinv_h_(0), obs_num_(0), analysis_variances_(0), minimal_required_obs_number_(0) {
42 oops::Log::trace() <<
"ObsBiasCovariance::Constructor starting" << std::endl;
54 throw eckit::UserError(
"obs bias.covariance section missing from the YAML file");
62 const std::vector<double> &range = biasCovParams.
varianceRange.value();
63 ASSERT(range.size() == 2);
94 if (biasCovParams.
prior.value() != boost::none) {
98 const double inflation_ratio = priorParams.
inflation.value().ratio;
101 const double large_inflation_ratio = priorParams.
inflation.value().ratioForSmallDataset;
105 this->
read(priorParams);
110 for (std::size_t j = 0; j <
vars_.size(); ++j) {
112 large_inflation_ratio : inflation_ratio;
113 for (std::size_t p = 0; p <
prednames_.size(); ++p) {
115 if (inflation > inflation_ratio)
126 oops::Log::trace() <<
"ObsBiasCovariance::Constructor is done" << std::endl;
132 oops::Log::trace() <<
"ObsBiasCovariance::read from file " << std::endl;
134 if (params.
inputFile.value() != boost::none) {
136 ioda::Engines::BackendNames backendName = ioda::Engines::BackendNames::Hdf5File;
137 ioda::Engines::BackendCreationParameters backendParams;
138 backendParams.fileName = *params.
inputFile.value();
139 backendParams.action = ioda::Engines::BackendFileActions::Open;
140 backendParams.openMode = ioda::Engines::BackendOpenModes::Read_Only;
144 ioda::Group backend = constructBackend(backendName, backendParams);
145 ioda::ObsGroup obsgroup = ioda::ObsGroup(backend,
146 ioda::detail::DataLayoutPolicy::generate(
147 ioda::detail::DataLayoutPolicy::Policies::None));
150 ioda::Variable bcerrvar = obsgroup.vars[
"bias_coeff_errors"];
151 Eigen::ArrayXXf allbcerrors;
152 bcerrvar.readWithEigenRegular(allbcerrors);
155 ioda::Variable nobsvar = obsgroup.vars[
"number_obs_assimilated"];
156 Eigen::ArrayXf nobsassim;
157 nobsvar.readWithEigenRegular(nobsassim);
167 for (
size_t jvar = 0; jvar < var_idx.size(); ++jvar) {
168 obs_num_[jvar] = nobsassim(var_idx[jvar]);
169 for (
size_t jpred = 0; jpred < pred_idx.size(); ++jpred) {
171 allbcerrors(pred_idx[jpred], var_idx[jvar]);
176 oops::Log::trace() <<
"ObsBiasCovariance::read is done " << std::endl;
182 oops::Log::trace() <<
"ObsBiasCovariance::write to file " << std::endl;
183 oops::Log::trace() <<
"ObsBiasCovariance::write is not implemented " << std::endl;
184 oops::Log::trace() <<
"ObsBiasCovariance::write is done " << std::endl;
190 oops::Log::trace() <<
"ObsBiasCovariance::linearize starts" << std::endl;
193 const int jouter = innerConf.getInt(
"iteration");
195 std::unique_ptr<ioda::Accumulator<std::vector<size_t>>> obs_num_accumulator =
196 odb_.distribution()->createAccumulator<
size_t>(
obs_num_.size());
199 const std::string qc_group_name =
"EffectiveQC" + std::to_string(jouter-1);
200 const std::vector<std::string> vars =
odb_.obsvariables().variables();
201 std::vector<int> qc_flags(
odb_.nlocs(), 999);
202 for (std::size_t jvar = 0; jvar < vars.size(); ++jvar) {
203 if (
odb_.has(qc_group_name, vars[jvar])) {
204 odb_.get_db(qc_group_name, vars[jvar], qc_flags);
205 for (std::size_t jloc = 0; jloc < qc_flags.size(); ++jloc)
206 if (qc_flags[jloc] == 0)
207 obs_num_accumulator->addTerm(jloc, jvar, 1);
209 throw eckit::UserError(
"Unable to find QC flags : " + vars[jvar] +
"@" + qc_group_name);
214 obs_num_ = obs_num_accumulator->computeResult();
220 const std::string err_group_name =
"EffectiveError" + std::to_string(jouter-1);
221 ioda::ObsVector r_inv(
odb_, err_group_name);
224 std::size_t nvars = r_inv.nvars();
225 for (
size_t vv = 0; vv < nvars; ++vv) {
226 for (
size_t ii = 0; ii < r_inv.nlocs(); ++ii) {
227 if (r_inv[ii*nvars + vv] !=
missing) {
228 r_inv[ii*nvars + vv] = 1.0f / pow(r_inv[ii*nvars + vv], 2);
230 r_inv[ii*nvars + vv] = 0.0f;
237 std::unique_ptr<ioda::Accumulator<std::vector<double>>> ht_rinv_h_accumulator =
238 odb_.distribution()->createAccumulator<
double>(
ht_rinv_h_.size());
239 for (std::size_t p = 0; p <
prednames_.size(); ++p) {
244 ASSERT(r_inv.nlocs() == predx.nlocs());
245 std::size_t nvars = predx.nvars();
247 for (
size_t vv = 0; vv < nvars; ++vv) {
248 for (
size_t ii = 0; ii < predx.nlocs(); ++ii)
249 ht_rinv_h_accumulator->addTerm(ii,
251 pow(predx[ii*nvars + vv], 2) * r_inv[ii*nvars + vv]);
256 ht_rinv_h_ = ht_rinv_h_accumulator->computeResult();
260 for (std::size_t j = 0; j <
obs_num_.size(); ++j) {
262 for (std::size_t p = 0; p <
prednames_.size(); ++p)
268 for (std::size_t j = 0; j <
vars_.size(); ++j) {
269 for (std::size_t p = 0; p <
prednames_.size(); ++p) {
270 const std::size_t index = j*
prednames_.size() + p;
285 oops::Log::trace() <<
"ObsBiasCovariance::linearize is done" << std::endl;
292 oops::Log::trace() <<
"ObsBiasCovariance::multiply starts" << std::endl;
296 oops::Log::trace() <<
"ObsBiasCovariance::multiply is done" << std::endl;
303 oops::Log::trace() <<
"ObsBiasCovariance::inverseMultiply starts" << std::endl;
307 oops::Log::trace() <<
"ObsBiasCovariance::inverseMultiply is done" << std::endl;
313 oops::Log::trace() <<
"ObsBiasCovariance::randomize starts" << std::endl;
315 static util::NormalDistribution<double> dist(
variances_.size());
316 for (std::size_t jj = 0; jj <
variances_.size(); ++jj) {
320 oops::Log::trace() <<
"ObsBiasCovariance::randomize is done" << std::endl;
std::vector< std::string > prednames_
void read(const ObsBiasCovariancePriorParameters &)
std::size_t minimal_required_obs_number_
Eigen::VectorXd variances_
std::vector< std::size_t > obs_num_
void write(const eckit::Configuration &)
std::vector< double > ht_rinv_h_
void inverseMultiply(const ObsBiasIncrement &, ObsBiasIncrement &) const
void randomize(ObsBiasIncrement &) const
ObsBiasCovariance(ioda::ObsSpace &odb, const Parameters_ ¶ms)
void multiply(const ObsBiasIncrement &, ObsBiasIncrement &) const
double smallest_variance_
std::vector< double > preconditioner_
double largest_analysis_variance_
oops::Variables vars_
variables for which bias correction coefficients will be updated
void linearize(const ObsBias &, const eckit::Configuration &)
std::vector< double > analysis_variances_
oops::RequiredParameter< size_t > minimalRequiredObsNumber
oops::OptionalParameter< ObsBiasCovariancePriorParameters > prior
oops::Parameter< std::vector< double > > varianceRange
oops::Parameter< double > largestAnalysisVariance
oops::Parameter< double > stepSize
oops::RequiredParameter< ObsBiasCovariancePriorInflationParameters > inflation
oops::OptionalParameter< std::string > inputFile
Contains increments to bias correction coefficients.
const Eigen::VectorXd & data() const
Return bias coefficient increments.
Parameters influencing the bias correction process.
oops::Parameter< StaticOrVariationalBCParameters > variationalBC
List of predictors with coefficients determined by variational analysis (VarBC).
oops::OptionalParameter< ObsBiasCovarianceParameters > covariance
Options controlling the covariance matrix.
static std::unique_ptr< PredictorBase > create(const PredictorParametersBase ¶meters, const oops::Variables &vars)
Create and return a new predictor.
Contains a polymorphic parameter holding an instance of a subclass of PredictorParametersBase.
std::vector< int > getRequiredVariableIndices(const ioda::ObsGroup &obsgroup, const std::string &varname, typename std::vector< std::string >::const_iterator elements_to_look_for_begin, typename std::vector< std::string >::const_iterator elements_to_look_for_end)
std::vector< int > getRequiredVarOrChannelIndices(const ioda::ObsGroup &obsgroup, const oops::Variables &vars_to_look_for)