www.mooseframework.org
DataIO.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
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 #include "DenseMatrix.h"
11 #include "MooseConfig.h"
12 #include "DataIO.h"
13 #include "MooseMesh.h"
14 #include "FEProblemBase.h"
15 #include "NonlinearSystemBase.h"
16 
17 #include "libmesh/vector_value.h"
18 #include "libmesh/tensor_value.h"
19 
20 #include "libmesh/elem.h"
21 #include "libmesh/petsc_vector.h"
22 #include "libmesh/enum_solver_package.h"
23 
24 #include "DualRealOps.h"
25 
26 template <>
27 void
28 dataStore(std::ostream & stream, Real & v, void * /*context*/)
29 {
30  stream.write((char *)&v, sizeof(v));
31 }
32 
33 template <>
34 void
35 dataStore(std::ostream & stream, std::string & v, void * /*context*/)
36 {
37  // Write the size of the string
38  unsigned int size = v.size();
39  stream.write((char *)&size, sizeof(size));
40 
41  // Write the string (Do not store the null byte)
42  stream.write(v.c_str(), sizeof(char) * size);
43 }
44 
45 template <>
46 void
47 dataStore(std::ostream & stream, VariableName & v, void * context)
48 {
49  auto & name = static_cast<std::string &>(v);
50  dataStore(stream, name, context);
51 }
52 
53 template <>
54 void
55 dataStore(std::ostream & stream, bool & v, void * /*context*/)
56 {
57  stream.write((char *)&v, sizeof(v));
58 }
59 
60 template <>
61 void
62 dataStore(std::ostream & stream, std::vector<bool> & v, void * context)
63 {
64  for (bool b : v)
65  dataStore(stream, b, context);
66 }
67 
68 template <>
69 void
70 dataStore(std::ostream & stream, RankTwoTensor & rtt, void * context)
71 {
72  dataStore(stream, rtt._coords, context);
73 }
74 
75 template <>
76 void
77 dataStore(std::ostream & stream, RankThreeTensor & rtht, void * context)
78 {
79  dataStore(stream, rtht._vals, context);
80 }
81 
82 template <>
83 void
84 dataStore(std::ostream & stream, RankFourTensor & rft, void * context)
85 {
86  dataStore(stream, rft._vals, context);
87 }
88 
89 template <>
90 void
91 dataStore(std::ostream & stream, DualReal & dn, void * context)
92 {
93  dataStore(stream, dn.value(), context);
94 
95  if (DualReal::do_derivatives)
96  {
97  auto & derivatives = dn.derivatives();
98  std::size_t size = derivatives.size();
99  dataStore(stream, size, context);
100  for (MooseIndex(size) i = 0; i < size; ++i)
101  {
102  dataStore(stream, derivatives.raw_index(i), context);
103  dataStore(stream, derivatives.raw_at(i), context);
104  }
105  }
106 }
107 
108 template <>
109 void
110 dataStore(std::ostream & stream, const Elem *& e, void * context)
111 {
112  // TODO: Write out the unique ID of this elem
114 
115  if (e)
116  {
117  id = e->id();
119  mooseError("Can't output Elems with invalid ids!");
120  }
121 
122  storeHelper(stream, id, context);
123 }
124 
125 template <>
126 void
127 dataStore(std::ostream & stream, const Node *& n, void * context)
128 {
129  // TODO: Write out the unique ID of this node
131 
132  if (n)
133  {
134  id = n->id();
136  mooseError("Can't output Nodes with invalid ids!");
137  }
138 
139  storeHelper(stream, id, context);
140 }
141 
142 template <>
143 void
144 dataStore(std::ostream & stream, Elem *& e, void * context)
145 {
146  // TODO: Write out the unique ID of this elem
148 
149  if (e)
150  {
151  id = e->id();
153  mooseError("Can't output Elems with invalid ids!");
154  }
155 
156  storeHelper(stream, id, context);
157 }
158 
159 template <>
160 void
161 dataStore(std::ostream & stream, Node *& n, void * context)
162 {
163  // TODO: Write out the unique ID of this node
165 
166  if (n)
167  {
168  id = n->id();
170  mooseError("Can't output Nodes with invalid ids!");
171  }
172 
173  storeHelper(stream, id, context);
174 }
175 
176 template <>
177 void
178 dataStore(std::ostream & stream, std::stringstream & s, void * /* context */)
179 {
180  const std::string & s_str = s.str();
181 
182  size_t s_size = s_str.size();
183  stream.write((char *)&s_size, sizeof(s_size));
184 
185  stream.write(s_str.c_str(), sizeof(char) * (s_str.size()));
186 }
187 
188 template <>
189 void
190 dataStore(std::ostream & stream, RealEigenVector & v, void * context)
191 {
192  unsigned int m = v.size();
193  stream.write((char *)&m, sizeof(m));
194  for (unsigned int i = 0; i < v.size(); i++)
195  {
196  Real r = v(i);
197  dataStore(stream, r, context);
198  }
199 }
200 
201 template <>
202 void
203 dataStore(std::ostream & stream, RealEigenMatrix & v, void * context)
204 {
205  unsigned int m = v.rows();
206  stream.write((char *)&m, sizeof(m));
207  unsigned int n = v.cols();
208  stream.write((char *)&n, sizeof(n));
209  for (unsigned int i = 0; i < m; i++)
210  for (unsigned int j = 0; j < n; j++)
211  {
212  Real r = v(i, j);
213  dataStore(stream, r, context);
214  }
215 }
216 
217 template <typename T>
218 void
219 dataStore(std::ostream & stream, TensorValue<T> & v, void * context)
220 {
221  for (const auto i : make_range(Moose::dim))
222  for (const auto j : make_range(Moose::dim))
223  {
224  T r = v(i, j);
225  dataStore(stream, r, context);
226  }
227 }
228 
229 template void dataStore(std::ostream & stream, TensorValue<Real> & v, void * context);
230 template void dataStore(std::ostream & stream, TensorValue<DualReal> & v, void * context);
231 
232 template <typename T>
233 void
234 dataStore(std::ostream & stream, DenseMatrix<T> & v, void * context)
235 {
236  unsigned int m = v.m();
237  unsigned int n = v.n();
238  stream.write((char *)&m, sizeof(m));
239  stream.write((char *)&n, sizeof(n));
240  for (unsigned int i = 0; i < m; i++)
241  for (unsigned int j = 0; j < n; j++)
242  {
243  T r = v(i, j);
244  dataStore(stream, r, context);
245  }
246 }
247 
248 template void dataStore(std::ostream & stream, DenseMatrix<Real> & v, void * context);
249 template void dataStore(std::ostream & stream, DenseMatrix<DualReal> & v, void * context);
250 
251 template <typename T>
252 void
253 dataStore(std::ostream & stream, VectorValue<T> & v, void * context)
254 {
255  // Obviously if someone loads data with different LIBMESH_DIM than was used for saving them, it
256  // won't work.
257  for (const auto i : make_range(Moose::dim))
258  {
259  T r = v(i);
260  dataStore(stream, r, context);
261  }
262 }
263 
264 template void dataStore(std::ostream & stream, VectorValue<Real> & v, void * context);
265 template void dataStore(std::ostream & stream, VectorValue<DualReal> & v, void * context);
266 
267 void
268 dataStore(std::ostream & stream, Point & p, void * context)
269 {
270  for (const auto i : make_range(Moose::dim))
271  {
272  Real r = p(i);
273  dataStore(stream, r, context);
274  }
275 }
276 
277 template <>
278 void
279 dataStore(std::ostream & stream, libMesh::Parameters & p, void * context)
280 {
281  // First store the size of the map
282  unsigned int size = p.n_parameters();
283  stream.write((char *)&size, sizeof(size));
284 
285  auto it = p.begin();
286  auto end = p.end();
287 
288  for (; it != end; ++it)
289  {
290  auto & key = const_cast<std::string &>(it->first);
291  auto type = it->second->type();
292 
293  storeHelper(stream, key, context);
294  storeHelper(stream, type, context);
295 
296 #define storescalar(ptype) \
297  else if (it->second->type() == demangle(typeid(ptype).name())) storeHelper( \
298  stream, \
299  (dynamic_cast<libMesh::Parameters::Parameter<ptype> *>(MooseUtils::get(it->second)))->get(), \
300  context)
301 
302  if (false)
303  ;
304  storescalar(Real);
305  storescalar(short);
306  storescalar(int);
307  storescalar(long);
308  storescalar(unsigned short);
309  storescalar(unsigned int);
310  storescalar(unsigned long);
311 
312 #undef storescalar
313  }
314 }
315 
316 template <>
317 void
318 dataStore(std::ostream & stream,
319  std::unique_ptr<libMesh::NumericVector<Number>> & v,
320  void * context)
321 {
322  mooseAssert(v, "Null vector");
323  mooseAssert(context, "Needs a context of the communicator");
324  const auto & comm = *static_cast<const libMesh::Parallel::Communicator *>(context);
325  mooseAssert(&comm == &v->comm(), "Inconsistent communicator");
326 
327  if (v->type() == GHOSTED)
328  mooseError("Cannot store ghosted numeric vectors");
329 
330  // Store the communicator size for sanity checking later
331  unsigned int comm_size = comm.size();
332  dataStore(stream, comm_size, nullptr);
333 
334  // Store the solver package so that we know what vector type to construct
335  libMesh::SolverPackage solver_package;
336  if (dynamic_cast<libMesh::PetscVector<Number> *>(v.get()))
337  solver_package = PETSC_SOLVERS;
338  else
339  mooseError("Can only store unique_ptrs of PetscVectors");
340  int solver_package_int = solver_package;
341  dataStore(stream, solver_package_int, nullptr);
342 
343  // Store the sizes
344  dof_id_type size = v->size();
345  dataStore(stream, size, nullptr);
346  dof_id_type local_size = v->local_size();
347  dataStore(stream, local_size, nullptr);
348 
349  // Store the vector itself
350  dataStore(stream, *v, nullptr);
351 }
352 
353 // global load functions
354 
355 template <>
356 void
357 dataLoad(std::istream & stream, Real & v, void * /*context*/)
358 {
359  stream.read((char *)&v, sizeof(v));
360 }
361 
362 template <>
363 void
364 dataLoad(std::istream & stream, std::string & v, void * /*context*/)
365 {
366  // Read the size of the string
367  unsigned int size = 0;
368  stream.read((char *)&size, sizeof(size));
369 
370  // Resize the string data
371  v.resize(size);
372 
373  // Read the string
374  stream.read(&v[0], sizeof(char) * size);
375 }
376 
377 template <>
378 void
379 dataLoad(std::istream & stream, VariableName & v, void * context)
380 {
381  auto & name = static_cast<std::string &>(v);
382  dataLoad(stream, name, context);
383 }
384 
385 template <>
386 void
387 dataLoad(std::istream & stream, bool & v, void * /*context*/)
388 {
389  stream.read((char *)&v, sizeof(v));
390 }
391 
392 template <>
393 void
394 dataLoad(std::istream & stream, std::vector<bool> & v, void * context)
395 {
396  for (bool b : v)
397  dataLoad(stream, b, context);
398 }
399 
400 template <>
401 void
402 dataLoad(std::istream & stream, DualReal & dn, void * context)
403 {
404  dataLoad(stream, dn.value(), context);
405 
406  if (DualReal::do_derivatives)
407  {
408  auto & derivatives = dn.derivatives();
409  std::size_t size = 0;
410  stream.read((char *)&size, sizeof(size));
411  derivatives.resize(size);
412 
413  for (MooseIndex(derivatives) i = 0; i < derivatives.size(); ++i)
414  {
415  dataLoad(stream, derivatives.raw_index(i), context);
416  dataLoad(stream, derivatives.raw_at(i), context);
417  }
418  }
419 }
420 
421 template <>
422 void
423 dataLoad(std::istream & stream, const Elem *& e, void * context)
424 {
425  if (!context)
426  mooseError("Can only load Elem objects using a MooseMesh context!");
427 
428  MooseMesh * mesh = static_cast<MooseMesh *>(context);
429 
430  // TODO: Write out the unique ID of this element
432 
433  loadHelper(stream, id, context);
434 
436  e = mesh->elemPtr(id);
437  else
438  e = NULL;
439 }
440 
441 template <>
442 void
443 dataLoad(std::istream & stream, const Node *& n, void * context)
444 {
445  if (!context)
446  mooseError("Can only load Node objects using a MooseMesh context!");
447 
448  MooseMesh * mesh = static_cast<MooseMesh *>(context);
449 
450  // TODO: Write out the unique ID of this nodeent
452 
453  loadHelper(stream, id, context);
454 
456  n = mesh->nodePtr(id);
457  else
458  n = NULL;
459 }
460 
461 template <>
462 void
463 dataLoad(std::istream & stream, Elem *& e, void * context)
464 {
465  if (!context)
466  mooseError("Can only load Elem objects using a MooseMesh context!");
467 
468  MooseMesh * mesh = static_cast<MooseMesh *>(context);
469 
470  // TODO: Write out the unique ID of this element
472 
473  loadHelper(stream, id, context);
474 
476  e = mesh->elemPtr(id);
477  else
478  e = NULL;
479 }
480 
481 template <>
482 void
483 dataLoad(std::istream & stream, Node *& n, void * context)
484 {
485  if (!context)
486  mooseError("Can only load Node objects using a MooseMesh context!");
487 
488  MooseMesh * mesh = static_cast<MooseMesh *>(context);
489 
490  // TODO: Write out the unique ID of this nodeent
492 
493  loadHelper(stream, id, context);
494 
496  n = mesh->nodePtr(id);
497  else
498  n = NULL;
499 }
500 
501 template <>
502 void
503 dataLoad(std::istream & stream, std::stringstream & s, void * /* context */)
504 {
505  size_t s_size = 0;
506  stream.read((char *)&s_size, sizeof(s_size));
507 
508  std::unique_ptr<char[]> s_s = std::make_unique<char[]>(s_size);
509  stream.read(s_s.get(), s_size);
510 
511  // Clear the stringstream before loading new data into it.
512  s.str(std::string());
513  s.write(s_s.get(), s_size);
514 }
515 
516 template <>
517 void
518 dataLoad(std::istream & stream, RealEigenVector & v, void * context)
519 {
520  unsigned int n = 0;
521  stream.read((char *)&n, sizeof(n));
522  v.resize(n);
523  for (unsigned int i = 0; i < n; i++)
524  {
525  Real r = 0;
526  dataLoad(stream, r, context);
527  v(i) = r;
528  }
529 }
530 
531 template <>
532 void
533 dataLoad(std::istream & stream, RealEigenMatrix & v, void * context)
534 {
535  unsigned int m = 0;
536  stream.read((char *)&m, sizeof(m));
537  unsigned int n = 0;
538  stream.read((char *)&n, sizeof(n));
539  v.resize(m, n);
540  for (unsigned int i = 0; i < m; i++)
541  for (unsigned int j = 0; j < n; j++)
542  {
543  Real r = 0;
544  dataLoad(stream, r, context);
545  v(i, j) = r;
546  }
547 }
548 
549 template <typename T>
550 void
551 dataLoad(std::istream & stream, TensorValue<T> & v, void * context)
552 {
553  // Obviously if someone loads data with different LIBMESH_DIM than was used for saving them, it
554  // won't work.
555  for (const auto i : make_range(Moose::dim))
556  for (const auto j : make_range(Moose::dim))
557  {
558  T r = 0;
559  dataLoad(stream, r, context);
560  v(i, j) = r;
561  }
562 }
563 
564 template void dataLoad(std::istream & stream, TensorValue<Real> & v, void * context);
565 template void dataLoad(std::istream & stream, TensorValue<DualReal> & v, void * context);
566 
567 template <typename T>
568 void
569 dataLoad(std::istream & stream, DenseMatrix<T> & v, void * context)
570 {
571  unsigned int m = 0, n = 0;
572  stream.read((char *)&m, sizeof(m));
573  stream.read((char *)&n, sizeof(n));
574  v.resize(m, n);
575  for (unsigned int i = 0; i < m; i++)
576  for (unsigned int j = 0; j < n; j++)
577  {
578  T r = 0;
579  dataLoad(stream, r, context);
580  v(i, j) = r;
581  }
582 }
583 
584 template void dataLoad(std::istream & stream, DenseMatrix<Real> & v, void * context);
585 template void dataLoad(std::istream & stream, DenseMatrix<DualReal> & v, void * context);
586 
587 template <typename T>
588 void
589 dataLoad(std::istream & stream, VectorValue<T> & v, void * context)
590 {
591  // Obviously if someone loads data with different LIBMESH_DIM than was used for saving them, it
592  // won't work.
593  for (const auto i : make_range(Moose::dim))
594  {
595  T r = 0;
596  dataLoad(stream, r, context);
597  v(i) = r;
598  }
599 }
600 
601 template void dataLoad(std::istream & stream, VectorValue<Real> & v, void * context);
602 template void dataLoad(std::istream & stream, VectorValue<DualReal> & v, void * context);
603 
604 void
605 dataLoad(std::istream & stream, Point & p, void * context)
606 {
607  for (const auto i : make_range(Moose::dim))
608  {
609  Real r = 0;
610  dataLoad(stream, r, context);
611  p(i) = r;
612  }
613 }
614 
615 template <>
616 void
617 dataLoad(std::istream & stream, libMesh::Parameters & p, void * context)
618 {
619  p.clear();
620 
621  // First read the size of the map
622  unsigned int size = 0;
623  stream.read((char *)&size, sizeof(size));
624 
625  for (unsigned int i = 0; i < size; i++)
626  {
627  std::string key, type;
628  loadHelper(stream, key, context);
629  loadHelper(stream, type, context);
630 
631 #define loadscalar(ptype) \
632  else if (type == demangle(typeid(ptype).name())) do \
633  { \
634  ptype & value = p.set<ptype>(key); \
635  loadHelper(stream, value, context); \
636  } \
637  while (0)
638 
639  if (false)
640  ;
641  loadscalar(Real);
642  loadscalar(short);
643  loadscalar(int);
644  loadscalar(long);
645  loadscalar(unsigned short);
646  loadscalar(unsigned int);
647  loadscalar(unsigned long);
648 
649 #undef loadscalar
650  }
651 }
652 
653 template <>
654 void
655 dataLoad(std::istream & stream, std::unique_ptr<libMesh::NumericVector<Number>> & v, void * context)
656 {
657  mooseAssert(context, "Needs a context of the communicator");
658  const auto & comm = *static_cast<const libMesh::Parallel::Communicator *>(context);
659  if (v)
660  mooseAssert(&comm == &v->comm(), "Inconsistent communicator");
661 
662  // Load the communicator size for consistency checks
663  unsigned int comm_size;
664  dataLoad(stream, comm_size, nullptr);
665  mooseAssert(comm.size() == comm_size, "Inconsistent communicator size");
666 
667  // Load the solver package to build the vector
668  int solver_package_int;
669  dataLoad(stream, solver_package_int, nullptr);
670  libMesh::SolverPackage solver_package = static_cast<libMesh::SolverPackage>(solver_package_int);
671 
672  // Load the sizes
673  dof_id_type size, local_size;
674  dataLoad(stream, size, nullptr);
675  dataLoad(stream, local_size, nullptr);
676 
677  // Construct the vector given the type, only if we need to. v could be non-null here
678  // if we're advancing back and loading a backup
679  if (!v)
680  {
681  v = NumericVector<Number>::build(comm, solver_package);
682  v->init(size, local_size);
683  }
684  else
685  mooseAssert(v->type() != GHOSTED, "Cannot be ghosted");
686 
687  // Make sure that the sizes are consistent; this will happen if we're calling this
688  // on a vector that has already been loaded previously
689  mooseAssert(v->size() == size, "Inconsistent size");
690  mooseAssert(v->local_size() == local_size, "Inconsistent local size");
691 
692  // Now that we have an initialized vector, fill the entries
693  dataLoad(stream, *v, nullptr);
694 }
695 
696 template <>
697 void
698 dataLoad(std::istream & stream, Vec & v, void * context)
699 {
700  PetscInt local_size;
701  VecGetLocalSize(v, &local_size);
702  PetscScalar * array;
703  VecGetArray(v, &array);
704  for (PetscInt i = 0; i < local_size; i++)
705  dataLoad(stream, array[i], context);
706 
707  VecRestoreArray(v, &array);
708 }
709 
710 template <>
711 void
712 dataStore(std::ostream & stream, Vec & v, void * context)
713 {
714  PetscInt local_size;
715  VecGetLocalSize(v, &local_size);
716  PetscScalar * array;
717  VecGetArray(v, &array);
718  for (PetscInt i = 0; i < local_size; i++)
719  dataStore(stream, array[i], context);
720 
721  VecRestoreArray(v, &array);
722 }
std::string name(const ElemQuality q)
RankFourTensorTempl is designed to handle any N-dimensional fourth order tensor, C.
PETSC_SOLVERS
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:299
DualNumber< Real, DNDerivativeType, true > DualReal
Definition: DualReal.h:49
MeshBase & mesh
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:148
T _coords[LIBMESH_DIM *LIBMESH_DIM]
RankThreeTensor is designed to handle any N-dimensional third order tensor, r.
void storeHelper(std::ostream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:856
void dataLoad(std::istream &stream, Real &v, void *)
Definition: DataIO.C:357
GHOSTED
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition: MooseMesh.h:88
static const dof_id_type invalid_id
T _vals[N3]
The values of the rank-three tensor stored by index=((i * LIBMESH_DIM + j) * LIBMESH_DIM + k) ...
T _vals[N4]
The values of the rank-four tensor stored by index=(((i * LIBMESH_DIM + j) * LIBMESH_DIM + k) * LIBME...
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic > RealEigenMatrix
Definition: MooseTypes.h:141
static std::unique_ptr< NumericVector< Number > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package())
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void clear()
IntRange< T > make_range(T beg, T end)
Eigen::Matrix< Real, Eigen::Dynamic, 1 > RealEigenVector
Definition: MooseTypes.h:138
std::size_t n_parameters() const
void loadHelper(std::istream &stream, P &data, void *context)
Scalar helper routine.
Definition: DataIO.h:948
void dataStore(std::ostream &stream, Real &v, void *)
Definition: DataIO.C:28
uint8_t dof_id_type