LCOV - code coverage report
Current view: top level - src/restart - RestartableEquationSystems.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 199 216 92.1 %
Date: 2025-08-08 20:01:16 Functions: 18 19 94.7 %
Legend: Lines: hit not hit

          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             : #include "RestartableEquationSystems.h"
      11             : 
      12             : #include "DataIO.h"
      13             : 
      14             : #include "libmesh/dof_map.h"
      15             : #include "libmesh/dof_object.h"
      16             : #include "libmesh/elem.h"
      17             : #include "libmesh/node.h"
      18             : 
      19             : const std::string RestartableEquationSystems::SystemHeader::system_solution_name =
      20             :     "SYSTEM_SOLUTION";
      21             : 
      22       62498 : RestartableEquationSystems::RestartableEquationSystems(libMesh::MeshBase & mesh)
      23       62498 :   : _es(mesh), _load_all_vectors(true)
      24             : {
      25       62498 : }
      26             : 
      27             : RestartableEquationSystems::EquationSystemsHeader
      28       45214 : RestartableEquationSystems::buildHeader(
      29             :     const std::vector<const libMesh::DofObject *> & ordered_objects) const
      30             : {
      31       45214 :   EquationSystemsHeader es_header;
      32             : 
      33             :   // Systems
      34      136666 :   for (const auto sys_num : make_range(_es.n_systems()))
      35             :   {
      36       91452 :     const auto & sys = _es.get_system(sys_num);
      37             : 
      38       91452 :     SystemHeader sys_header;
      39       91452 :     sys_header.name = sys.name();
      40       91452 :     sys_header.type = sys.system_type();
      41             : 
      42             :     // Variables in the system
      43      183043 :     for (const auto var_num : make_range(sys.n_vars()))
      44             :     {
      45       91591 :       const auto & var = sys.variable(var_num);
      46             : 
      47       91591 :       VariableHeader var_header;
      48       91591 :       var_header.name = var.name();
      49       91591 :       var_header.type = var.type();
      50       91591 :       var_header.size = 0;
      51       91591 :       var_header.variable = &var;
      52             : 
      53             :       mooseAssert(_es.comm().verify("sys_" + sys.name() + "_var_" + var.name()),
      54             :                   "Out of order in parallel");
      55             :       mooseAssert(!sys_header.variables.count(var.name()), "Already inserted");
      56             : 
      57             :       // Non-SCALAR variable
      58       91591 :       if (var.type().family != SCALAR)
      59             :       {
      60    18530584 :         for (const auto & obj : ordered_objects)
      61    18440684 :           var_header.size += sizeof(Real) * obj->n_comp(sys.number(), var.number());
      62             :       }
      63             :       // SCALAR variable on the last rank
      64        1691 :       else if (_es.processor_id() == _es.n_processors() - 1)
      65             :       {
      66        1654 :         std::vector<dof_id_type> scalar_dofs;
      67        1654 :         sys.get_dof_map().SCALAR_dof_indices(scalar_dofs, var.number());
      68        1654 :         var_header.size += sizeof(Real) * scalar_dofs.size();
      69        1654 :       }
      70             : 
      71       91591 :       sys_header.variables.emplace(var.name(), var_header);
      72       91591 :     }
      73             : 
      74             :     // System vector
      75       91452 :     auto & sys_vec_header = sys_header.vectors[SystemHeader::system_solution_name];
      76       91452 :     sys_vec_header.name = SystemHeader::system_solution_name;
      77       91452 :     sys_vec_header.vector = sys.solution.get();
      78       91452 :     sys_vec_header.type = sys_vec_header.vector->type();
      79      430719 :     for (const auto vec_num : make_range(sys.n_vectors()))
      80             :     {
      81             :       mooseAssert(_es.comm().verify("sys_" + sys.name() + "_vec_" + sys.vector_name(vec_num)),
      82             :                   "Out of order in parallel");
      83      339267 :       const auto & name = sys.vector_name(vec_num);
      84             :       mooseAssert(!sys_header.vectors.count(name), "Already inserted");
      85      339267 :       auto & vec_header = sys_header.vectors[name];
      86      339267 :       vec_header.name = sys.vector_name(vec_num);
      87      339267 :       vec_header.projections = sys.vector_preservation(vec_header.name);
      88      339267 :       vec_header.vector = &sys.get_vector(vec_header.name);
      89      339267 :       vec_header.type = vec_header.vector->type();
      90             :     }
      91             : 
      92             :     // System in this EquationSystems
      93             :     mooseAssert(!es_header.systems.count(sys.name()), "Already inserted");
      94       91452 :     es_header.systems.emplace(sys.name(), sys_header);
      95       91452 :   }
      96             : 
      97             :   // Setup the positions in each vector for easy access later
      98       45214 :   std::size_t offset = 0;
      99      136666 :   for (auto & sys_name_header_pair : es_header.systems)
     100             :   {
     101       91452 :     auto & sys_header = sys_name_header_pair.second;
     102      522171 :     for (auto & vec_name_header_pair : sys_header.vectors)
     103             :     {
     104      430719 :       auto & vec_header = vec_name_header_pair.second;
     105      861875 :       for (const auto & var_name_header_pair : sys_header.variables)
     106             :       {
     107      431156 :         const auto & var_header = var_name_header_pair.second;
     108             :         mooseAssert(!vec_header.variable_offset.count(var_header.name), "Already inserted");
     109      431156 :         vec_header.variable_offset[var_header.name] = offset;
     110      431156 :         offset += var_header.size;
     111             :       }
     112             :     }
     113             :   }
     114             : 
     115       45214 :   es_header.data_size = offset;
     116             : 
     117       45214 :   return es_header;
     118           0 : }
     119             : 
     120             : std::vector<const libMesh::DofObject *>
     121       59455 : RestartableEquationSystems::orderDofObjects() const
     122             : {
     123       59455 :   std::vector<const libMesh::DofObject *> objects;
     124      356730 :   auto add = [&objects](const auto begin, const auto end)
     125             :   {
     126      118910 :     std::set<const libMesh::DofObject *, libMesh::CompareDofObjectsByID> ordered(begin, end);
     127      118910 :     objects.insert(objects.end(), ordered.begin(), ordered.end());
     128      178365 :   };
     129             : 
     130       59455 :   const auto & mesh = _es.get_mesh();
     131       59455 :   add(mesh.local_elements_begin(), mesh.local_elements_end());
     132       59455 :   add(mesh.local_nodes_begin(), mesh.local_nodes_end());
     133             : 
     134      118910 :   return objects;
     135           0 : }
     136             : 
     137             : void
     138       45214 : RestartableEquationSystems::store(std::ostream & stream) const
     139             : {
     140             :   // Order objects (elements and then nodes) by ID for storing
     141       45214 :   const auto ordered_objects = orderDofObjects();
     142             : 
     143             :   // Store the header (systems, variables, vectors)
     144       45214 :   EquationSystemsHeader es_header = buildHeader(ordered_objects);
     145       45214 :   dataStore(stream, es_header, nullptr);
     146             : 
     147             :   // Store the ordered objects so we can do a sanity check on if we're
     148             :   // loading the same thing
     149             :   {
     150       45214 :     std::vector<dof_id_type> ordered_objects_ids(ordered_objects.size());
     151     9802013 :     for (const auto i : index_range(ordered_objects))
     152     9756799 :       ordered_objects_ids[i] = ordered_objects[i]->id();
     153       45214 :     dataStore(stream, ordered_objects_ids, nullptr);
     154       45214 :   }
     155             : 
     156             : #ifndef NDEBUG
     157             :   const std::size_t data_initial_position = static_cast<std::size_t>(stream.tellp());
     158             : #endif
     159             : 
     160             :   // Store each system
     161      136666 :   for (const auto & sys_name_header_pair : es_header.systems)
     162             :   {
     163       91452 :     const auto & sys_header = sys_name_header_pair.second;
     164       91452 :     const auto & sys = _es.get_system(sys_header.name);
     165             : 
     166             :     // Store each vector and variable
     167      522171 :     for (const auto & vec_name_header_pair : sys_header.vectors)
     168             :     {
     169      430719 :       const auto & vec_header = vec_name_header_pair.second;
     170      430719 :       const auto & vec = *vec_header.vector;
     171      861875 :       for (const auto & var_name_header_pair : sys_header.variables)
     172             :       {
     173      431156 :         const auto & var_header = var_name_header_pair.second;
     174      431156 :         const auto & var = *var_header.variable;
     175             : 
     176             : #ifndef NDEBUG
     177             :         const std::size_t var_initial_position = stream.tellp();
     178             : #endif
     179             : 
     180             :         // Non-SCALAR variable
     181      431156 :         if (var.type().family != SCALAR)
     182             :         {
     183             :           // Store for each component of each element and node
     184    81862601 :           for (const auto & obj : ordered_objects)
     185   123034066 :             for (const auto comp : make_range(obj->n_comp(sys.number(), var.number())))
     186             :             {
     187    41594489 :               auto val = vec(obj->dof_number(sys.number(), var.number(), comp));
     188    41594489 :               dataStore(stream, val, nullptr);
     189             :             }
     190             :         }
     191             :         // SCALAR variable on the last rank
     192        8132 :         else if (_es.processor_id() == _es.n_processors() - 1)
     193             :         {
     194        8021 :           const auto & dof_map = sys.get_dof_map();
     195        8021 :           std::vector<dof_id_type> scalar_dofs;
     196        8021 :           dof_map.SCALAR_dof_indices(scalar_dofs, var.number());
     197       17408 :           for (const auto dof : scalar_dofs)
     198             :           {
     199        9387 :             auto val = vec(dof);
     200        9387 :             dataStore(stream, val, nullptr);
     201             :           }
     202        8021 :         }
     203             : 
     204             : #ifndef NDEBUG
     205             :         const std::size_t data_offset = var_initial_position - data_initial_position;
     206             :         mooseAssert(vec_header.variable_offset.at(var_header.name) == data_offset,
     207             :                     "Invalid offset");
     208             : 
     209             :         const std::size_t current_position = static_cast<std::size_t>(stream.tellp());
     210             :         const std::size_t var_size = current_position - var_initial_position;
     211             :         mooseAssert(var_size == sys_header.variables.at(var.name()).size, "Incorrect assumed size");
     212             : #endif
     213             :       }
     214             :     }
     215             :   }
     216             : 
     217             :   mooseAssert((data_initial_position + es_header.data_size) ==
     218             :                   static_cast<std::size_t>(stream.tellp()),
     219             :               "Incorrect assumed size");
     220       45214 : }
     221             : 
     222             : void
     223       14241 : RestartableEquationSystems::load(std::istream & stream)
     224             : {
     225             :   // Load the header (systems, variables, vectors)
     226             :   // We do this first so that the loader can make informed decisions
     227             :   // on what to put where based on everything that is available
     228       14241 :   _loaded_header.systems.clear();
     229       14241 :   dataLoad(stream, _loaded_header, nullptr);
     230             : 
     231             :   // Order objects (elements and then node) by ID for storing
     232       14241 :   _loaded_ordered_objects = orderDofObjects();
     233             : 
     234             :   // Sanity check on if we're loading the same thing
     235             :   {
     236       14241 :     std::vector<dof_id_type> from_ordered_objects_ids;
     237       14241 :     dataLoad(stream, from_ordered_objects_ids, nullptr);
     238       14241 :     if (_loaded_ordered_objects.size() != from_ordered_objects_ids.size())
     239           0 :       mooseError("RestartableEquationSystems::load(): Number of previously stored elements/nodes (",
     240           0 :                  _loaded_ordered_objects.size(),
     241             :                  ") does not "
     242             :                  "match the current number of elements/nodes (",
     243           0 :                  from_ordered_objects_ids.size(),
     244             :                  ")");
     245     3667448 :     for (const auto i : index_range(_loaded_ordered_objects))
     246     3653207 :       if (_loaded_ordered_objects[i]->id() != from_ordered_objects_ids[i])
     247           0 :         mooseError("RestartableEquationSystems::load(): Id of previously stored element/node (",
     248           0 :                    _loaded_ordered_objects[i]->id(),
     249             :                    ") does not "
     250             :                    "match the current element/node id (",
     251           0 :                    from_ordered_objects_ids[i],
     252             :                    ")");
     253       14241 :   }
     254             : 
     255       14241 :   _loaded_stream_data_begin = static_cast<std::size_t>(stream.tellg());
     256             : 
     257             :   // Load everything that we have available at the moment
     258       42840 :   for (const auto & sys_name_header_pair : _loaded_header.systems)
     259             :   {
     260       28599 :     const auto & sys_header = sys_name_header_pair.second;
     261       28599 :     if (!_es.has_system(sys_header.name))
     262          62 :       continue;
     263       28537 :     auto & sys = _es.get_system(sys_header.name);
     264             : 
     265       28537 :     bool modified_sys = false;
     266             : 
     267      148949 :     for (const auto & vec_name_header_pair : sys_header.vectors)
     268             :     {
     269      120412 :       bool modified_vec = false;
     270             : 
     271      120412 :       const auto & vec_header = vec_name_header_pair.second;
     272      120412 :       const bool is_solution = vec_header.name == SystemHeader::system_solution_name;
     273             : 
     274      120412 :       if (!is_solution && !sys.have_vector(vec_header.name))
     275             :       {
     276         102 :         if (_load_all_vectors)
     277          18 :           sys.add_vector(vec_header.name, vec_header.projections, vec_header.type);
     278             :         else
     279          84 :           continue;
     280             :       }
     281             : 
     282      120328 :       auto & vec = is_solution ? *sys.solution : sys.get_vector(vec_header.name);
     283             : 
     284      238918 :       for (const auto & var_name_header_pair : sys_header.variables)
     285             :       {
     286      118590 :         const auto & var_header = var_name_header_pair.second;
     287      118590 :         if (!sys.has_variable(var_header.name))
     288          14 :           continue;
     289      118576 :         const auto & var = sys.variable(sys.variable_number(var_header.name));
     290      118576 :         if (var.type() != var_header.type)
     291           0 :           continue;
     292             : 
     293      118576 :         restore(sys_header, vec_header, var_header, sys, vec, var, stream);
     294      118576 :         modified_vec = true;
     295             :       }
     296             : 
     297      120328 :       if (modified_vec)
     298             :       {
     299       96893 :         vec.close();
     300       96893 :         modified_sys = true;
     301             :       }
     302             :     }
     303             : 
     304       28537 :     if (modified_sys)
     305       21831 :       sys.update();
     306             :   }
     307             : 
     308             :   // Move the stream to the end of our data so that we make RestartableDataReader happy
     309       14241 :   stream.seekg(_loaded_stream_data_begin + _loaded_header.data_size);
     310       14241 : }
     311             : 
     312             : void
     313      118576 : RestartableEquationSystems::restore(const SystemHeader & from_sys_header,
     314             :                                     const VectorHeader & from_vec_header,
     315             :                                     const VariableHeader & from_var_header,
     316             :                                     const libMesh::System & to_sys,
     317             :                                     libMesh::NumericVector<libMesh::Number> & to_vec,
     318             :                                     const libMesh::Variable & to_var,
     319             :                                     std::istream & stream)
     320             : {
     321             : #ifndef NDEBUG
     322             :   const auto sys_it = _loaded_header.systems.find(from_sys_header.name);
     323             :   mooseAssert(sys_it != _loaded_header.systems.end(), "System does not exist");
     324             :   const auto & sys_header = sys_it->second;
     325             :   mooseAssert(sys_header == from_sys_header, "Not my system");
     326             :   const auto vec_it = sys_header.vectors.find(from_vec_header.name);
     327             :   mooseAssert(vec_it != sys_header.vectors.end(), "Vector does not exist");
     328             :   const auto & vec_header = vec_it->second;
     329             :   mooseAssert(vec_header == from_vec_header, "Not my vector");
     330             :   const auto var_it = sys_header.variables.find(from_var_header.name);
     331             :   mooseAssert(var_it != sys_header.variables.end(), "Variable does not exist");
     332             :   const auto & var_header = var_it->second;
     333             :   mooseAssert(var_header == from_var_header, "Not my variable");
     334             : #endif
     335             : 
     336             :   const auto error =
     337           0 :       [&from_sys_header, &from_vec_header, &from_var_header, &to_sys, &to_var](auto... args)
     338             :   {
     339           0 :     mooseError("An error occured while restoring a system:\n",
     340             :                args...,
     341             :                "\n\nFrom system: ",
     342           0 :                from_sys_header.name,
     343             :                "\nFrom vector: ",
     344           0 :                from_vec_header.name,
     345             :                "\nFrom variable: ",
     346           0 :                from_var_header.name,
     347             :                "\nTo system: ",
     348           0 :                to_sys.name(),
     349             :                "\nTo variable: ",
     350           0 :                to_var.name());
     351      118576 :   };
     352             : 
     353      118576 :   if (from_var_header.type != to_var.type())
     354           0 :     error("Cannot restore to a variable of a different type");
     355             : 
     356      118576 :   const auto offset = from_vec_header.variable_offset.at(from_var_header.name);
     357      118576 :   stream.seekg(_loaded_stream_data_begin + offset);
     358             : 
     359             :   // Non-SCALAR variable
     360      118576 :   if (to_var.type().family != SCALAR)
     361             :   {
     362    27280799 :     for (const auto & obj : _loaded_ordered_objects)
     363    41227670 :       for (const auto comp : make_range(obj->n_comp(to_sys.number(), to_var.number())))
     364             :       {
     365             :         Real val;
     366    14064752 :         dataLoad(stream, val, nullptr);
     367    14064752 :         to_vec.set(obj->dof_number(to_sys.number(), to_var.number(), comp), val);
     368             :       }
     369             :   }
     370             :   // SCALAR variable on the last rank
     371         695 :   else if (_es.processor_id() == _es.n_processors() - 1)
     372             :   {
     373         692 :     const auto & dof_map = to_sys.get_dof_map();
     374         692 :     std::vector<dof_id_type> scalar_dofs;
     375         692 :     dof_map.SCALAR_dof_indices(scalar_dofs, to_var.number());
     376        1627 :     for (const auto dof : scalar_dofs)
     377             :     {
     378             :       Real val;
     379         935 :       dataLoad(stream, val, nullptr);
     380         935 :       to_vec.set(dof, val);
     381             :     }
     382         692 :   }
     383      118576 : }
     384             : 
     385             : void
     386       45214 : dataStore(std::ostream & stream, RestartableEquationSystems & res, void *)
     387             : {
     388       45214 :   res.store(stream);
     389       45214 : }
     390             : 
     391             : void
     392       14241 : dataLoad(std::istream & stream, RestartableEquationSystems & res, void *)
     393             : {
     394       14241 :   res.load(stream);
     395       14241 : }
     396             : 
     397             : void
     398       45214 : dataStore(std::ostream & stream, RestartableEquationSystems::EquationSystemsHeader & header, void *)
     399             : {
     400       45214 :   dataStore(stream, header.systems, nullptr);
     401       45214 :   dataStore(stream, header.data_size, nullptr);
     402       45214 : }
     403             : 
     404             : void
     405       14241 : dataLoad(std::istream & stream, RestartableEquationSystems::EquationSystemsHeader & header, void *)
     406             : {
     407       14241 :   dataLoad(stream, header.systems, nullptr);
     408       14241 :   dataLoad(stream, header.data_size, nullptr);
     409       14241 : }
     410             : 
     411             : void
     412       91452 : dataStore(std::ostream & stream, RestartableEquationSystems::SystemHeader & header, void *)
     413             : {
     414       91452 :   dataStore(stream, header.name, nullptr);
     415       91452 :   dataStore(stream, header.type, nullptr);
     416       91452 :   dataStore(stream, header.variables, nullptr);
     417       91452 :   dataStore(stream, header.vectors, nullptr);
     418       91452 : }
     419             : 
     420             : void
     421       28599 : dataLoad(std::istream & stream, RestartableEquationSystems::SystemHeader & header, void *)
     422             : {
     423       28599 :   dataLoad(stream, header.name, nullptr);
     424       28599 :   dataLoad(stream, header.type, nullptr);
     425       28599 :   dataLoad(stream, header.variables, nullptr);
     426       28599 :   dataLoad(stream, header.vectors, nullptr);
     427       28599 : }
     428             : 
     429             : void
     430       91591 : dataStore(std::ostream & stream, RestartableEquationSystems::VariableHeader & header, void *)
     431             : {
     432       91591 :   dataStore(stream, header.name, nullptr);
     433       91591 :   dataStore(stream, header.type, nullptr);
     434       91591 : }
     435             : void
     436       29028 : dataLoad(std::istream & stream, RestartableEquationSystems::VariableHeader & header, void *)
     437             : {
     438       29028 :   dataLoad(stream, header.name, nullptr);
     439       29028 :   dataLoad(stream, header.type, nullptr);
     440       29028 : }
     441             : 
     442             : void
     443      430719 : dataStore(std::ostream & stream, RestartableEquationSystems::VectorHeader & header, void *)
     444             : {
     445      430719 :   dataStore(stream, header.name, nullptr);
     446      430719 :   dataStore(stream, header.projections, nullptr);
     447      430719 :   dataStore(stream, header.type, nullptr);
     448      430719 :   dataStore(stream, header.variable_offset, nullptr);
     449      430719 : }
     450             : void
     451      120540 : dataLoad(std::istream & stream, RestartableEquationSystems::VectorHeader & header, void *)
     452             : {
     453      120540 :   dataLoad(stream, header.name, nullptr);
     454      120540 :   dataLoad(stream, header.projections, nullptr);
     455      120540 :   dataLoad(stream, header.type, nullptr);
     456      120540 :   dataLoad(stream, header.variable_offset, nullptr);
     457      120540 : }

Generated by: LCOV version 1.14