LCOV - code coverage report
Current view: top level - src/actions - MeshOnlyAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 84 86 97.7 %
Date: 2025-07-17 01:28:37 Functions: 3 3 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 "MeshOnlyAction.h"
      11             : 
      12             : #include "MooseApp.h"
      13             : #include "MooseMesh.h"
      14             : #include "Exodus.h"
      15             : #include "AddOutputAction.h"
      16             : #include "RestartableDataWriter.h"
      17             : 
      18             : #include <filesystem>
      19             : 
      20             : #include "libmesh/exodusII_io.h"
      21             : #include "libmesh/exodusII_io_helper.h"
      22             : #include "libmesh/checkpoint_io.h"
      23             : 
      24             : using namespace libMesh;
      25             : 
      26             : registerMooseAction("MooseApp", MeshOnlyAction, "mesh_only");
      27             : 
      28             : InputParameters
      29        3531 : MeshOnlyAction::validParams()
      30             : {
      31        3531 :   return Action::validParams();
      32             : }
      33             : 
      34        3531 : MeshOnlyAction::MeshOnlyAction(const InputParameters & params) : Action(params) {}
      35             : 
      36             : void
      37        3031 : MeshOnlyAction::act()
      38             : {
      39             :   // Run error checking on input file first before trying to generate a mesh
      40        3031 :   bool warn = _app.unusedFlagIsWarning();
      41        3031 :   bool err = _app.unusedFlagIsError();
      42        3031 :   _app.builder().errorCheck(comm(), warn, err);
      43             : 
      44        3027 :   std::string mesh_file = _app.parameters().get<std::string>("mesh_only");
      45        3027 :   auto & mesh_ptr = _app.actionWarehouse().mesh();
      46             : 
      47             :   // Print information about the mesh
      48        3027 :   _console << mesh_ptr->getMesh().get_info(/* verbosity = */ 2) << std::endl;
      49             : 
      50        3027 :   if (mesh_file.empty())
      51             :   {
      52        2178 :     mesh_file = _app.builder().getPrimaryFileName();
      53        2178 :     size_t pos = mesh_file.find_last_of('.');
      54             : 
      55             :     // Default to writing out an ExodusII mesh base on the input filename.
      56        2178 :     mesh_file = mesh_file.substr(0, pos) + "_in.e";
      57             :   }
      58             : 
      59             :   /**
      60             :    * If we're writing an Exodus file, write the Mesh using it's effective spatial dimension unless
      61             :    * it's a 1D mesh. This is to work around a Paraview bug where 1D meshes are not visualized
      62             :    * properly.
      63             :    */
      64        3027 :   if (mesh_file.find(".e") + 2 == mesh_file.size())
      65             :   {
      66        3006 :     TIME_SECTION("act", 1, "Writing Exodus");
      67             : 
      68        3006 :     auto & output_mesh = mesh_ptr->getMesh();
      69        3006 :     ExodusII_IO exio(output_mesh);
      70             : 
      71        3006 :     Exodus::setOutputDimensionInExodusWriter(exio, *mesh_ptr);
      72             : 
      73             :     // Default to non-HDF5 output for wider compatibility
      74        3006 :     exio.set_hdf5_writing(false);
      75             : 
      76        3006 :     exio.write(mesh_file);
      77             : 
      78             :     // Check if extra element integers should be outputted to Exodus file
      79        3002 :     unsigned int n_eeid = output_mesh.n_elem_integers();
      80             : 
      81             :     // Iterate through all actions and see if `Outputs/output_extra_element_ids = true` in input
      82             :     // file
      83        3002 :     const auto & output_actions = _app.actionWarehouse().getActionListByName("add_output");
      84             :     // Truth of whether to output extra element ids is initially determined by whether
      85             :     // there are extra element ids defined on the mesh
      86        3002 :     bool output_extra_ids = (n_eeid > 0);
      87        3002 :     bool restrict_element_id_names = false;
      88        3002 :     std::vector<std::string> element_id_names;
      89       16180 :     for (const auto & act : output_actions)
      90             :     {
      91             :       // Extract the Output action
      92       13232 :       AddOutputAction * action = dynamic_cast<AddOutputAction *>(act);
      93       13232 :       if (!action)
      94        3002 :         continue;
      95             : 
      96       10230 :       InputParameters & params = action->getObjectParams();
      97       10230 :       if (params.isParamSetByUser("output_extra_element_ids"))
      98             :       {
      99             :         // User has set output_extra_element_ids, truth of output_extra_ids determined by value of
     100             :         // parameter
     101          54 :         output_extra_ids = params.get<bool>("output_extra_element_ids");
     102          54 :         if (output_extra_ids)
     103             :         {
     104             :           // `Outputs/extra_element_ids_to_output` sets a subset of extra element ids that should
     105             :           // be outputted to Exodus
     106          14 :           restrict_element_id_names = params.isParamValid("extra_element_ids_to_output");
     107          14 :           if (restrict_element_id_names)
     108             :           {
     109          14 :             element_id_names = params.get<std::vector<std::string>>("extra_element_ids_to_output");
     110             :             // Check which element id names actually are defined on the mesh, remove from
     111             :             // element_id_names if they don't belong
     112          24 :             for (auto it = element_id_names.begin(); it != element_id_names.end();)
     113             :             {
     114             :               // Erase contents of iterator and return iterator if element integer does not exist
     115          14 :               if (!output_mesh.has_elem_integer(*it))
     116             :               {
     117           4 :                 it = element_id_names.erase(it);
     118           4 :                 mooseWarning("Extra element id ",
     119           4 :                              *it,
     120             :                              " defined in Outputs/extra_element_ids_to_output "
     121             :                              "is not defined on the mesh and will be ignored.");
     122             :               }
     123             :               // Increment iterator if element integer exists
     124             :               else
     125          10 :                 ++it;
     126             :             }
     127             :           }
     128             :         }
     129          50 :         break;
     130             :       }
     131             :     }
     132             : 
     133        2998 :     if (output_extra_ids)
     134             :     {
     135             :       // Retrieve extra element id names and associated data
     136          60 :       const auto n_elem = output_mesh.n_elem();
     137          60 :       std::vector<std::string> eeid_vars;
     138          60 :       const auto n_eeid_to_output = restrict_element_id_names ? element_id_names.size() : n_eeid;
     139          60 :       std::vector<Number> eeid_soln(n_elem * n_eeid_to_output);
     140          60 :       unsigned int soln_index = 0;
     141         120 :       for (unsigned int i = 0; i < n_eeid; i++)
     142             :       {
     143          60 :         const auto eeid_name = output_mesh.get_elem_integer_name(i);
     144             :         // If `Outputs/extra_element_ids_to_output` is not set, output all ids to Exodus
     145             :         // Otherwise only output if the extra id name is contained within
     146             :         // `Outputs/extra_element_ids_to_output`
     147          70 :         if (!restrict_element_id_names ||
     148          10 :             (std::find(element_id_names.begin(), element_id_names.end(), eeid_name) !=
     149          70 :              element_id_names.end()))
     150             :         {
     151          60 :           eeid_vars.push_back(output_mesh.get_elem_integer_name(i));
     152        2246 :           for (const auto & elem : output_mesh.element_ptr_range())
     153             :           {
     154        2186 :             eeid_soln[soln_index] = (int)elem->get_extra_integer(i);
     155        2186 :             ++soln_index;
     156          60 :           }
     157             :         }
     158          60 :       }
     159             : 
     160             :       // Check size of output variables just in case none of the variables in
     161             :       // `Outpus/extra_element_ids_to_output` are specified on the actual mesh
     162          60 :       if (eeid_vars.size() > 0)
     163             :       {
     164             :         // Invoke ExodusII_IO_Helper to output extra element ids to Exodus file
     165          60 :         auto & exio_helper = exio.get_exio_helper();
     166             : 
     167             :         // Output empty timestep to Exodus file
     168          60 :         int empty_timestep = 1;
     169          60 :         Real default_time = 1.0;
     170          60 :         exio_helper.write_timestep(empty_timestep, default_time);
     171             : 
     172             :         // Write extra element id data to Exodus file
     173          60 :         std::vector<std::set<subdomain_id_type>> vars_active_subdomains;
     174          60 :         vars_active_subdomains.resize(n_eeid_to_output);
     175          60 :         exio_helper.initialize_element_variables(eeid_vars, vars_active_subdomains);
     176          60 :         exio_helper.write_element_values(
     177             :             output_mesh, eeid_soln, empty_timestep, vars_active_subdomains);
     178          60 :       }
     179             :       else
     180           0 :         mooseWarning(
     181             :             "Outputs/output_extra_element_ids is set to true but no extra element ids are being "
     182             :             "outputted. Please check extra element ids are properly defined on the mesh and any "
     183             :             "variables specified in Outputs/extra_element_ids_to_output are spelled correctly.");
     184          60 :     }
     185        3006 :   }
     186             : 
     187          21 :   else if (mesh_file.find(".cpa.gz") + 7 == mesh_file.size())
     188             :   {
     189          21 :     TIME_SECTION("act", 1, "Writing Checkpoint");
     190             : 
     191          21 :     CheckpointIO io(mesh_ptr->getMesh(), false);
     192          21 :     io.write(mesh_file);
     193             : 
     194             :     // Write mesh metadata
     195          21 :     if (processor_id() == 0)
     196             :     {
     197           7 :       const auto filenames = _app.writeRestartableMetaData(MooseApp::MESH_META_DATA, mesh_file);
     198           7 :       Moose::out << "Mesh meta data written into "
     199           7 :                  << std::filesystem::absolute(filenames[0].parent_path()) << "." << std::endl;
     200           7 :     }
     201          21 :   }
     202             :   else
     203             :   {
     204             :     // Just write the file using the name requested by the user.
     205           0 :     mesh_ptr->getMesh().write(mesh_file);
     206             :   }
     207        3023 : }

Generated by: LCOV version 1.14