12 #include "ioda/Engines/Factory.h"
13 #include "ioda/Engines/HH.h"
14 #include "ioda/Layout.h"
15 #include "ioda/ObsGroup.h"
22 ioda::ObsSpace & obspace,
23 const eckit::mpi::Comm &timeComm)
24 : ObsErrorBase(timeComm),
25 stddev_(obspace,
"ObsError"),
26 varcorrelations_(Eigen::MatrixXd::Identity(stddev_.nvars(), stddev_.nvars()))
29 ioda::Engines::BackendNames backendName = ioda::Engines::BackendNames::Hdf5File;
30 ioda::Engines::BackendCreationParameters backendParams;
31 backendParams.fileName = options.
inputFile;
32 backendParams.action = ioda::Engines::BackendFileActions::Open;
33 backendParams.openMode = ioda::Engines::BackendOpenModes::Read_Only;
35 ioda::Group backend = constructBackend(backendName, backendParams);
36 ioda::ObsGroup obsgroup = ioda::ObsGroup(backend,
37 ioda::detail::DataLayoutPolicy::generate(
38 ioda::detail::DataLayoutPolicy::Policies::None));
40 ioda::Variable corrvar = obsgroup.vars[
"obserror_correlations"];
43 const size_t nvars =
stddev_.nvars();
45 std::string errormsg = std::string(
"Correlation matrix for R, specified in ") +
46 options.
inputFile.value() + std::string(
" should be size ") +
47 std::to_string(nvars) + std::string(
" by ") + std::to_string(nvars);
48 throw eckit::UserError(errormsg, Here());
69 const size_t nlocs = dy.nlocs();
70 const size_t nvars = dy.nvars();
71 const double missing = util::missingValue(
double());
73 std::vector<int> usedobs_indices(nvars);
74 Eigen::VectorXd dy_at_loc(nvars);
75 Eigen::MatrixXd corr = Eigen::MatrixXd::Identity(nvars, nvars);
78 for (
size_t jloc = 0; jloc <
nlocs; ++jloc) {
82 for (
size_t jvar = 0; jvar < nvars; ++jvar) {
83 if (dy[jloc*nvars + jvar] !=
missing) usedobs_indices[nused++] = jvar;
85 for (
size_t jvar = 0; jvar < nused; ++jvar) {
86 int ind = usedobs_indices[jvar];
87 dy_at_loc(jvar) = dy[jloc*nvars + ind];
88 for (
size_t jvar2 = jvar+1; jvar2 < nused; ++jvar2) {
89 int ind2 = usedobs_indices[jvar2];
95 dy_at_loc.head(nused) = corr.block(0, 0, nused, nused) * dy_at_loc.head(nused);
97 for (
size_t jvar = 0; jvar < nused; ++jvar) {
98 dy[jloc*nvars + usedobs_indices[jvar]] = dy_at_loc[jvar];
117 const size_t nlocs = dy.nlocs();
118 const size_t nvars = dy.nvars();
119 const double missing = util::missingValue(
double());
121 std::vector<int> usedobs_indices(nvars);
122 Eigen::VectorXd dy_at_loc(nvars);
123 Eigen::MatrixXd corr = Eigen::MatrixXd::Identity(nvars, nvars);
125 for (
size_t jloc = 0; jloc <
nlocs; ++jloc) {
129 for (
size_t jvar = 0; jvar < nvars; ++jvar) {
130 if (dy[jloc*nvars + jvar] !=
missing) usedobs_indices[nused++] = jvar;
132 for (
size_t jvar = 0; jvar < nused; ++jvar) {
133 int ind = usedobs_indices[jvar];
134 dy_at_loc(jvar) = dy[jloc*nvars + ind];
135 for (
size_t jvar2 = jvar+1; jvar2 < nused; ++jvar2) {
136 int ind2 = usedobs_indices[jvar2];
143 corr.topLeftCorner(nused, nused).llt().solveInPlace(dy_at_loc.head(nused));
145 for (
size_t jvar = 0; jvar < nused; ++jvar) {
146 dy[jloc*nvars + usedobs_indices[jvar]] = dy_at_loc[jvar];
170 return std::make_unique<ioda::ObsVector>(
stddev_);
176 std::unique_ptr<ioda::ObsVector> inverseVariance = std::make_unique<ioda::ObsVector>(
stddev_);
178 inverseVariance->invert();
179 return inverseVariance;
184 os <<
"Observation error covariance with cross-variable correlations." << std::endl;
185 os <<
" Obs error stddev: " <<
stddev_ << std::endl;
ObsErrorCrossVarCov(const Parameters_ &, ioda::ObsSpace &, const eckit::mpi::Comm &timeComm)
Initialize observation errors.
void randomize(ioda::ObsVector &y) const override
Generate y as a random perturbation.
void multiply(ioda::ObsVector &y) const override
std::unique_ptr< ioda::ObsVector > getObsErrors() const override
Return obs errors std deviation.
Eigen::MatrixXd varcorrelations_
Correlations between variables.
void save(const std::string &name) const override
Save obs error standard deviations under name group name.
void update(const ioda::ObsVector &stddev) override
Update obs error standard deviations to be equal to stddev.
ioda::ObsVector stddev_
Observation error standard deviations.
void inverseMultiply(ioda::ObsVector &y) const override
void print(std::ostream &) const override
Print covariance details (for logging)
std::unique_ptr< ioda::ObsVector > getInverseVariance() const override
Return inverse of obs error variance.
Parameters for obs errors with cross-variable correlations.
oops::RequiredParameter< std::string > inputFile
Input file containing correlations.
integer function nlocs(this)
Return the number of observational locations in this Locations object.