Tatooine
netcdf.h
Go to the documentation of this file.
1#ifdef TATOOINE_NETCDF_AVAILABLE
2#ifndef TATOOINE_NETCDF_H
3#define TATOOINE_NETCDF_H
4//==============================================================================
6#include <tatooine/concepts.h>
7#include <tatooine/multidim.h>
9
10#include <cassert>
11#include <tatooine/filesystem.h>
12#include <memory>
13#include <mutex>
14#include <netcdf>
15#include <numeric>
16#include <vector>
17//==============================================================================
19//==============================================================================
20template <typename T>
21struct nc_type;
22// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23template <>
24struct nc_type<int> {
25 static auto value() { return netCDF::ncInt; }
26};
27// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28template <>
29struct nc_type<float> {
30 static auto value() { return netCDF::ncFloat; }
31};
32// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
33template <>
34struct nc_type<double> {
35 static auto value() { return netCDF::ncDouble; }
36};
37// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
38template <typename T, std::size_t M, std::size_t N>
39struct nc_type<mat<T, M, N>> {
40 static auto value() { return nc_type<T>::value(); }
41};
42// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
43template <typename T, std::size_t N>
44struct nc_type<vec<T, N>> {
45 static auto value() { return nc_type<T>::value(); }
46};
47// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
48template <typename T, std::size_t... Dims>
49struct nc_type<tensor<T, Dims...>> {
50 static auto value() { return nc_type<T>::value(); }
51};
52//==============================================================================
53class group {};
54//==============================================================================
55class attribute {};
56//==============================================================================
57template <typename T>
58class variable {
59 public:
61 using value_type = T;
62
63 private:
64 mutable std::shared_ptr<netCDF::NcFile> m_file;
65 mutable std::shared_ptr<std::mutex> m_mutex;
66 netCDF::NcVar m_var;
67 //============================================================================
68 public:
69 variable(std::shared_ptr<netCDF::NcFile>& file,
70 std::shared_ptr<std::mutex>& mutex, netCDF::NcVar const& var)
71 : m_file{file}, m_mutex{mutex}, m_var{var} {}
72 //----------------------------------------------------------------------------
73 variable(variable const&) = default;
74 variable(variable&&) noexcept = default;
75 //----------------------------------------------------------------------------
76 auto operator=(variable const&) -> variable& = default;
77 auto operator=(variable&&) noexcept -> variable& = default;
78 //============================================================================
79 auto write(std::vector<std::size_t> const& is, T const& t) {
80 std::lock_guard lock{*m_mutex};
81 // std::reverse(begin(is), end(is));
82 return m_var.putVar(is, t);
83 }
84 auto write(std::vector<std::size_t> const& is, std::vector<std::size_t> const& count,
85 T const* const arr) {
86 std::lock_guard lock{*m_mutex};
87 // std::reverse(begin(is), end(is));
88 // std::reverse(begin(count), end(count));
89 return m_var.putVar(is, count, arr);
90 }
91 auto write(T const* const arr) {
92 std::lock_guard lock{*m_mutex};
93 return m_var.putVar(arr);
94 }
95 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96 auto write(std::vector<T> const& arr) {
97 std::lock_guard lock{*m_mutex};
98 return m_var.putVar(arr.data());
99 }
100 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101 auto write(range auto const r) { return write(std::vector(begin(r), end(r))); }
102 //----------------------------------------------------------------------------
103 auto num_components() const {
104 std::size_t c = 1;
105 for (std::size_t i = 0; i < num_dimensions(); ++i) {
106 c *= size(i);
107 }
108 return c;
109 }
110 //----------------------------------------------------------------------------
111 auto read() const {
113 read(arr);
114 return arr;
115 }
116 //----------------------------------------------------------------------------
118 auto const n = num_dimensions();
119 bool must_resize = n != arr.num_dimensions();
120 if (!must_resize) {
121 for (std::size_t i = 0; i < n; ++i) {
122 if (arr.size(i) != size(i)) {
123 break;
124 }
125 }
126 }
127 if (must_resize) {
128 auto s = size();
129 //std::reverse(begin(s), end(s));
130 arr.resize(s);
131 }
132
133 std::lock_guard lock{*m_mutex};
134 m_var.getVar(arr.data());
135 }
136 //----------------------------------------------------------------------------
137 auto read_chunked(std::size_t const chunk_size = 10) const {
139 std::vector<std::size_t>(num_dimensions(), 0),
140 std::vector<std::size_t>(num_dimensions(), chunk_size)};
141 read(arr);
142 return arr;
143 }
144 //----------------------------------------------------------------------------
145 auto read_chunked(std::vector<std::size_t> const& chunk_size) const {
147 std::vector<std::size_t>(num_dimensions(), 0), chunk_size};
148 read(arr);
149 return arr;
150 }
151 //----------------------------------------------------------------------------
153 bool must_resize = arr.num_dimensions() != num_dimensions();
154 if (!must_resize) {
155 for (std::size_t i = 0; i < num_dimensions(); ++i) {
156 must_resize = size(i) != arr.size(num_dimensions() - i - 1);
157 if (must_resize) {
158 break;
159 }
160 }
161 }
162 if (must_resize) {
163 auto s = size();
164 //std::reverse(begin(s), end(s));
165 arr.resize(s);
166 }
167
168 for (auto const& chunk_indices : dynamic_multidim(arr.chunk_size())) {
169 auto start_indices = arr.global_indices_from_chunk_indices(chunk_indices);
170 auto const plain_chunk_index =
171 arr.plain_chunk_index_from_chunk_indices(chunk_indices);
172
173 if (arr.chunk_at_is_null(plain_chunk_index)) {
174 arr.create_chunk_at(plain_chunk_index);
175 }
176
177 //std::reverse(begin(start_indices), end(start_indices));
178 auto s = arr.internal_chunk_size();
179 //std::reverse(begin(s), end(s));
180 read_chunk(start_indices, s, *arr.chunk_at(plain_chunk_index));
181 if constexpr (std::is_arithmetic_v<T>) {
182 bool all_zero = true;
183 for (auto const& v : arr.chunk_at(plain_chunk_index)->internal_container()) {
184 if (v != 0) {
185 all_zero = false;
186 break;
187 }
188 }
189 if (all_zero) {
190 arr.destroy_chunk_at(plain_chunk_index);
191 }
192 }
193 }
194 }
195 //----------------------------------------------------------------------------
196 template <typename MemLoc, std::size_t... Resolution>
197 auto read(
199 assert(sizeof...(Resolution) == num_dimensions());
200 assert(std::vector{Resolution...} == size());
201 std::lock_guard lock{*m_mutex};
202 m_var.getVar(arr.data());
203 }
204 //----------------------------------------------------------------------------
205 auto read(std::vector<T>& arr) const {
206 if (auto const n = num_components(); arr.size() != n) {
207 arr.resize(n);
208 }
209 std::lock_guard lock{*m_mutex};
210 m_var.getVar(arr.data());
211 }
212 //----------------------------------------------------------------------------
213 auto read(T* const ptr) const {
214 std::lock_guard lock{*m_mutex};
215 m_var.getVar(ptr);
216 }
217 //----------------------------------------------------------------------------
218 auto read_as_vector() const {
219 std::vector<T> arr(num_components());
220 std::lock_guard lock{*m_mutex};
221 m_var.getVar(arr.data());
222 return arr;
223 }
224 //----------------------------------------------------------------------------
225 auto read_single(std::vector<std::size_t> const& start_indices) const {
226 assert(size(start_indices) == num_dimensions());
227 T t;
228 std::lock_guard lock{*m_mutex};
229 m_var.getVar(start_indices, std::vector<std::size_t>(num_dimensions(), 1), &t);
230 return t;
231 }
232 //----------------------------------------------------------------------------
233 auto read_single(integral auto const... is) const {
234 assert(num_dimensions() == sizeof...(is));
235 T t;
236 std::lock_guard lock{*m_mutex};
237 m_var.getVar({static_cast<std::size_t>(is)...}, {((void)is, std::size_t(1))...}, &t);
238 return t;
239 }
240 //----------------------------------------------------------------------------
241 auto read_chunk(std::vector<std::size_t> start_indices,
242 std::vector<std::size_t> counts) const {
243 assert(start_indices.size() == counts.size());
244 assert(start_indices.size() == num_dimensions());
245
246 auto arr = dynamic_multidim_array<T> {counts};
247 //std::reverse(begin(start_indices), end(start_indices));
248 //std::reverse(begin(counts), end(counts));
249 std::lock_guard lock{*m_mutex};
250 m_var.getVar(start_indices, counts, arr.data());
251 return arr;
252 }
253 //----------------------------------------------------------------------------
254 auto read_chunk(std::vector<std::size_t> start_indices, std::vector<std::size_t> counts,
255 T* ptr) const {
256 assert(start_indices.size() == counts.size());
257 assert(start_indices.size() == num_dimensions());
258
259 //std::reverse(begin(start_indices), end(start_indices));
260 //std::reverse(begin(counts), end(counts));
261 std::lock_guard lock{*m_mutex};
262 m_var.getVar(start_indices, counts, ptr);
263 }
264 //----------------------------------------------------------------------------
265 auto read_chunk(std::vector<std::size_t> const& start_indices,
266 std::vector<std::size_t> const& counts,
268 if (num_dimensions() != arr.num_dimensions()) {
269 arr.resize(counts);
270 } else {
271 for (std::size_t i = 0; i < num_dimensions(); ++i) {
272 if (arr.size(i) != size(i)) {
273 arr.resize(counts);
274 break;
275 }
276 }
277 }
278 std::lock_guard lock{*m_mutex};
279 m_var.getVar(start_indices, counts, arr.data());
280 }
281 //----------------------------------------------------------------------------
282 template <typename MemLoc, std::size_t... Resolution>
285 integral auto const... start_indices) const {
286 static_assert(sizeof...(start_indices) == sizeof...(Resolution));
287 assert(sizeof...(Resolution) == num_dimensions());
288 std::lock_guard lock{*m_mutex};
289 m_var.getVar(std::vector{static_cast<std::size_t>(start_indices)...},
290 std::vector{Resolution...}, arr.data());
291 }
292 //----------------------------------------------------------------------------
293 template <typename MemLoc, std::size_t... Resolution>
295 std::vector<std::size_t> const& start_indices,
297 std::lock_guard lock{*m_mutex};
298 m_var.getVar(start_indices, std::vector{Resolution...}, arr.data());
299 }
300 //----------------------------------------------------------------------------
301 auto read_chunk(std::vector<std::size_t> const& start_indices,
302 std::vector<std::size_t> const& counts,
303 std::vector<T>& arr) const {
304 auto const n = std::accumulate(begin(counts), end(counts), std::size_t(1),
305 std::multiplies<std::size_t>{});
306 if (size(arr) != n) {
307 arr.resize(n);
308 }
309 std::lock_guard lock{*m_mutex};
310 m_var.getVar(start_indices, counts, arr.data());
311 }
312 //----------------------------------------------------------------------------
313 auto is_null() const {
314 std::lock_guard lock{*m_mutex};
315 return m_var.isNull();
316 }
317 //----------------------------------------------------------------------------
318 auto num_dimensions() const {
319 std::lock_guard lock{*m_mutex};
320 return static_cast<std::size_t>(m_var.getDimCount());
321 }
322 //----------------------------------------------------------------------------
323 auto size(std::size_t i) const {
324 auto lock = std::lock_guard{*m_mutex};
325 return m_var.getDim(static_cast<int>(i)).getSize();
326 }
327 //----------------------------------------------------------------------------
328 auto dimension_name(std::size_t i) const {
329 std::lock_guard lock{*m_mutex};
330 return m_var.getDim(static_cast<int>(i)).getName();
331 }
332 //----------------------------------------------------------------------------
333 auto size() const {
334 std::vector<std::size_t> res;
335 res.reserve(num_dimensions());
336 for (std::size_t i = 0; i < num_dimensions(); ++i) {
337 res.push_back(size(i));
338 }
339 return res;
340 }
341 //----------------------------------------------------------------------------
342 auto name() const {
343 std::lock_guard lock{*m_mutex};
344 return m_var.getName();
345 }
346};
347//==============================================================================
348class size {};
349//==============================================================================
350class file {
351 mutable std::shared_ptr<netCDF::NcFile> m_file;
352 mutable std::shared_ptr<std::mutex> m_mutex;
353 //============================================================================
354 public:
355 template <typename... Ts>
356 file(filesystem::path const& path, Ts&&... ts)
357 : m_file{new netCDF::NcFile{path.string(), std::forward<Ts>(ts)...}},
358 m_mutex{std::make_shared<std::mutex>()} {}
359 //============================================================================
360 template <typename T>
361 auto add_variable(std::string const& variable_name,
362 netCDF::NcDim const& dim) {
363 return netcdf::variable<T>{
365 m_file->addVar(variable_name, nc_type<T>::value(), dim)};
366 }
367 //----------------------------------------------------------------------------
368 template <typename T>
369 auto add_variable(std::string const& variable_name,
370 std::vector<netCDF::NcDim> const& dims) {
371 return netcdf::variable<T>{
373 m_file->addVar(variable_name, nc_type<T>::value(), dims)};
374 }
375 //----------------------------------------------------------------------------
376 template <typename T>
377 auto variable(std::string const& variable_name) const {
378 return netcdf::variable<T>{m_file, m_mutex, m_file->getVar(variable_name)};
379 }
380 //----------------------------------------------------------------------------
381 auto add_dimension(std::string const& dimension_name) {
382 return m_file->addDim(dimension_name);
383 }
384 //----------------------------------------------------------------------------
385 auto add_dimension(std::string const& dimension_name, std::size_t const size) {
386 return m_file->addDim(dimension_name, size);
387 }
388 //----------------------------------------------------------------------------
389 auto dimensions() const { return m_file->getDims(); }
390 //----------------------------------------------------------------------------
391 auto attributes() const { return m_file->getAtts(); }
392 //----------------------------------------------------------------------------
393 auto num_dimensions() const -> std::size_t {
394 return static_cast<std::size_t>(m_file->getDimCount());
395 }
396 //----------------------------------------------------------------------------
397 auto size() const { return m_file->getDims(); }
398 //----------------------------------------------------------------------------
399 auto groups() const { return m_file->getGroups(); }
400 //----------------------------------------------------------------------------
401 template <typename T>
402 auto variables() const {
403 std::vector<netcdf::variable<T>> vars;
404 for (auto& [name, var] : m_file->getVars()) {
405 if (var.getType() == nc_type<T>::value()) {
406 vars.push_back(netcdf::variable<T>{m_file, m_mutex, std::move(var)});
407 }
408 }
409 return vars;
410 }
411};
412//==============================================================================
413} // namespace tatooine::netcdf
414//==============================================================================
415#endif
416#endif
T value
Definition: cache_alignment.h:22
Definition: dynamic_multidim_array.h:18
constexpr auto data(std::size_t const i) -> auto &
Definition: dynamic_multidim_array.h:311
auto size() const -> auto const &
Definition: dynamic_multidim_size.h:107
auto resize(integral auto const ... size) -> void
Definition: dynamic_multidim_array.h:273
auto num_dimensions() const
Definition: dynamic_multidim_size.h:105
Definition: netcdf.h:55
Definition: netcdf.h:350
auto add_dimension(std::string const &dimension_name, std::size_t const size)
Definition: netcdf.h:385
auto variables() const
Definition: netcdf.h:402
std::shared_ptr< std::mutex > m_mutex
Definition: netcdf.h:352
auto dimensions() const
Definition: netcdf.h:389
auto variable(std::string const &variable_name) const
Definition: netcdf.h:377
auto add_variable(std::string const &variable_name, std::vector< netCDF::NcDim > const &dims)
Definition: netcdf.h:369
auto add_variable(std::string const &variable_name, netCDF::NcDim const &dim)
Definition: netcdf.h:361
auto size() const
Definition: netcdf.h:397
auto add_dimension(std::string const &dimension_name)
Definition: netcdf.h:381
auto attributes() const
Definition: netcdf.h:391
file(filesystem::path const &path, Ts &&... ts)
Definition: netcdf.h:356
std::shared_ptr< netCDF::NcFile > m_file
Definition: netcdf.h:351
auto num_dimensions() const -> std::size_t
Definition: netcdf.h:393
auto groups() const
Definition: netcdf.h:399
Definition: netcdf.h:53
Definition: netcdf.h:348
Definition: netcdf.h:58
auto read(std::vector< T > &arr) const
Definition: netcdf.h:205
auto num_components() const
Definition: netcdf.h:103
auto read_as_vector() const
Definition: netcdf.h:218
auto write(std::vector< std::size_t > const &is, std::vector< std::size_t > const &count, T const *const arr)
Definition: netcdf.h:84
variable(std::shared_ptr< netCDF::NcFile > &file, std::shared_ptr< std::mutex > &mutex, netCDF::NcVar const &var)
Definition: netcdf.h:69
auto read(dynamic_multidim_array< T, x_fastest > &arr) const
Definition: netcdf.h:117
auto read_chunk(std::vector< std::size_t > start_indices, std::vector< std::size_t > counts) const
Definition: netcdf.h:241
auto read(static_multidim_array< T, x_fastest, MemLoc, Resolution... > &arr) const
Definition: netcdf.h:197
std::shared_ptr< std::mutex > m_mutex
Definition: netcdf.h:65
auto write(std::vector< T > const &arr)
Definition: netcdf.h:96
auto read_chunk(std::vector< std::size_t > const &start_indices, static_multidim_array< T, x_fastest, MemLoc, Resolution... > &arr) const
Definition: netcdf.h:294
auto name() const
Definition: netcdf.h:342
auto read_chunk(std::vector< std::size_t > const &start_indices, std::vector< std::size_t > const &counts, dynamic_multidim_array< T, x_fastest > &arr) const
Definition: netcdf.h:265
auto size(std::size_t i) const
Definition: netcdf.h:323
variable(variable const &)=default
std::shared_ptr< netCDF::NcFile > m_file
Definition: netcdf.h:64
auto read_chunked(std::size_t const chunk_size=10) const
Definition: netcdf.h:137
auto read() const
Definition: netcdf.h:111
auto read_chunk(std::vector< std::size_t > start_indices, std::vector< std::size_t > counts, T *ptr) const
Definition: netcdf.h:254
auto read_single(integral auto const ... is) const
Definition: netcdf.h:233
variable(variable &&) noexcept=default
auto num_dimensions() const
Definition: netcdf.h:318
auto write(std::vector< std::size_t > const &is, T const &t)
Definition: netcdf.h:79
auto read_chunked(std::vector< std::size_t > const &chunk_size) const
Definition: netcdf.h:145
auto read_chunk(std::vector< std::size_t > const &start_indices, std::vector< std::size_t > const &counts, std::vector< T > &arr) const
Definition: netcdf.h:301
auto write(range auto const r)
Definition: netcdf.h:101
auto read(chunked_multidim_array< T, x_fastest > &arr) const
Definition: netcdf.h:152
auto is_null() const
Definition: netcdf.h:313
auto write(T const *const arr)
Definition: netcdf.h:91
auto dimension_name(std::size_t i) const
Definition: netcdf.h:328
auto read(T *const ptr) const
Definition: netcdf.h:213
auto read_single(std::vector< std::size_t > const &start_indices) const
Definition: netcdf.h:225
auto read_chunk(static_multidim_array< T, x_fastest, MemLoc, Resolution... > &arr, integral auto const ... start_indices) const
Definition: netcdf.h:283
netCDF::NcVar m_var
Definition: netcdf.h:66
T value_type
Definition: netcdf.h:61
auto size() const
Definition: netcdf.h:333
Definition: static_multidim_array.h:19
constexpr auto data() -> ValueType *
Definition: static_multidim_array.h:260
Definition: concepts.h:21
Definition: concepts.h:84
Definition: netcdf.h:18
auto begin(Range &&range)
Definition: iterator_facade.h:318
auto end(Range &&range)
Definition: iterator_facade.h:322
static constexpr forward_tag forward
Definition: tags.h:9
Definition: chunked_multidim_array.h:27
auto global_indices_from_chunk_indices(std::vector< Int > is) const
Definition: chunked_multidim_array.h:220
auto internal_chunk_size() const
Definition: chunked_multidim_array.h:335
auto plain_chunk_index_from_chunk_indices(integral auto const ... chunk_indices) const
Definition: chunked_multidim_array.h:228
auto chunk_at(integral auto const chunk_index0, integral auto const ... chunk_indices) const -> auto const &
Definition: chunked_multidim_array.h:241
auto chunk_size() const
Definition: chunked_multidim_array.h:332
auto create_chunk_at(std::size_t const plain_chunk_index, std::vector< std::size_t > const &multi_indices) const -> auto const &
Definition: chunked_multidim_array.h:269
auto chunk_at_is_null(integral auto const chunk_index0, integral auto const ... chunk_indices) const
Definition: chunked_multidim_array.h:252
auto size() const -> auto const &
Definition: dynamic_multidim_size.h:107
auto num_dimensions() const
Definition: dynamic_multidim_size.h:105
auto destroy_chunk_at(integral auto const chunk_index0, integral auto const ... chunk_indices) const
Definition: chunked_multidim_array.h:303
auto resize(SizeRange &&size) -> void requires(is_integral< typename std::decay_t< SizeRange >::value_type >)
Definition: chunked_multidim_array.h:87
Definition: multidim.h:11
Definition: mat.h:14
static auto value()
Definition: netcdf.h:35
static auto value()
Definition: netcdf.h:30
static auto value()
Definition: netcdf.h:25
static auto value()
Definition: netcdf.h:40
static auto value()
Definition: netcdf.h:50
static auto value()
Definition: netcdf.h:45
Definition: netcdf.h:21
Definition: tensor.h:17
Definition: vec.h:12