Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #pragma once
11 :
12 : // MOOSE includes
13 : #include "ADReal.h"
14 : #include "MooseTypes.h"
15 : #include "HashMap.h"
16 : #include "MooseError.h"
17 : #include "RankTwoTensor.h"
18 : #include "RankThreeTensor.h"
19 : #include "RankFourTensor.h"
20 : #include "ColumnMajorMatrix.h"
21 : #include "UniqueStorage.h"
22 : #include "TwoVector.h"
23 :
24 : #include "libmesh/parallel.h"
25 : #include "libmesh/parameters.h"
26 : #include "libmesh/numeric_vector.h"
27 :
28 : #ifdef LIBMESH_HAVE_CXX11_TYPE_TRAITS
29 : #include <type_traits>
30 : #endif
31 :
32 : // C++ includes
33 : #include <string>
34 : #include <vector>
35 : #include <list>
36 : #include <iostream>
37 : #include <map>
38 : #include <unordered_map>
39 : #include <unordered_set>
40 : #include <memory>
41 : #include <optional>
42 :
43 : namespace libMesh
44 : {
45 : template <typename T>
46 : class DenseMatrix;
47 : template <typename T>
48 : class DenseVector;
49 : template <typename T>
50 : class VectorValue;
51 : template <typename T>
52 : class TensorValue;
53 : class Elem;
54 : class FEType;
55 : class Point;
56 : }
57 :
58 : /**
59 : * Scalar helper routine
60 : */
61 : template <typename P>
62 : inline void storeHelper(std::ostream & stream, P & data, void * context);
63 :
64 : /**
65 : * Vector helper routine
66 : */
67 : template <typename P>
68 : inline void storeHelper(std::ostream & stream, std::vector<P> & data, void * context);
69 :
70 : /**
71 : * Shared pointer helper routine
72 : */
73 : template <typename P>
74 : inline void storeHelper(std::ostream & stream, std::shared_ptr<P> & data, void * context);
75 :
76 : /**
77 : * Unique pointer helper routine
78 : */
79 : template <typename P>
80 : inline void storeHelper(std::ostream & stream, std::unique_ptr<P> & data, void * context);
81 :
82 : /**
83 : * Set helper routine
84 : */
85 : template <typename P>
86 : inline void storeHelper(std::ostream & stream, std::set<P> & data, void * context);
87 :
88 : /**
89 : * Map helper routine
90 : */
91 : template <typename P, typename Q>
92 : inline void storeHelper(std::ostream & stream, std::map<P, Q> & data, void * context);
93 :
94 : /**
95 : * Unordered_map helper routine
96 : */
97 : template <typename P, typename Q>
98 : inline void storeHelper(std::ostream & stream, std::unordered_map<P, Q> & data, void * context);
99 :
100 : /**
101 : * Optional helper routine
102 : */
103 : template <typename P>
104 : inline void storeHelper(std::ostream & stream, std::optional<P> & data, void * context);
105 :
106 : /**
107 : * HashMap helper routine
108 : */
109 : template <typename P, typename Q>
110 : inline void storeHelper(std::ostream & stream, HashMap<P, Q> & data, void * context);
111 :
112 : /**
113 : * UniqueStorage helper routine
114 : */
115 : template <typename T>
116 : inline void storeHelper(std::ostream & stream, UniqueStorage<T> & data, void * context);
117 :
118 : /**
119 : * Scalar helper routine
120 : */
121 : template <typename P>
122 : inline void loadHelper(std::istream & stream, P & data, void * context);
123 :
124 : /**
125 : * Vector helper routine
126 : */
127 : template <typename P>
128 : inline void loadHelper(std::istream & stream, std::vector<P> & data, void * context);
129 :
130 : /**
131 : * Shared Pointer helper routine
132 : */
133 : template <typename P>
134 : inline void loadHelper(std::istream & stream, std::shared_ptr<P> & data, void * context);
135 :
136 : /**
137 : * Unique Pointer helper routine
138 : */
139 : template <typename P>
140 : inline void loadHelper(std::istream & stream, std::unique_ptr<P> & data, void * context);
141 :
142 : /**
143 : * Set helper routine
144 : */
145 : template <typename P>
146 : inline void loadHelper(std::istream & stream, std::set<P> & data, void * context);
147 :
148 : /**
149 : * Map helper routine
150 : */
151 : template <typename P, typename Q>
152 : inline void loadHelper(std::istream & stream, std::map<P, Q> & data, void * context);
153 :
154 : /**
155 : * Unordered_map helper routine
156 : */
157 : template <typename P, typename Q>
158 : inline void loadHelper(std::istream & stream, std::unordered_map<P, Q> & data, void * context);
159 :
160 : /**
161 : * Optional helper routine
162 : */
163 : template <typename P>
164 : inline void loadHelper(std::istream & stream, std::optional<P> & data, void * context);
165 :
166 : /**
167 : * Hashmap helper routine
168 : */
169 : template <typename P, typename Q>
170 : inline void loadHelper(std::istream & stream, HashMap<P, Q> & data, void * context);
171 :
172 : /**
173 : * UniqueStorage helper routine
174 : */
175 : template <typename T>
176 : inline void loadHelper(std::istream & stream, UniqueStorage<T> & data, void * context);
177 :
178 : template <typename T>
179 : inline void dataStore(std::ostream & stream, T & v, void * /*context*/);
180 :
181 : // DO NOT MODIFY THE NEXT LINE - It is used by MOOSEDocs
182 : // *************** Global Store Declarations *****************
183 : template <typename T>
184 : inline void
185 62254702 : dataStore(std::ostream & stream, T & v, void * /*context*/)
186 : {
187 : #ifdef LIBMESH_HAVE_CXX11_TYPE_TRAITS
188 : static_assert(std::is_polymorphic<T>::value == false,
189 : "Cannot serialize a class that has virtual "
190 : "members!\nWrite a custom dataStore() "
191 : "template specialization!\n\n");
192 : static_assert(std::is_trivially_copyable<T>::value,
193 : "Cannot serialize a class that is not trivially copyable!\nWrite a custom "
194 : "dataStore() template specialization!\n\n");
195 : #endif
196 :
197 62254702 : stream.write((char *)&v, sizeof(v));
198 : mooseAssert(!stream.bad(), "Failed to store");
199 62254702 : }
200 :
201 : template <typename T>
202 : inline void
203 3 : dataStore(std::ostream & /*stream*/, T *& /*v*/, void * /*context*/)
204 : {
205 3 : mooseError("Attempting to store a raw pointer type: \"",
206 : libMesh::demangle(typeid(T).name()),
207 : " *\" as restartable data!\nWrite a custom dataStore() template specialization!\n\n");
208 : }
209 :
210 : void dataStore(std::ostream & stream, Point & p, void * context);
211 :
212 : template <typename T, typename U>
213 : inline void
214 1137379 : dataStore(std::ostream & stream, std::pair<T, U> & p, void * context)
215 : {
216 1137379 : storeHelper(stream, p.first, context);
217 1137379 : storeHelper(stream, p.second, context);
218 1137379 : }
219 :
220 : template <typename T>
221 : inline void
222 1497398 : dataStore(std::ostream & stream, std::vector<T> & v, void * context)
223 : {
224 : // First store the size of the vector
225 1497398 : unsigned int size = v.size();
226 1497398 : dataStore(stream, size, nullptr);
227 :
228 13426915 : for (unsigned int i = 0; i < size; i++)
229 11929517 : storeHelper(stream, v[i], context);
230 1497398 : }
231 :
232 : template <typename T>
233 : inline void
234 : dataStore(std::ostream & stream, std::shared_ptr<T> & v, void * context)
235 : {
236 : T * tmp = v.get();
237 :
238 : storeHelper(stream, tmp, context);
239 : }
240 :
241 : template <typename T>
242 : inline void
243 : dataStore(std::ostream & stream, std::unique_ptr<T> & v, void * context)
244 : {
245 : T * tmp = v.get();
246 :
247 : storeHelper(stream, tmp, context);
248 : }
249 :
250 : template <typename T>
251 : inline void
252 10895 : dataStore(std::ostream & stream, std::set<T> & s, void * context)
253 : {
254 : // First store the size of the set
255 10895 : unsigned int size = s.size();
256 10895 : dataStore(stream, size, nullptr);
257 :
258 10895 : typename std::set<T>::iterator it = s.begin();
259 10895 : typename std::set<T>::iterator end = s.end();
260 :
261 20217 : for (; it != end; ++it)
262 : {
263 9322 : T & x = const_cast<T &>(*it);
264 9322 : storeHelper(stream, x, context);
265 : }
266 10895 : }
267 :
268 : template <typename T>
269 : inline void
270 0 : dataStore(std::ostream & stream, std::list<T> & l, void * context)
271 : {
272 : // First store the size of the set
273 0 : unsigned int size = l.size();
274 0 : dataStore(stream, size, nullptr);
275 :
276 0 : typename std::list<T>::iterator it = l.begin();
277 0 : typename std::list<T>::iterator end = l.end();
278 :
279 0 : for (; it != end; ++it)
280 : {
281 0 : T & x = const_cast<T &>(*it);
282 0 : storeHelper(stream, x, context);
283 : }
284 0 : }
285 :
286 : template <typename T>
287 : inline void
288 45637 : dataStore(std::ostream & stream, std::deque<T> & l, void * context)
289 : {
290 : // First store the size of the container
291 45637 : unsigned int size = l.size();
292 45637 : dataStore(stream, size, nullptr);
293 :
294 45637 : typename std::deque<T>::iterator it = l.begin();
295 45637 : typename std::deque<T>::iterator end = l.end();
296 :
297 7235232 : for (; it != end; ++it)
298 : {
299 7189595 : T & x = const_cast<T &>(*it);
300 7189595 : storeHelper(stream, x, context);
301 : }
302 45637 : }
303 :
304 : template <typename T, typename U>
305 : inline void
306 2181196 : dataStore(std::ostream & stream, std::map<T, U> & m, void * context)
307 : {
308 : // First store the size of the map
309 2181196 : unsigned int size = m.size();
310 2181196 : dataStore(stream, size, nullptr);
311 :
312 2181196 : typename std::map<T, U>::iterator it = m.begin();
313 2181196 : typename std::map<T, U>::iterator end = m.end();
314 :
315 4894866 : for (; it != end; ++it)
316 : {
317 2713670 : T & key = const_cast<T &>(it->first);
318 :
319 2713670 : storeHelper(stream, key, context);
320 :
321 2713670 : storeHelper(stream, it->second, context);
322 : }
323 2181196 : }
324 :
325 : template <typename T, typename U>
326 : inline void
327 50 : dataStore(std::ostream & stream, std::unordered_map<T, U> & m, void * context)
328 : {
329 : // First store the size of the map
330 50 : unsigned int size = m.size();
331 50 : dataStore(stream, size, nullptr);
332 :
333 50 : typename std::unordered_map<T, U>::iterator it = m.begin();
334 50 : typename std::unordered_map<T, U>::iterator end = m.end();
335 :
336 100 : for (; it != end; ++it)
337 : {
338 50 : T & key = const_cast<T &>(it->first);
339 :
340 50 : storeHelper(stream, key, context);
341 :
342 50 : storeHelper(stream, it->second, context);
343 : }
344 50 : }
345 :
346 : template <typename T>
347 : inline void
348 81783 : dataStore(std::ostream & stream, std::unordered_set<T> & s, void * context)
349 : {
350 : // First store the size of the set
351 81783 : std::size_t size = s.size();
352 81783 : dataStore(stream, size, nullptr);
353 :
354 81787 : for (auto & element : s)
355 4 : dataStore(stream, element, context);
356 81783 : }
357 :
358 : template <typename T>
359 : inline void
360 8232 : dataStore(std::ostream & stream, std::optional<T> & m, void * context)
361 : {
362 8232 : bool has_value = m.has_value();
363 8232 : dataStore(stream, has_value, nullptr);
364 :
365 8232 : if (has_value)
366 8080 : storeHelper(stream, *m, context);
367 8232 : }
368 :
369 : template <typename T, typename U>
370 : inline void
371 : dataStore(std::ostream & stream, HashMap<T, U> & m, void * context)
372 : {
373 : // First store the size of the map
374 : unsigned int size = m.size();
375 : dataStore(stream, size, nullptr);
376 :
377 : typename HashMap<T, U>::iterator it = m.begin();
378 : typename HashMap<T, U>::iterator end = m.end();
379 :
380 : for (; it != end; ++it)
381 : {
382 : T & key = const_cast<T &>(it->first);
383 :
384 : storeHelper(stream, key, context);
385 :
386 : storeHelper(stream, it->second, context);
387 : }
388 : }
389 :
390 : template <typename T, int Rows, int Cols>
391 : void
392 2 : dataStore(std::ostream & stream, Eigen::Matrix<T, Rows, Cols> & v, void * context)
393 : {
394 2 : auto m = cast_int<unsigned int>(v.rows());
395 2 : dataStore(stream, m, context);
396 2 : auto n = cast_int<unsigned int>(v.cols());
397 2 : dataStore(stream, n, context);
398 9 : for (const auto i : make_range(m))
399 18 : for (const auto j : make_range(n))
400 : {
401 11 : auto & r = v(i, j);
402 11 : dataStore(stream, r, context);
403 : }
404 2 : }
405 :
406 : template <typename T>
407 : void
408 : dataStore(std::ostream & stream, GenericTwoVector<T> & v, void * context)
409 : {
410 : dataStore(stream, static_cast<Eigen::Matrix<T, 2, 1> &>(v), context);
411 : }
412 :
413 : // Specializations (defined in .C)
414 : template <>
415 : void dataStore(std::ostream & stream, Real & v, void * context);
416 : template <>
417 : void dataStore(std::ostream & stream, std::string & v, void * context);
418 : template <>
419 : void dataStore(std::ostream & stream, VariableName & v, void * context);
420 : template <>
421 : void dataStore(std::ostream & stream, UserObjectName & v, void * context);
422 : template <>
423 : void dataStore(std::ostream & stream, bool & v, void * context);
424 : template <>
425 : void dataStore(std::ostream & stream, libMesh::FEType & v, void * context);
426 : // Vectors of bools are special
427 : // https://en.wikipedia.org/w/index.php?title=Sequence_container_(C%2B%2B)&oldid=767869909#Specialization_for_bool
428 : template <>
429 : void dataStore(std::ostream & stream, std::vector<bool> & v, void * context);
430 : template <>
431 : void dataStore(std::ostream & stream, const Elem *& e, void * context);
432 : template <>
433 : void dataStore(std::ostream & stream, const Node *& n, void * context);
434 : template <>
435 : void dataStore(std::ostream & stream, Elem *& e, void * context);
436 : template <>
437 : void dataStore(std::ostream & stream, Node *& n, void * context);
438 : template <>
439 : void dataStore(std::ostream & stream, std::stringstream & s, void * context);
440 : template <>
441 : void dataStore(std::ostream & stream, ADReal & dn, void * context);
442 : template <>
443 : void dataStore(std::ostream & stream, libMesh::Parameters & p, void * context);
444 :
445 : template <>
446 : /**
447 : * Stores an owned numeric vector.
448 : *
449 : * This should be used in lieu of the NumericVector<Number> & implementation
450 : * when the vector may not necessarily be initialized yet on the loading of
451 : * the data. It stores the partitioning (total and local number of entries).
452 : *
453 : * Requirements: the unique_ptr must exist (cannot be null), the vector
454 : * cannot be ghosted, and the provided context must be the Communicator.
455 : */
456 : void dataStore(std::ostream & stream,
457 : std::unique_ptr<libMesh::NumericVector<libMesh::Number>> & v,
458 : void * context);
459 :
460 : template <std::size_t N>
461 : inline void
462 0 : dataStore(std::ostream & stream, std::array<ADReal, N> & dn, void * context)
463 : {
464 0 : for (std::size_t i = 0; i < N; ++i)
465 0 : dataStore(stream, dn[i], context);
466 0 : }
467 :
468 : template <std::size_t N>
469 : inline void
470 0 : dataStore(std::ostream & stream, ADReal (&dn)[N], void * context)
471 : {
472 0 : for (std::size_t i = 0; i < N; ++i)
473 0 : dataStore(stream, dn[i], context);
474 0 : }
475 :
476 : template <typename T>
477 : void
478 10 : dataStore(std::ostream & stream, libMesh::NumericVector<T> & v, void * context)
479 : {
480 10 : v.close();
481 :
482 10 : numeric_index_type size = v.local_size();
483 :
484 984 : for (numeric_index_type i = v.first_local_index(); i < v.first_local_index() + size; i++)
485 : {
486 974 : T r = v(i);
487 974 : dataStore(stream, r, context);
488 : }
489 10 : }
490 :
491 : template <>
492 : void dataStore(std::ostream & stream, Vec & v, void * context);
493 :
494 : template <typename T>
495 : void
496 48 : dataStore(std::ostream & stream, DenseVector<T> & v, void * context)
497 : {
498 48 : unsigned int m = v.size();
499 48 : dataStore(stream, m, nullptr);
500 192 : for (unsigned int i = 0; i < v.size(); i++)
501 : {
502 144 : T r = v(i);
503 144 : dataStore(stream, r, context);
504 : }
505 48 : }
506 :
507 : template <typename T>
508 : void dataStore(std::ostream & stream, libMesh::TensorValue<T> & v, void * context);
509 :
510 : template <typename T>
511 : void dataStore(std::ostream & stream, libMesh::DenseMatrix<T> & v, void * context);
512 :
513 : template <typename T>
514 : void dataStore(std::ostream & stream, libMesh::VectorValue<T> & v, void * context);
515 :
516 : template <typename T>
517 : void
518 0 : dataStore(std::ostream & stream, RankTwoTensorTempl<T> & rtt, void * context)
519 : {
520 0 : dataStore(stream, rtt._coords, context);
521 0 : }
522 :
523 : template <typename T>
524 : void
525 0 : dataStore(std::ostream & stream, RankThreeTensorTempl<T> & rtt, void * context)
526 : {
527 0 : dataStore(stream, rtt._vals, context);
528 0 : }
529 :
530 : template <typename T>
531 : void
532 0 : dataStore(std::ostream & stream, RankFourTensorTempl<T> & rft, void * context)
533 : {
534 0 : dataStore(stream, rft._vals, context);
535 0 : }
536 :
537 : template <typename T>
538 : void
539 0 : dataStore(std::ostream & stream, SymmetricRankTwoTensorTempl<T> & srtt, void * context)
540 : {
541 0 : dataStore(stream, srtt._vals, context);
542 0 : }
543 :
544 : template <typename T>
545 : void
546 0 : dataStore(std::ostream & stream, SymmetricRankFourTensorTempl<T> & srft, void * context)
547 : {
548 0 : dataStore(stream, srft._vals, context);
549 0 : }
550 :
551 : template <typename T>
552 : void
553 : dataStore(std::ostream & stream, ColumnMajorMatrixTempl<T> & cmm, void * context)
554 : {
555 : dataStore(stream, cmm._values, context);
556 : }
557 :
558 : // DO NOT MODIFY THE NEXT LINE - It is used by MOOSEDocs
559 : // *************** Global Load Declarations *****************
560 : template <typename T>
561 : inline void
562 18976439 : dataLoad(std::istream & stream, T & v, void * /*context*/)
563 : {
564 18976439 : stream.read((char *)&v, sizeof(v));
565 : mooseAssert(!stream.bad(), "Failed to load");
566 18976439 : }
567 :
568 : template <typename T>
569 : void
570 4 : dataLoad(std::istream & /*stream*/, T *& /*v*/, void * /*context*/)
571 : {
572 4 : mooseError("Attempting to load a raw pointer type: \"",
573 : libMesh::demangle(typeid(T).name()),
574 : " *\" as restartable data!\nWrite a custom dataLoad() template specialization!\n\n");
575 : }
576 :
577 : template <typename T, typename U>
578 : inline void
579 30626 : dataLoad(std::istream & stream, std::pair<T, U> & p, void * context)
580 : {
581 30626 : loadHelper(stream, p.first, context);
582 30626 : loadHelper(stream, p.second, context);
583 30626 : }
584 :
585 : template <typename T>
586 : inline void
587 415298 : dataLoad(std::istream & stream, std::vector<T> & v, void * context)
588 : {
589 : // First read the size of the vector
590 415298 : unsigned int size = 0;
591 415298 : dataLoad(stream, size, nullptr);
592 :
593 415298 : v.resize(size);
594 :
595 6361249 : for (unsigned int i = 0; i < size; i++)
596 5945951 : loadHelper(stream, v[i], context);
597 415298 : }
598 :
599 : template <typename T>
600 : inline void
601 : dataLoad(std::istream & stream, std::shared_ptr<T> & v, void * context)
602 : {
603 : T * tmp = v.get();
604 :
605 : loadHelper(stream, tmp, context);
606 : }
607 :
608 : template <typename T>
609 : inline void
610 : dataLoad(std::istream & stream, std::unique_ptr<T> & v, void * context)
611 : {
612 : T * tmp = v.get();
613 :
614 : loadHelper(stream, tmp, context);
615 : }
616 :
617 : template <typename T>
618 : inline void
619 7055 : dataLoad(std::istream & stream, std::set<T> & s, void * context)
620 : {
621 : // First read the size of the set
622 7055 : unsigned int size = 0;
623 7055 : dataLoad(stream, size, nullptr);
624 :
625 14407 : for (unsigned int i = 0; i < size; i++)
626 : {
627 7216 : T data;
628 7352 : loadHelper(stream, data, context);
629 7352 : s.insert(std::move(data));
630 : }
631 7055 : }
632 :
633 : template <typename T>
634 : inline void
635 0 : dataLoad(std::istream & stream, std::list<T> & l, void * context)
636 : {
637 : // First read the size of the set
638 0 : unsigned int size = 0;
639 0 : dataLoad(stream, size, nullptr);
640 :
641 0 : for (unsigned int i = 0; i < size; i++)
642 : {
643 0 : T data;
644 0 : loadHelper(stream, data, context);
645 0 : l.push_back(std::move(data));
646 : }
647 0 : }
648 :
649 : template <typename T>
650 : inline void
651 : dataLoad(std::istream & stream, std::deque<T> & l, void * context)
652 : {
653 : // First read the size of the container
654 : unsigned int size = 0;
655 : dataLoad(stream, size, nullptr);
656 :
657 : for (unsigned int i = 0; i < size; i++)
658 : {
659 : T data;
660 : loadHelper(stream, data, context);
661 : l.push_back(std::move(data));
662 : }
663 : }
664 :
665 : template <typename T, typename U>
666 : inline void
667 321493 : dataLoad(std::istream & stream, std::map<T, U> & m, void * context)
668 : {
669 321493 : m.clear();
670 :
671 : // First read the size of the map
672 321493 : unsigned int size = 0;
673 321493 : dataLoad(stream, size, nullptr);
674 :
675 700109 : for (unsigned int i = 0; i < size; i++)
676 : {
677 364845 : T key;
678 378616 : loadHelper(stream, key, context);
679 :
680 378616 : U & value = m[key];
681 378616 : loadHelper(stream, value, context);
682 : }
683 321493 : }
684 :
685 : template <typename T, typename U>
686 : inline void
687 10 : dataLoad(std::istream & stream, std::unordered_map<T, U> & m, void * context)
688 : {
689 10 : m.clear();
690 :
691 : // First read the size of the map
692 10 : unsigned int size = 0;
693 10 : dataLoad(stream, size, nullptr);
694 :
695 20 : for (unsigned int i = 0; i < size; i++)
696 : {
697 : T key;
698 10 : loadHelper(stream, key, context);
699 :
700 10 : U & value = m[key];
701 10 : loadHelper(stream, value, context);
702 : }
703 10 : }
704 :
705 : template <typename T>
706 : inline void
707 22362 : dataLoad(std::istream & stream, std::unordered_set<T> & s, void * context)
708 : {
709 22362 : s.clear();
710 :
711 : // First read the size of the set
712 22362 : std::size_t size = 0;
713 22362 : dataLoad(stream, size, nullptr);
714 22362 : s.reserve(size);
715 :
716 22364 : for (std::size_t i = 0; i < size; i++)
717 : {
718 : T element;
719 2 : dataLoad(stream, element, context);
720 2 : s.insert(element);
721 : }
722 22362 : }
723 :
724 : template <typename T>
725 : inline void
726 6975 : dataLoad(std::istream & stream, std::optional<T> & m, void * context)
727 : {
728 : bool has_value;
729 6975 : dataLoad(stream, has_value, nullptr);
730 :
731 6975 : if (has_value)
732 : {
733 6825 : m = T{};
734 6825 : loadHelper(stream, *m, context);
735 : }
736 : else
737 150 : m.reset();
738 13800 : }
739 :
740 : template <typename T, typename U>
741 : inline void
742 : dataLoad(std::istream & stream, HashMap<T, U> & m, void * context)
743 : {
744 : // First read the size of the map
745 : unsigned int size = 0;
746 : dataLoad(stream, size, nullptr);
747 :
748 : for (unsigned int i = 0; i < size; i++)
749 : {
750 : T key;
751 : loadHelper(stream, key, context);
752 :
753 : U & value = m[key];
754 : loadHelper(stream, value, context);
755 : }
756 : }
757 :
758 : template <typename T, int Rows, int Cols>
759 : void
760 2 : dataLoad(std::istream & stream, Eigen::Matrix<T, Rows, Cols> & v, void * context)
761 : {
762 2 : unsigned int m = 0;
763 2 : dataLoad(stream, m, context);
764 2 : unsigned int n = 0;
765 2 : dataLoad(stream, n, context);
766 2 : v.resize(m, n);
767 9 : for (const auto i : make_range(m))
768 18 : for (const auto j : make_range(n))
769 : {
770 11 : T r{};
771 11 : dataLoad(stream, r, context);
772 11 : v(i, j) = r;
773 : }
774 2 : }
775 :
776 : template <typename T>
777 : void
778 : dataLoad(std::istream & stream, GenericTwoVector<T> & v, void * context)
779 : {
780 : dataLoad(stream, static_cast<Eigen::Matrix<T, 2, 1> &>(v), context);
781 : }
782 :
783 : // Specializations (defined in .C)
784 : template <>
785 : void dataLoad(std::istream & stream, Real & v, void * /*context*/);
786 : template <>
787 : void dataLoad(std::istream & stream, std::string & v, void * /*context*/);
788 : template <>
789 : void dataLoad(std::istream & stream, VariableName & v, void * /*context*/);
790 : template <>
791 : void dataLoad(std::istream & stream, UserObjectName & v, void * /*context*/);
792 : template <>
793 : void dataLoad(std::istream & stream, bool & v, void * /*context*/);
794 : template <>
795 : void dataLoad(std::istream & stream, libMesh::FEType & v, void * /*context*/);
796 : // Vectors of bools are special
797 : // https://en.wikipedia.org/w/index.php?title=Sequence_container_(C%2B%2B)&oldid=767869909#Specialization_for_bool
798 : template <>
799 : void dataLoad(std::istream & stream, std::vector<bool> & v, void * /*context*/);
800 : template <>
801 : void dataLoad(std::istream & stream, const Elem *& e, void * context);
802 : template <>
803 : void dataLoad(std::istream & stream, const Node *& e, void * context);
804 : template <>
805 : void dataLoad(std::istream & stream, Elem *& e, void * context);
806 : template <>
807 : void dataLoad(std::istream & stream, Node *& e, void * context);
808 : template <>
809 : void dataLoad(std::istream & stream, std::stringstream & s, void * context);
810 : template <>
811 : void dataLoad(std::istream & stream, ADReal & dn, void * context);
812 : template <>
813 : void dataLoad(std::istream & stream, libMesh::Parameters & p, void * context);
814 : template <>
815 : /**
816 : * Loads an owned numeric vector.
817 : *
818 : * This is used in lieu of the NumericVector<double> & implementation when
819 : * the vector may not necessarily be initialized yet on the loading of the data.
820 : *
821 : * If \p is not null, it must have the same global and local sizes that it
822 : * was stored with. In this case, the data is simply filled into the vector.
823 : *
824 : * If \p is null, it will be constructed with the type (currently just a
825 : * PetscVector) stored and initialized with the global and local sizes stored.
826 : * The data will then be filled after initialization.
827 : *
828 : * Requirements: the vector cannot be ghosted, the provided context must be
829 : * the Communicator, and if \p v is initialized, it must have the same global
830 : * and local sizes that the vector was stored with.
831 : */
832 : void dataLoad(std::istream & stream,
833 : std::unique_ptr<libMesh::NumericVector<libMesh::Number>> & v,
834 : void * context);
835 :
836 : template <std::size_t N>
837 : inline void
838 0 : dataLoad(std::istream & stream, std::array<ADReal, N> & dn, void * context)
839 : {
840 0 : for (std::size_t i = 0; i < N; ++i)
841 0 : dataLoad(stream, dn[i], context);
842 0 : }
843 :
844 : template <std::size_t N>
845 : inline void
846 0 : dataLoad(std::istream & stream, ADReal (&dn)[N], void * context)
847 : {
848 0 : for (std::size_t i = 0; i < N; ++i)
849 0 : dataLoad(stream, dn[i], context);
850 0 : }
851 :
852 : template <typename T>
853 : void
854 8 : dataLoad(std::istream & stream, libMesh::NumericVector<T> & v, void * context)
855 : {
856 8 : numeric_index_type size = v.local_size();
857 504 : for (numeric_index_type i = v.first_local_index(); i < v.first_local_index() + size; i++)
858 : {
859 496 : T r = 0;
860 496 : dataLoad(stream, r, context);
861 496 : v.set(i, r);
862 : }
863 8 : v.close();
864 8 : }
865 :
866 : template <>
867 : void dataLoad(std::istream & stream, Vec & v, void * context);
868 :
869 : template <typename T>
870 : void
871 68 : dataLoad(std::istream & stream, DenseVector<T> & v, void * context)
872 : {
873 68 : unsigned int n = 0;
874 68 : dataLoad(stream, n, nullptr);
875 68 : v.resize(n);
876 272 : for (unsigned int i = 0; i < n; i++)
877 : {
878 204 : T r = 0;
879 204 : dataLoad(stream, r, context);
880 204 : v(i) = r;
881 : }
882 68 : }
883 :
884 : template <typename T>
885 : void dataLoad(std::istream & stream, libMesh::TensorValue<T> & v, void * context);
886 :
887 : template <typename T>
888 : void dataLoad(std::istream & stream, libMesh::DenseMatrix<T> & v, void * context);
889 :
890 : template <typename T>
891 : void dataLoad(std::istream & stream, libMesh::VectorValue<T> & v, void * context);
892 :
893 : template <typename T>
894 : void
895 0 : dataLoad(std::istream & stream, RankTwoTensorTempl<T> & rtt, void * context)
896 : {
897 0 : dataLoad(stream, rtt._coords, context);
898 0 : }
899 :
900 : template <typename T>
901 : void
902 0 : dataLoad(std::istream & stream, RankThreeTensorTempl<T> & rtt, void * context)
903 : {
904 0 : dataLoad(stream, rtt._vals, context);
905 0 : }
906 :
907 : template <typename T>
908 : void
909 0 : dataLoad(std::istream & stream, RankFourTensorTempl<T> & rft, void * context)
910 : {
911 0 : dataLoad(stream, rft._vals, context);
912 0 : }
913 :
914 : template <typename T>
915 : void
916 0 : dataLoad(std::istream & stream, SymmetricRankTwoTensorTempl<T> & rtt, void * context)
917 : {
918 0 : dataLoad(stream, rtt._vals, context);
919 0 : }
920 :
921 : template <typename T>
922 : void
923 0 : dataLoad(std::istream & stream, SymmetricRankFourTensorTempl<T> & rft, void * context)
924 : {
925 0 : dataLoad(stream, rft._vals, context);
926 0 : }
927 :
928 : template <typename T>
929 : void
930 : dataLoad(std::istream & stream, ColumnMajorMatrixTempl<T> & cmm, void * context)
931 : {
932 : dataLoad(stream, cmm._values, context);
933 : }
934 :
935 : // Scalar Helper Function
936 : template <typename P>
937 : inline void
938 26654632 : storeHelper(std::ostream & stream, P & data, void * context)
939 : {
940 26654632 : dataStore(stream, data, context);
941 26654629 : }
942 :
943 : // Vector Helper Function
944 : template <typename P>
945 : inline void
946 710597 : storeHelper(std::ostream & stream, std::vector<P> & data, void * context)
947 : {
948 710597 : dataStore(stream, data, context);
949 710597 : }
950 :
951 : // std::shared_ptr Helper Function
952 : template <typename P>
953 : inline void
954 1589718 : storeHelper(std::ostream & stream, std::shared_ptr<P> & data, void * context)
955 : {
956 1589718 : dataStore(stream, data, context);
957 1589718 : }
958 :
959 : // std::unique Helper Function
960 : template <typename P>
961 : inline void
962 167093 : storeHelper(std::ostream & stream, std::unique_ptr<P> & data, void * context)
963 : {
964 167093 : dataStore(stream, data, context);
965 167093 : }
966 :
967 : // Set Helper Function
968 : template <typename P>
969 : inline void
970 2791 : storeHelper(std::ostream & stream, std::set<P> & data, void * context)
971 : {
972 2791 : dataStore(stream, data, context);
973 2791 : }
974 :
975 : // Map Helper Function
976 : template <typename P, typename Q>
977 : inline void
978 1549882 : storeHelper(std::ostream & stream, std::map<P, Q> & data, void * context)
979 : {
980 1549882 : dataStore(stream, data, context);
981 1549882 : }
982 :
983 : // Unordered_map Helper Function
984 : template <typename P, typename Q>
985 : inline void
986 50 : storeHelper(std::ostream & stream, std::unordered_map<P, Q> & data, void * context)
987 : {
988 50 : dataStore(stream, data, context);
989 50 : }
990 :
991 : // Optional Helper Function
992 : template <typename P>
993 : inline void
994 8232 : storeHelper(std::ostream & stream, std::optional<P> & data, void * context)
995 : {
996 8232 : dataStore(stream, data, context);
997 8232 : }
998 :
999 : // HashMap Helper Function
1000 : template <typename P, typename Q>
1001 : inline void
1002 : storeHelper(std::ostream & stream, HashMap<P, Q> & data, void * context)
1003 : {
1004 : dataStore(stream, data, context);
1005 : }
1006 :
1007 : /**
1008 : * UniqueStorage helper routine
1009 : *
1010 : * The data within the UniqueStorage object cannot be null. The helper
1011 : * for unique_ptr<T> is called to store the data.
1012 : */
1013 : template <typename T>
1014 : inline void
1015 2 : storeHelper(std::ostream & stream, UniqueStorage<T> & data, void * context)
1016 : {
1017 2 : std::size_t size = data.size();
1018 2 : dataStore(stream, size, nullptr);
1019 :
1020 8 : for (const auto i : index_range(data))
1021 : {
1022 : mooseAssert(data.hasValue(i), "Data doesn't have a value");
1023 6 : storeHelper(stream, data.pointerValue(i), context);
1024 : }
1025 2 : }
1026 :
1027 : // Scalar Helper Function
1028 : template <typename P>
1029 : inline void
1030 7420748 : loadHelper(std::istream & stream, P & data, void * context)
1031 : {
1032 7420748 : dataLoad(stream, data, context);
1033 7420723 : }
1034 :
1035 : // Vector Helper Function
1036 : template <typename P>
1037 : inline void
1038 164353 : loadHelper(std::istream & stream, std::vector<P> & data, void * context)
1039 : {
1040 164353 : dataLoad(stream, data, context);
1041 164353 : }
1042 :
1043 : // std::shared_ptr Helper Function
1044 : template <typename P>
1045 : inline void
1046 65148 : loadHelper(std::istream & stream, std::shared_ptr<P> & data, void * context)
1047 : {
1048 65148 : dataLoad(stream, data, context);
1049 65148 : }
1050 :
1051 : // Unique Pointer Helper Function
1052 : template <typename P>
1053 : inline void
1054 45879 : loadHelper(std::istream & stream, std::unique_ptr<P> & data, void * context)
1055 : {
1056 45879 : dataLoad(stream, data, context);
1057 45879 : }
1058 :
1059 : // Set Helper Function
1060 : template <typename P>
1061 : inline void
1062 186 : loadHelper(std::istream & stream, std::set<P> & data, void * context)
1063 : {
1064 186 : dataLoad(stream, data, context);
1065 186 : }
1066 :
1067 : // Map Helper Function
1068 : template <typename P, typename Q>
1069 : inline void
1070 139751 : loadHelper(std::istream & stream, std::map<P, Q> & data, void * context)
1071 : {
1072 139751 : dataLoad(stream, data, context);
1073 139751 : }
1074 :
1075 : // Unordered_map Helper Function
1076 : template <typename P, typename Q>
1077 : inline void
1078 10 : loadHelper(std::istream & stream, std::unordered_map<P, Q> & data, void * context)
1079 : {
1080 10 : dataLoad(stream, data, context);
1081 10 : }
1082 :
1083 : // Optional Helper Function
1084 : template <typename P>
1085 : inline void
1086 6975 : loadHelper(std::istream & stream, std::optional<P> & data, void * context)
1087 : {
1088 6975 : dataLoad(stream, data, context);
1089 6975 : }
1090 :
1091 : // HashMap Helper Function
1092 : template <typename P, typename Q>
1093 : inline void
1094 : loadHelper(std::istream & stream, HashMap<P, Q> & data, void * context)
1095 : {
1096 : dataLoad(stream, data, context);
1097 : }
1098 :
1099 : /**
1100 : * UniqueStorage Helper Function
1101 : *
1102 : * The unique_ptr<T> loader is called to load the data. That is,
1103 : * you will likely need a specialization of unique_ptr<T> that will
1104 : * appropriately construct and then fill the piece of data.
1105 : */
1106 : template <typename T>
1107 : inline void
1108 2 : loadHelper(std::istream & stream, UniqueStorage<T> & data, void * context)
1109 : {
1110 : std::size_t size;
1111 2 : dataLoad(stream, size, nullptr);
1112 2 : data.resize(size);
1113 :
1114 8 : for (const auto i : index_range(data))
1115 6 : loadHelper(stream, data.pointerValue(i), context);
1116 2 : }
1117 :
1118 : void dataLoad(std::istream & stream, Point & p, void * context);
1119 :
1120 : #ifndef TIMPI_HAVE_STRING_PACKING
1121 : /**
1122 : * The following methods are specializations for using the libMesh::Parallel::packed_range_*
1123 : * routines
1124 : * for std::strings. These are here because the dataLoad/dataStore routines create raw string
1125 : * buffers that can be communicated in a standard way using packed ranges.
1126 : */
1127 : namespace libMesh
1128 : {
1129 : namespace Parallel
1130 : {
1131 : template <typename T>
1132 : class Packing<std::basic_string<T>>
1133 : {
1134 : public:
1135 : static const unsigned int size_bytes = 4;
1136 :
1137 : typedef T buffer_type;
1138 :
1139 : static unsigned int get_string_len(typename std::vector<T>::const_iterator in)
1140 : {
1141 : unsigned int string_len = reinterpret_cast<const unsigned char &>(in[size_bytes - 1]);
1142 : for (signed int i = size_bytes - 2; i >= 0; --i)
1143 : {
1144 : string_len *= 256;
1145 : string_len += reinterpret_cast<const unsigned char &>(in[i]);
1146 : }
1147 : return string_len;
1148 : }
1149 :
1150 : static unsigned int packed_size(typename std::vector<T>::const_iterator in)
1151 : {
1152 : return get_string_len(in) + size_bytes;
1153 : }
1154 :
1155 : static unsigned int packable_size(const std::basic_string<T> & s, const void *)
1156 : {
1157 : return s.size() + size_bytes;
1158 : }
1159 :
1160 : template <typename Iter>
1161 : static void pack(const std::basic_string<T> & b, Iter data_out, const void *)
1162 : {
1163 : unsigned int string_len = b.size();
1164 : for (unsigned int i = 0; i != size_bytes; ++i)
1165 : {
1166 : *data_out++ = (string_len % 256);
1167 : string_len /= 256;
1168 : }
1169 :
1170 : std::copy(b.begin(), b.end(), data_out);
1171 : }
1172 :
1173 : static std::basic_string<T> unpack(typename std::vector<T>::const_iterator in, void *)
1174 : {
1175 : unsigned int string_len = get_string_len(in);
1176 :
1177 : std::ostringstream oss;
1178 : for (unsigned int i = 0; i < string_len; ++i)
1179 : oss << reinterpret_cast<const unsigned char &>(in[i + size_bytes]);
1180 :
1181 : in += size_bytes + string_len;
1182 :
1183 : return oss.str();
1184 : }
1185 : };
1186 :
1187 : } // namespace Parallel
1188 :
1189 : } // namespace libMesh
1190 :
1191 : #endif
|