LCOV - code coverage report
Current view: top level - src/restart - RestartableEquationSystems.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 199 216 92.1 %
Date: 2025-07-17 01:28:37 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       57974 : RestartableEquationSystems::RestartableEquationSystems(libMesh::MeshBase & mesh)
      23       57974 :   : _es(mesh), _load_all_vectors(true)
      24             : {
      25       57974 : }
      26             : 
      27             : RestartableEquationSystems::EquationSystemsHeader
      28       41839 : RestartableEquationSystems::buildHeader(
      29             :     const std::vector<const libMesh::DofObject *> & ordered_objects) const
      30             : {
      31       41839 :   EquationSystemsHeader es_header;
      32             : 
      33             :   // Systems
      34      126453 :   for (const auto sys_num : make_range(_es.n_systems()))
      35             :   {
      36       84614 :     const auto & sys = _es.get_system(sys_num);
      37             : 
      38       84614 :     SystemHeader sys_header;
      39       84614 :     sys_header.name = sys.name();
      40       84614 :     sys_header.type = sys.system_type();
      41             : 
      42             :     // Variables in the system
      43      170258 :     for (const auto var_num : make_range(sys.n_vars()))
      44             :     {
      45       85644 :       const auto & var = sys.variable(var_num);
      46             : 
      47       85644 :       VariableHeader var_header;
      48       85644 :       var_header.name = var.name();
      49       85644 :       var_header.type = var.type();
      50       85644 :       var_header.size = 0;
      51       85644 :       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       85644 :       if (var.type().family != SCALAR)
      59             :       {
      60    17345094 :         for (const auto & obj : ordered_objects)
      61    17261066 :           var_header.size += sizeof(Real) * obj->n_comp(sys.number(), var.number());
      62             :       }
      63             :       // SCALAR variable on the last rank
      64        1616 :       else if (_es.processor_id() == _es.n_processors() - 1)
      65             :       {
      66        1579 :         std::vector<dof_id_type> scalar_dofs;
      67        1579 :         sys.get_dof_map().SCALAR_dof_indices(scalar_dofs, var.number());
      68        1579 :         var_header.size += sizeof(Real) * scalar_dofs.size();
      69        1579 :       }
      70             : 
      71       85644 :       sys_header.variables.emplace(var.name(), var_header);
      72       85644 :     }
      73             : 
      74             :     // System vector
      75       84614 :     auto & sys_vec_header = sys_header.vectors[SystemHeader::system_solution_name];
      76       84614 :     sys_vec_header.name = SystemHeader::system_solution_name;
      77       84614 :     sys_vec_header.vector = sys.solution.get();
      78       84614 :     sys_vec_header.type = sys_vec_header.vector->type();
      79      398922 :     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      314308 :       const auto & name = sys.vector_name(vec_num);
      84             :       mooseAssert(!sys_header.vectors.count(name), "Already inserted");
      85      314308 :       auto & vec_header = sys_header.vectors[name];
      86      314308 :       vec_header.name = sys.vector_name(vec_num);
      87      314308 :       vec_header.projections = sys.vector_preservation(vec_header.name);
      88      314308 :       vec_header.vector = &sys.get_vector(vec_header.name);
      89      314308 :       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       84614 :     es_header.systems.emplace(sys.name(), sys_header);
      95       84614 :   }
      96             : 
      97             :   // Setup the positions in each vector for easy access later
      98       41839 :   std::size_t offset = 0;
      99      126453 :   for (auto & sys_name_header_pair : es_header.systems)
     100             :   {
     101       84614 :     auto & sys_header = sys_name_header_pair.second;
     102      483536 :     for (auto & vec_name_header_pair : sys_header.vectors)
     103             :     {
     104      398922 :       auto & vec_header = vec_name_header_pair.second;
     105      801846 :       for (const auto & var_name_header_pair : sys_header.variables)
     106             :       {
     107      402924 :         const auto & var_header = var_name_header_pair.second;
     108             :         mooseAssert(!vec_header.variable_offset.count(var_header.name), "Already inserted");
     109      402924 :         vec_header.variable_offset[var_header.name] = offset;
     110      402924 :         offset += var_header.size;
     111             :       }
     112             :     }
     113             :   }
     114             : 
     115       41839 :   es_header.data_size = offset;
     116             : 
     117       41839 :   return es_header;
     118           0 : }
     119             : 
     120             : std::vector<const libMesh::DofObject *>
     121       55047 : RestartableEquationSystems::orderDofObjects() const
     122             : {
     123       55047 :   std::vector<const libMesh::DofObject *> objects;
     124      330282 :   auto add = [&objects](const auto begin, const auto end)
     125             :   {
     126      110094 :     std::set<const libMesh::DofObject *, libMesh::CompareDofObjectsByID> ordered(begin, end);
     127      110094 :     objects.insert(objects.end(), ordered.begin(), ordered.end());
     128      165141 :   };
     129             : 
     130       55047 :   const auto & mesh = _es.get_mesh();
     131       55047 :   add(mesh.local_elements_begin(), mesh.local_elements_end());
     132       55047 :   add(mesh.local_nodes_begin(), mesh.local_nodes_end());
     133             : 
     134      110094 :   return objects;
     135           0 : }
     136             : 
     137             : void
     138       41839 : RestartableEquationSystems::store(std::ostream & stream) const
     139             : {
     140             :   // Order objects (elements and then nodes) by ID for storing
     141       41839 :   const auto ordered_objects = orderDofObjects();
     142             : 
     143             :   // Store the header (systems, variables, vectors)
     144       41839 :   EquationSystemsHeader es_header = buildHeader(ordered_objects);
     145       41839 :   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       41839 :     std::vector<dof_id_type> ordered_objects_ids(ordered_objects.size());
     151     9142325 :     for (const auto i : index_range(ordered_objects))
     152     9100486 :       ordered_objects_ids[i] = ordered_objects[i]->id();
     153       41839 :     dataStore(stream, ordered_objects_ids, nullptr);
     154       41839 :   }
     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      126453 :   for (const auto & sys_name_header_pair : es_header.systems)
     162             :   {
     163       84614 :     const auto & sys_header = sys_name_header_pair.second;
     164       84614 :     const auto & sys = _es.get_system(sys_header.name);
     165             : 
     166             :     // Store each vector and variable
     167      483536 :     for (const auto & vec_name_header_pair : sys_header.vectors)
     168             :     {
     169      398922 :       const auto & vec_header = vec_name_header_pair.second;
     170      398922 :       const auto & vec = *vec_header.vector;
     171      801846 :       for (const auto & var_name_header_pair : sys_header.variables)
     172             :       {
     173      402924 :         const auto & var_header = var_name_header_pair.second;
     174      402924 :         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      402924 :         if (var.type().family != SCALAR)
     182             :         {
     183             :           // Store for each component of each element and node
     184    76253790 :           for (const auto & obj : ordered_objects)
     185   114705791 :             for (const auto comp : make_range(obj->n_comp(sys.number(), var.number())))
     186             :             {
     187    38847016 :               auto val = vec(obj->dof_number(sys.number(), var.number(), comp));
     188    38847016 :               dataStore(stream, val, nullptr);
     189             :             }
     190             :         }
     191             :         // SCALAR variable on the last rank
     192        7909 :         else if (_es.processor_id() == _es.n_processors() - 1)
     193             :         {
     194        7798 :           const auto & dof_map = sys.get_dof_map();
     195        7798 :           std::vector<dof_id_type> scalar_dofs;
     196        7798 :           dof_map.SCALAR_dof_indices(scalar_dofs, var.number());
     197       16794 :           for (const auto dof : scalar_dofs)
     198             :           {
     199        8996 :             auto val = vec(dof);
     200        8996 :             dataStore(stream, val, nullptr);
     201             :           }
     202        7798 :         }
     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       41839 : }
     221             : 
     222             : void
     223       13208 : 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       13208 :   _loaded_header.systems.clear();
     229       13208 :   dataLoad(stream, _loaded_header, nullptr);
     230             : 
     231             :   // Order objects (elements and then node) by ID for storing
     232       13208 :   _loaded_ordered_objects = orderDofObjects();
     233             : 
     234             :   // Sanity check on if we're loading the same thing
     235             :   {
     236       13208 :     std::vector<dof_id_type> from_ordered_objects_ids;
     237       13208 :     dataLoad(stream, from_ordered_objects_ids, nullptr);
     238       13208 :     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     3467848 :     for (const auto i : index_range(_loaded_ordered_objects))
     246     3454640 :       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       13208 :   }
     254             : 
     255       13208 :   _loaded_stream_data_begin = static_cast<std::size_t>(stream.tellg());
     256             : 
     257             :   // Load everything that we have available at the moment
     258       39720 :   for (const auto & sys_name_header_pair : _loaded_header.systems)
     259             :   {
     260       26512 :     const auto & sys_header = sys_name_header_pair.second;
     261       26512 :     if (!_es.has_system(sys_header.name))
     262          58 :       continue;
     263       26454 :     auto & sys = _es.get_system(sys_header.name);
     264             : 
     265       26454 :     bool modified_sys = false;
     266             : 
     267      138226 :     for (const auto & vec_name_header_pair : sys_header.vectors)
     268             :     {
     269      111772 :       bool modified_vec = false;
     270             : 
     271      111772 :       const auto & vec_header = vec_name_header_pair.second;
     272      111772 :       const bool is_solution = vec_header.name == SystemHeader::system_solution_name;
     273             : 
     274      111772 :       if (!is_solution && !sys.have_vector(vec_header.name))
     275             :       {
     276          95 :         if (_load_all_vectors)
     277          18 :           sys.add_vector(vec_header.name, vec_header.projections, vec_header.type);
     278             :         else
     279          77 :           continue;
     280             :       }
     281             : 
     282      111695 :       auto & vec = is_solution ? *sys.solution : sys.get_vector(vec_header.name);
     283             : 
     284      222449 :       for (const auto & var_name_header_pair : sys_header.variables)
     285             :       {
     286      110754 :         const auto & var_header = var_name_header_pair.second;
     287      110754 :         if (!sys.has_variable(var_header.name))
     288          13 :           continue;
     289      110741 :         const auto & var = sys.variable(sys.variable_number(var_header.name));
     290      110741 :         if (var.type() != var_header.type)
     291           0 :           continue;
     292             : 
     293      110741 :         restore(sys_header, vec_header, var_header, sys, vec, var, stream);
     294      110741 :         modified_vec = true;
     295             :       }
     296             : 
     297      111695 :       if (modified_vec)
     298             :       {
     299       90193 :         vec.close();
     300       90193 :         modified_sys = true;
     301             :       }
     302             :     }
     303             : 
     304       26454 :     if (modified_sys)
     305       20301 :       sys.update();
     306             :   }
     307             : 
     308             :   // Move the stream to the end of our data so that we make RestartableDataReader happy
     309       13208 :   stream.seekg(_loaded_stream_data_begin + _loaded_header.data_size);
     310       13208 : }
     311             : 
     312             : void
     313      110741 : 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      110741 :   };
     352             : 
     353      110741 :   if (from_var_header.type != to_var.type())
     354           0 :     error("Cannot restore to a variable of a different type");
     355             : 
     356      110741 :   const auto offset = from_vec_header.variable_offset.at(from_var_header.name);
     357      110741 :   stream.seekg(_loaded_stream_data_begin + offset);
     358             : 
     359             :   // Non-SCALAR variable
     360      110741 :   if (to_var.type().family != SCALAR)
     361             :   {
     362    25760971 :     for (const auto & obj : _loaded_ordered_objects)
     363    38904244 :       for (const auto comp : make_range(obj->n_comp(to_sys.number(), to_var.number())))
     364             :       {
     365             :         Real val;
     366    13253374 :         dataLoad(stream, val, nullptr);
     367    13253374 :         to_vec.set(obj->dof_number(to_sys.number(), to_var.number(), comp), val);
     368             :       }
     369             :   }
     370             :   // SCALAR variable on the last rank
     371         640 :   else if (_es.processor_id() == _es.n_processors() - 1)
     372             :   {
     373         637 :     const auto & dof_map = to_sys.get_dof_map();
     374         637 :     std::vector<dof_id_type> scalar_dofs;
     375         637 :     dof_map.SCALAR_dof_indices(scalar_dofs, to_var.number());
     376        1451 :     for (const auto dof : scalar_dofs)
     377             :     {
     378             :       Real val;
     379         814 :       dataLoad(stream, val, nullptr);
     380         814 :       to_vec.set(dof, val);
     381             :     }
     382         637 :   }
     383      110741 : }
     384             : 
     385             : void
     386       41839 : dataStore(std::ostream & stream, RestartableEquationSystems & res, void *)
     387             : {
     388       41839 :   res.store(stream);
     389       41839 : }
     390             : 
     391             : void
     392       13208 : dataLoad(std::istream & stream, RestartableEquationSystems & res, void *)
     393             : {
     394       13208 :   res.load(stream);
     395       13208 : }
     396             : 
     397             : void
     398       41839 : dataStore(std::ostream & stream, RestartableEquationSystems::EquationSystemsHeader & header, void *)
     399             : {
     400       41839 :   dataStore(stream, header.systems, nullptr);
     401       41839 :   dataStore(stream, header.data_size, nullptr);
     402       41839 : }
     403             : 
     404             : void
     405       13208 : dataLoad(std::istream & stream, RestartableEquationSystems::EquationSystemsHeader & header, void *)
     406             : {
     407       13208 :   dataLoad(stream, header.systems, nullptr);
     408       13208 :   dataLoad(stream, header.data_size, nullptr);
     409       13208 : }
     410             : 
     411             : void
     412       84614 : dataStore(std::ostream & stream, RestartableEquationSystems::SystemHeader & header, void *)
     413             : {
     414       84614 :   dataStore(stream, header.name, nullptr);
     415       84614 :   dataStore(stream, header.type, nullptr);
     416       84614 :   dataStore(stream, header.variables, nullptr);
     417       84614 :   dataStore(stream, header.vectors, nullptr);
     418       84614 : }
     419             : 
     420             : void
     421       26512 : dataLoad(std::istream & stream, RestartableEquationSystems::SystemHeader & header, void *)
     422             : {
     423       26512 :   dataLoad(stream, header.name, nullptr);
     424       26512 :   dataLoad(stream, header.type, nullptr);
     425       26512 :   dataLoad(stream, header.variables, nullptr);
     426       26512 :   dataLoad(stream, header.vectors, nullptr);
     427       26512 : }
     428             : 
     429             : void
     430       85644 : dataStore(std::ostream & stream, RestartableEquationSystems::VariableHeader & header, void *)
     431             : {
     432       85644 :   dataStore(stream, header.name, nullptr);
     433       85644 :   dataStore(stream, header.type, nullptr);
     434       85644 : }
     435             : void
     436       27177 : dataLoad(std::istream & stream, RestartableEquationSystems::VariableHeader & header, void *)
     437             : {
     438       27177 :   dataLoad(stream, header.name, nullptr);
     439       27177 :   dataLoad(stream, header.type, nullptr);
     440       27177 : }
     441             : 
     442             : void
     443      398922 : dataStore(std::ostream & stream, RestartableEquationSystems::VectorHeader & header, void *)
     444             : {
     445      398922 :   dataStore(stream, header.name, nullptr);
     446      398922 :   dataStore(stream, header.projections, nullptr);
     447      398922 :   dataStore(stream, header.type, nullptr);
     448      398922 :   dataStore(stream, header.variable_offset, nullptr);
     449      398922 : }
     450             : void
     451      111892 : dataLoad(std::istream & stream, RestartableEquationSystems::VectorHeader & header, void *)
     452             : {
     453      111892 :   dataLoad(stream, header.name, nullptr);
     454      111892 :   dataLoad(stream, header.projections, nullptr);
     455      111892 :   dataLoad(stream, header.type, nullptr);
     456      111892 :   dataLoad(stream, header.variable_offset, nullptr);
     457      111892 : }

Generated by: LCOV version 1.14