LCOV - code coverage report
Current view: top level - src/outputs - Nemesis.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 88 98 89.8 %
Date: 2025-07-17 01:28:37 Functions: 9 9 100.0 %
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 "Nemesis.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "FEProblem.h"
      14             : #include "MooseApp.h"
      15             : #include "MooseMesh.h"
      16             : #include "MooseVariableScalar.h"
      17             : #include "SystemBase.h"
      18             : 
      19             : #include "libmesh/dof_map.h"
      20             : #include "libmesh/nemesis_io.h"
      21             : 
      22             : using namespace libMesh;
      23             : 
      24             : registerMooseObject("MooseApp", Nemesis);
      25             : 
      26             : InputParameters
      27       14761 : Nemesis::validParams()
      28             : {
      29       14761 :   InputParameters params = AdvancedOutput::validParams();
      30       14761 :   params += AdvancedOutput::enableOutputTypes("scalar postprocessor input");
      31       14761 :   params.addParam<bool>("write_hdf5", false, "Enables HDF5 output format for Nemesis files.");
      32       14761 :   params.addClassDescription("Object for output data in the Nemesis (parallel ExodusII) format.");
      33       14761 :   return params;
      34           0 : }
      35             : 
      36         248 : Nemesis::Nemesis(const InputParameters & parameters)
      37             :   : AdvancedOutput(parameters),
      38         248 :     _nemesis_io_ptr(nullptr),
      39         248 :     _file_num(declareRestartableData<unsigned int>("nemesis_file_num", 0)),
      40         248 :     _nemesis_num(declareRestartableData<unsigned int>("nemesis_num", 0)),
      41         248 :     _nemesis_initialized(false),
      42         248 :     _recovering(_app.isRecovering()),
      43         248 :     _nemesis_mesh_changed(declareRestartableData<bool>("nemesis_mesh_changed", true)),
      44         496 :     _write_hdf5(getParam<bool>("write_hdf5"))
      45             : {
      46         248 : }
      47             : 
      48             : void
      49         248 : Nemesis::initialSetup()
      50             : {
      51         248 :   AdvancedOutput::initialSetup();
      52         248 : }
      53             : 
      54             : void
      55         217 : Nemesis::meshChanged()
      56             : {
      57             :   // Do not delete the Nemesis_IO object if it has not been used; also there is no need to setup
      58             :   // the object in this case, so just return
      59         217 :   if (_nemesis_io_ptr != nullptr && !_nemesis_initialized)
      60           0 :     return;
      61             : 
      62             :   // Indicate to the Nemesis object that the mesh has changed
      63         217 :   _nemesis_mesh_changed = true;
      64             : }
      65             : 
      66             : void
      67         863 : Nemesis::outputSetup()
      68             : {
      69         863 :   if (_nemesis_io_ptr)
      70             :   {
      71             :     // Do nothing if the Nemesis_IO objects exists, but has not been initialized
      72         626 :     if (!_nemesis_initialized)
      73           0 :       return;
      74             : 
      75             :     // Do nothing if the mesh has not changed
      76         626 :     if (!_nemesis_mesh_changed)
      77         514 :       return;
      78             :   }
      79             : 
      80             :   // Create the new NemesisIO object
      81         349 :   _nemesis_io_ptr = std::make_unique<Nemesis_IO>(_problem_ptr->mesh().getMesh());
      82         349 :   _nemesis_initialized = false;
      83             : 
      84         349 :   if (_write_hdf5)
      85             :   {
      86             : #ifndef LIBMESH_HAVE_HDF5
      87             :     mooseError("Moose input requested HDF Nemesis output, but libMesh was built without HDF5.");
      88             : #endif
      89             : 
      90             :     // This is redundant unless the libMesh default changes
      91           0 :     _nemesis_io_ptr->set_hdf5_writing(true);
      92             :   }
      93             :   else
      94             :   {
      95         349 :     _nemesis_io_ptr->set_hdf5_writing(false);
      96             :   }
      97             : 
      98         349 :   if (_recovering && !_nemesis_mesh_changed && _nemesis_num > 0)
      99             :   {
     100             :     // Set the recovering flag to false so that this special case is not triggered again
     101          17 :     _recovering = false;
     102             : 
     103             :     // Set the append flag to true b/c on recover the file is being appended
     104          17 :     _nemesis_io_ptr->append(true);
     105             :   }
     106             :   else
     107             :   {
     108             :     // Increment file counter
     109         332 :     if (_nemesis_mesh_changed)
     110         332 :       _file_num++;
     111             : 
     112             :     // Disable file appending and reset nemesis file number count
     113         332 :     _nemesis_io_ptr->append(false);
     114         332 :     _nemesis_num = 1;
     115             :   }
     116             : }
     117             : 
     118             : void
     119          72 : Nemesis::outputPostprocessors()
     120             : {
     121             :   // List of desired postprocessor outputs
     122          72 :   const std::set<std::string> & pps = getPostprocessorOutput();
     123             : 
     124             :   // Append the postprocessor data to the global name value parameters; scalar outputs
     125             :   // also append these member variables
     126         144 :   for (const auto & name : pps)
     127             :   {
     128          72 :     _global_names.push_back(name);
     129          72 :     _global_values.push_back(_problem_ptr->getPostprocessorValueByName(name));
     130             :   }
     131          72 : }
     132             : 
     133             : void
     134         112 : Nemesis::outputScalarVariables()
     135             : {
     136             :   // List of desired scalar outputs
     137         112 :   const std::set<std::string> & out = getScalarOutput();
     138             : 
     139             :   // Append the scalar to the global output lists
     140         448 :   for (const auto & out_name : out)
     141             :   {
     142             :     // Make sure scalar values are in sync with the solution vector
     143             :     // and are visible on this processor.  See TableOutput.C for
     144             :     // TableOutput::outputScalarVariables() explanatory comments
     145             : 
     146         336 :     MooseVariableScalar & scalar_var = _problem_ptr->getScalarVariable(0, out_name);
     147         336 :     scalar_var.reinit();
     148         336 :     VariableValue value(scalar_var.sln());
     149             : 
     150         336 :     const std::vector<dof_id_type> & dof_indices = scalar_var.dofIndices();
     151         336 :     const unsigned int n = dof_indices.size();
     152         336 :     value.resize(n);
     153             : 
     154         336 :     const DofMap & dof_map = scalar_var.sys().dofMap();
     155         672 :     for (unsigned int i = 0; i != n; ++i)
     156             :     {
     157         336 :       const processor_id_type pid = dof_map.dof_owner(dof_indices[i]);
     158         336 :       this->comm().broadcast(value[i], pid);
     159             :     }
     160             : 
     161             :     // If the scalar has a single component, output the name directly
     162         336 :     if (n == 1)
     163             :     {
     164         336 :       _global_names.push_back(out_name);
     165         336 :       _global_values.push_back(value[0]);
     166             :     }
     167             : 
     168             :     // If the scalar as many components add indices to the end of the name
     169             :     else
     170             :     {
     171           0 :       for (unsigned int i = 0; i < n; ++i)
     172             :       {
     173           0 :         std::ostringstream os;
     174           0 :         os << out_name << "_" << i;
     175           0 :         _global_names.push_back(os.str());
     176           0 :         _global_values.push_back(value[i]);
     177           0 :       }
     178             :     }
     179         336 :   }
     180         112 : }
     181             : 
     182             : void
     183         863 : Nemesis::output()
     184             : {
     185         863 :   outputSetup();
     186             : 
     187             :   // Clear the global variables (postprocessors and scalars)
     188         863 :   _global_names.clear();
     189         863 :   _global_values.clear();
     190             : 
     191             :   // Call the output methods
     192         863 :   AdvancedOutput::output();
     193             : 
     194             :   // Set up the whitelist of nodal variable names to write.
     195        1726 :   _nemesis_io_ptr->set_output_variables(
     196        1726 :       std::vector<std::string>(getNodalVariableOutput().begin(), getNodalVariableOutput().end()));
     197             : 
     198             :   // Write nodal data
     199        1726 :   _nemesis_io_ptr->write_timestep(
     200        1726 :       filename(), *_es_ptr, _nemesis_num, getOutputTime() + _app.getGlobalTimeOffset());
     201         863 :   _nemesis_initialized = true;
     202             : 
     203             :   // Write elemental data
     204         863 :   std::vector<std::string> elemental(getElementalVariableOutput().begin(),
     205        1726 :                                      getElementalVariableOutput().end());
     206         863 :   _nemesis_io_ptr->set_output_variables(elemental);
     207         863 :   _nemesis_io_ptr->write_element_data(*_es_ptr);
     208             : 
     209             :   // Increment output call counter for the current file
     210         863 :   _nemesis_num++;
     211             : 
     212             :   // Write the global variables (populated by the output methods)
     213         863 :   if (!_global_values.empty())
     214         184 :     _nemesis_io_ptr->write_global_data(_global_values, _global_names);
     215             : 
     216             :   // Reset the mesh changed flag
     217         863 :   _nemesis_mesh_changed = false;
     218         863 : }
     219             : 
     220             : std::string
     221        1111 : Nemesis::filename()
     222             : {
     223             :   // Append the .e extension on the base file name
     224        1111 :   std::ostringstream output;
     225        1111 :   output << _file_base << ".e";
     226             : 
     227             :   // Add the _000x extension to the file
     228        1111 :   if (_file_num > 1)
     229         112 :     output << "-s" << std::setw(_padding) << std::setprecision(0) << std::setfill('0') << std::right
     230         112 :            << _file_num;
     231             : 
     232             :   // Return the filename
     233        2222 :   return output.str();
     234        1111 : }

Generated by: LCOV version 1.14