14
14
15
15
#include " eckit/log/JSON.h"
16
16
#include " eckit/utils/MD5.h"
17
- #include " eckit/utils/StringTools.h"
18
17
19
- #include " mir/action/context/Context.h"
20
- #include " mir/caching/InMemoryCacheUsage.h"
21
- #include " mir/caching/matrix/MatrixLoader.h"
22
- #include " mir/config/LibMir.h"
23
- #include " mir/data/MIRField.h"
24
- #include " mir/data/Space.h"
25
- #include " mir/method/MethodWeighted.h"
26
- #include " mir/method/nonlinear/NonLinear.h"
27
- #include " mir/method/solver/Multiply.h"
28
- #include " mir/method/solver/Statistics.h"
29
18
#include " mir/param/MIRParametrisation.h"
30
- #include " mir/repres/Representation.h"
31
- #include " mir/stats/Field.h"
32
19
#include " mir/util/Exceptions.h"
33
- #include " mir/util/Log.h"
34
- #include " mir/util/MIRStatistics.h"
35
- #include " mir/util/Trace.h"
36
20
37
21
38
22
namespace mir ::method {
@@ -41,225 +25,64 @@ namespace mir::method {
41
25
static const MethodBuilder<Matrix> __builder (" matrix" );
42
26
43
27
44
- Matrix::Matrix (const param::MIRParametrisation& param) : Method (param) {
28
+ Matrix::Matrix (const param::MIRParametrisation& param) : MethodWeighted (param) {
45
29
std::string matrix;
46
30
if (!parametrisation_.get (" interpolation-matrix" , matrix)) {
47
31
throw exception::UserError (" Matrix: option interpolation-matrix missing" );
48
32
}
49
33
50
34
matrix_ = matrix;
51
35
if (!matrix_.exists ()) {
52
- throw exception::UserError (" Matrix: matrix path does not exist '" + matrix + " '" );
36
+ throw exception::UserError (" Matrix: path does not exist '" + matrix + " '" );
53
37
}
54
38
55
- std::string nonLinear = " missing-if-heaviest-missing" ;
56
- parametrisation_.get (" non-linear" , nonLinear);
57
- for (auto & n : eckit::StringTools::split (" /" , nonLinear)) {
58
- nonLinear_.emplace_back (nonlinear::NonLinearFactory::build (n, parametrisation_));
59
- ASSERT (nonLinear_.back ());
60
- }
61
-
62
- if (std::string stats = " maximum" ; parametrisation_.get (" interpolation-statistics" , stats)) {
63
- solver_ =
64
- std::make_unique<solver::Statistics>(parametrisation_, stats::FieldFactory::build (stats, parametrisation_));
65
- }
66
- else {
67
- solver_ = std::make_unique<solver::Multiply>(parametrisation_);
68
- }
69
- ASSERT (solver_);
70
-
71
- matrix_loader_ = LibMir::cacheLoader (LibMir::cache_loader::MATRIX);
72
- parametrisation_.get (" matrix-loader" , matrix_loader_);
73
-
74
- parametrisation_.get (" vector-space" , vector_space_);
39
+ matrix_path_ = matrix_.realName ().asString ();
75
40
}
76
41
77
42
78
43
void Matrix::json (eckit::JSON& j) const {
79
44
j.startObject ();
80
-
81
- j << " type" << " matrix" ;
82
- j << " matrix" << matrix_;
83
- j << " solver" << *solver_;
84
- j << " nonLinear" ;
85
- j.startList ();
86
- for (const auto & n : nonLinear_) {
87
- j << *n;
88
- }
89
- j.endList ();
90
-
45
+ j << " interpolation-matrix=" << matrix_;
46
+ MethodWeighted::json (j);
91
47
j.endObject ();
92
48
}
93
49
94
50
95
- void Matrix::execute (context::Context& ctx, const repres::Representation& in, const repres::Representation& out) const {
96
- trace::Timer timer (" Matrix::execute" );
97
-
98
- auto & log = Log::debug ();
99
- log << " Matrix::execute (input: " << in << " , output: " << out << " , matrix: " << matrix_ << " )" << std::endl;
100
-
101
- if (!matrix_.exists ()) {
102
- throw exception::UserError (" Matrix: file not found: '" + matrix_.realName () + " '" );
103
- }
104
-
105
-
106
- // get matrix from in-memory cache, or insert an empty entry
107
- auto & cache = MethodWeighted::matrix_cache ();
108
-
109
- auto key = matrix_.realName ().asString ();
110
- auto & W = cache[key];
111
-
112
- if (W.empty ()) {
113
- log << " Load matrix from file " << matrix_loader_ << std::endl;
114
- WeightMatrix M (caching::matrix::MatrixLoaderFactory::build (matrix_loader_, matrix_));
115
- W.swap (M);
116
-
117
- // update memory footprint
118
- auto shared = W.inSharedMemory ();
119
- caching::InMemoryCacheUsage usage (shared ? 0 : W.footprint (), shared ? W.footprint () : 0 );
120
- cache.footprint (key, usage);
121
-
122
- log << " Matrix footprint " << W.owner () << " " << usage << " W -> " << W.owner () << std::endl;
123
- }
124
- else {
125
- log << " Using matrix from InMemoryCache" << std::endl;
126
- }
127
-
128
- log << " Matrix: " << W << std::endl;
129
- ASSERT_NONEMPTY_INTERPOLATION (" Matrix" , !W.empty ());
130
-
131
-
132
- // ensure unique missingValue on no input missing values
133
- auto & field = ctx.field ();
134
- const bool hasMissing = field.hasMissing ();
135
- if (!hasMissing) {
136
- field.missingValue (std::numeric_limits<double >::lowest ());
137
- }
138
-
139
- const double missingValue = field.missingValue ();
140
-
141
-
142
- // check if matrix copy is required: run-time modifiable matrix is not cacheable
143
- const bool matrixCopy = std::any_of (nonLinear_.begin (), nonLinear_.end (),
144
- [&field](const std::unique_ptr<const nonlinear::NonLinear>& n) {
145
- return n->modifiesMatrix (field.hasMissing ());
146
- });
147
-
148
-
149
- // check if forcing of missing values is required
150
- std::vector<size_t > forceMissing; // reserving size unnecessary (not the general case)
151
- {
152
- auto begin = W.begin (0 );
153
- auto end (begin);
154
- for (size_t r = 0 ; r < W.rows (); r++) {
155
- if (begin == (end = W.end (r))) {
156
- forceMissing.push_back (r);
157
- }
158
- begin = end;
159
- }
160
- }
161
-
162
-
163
- // solve
164
-
165
- auto npts_inp = in.numberOfPoints ();
166
- auto npts_out = out.numberOfPoints ();
167
-
168
- const auto & sp = data::SpaceChooser::lookup (vector_space_);
169
-
170
- for (size_t i = 0 ; i < field.dimensions (); i++) {
171
- MIRValuesVector result (npts_out); // field.update() takes ownership with std::swap()
172
-
173
- WeightMatrix::Matrix A;
174
- WeightMatrix::Matrix B;
175
- MethodWeighted::set_operand_matrices_from_vectors (B, A, result, field.values (i), missingValue, sp);
176
- ASSERT (A.rows () == npts_inp);
177
- ASSERT (B.rows () == npts_out);
178
-
179
-
180
- // modify matrix (as a copy) if there are non-linear treatments
181
- if (matrixCopy) {
182
- auto timing (ctx.statistics ().matrixTimer ());
183
- WeightMatrix M (W); // modifiable matrix copy
184
-
185
- for (const auto & n : nonLinear_) {
186
- n->treatment (A, M, B, field.values (i), missingValue);
187
- }
188
-
189
- solver_->solve (A, M, B, missingValue);
190
- }
191
- else {
192
- auto timing (ctx.statistics ().matrixTimer ());
193
- solver_->solve (A, W, B, missingValue);
194
- }
51
+ const char * Matrix::name () const {
52
+ return " matrix" ;
53
+ }
195
54
196
55
197
- // update field values with interpolation result
198
- MethodWeighted::set_vector_from_operand_matrix (B, result, missingValue, sp);
56
+ MethodWeighted::CacheKeys Matrix::getDiskAndMemoryCacheKeys (const repres::Representation& in,
57
+ const repres::Representation& out,
58
+ const lsm::LandSeaMasks&) const {
59
+ return {matrix_path_, matrix_path_};
60
+ }
199
61
200
- for (auto & r : forceMissing) {
201
- result[r] = missingValue;
202
- }
203
62
204
- field.update (result, i, hasMissing || !forceMissing.empty ());
205
- }
63
+ void Matrix::assemble (util::MIRStatistics&, WeightMatrix&, const repres::Representation& in,
64
+ const repres::Representation& out) const {
65
+ NOTIMP;
206
66
}
207
67
208
68
209
69
void Matrix::hash (eckit::MD5& h) const {
210
- h << matrix_.asString ();
211
-
212
- for (const auto & n : nonLinear_) {
213
- n->hash (h);
214
- }
215
-
216
- solver_->hash (h);
217
-
218
- if (auto v = version (); v != 0 ) {
219
- h.add (v);
220
- }
70
+ h << matrix_path_;
71
+ MethodWeighted::hash (h);
221
72
}
222
73
223
74
224
75
bool Matrix::sameAs (const Method& other) const {
225
- auto sameNonLinearities = [](const auto & a, const auto & b) {
226
- if (a.size () != b.size ()) {
227
- return false ;
228
- }
229
- for (size_t i = 0 ; i < a.size (); ++i) {
230
- if (!a[i]->sameAs (*b[i])) {
231
- return false ;
232
- }
233
- }
234
- return true ;
235
- };
236
-
237
76
const auto * o = dynamic_cast <const Matrix*>(&other);
238
- return (o != nullptr ) && matrix_.sameAs (o->matrix_ ) && sameNonLinearities (nonLinear_, o->nonLinear_ ) &&
239
- solver_->sameAs (*o->solver_ );
77
+ return (o != nullptr ) && matrix_path_ == o->matrix_path_ && MethodWeighted::sameAs (other);
240
78
}
241
79
242
80
243
81
void Matrix::print (std::ostream& out) const {
244
82
out << " Matrix["
245
- << " InterpolationMatrix=" << matrix_ << " ,Solver=" << (*solver_) << " ,nonLinear[" ;
246
- const auto * sep = " " ;
247
- for (const auto & n : nonLinear_) {
248
- out << sep << (*n);
249
- sep = " ," ;
250
- }
251
- out << " ]"
252
- << " ]" ;
253
- }
254
-
255
-
256
- void Matrix::setCropping (const util::BoundingBox&) {
257
- NOTIMP;
258
- }
259
-
260
-
261
- const util::BoundingBox& Matrix::getCropping () const {
262
- NOTIMP;
83
+ << " InterpolationMatrix=" << matrix_ << " ," ;
84
+ MethodWeighted::print (out);
85
+ out << " ]" ;
263
86
}
264
87
265
88
0 commit comments