LCOV - code coverage report
Current view: top level - src/meshgenerators - FileMeshGenerator.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 84 89 94.4 %
Date: 2025-07-17 01:28:37 Functions: 4 4 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 "FileMeshGenerator.h"
      11             : #include "CastUniquePointer.h"
      12             : 
      13             : #include "libmesh/replicated_mesh.h"
      14             : #include "libmesh/face_quad4.h"
      15             : #include "libmesh/exodusII_io.h"
      16             : #include "libmesh/mesh_communication.h"
      17             : #include "libmesh/mesh_tools.h"
      18             : #include "libmesh/sparse_matrix.h"
      19             : 
      20             : registerMooseObject("MooseApp", FileMeshGenerator);
      21             : 
      22             : InputParameters
      23       18537 : FileMeshGenerator::validParams()
      24             : {
      25       18537 :   InputParameters params = MeshGenerator::validParams();
      26             : 
      27       18537 :   params.addRequiredParam<MeshFileName>("file", "The filename to read.");
      28       18537 :   params.addParam<std::vector<std::string>>(
      29             :       "exodus_extra_element_integers",
      30             :       "The variable names in the mesh file for loading extra element integers");
      31       55611 :   params.addParam<bool>("use_for_exodus_restart",
      32       37074 :                         false,
      33             :                         "True to indicate that the mesh file this generator is reading can be used "
      34             :                         "for restarting variables");
      35       55611 :   params.addParam<bool>("skip_partitioning",
      36       37074 :                         false,
      37             :                         "True to skip partitioning, only after this mesh generator, "
      38             :                         "because the mesh was pre-split for example.");
      39       55611 :   params.addParam<bool>("allow_renumbering",
      40       37074 :                         true,
      41             :                         "Whether to allow the mesh to renumber nodes and elements, if not "
      42             :                         "overridden by a global parameter or by a requirement (e.g. an exodus "
      43             :                         "restart or a constraint matrix) that disables renumbering.");
      44       55611 :   params.addParam<bool>("clear_spline_nodes",
      45       37074 :                         false,
      46             :                         "If clear_spline_nodes=true, IsoGeometric Analyis spline nodes "
      47             :                         "and constraints are removed from an IGA mesh, after which only "
      48             :                         "C^0 Rational-Bernstein-Bezier elements will remain.");
      49       55611 :   params.addParam<bool>("discontinuous_spline_extraction",
      50       37074 :                         false,
      51             :                         "If discontinuous_spline_extraction=true, "
      52             :                         "Rational-Bernstein-Bezier elements extracted from a spline mesh "
      53             :                         "will be disconnected from neighboring elements, coupled only via "
      54             :                         "their extraction operators.  This may be less efficient than the "
      55             :                         "default C^0 extracted mesh, but may be necessary if the extracted "
      56             :                         "mesh is non-conforming.");
      57       18537 :   params.addParam<MatrixFileName>(
      58             :       "constraint_matrix", "", "The name of a constraint matrix file to apply to the mesh");
      59       55611 :   params.addParam<Real>("constraint_preconditioning",
      60       37074 :                         0.0,
      61             :                         "Whether to attempt preconditioning with constraint matrix application");
      62       18537 :   params.addClassDescription("Read a mesh from a file.");
      63       18537 :   params.addParamNamesToGroup(
      64             :       "clear_spline_nodes discontinuous_spline_extraction constraint_matrix",
      65             :       "IsoGeometric Analysis (IGA) and other mesh constraint options");
      66       18537 :   return params;
      67           0 : }
      68             : 
      69        2131 : FileMeshGenerator::FileMeshGenerator(const InputParameters & parameters)
      70             :   : MeshGenerator(parameters),
      71        2131 :     _file_name(getParam<MeshFileName>("file")),
      72        2131 :     _matrix_file_name(getParam<MatrixFileName>("constraint_matrix")),
      73        2131 :     _matrix_preconditioning(getParam<Real>("constraint_preconditioning")),
      74        2131 :     _skip_partitioning(getParam<bool>("skip_partitioning")),
      75        4262 :     _allow_renumbering(getParam<bool>("allow_renumbering"))
      76             : {
      77        2131 :   if (_matrix_preconditioning && _matrix_file_name.empty())
      78           0 :     paramError("constraint_preconditioning",
      79             :                "The 'constraint_preconditioning' parameter is only applicable to "
      80             :                "meshes loaded with a corresponding 'constraint_matrix'.");
      81        2131 :   if (_matrix_preconditioning && _matrix_preconditioning != 1.0)
      82           0 :     paramError("constraint_preconditioning",
      83             :                "This version of MOOSE only supports a 'constraint_preconditioning' "
      84             :                "value of 1.0 if it is enabled.  Non-binary preconditioning values "
      85             :                "are reserved for future use.");
      86        2131 : }
      87             : 
      88             : std::unique_ptr<MeshBase>
      89        1952 : FileMeshGenerator::generate()
      90             : {
      91        1952 :   auto mesh = buildMeshBaseObject();
      92             : 
      93             :   // Maybe we'll reallow renumbering after constraints are applied?
      94        1952 :   bool eventually_allow_renumbering = _allow_renumbering && mesh->allow_renumbering();
      95             : 
      96             :   // If we have a constraint matrix, we need its numbering to match
      97             :   // the numbering in the mesh file
      98        1952 :   if (!_matrix_file_name.empty())
      99          40 :     mesh->allow_renumbering(false);
     100             : 
     101             :   // Figure out if we are reading an Exodus file, but not Tetgen (*.ele)
     102        3904 :   bool exodus = (_file_name.rfind(".exd") < _file_name.size() ||
     103        3904 :                  _file_name.rfind(".e") < _file_name.size()) &&
     104        1621 :                 _file_name.rfind(".ele") == std::string::npos;
     105        1952 :   bool has_exodus_integers = isParamValid("exodus_extra_element_integers");
     106        1952 :   bool restart_exodus = (getParam<bool>("use_for_exodus_restart") && _app.getExodusFileRestart());
     107        1952 :   if (exodus)
     108             :   {
     109        1611 :     auto exreader = std::make_shared<libMesh::ExodusII_IO>(*mesh);
     110        1611 :     MooseUtils::checkFileReadable(_file_name);
     111             : 
     112        1607 :     if (has_exodus_integers)
     113         174 :       exreader->set_extra_integer_vars(
     114             :           getParam<std::vector<std::string>>("exodus_extra_element_integers"));
     115             : 
     116        1607 :     if (restart_exodus)
     117             :     {
     118         128 :       _app.setExReaderForRestart(std::move(exreader));
     119         128 :       exreader->read(_file_name);
     120         128 :       eventually_allow_renumbering = false;
     121         128 :       mesh->allow_renumbering(false);
     122             :     }
     123             :     else
     124             :     {
     125        1479 :       if (mesh->processor_id() == 0)
     126             :       {
     127        1059 :         if (getParam<bool>("discontinuous_spline_extraction"))
     128          28 :           exreader->set_discontinuous_bex(true);
     129             : 
     130        1059 :         exreader->read(_file_name);
     131             : 
     132        1059 :         if (getParam<bool>("clear_spline_nodes"))
     133          14 :           MeshTools::clear_spline_nodes(*mesh);
     134             :       }
     135        1479 :       libMesh::MeshCommunication().broadcast(*mesh);
     136             :     }
     137             :     // Skip partitioning if the user requested it
     138        1607 :     if (_skip_partitioning)
     139          32 :       mesh->skip_partitioning(true);
     140        1607 :     mesh->prepare_for_use();
     141        1603 :     mesh->skip_partitioning(false);
     142        1603 :   }
     143             :   else
     144             :   {
     145         341 :     if (_pars.isParamSetByUser("exodus_extra_element_integers"))
     146           0 :       mooseError("\"exodus_extra_element_integers\" should be given only for Exodus mesh files");
     147         341 :     if (_pars.isParamSetByUser("use_for_exodus_restart"))
     148           0 :       mooseError("\"use_for_exodus_restart\" should be given only for Exodus mesh files");
     149             : 
     150         341 :     const auto file_name = deduceCheckpointPath(*this, _file_name);
     151         341 :     MooseUtils::checkFileReadable(file_name);
     152             : 
     153         341 :     mesh->skip_partitioning(_skip_partitioning);
     154         341 :     mesh->allow_renumbering(_allow_renumbering);
     155         341 :     mesh->read(file_name);
     156             : 
     157             :     // Load the meta data if it is available
     158         341 :     _app.possiblyLoadRestartableMetaData(MooseApp::MESH_META_DATA, (std::string)file_name);
     159         341 :   }
     160             : 
     161        1944 :   if (!_matrix_file_name.empty())
     162             :   {
     163          40 :     auto matrix = SparseMatrix<Number>::build(mesh->comm());
     164          40 :     matrix->read_matlab(_matrix_file_name);
     165             : 
     166             :     // In the future we might deduce matrix orientation via matrix
     167             :     // size; for now we simply hardcode that the Flex IGA standard for
     168             :     // projection operator matrices is the transpose of our standard
     169             :     // for constraint equations.
     170          40 :     matrix->get_transpose(*matrix);
     171          40 :     mesh->copy_constraint_rows(*matrix, _matrix_preconditioning);
     172             : 
     173             :     // libMesh should probably update this in copy_constraint_rows();
     174             :     // once it does this will be a redundant sweep we can remove.
     175          40 :     mesh->cache_elem_data();
     176          40 :   }
     177             : 
     178        1944 :   mesh->allow_renumbering(eventually_allow_renumbering);
     179             : 
     180        3888 :   return dynamic_pointer_cast<MeshBase>(mesh);
     181        1944 : }
     182             : 
     183             : std::string
     184        3379 : FileMeshGenerator::deduceCheckpointPath(const MooseObject & object, const std::string & file_name)
     185             : {
     186             :   // Just exists, use it
     187        3379 :   if (MooseUtils::pathExists(file_name))
     188        3353 :     return file_name;
     189             : 
     190             :   // LATEST
     191          52 :   return MooseUtils::convertLatestCheckpoint(file_name) + object.getMooseApp().checkpointSuffix();
     192             : }

Generated by: LCOV version 1.14