13
13
#include " mir/method/ProxyWeightedMethod.h"
14
14
15
15
#include < ostream>
16
+ #include < vector>
16
17
17
18
#include " eckit/log/JSON.h"
18
19
#include " eckit/utils/MD5.h"
19
20
20
21
#include " mir/param/MIRParametrisation.h"
21
22
#include " mir/repres/Representation.h"
22
23
#include " mir/util/Exceptions.h"
24
+ #include " mir/util/Log.h"
25
+ #include " mir/util/allocator/InPlaceAllocator.h"
23
26
24
27
25
28
namespace mir ::method {
26
29
27
30
31
+ namespace {
32
+
33
+
28
34
struct StructuredBicubic final : public ProxyWeightedMethod {
29
35
explicit StructuredBicubic (const param::MIRParametrisation& param) :
30
- ProxyWeightedMethod(param, " structured-bicubic" ) {}
36
+ ProxyWeightedMethod(param, " structured-bicubic" , " serial-halo to serial " ) {}
31
37
};
32
38
33
39
40
+ } // namespace
41
+
42
+
34
43
static const MethodFactory* METHODS[]{
35
44
new MethodBuilder<StructuredBicubic>(" structured-bicubic" ),
36
45
};
37
46
38
47
39
- ProxyWeightedMethod::ProxyWeightedMethod (const param::MIRParametrisation& param, const std::string& type) :
40
- MethodWeighted (param), type_(type) {
41
- options_ = {" type" , type};
42
- options_.set (" matrix_free" , false );
48
+ ProxyWeightedMethod::ProxyWeightedMethod (const param::MIRParametrisation& param, const std::string& interpolation_type,
49
+ const std::string& renumber_type) :
50
+ MethodWeighted (param), type_(interpolation_type) {
51
+ interpol_.set (" matrix_free" , false );
52
+ interpol_.set (" type" , interpolation_type);
53
+ renumber_.set (" type" , renumber_type);
43
54
}
44
55
45
56
@@ -55,70 +66,72 @@ int ProxyWeightedMethod::version() const {
55
66
56
67
void ProxyWeightedMethod::hash (eckit::MD5& h) const {
57
68
MethodWeighted::hash (h);
58
- h.add (options_ );
69
+ h.add (interpol_ );
59
70
}
60
71
61
72
62
73
bool ProxyWeightedMethod::sameAs (const Method& other) const {
63
- auto digest = [](const auto & options ) {
74
+ auto digest = [](const auto & config ) {
64
75
eckit::MD5 h;
65
- h. add (options );
76
+ config. hash (h );
66
77
return h.digest ();
67
78
};
68
79
69
80
const auto * o = dynamic_cast <const ProxyWeightedMethod*>(&other);
70
- return (o != nullptr ) && name () == std::string{o->name ()} && digest (options_ ) == digest (o->options_ ) &&
71
- MethodWeighted::sameAs (*o);
81
+ return (o != nullptr ) && name () == std::string{o->name ()} && digest (interpol_ ) == digest (o->interpol_ ) &&
82
+ digest (renumber_) == digest (o-> renumber_ ) && MethodWeighted::sameAs (*o);
72
83
}
73
84
74
85
75
86
void ProxyWeightedMethod::print (std::ostream& out) const {
76
- out << " ProxyWeightedMethod[options =" << options_ << " ," ;
87
+ out << " ProxyWeightedMethod[interpolation =" << interpol_ << " ,renumber= " << renumber_ << " ," ;
77
88
MethodWeighted::print (out);
78
89
out << " ]" ;
79
90
}
80
91
81
92
82
93
void ProxyWeightedMethod::json (eckit::JSON& j) const {
83
94
j.startObject ();
84
- j << " options" << options_ .json (eckit::JSON::Formatting::compact ());
95
+ j << " options" << interpol_ .json (eckit::JSON::Formatting::compact ());
85
96
MethodWeighted::json (j);
86
97
j.endObject ();
87
98
}
88
99
89
100
90
101
void ProxyWeightedMethod::assemble (util::MIRStatistics&, WeightMatrix& W, const repres::Representation& in,
91
102
const repres::Representation& out) const {
92
- atlas::Interpolation interpol (options_, in.atlasGrid (), out.atlasGrid ());
93
-
94
- auto cache = interpol.createCache ();
95
- ASSERT (cache);
96
-
97
- const auto * entry = dynamic_cast <const atlas::interpolation::MatrixCacheEntry*>(cache.get (" Matrix" ));
98
- ASSERT (entry != nullptr );
99
-
100
- W.swap (const_cast <eckit::linalg::SparseMatrix&>(entry->matrix ()));
101
-
102
- auto & fs = interpol.source ();
103
- const auto gi{atlas::array::make_view<atlas::gidx_t , 1 >(fs.global_index ())};
104
-
105
- atlas::gidx_t min = std::numeric_limits<atlas::gidx_t >::max ();
106
- atlas::gidx_t max = std::numeric_limits<atlas::gidx_t >::min ();
107
- for (size_t i = 0 ; i < gi.size (); ++i) {
108
- min = std::min (min, gi (i));
109
- max = std::max (max, gi (i));
103
+ // interpolation matrix build and assign (with a halo on the source grid)
104
+ atlas::Interpolation interpol{interpol_, in.atlasGrid (), out.atlasGrid ()};
105
+ {
106
+ atlas::interpolation::MatrixCache cache{interpol};
107
+ const auto & M = cache.matrix ();
108
+ W.swap (const_cast <eckit::linalg::SparseMatrix&>(M));
110
109
}
111
110
112
- std::cout << " min: " << min << std::endl;
113
- std::cout << " max: " << max << std::endl;
114
-
111
+ // fold serial+halo into serial
112
+ const auto Nr = out.numberOfPoints ();
113
+ const auto Nc = in.numberOfPoints ();
114
+ ASSERT (Nr == W.rows ());
115
+ ASSERT (Nc < W.cols ());
116
+
117
+ {
118
+ const auto & fs = interpol.source ();
119
+ const auto gidx{atlas::array::make_view<atlas::gidx_t , 1 >(fs.global_index ())};
120
+
121
+ auto * a = const_cast <eckit::linalg::Scalar*>(W.data ());
122
+ for (auto c = Nc; c < W.cols (); ++c) {
123
+ ASSERT (1 <= gidx[c] && gidx[c] < Nc + 1 ); // (global indexing is 1-based)
124
+ a[gidx[c] - 1 ] += a[c];
125
+ a[c] = 0 .;
126
+ }
127
+ W.prune ();
128
+ }
115
129
116
- auto Nr = W.rows ();
117
- auto Nc = W.cols ();
118
- auto Nin = in.numberOfPoints ();
119
- auto Nout = out.numberOfPoints ();
120
- ASSERT (Nr == Nout);
121
- ASSERT (Nc == Nin);
130
+ // reshape matrix
131
+ WeightMatrix M (new util::allocator::InPlaceAllocator{
132
+ Nr, Nc, W.nonZeros (), const_cast <eckit::linalg::Index*>(W.outer ()),
133
+ const_cast <eckit::linalg::Index*>(W.inner ()), const_cast <eckit::linalg::Scalar*>(W.data ())});
134
+ W.swap (M);
122
135
}
123
136
124
137
0 commit comments