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 "FileMesh.h" 11 : #include "Parser.h" 12 : #include "MooseUtils.h" 13 : #include "Moose.h" 14 : #include "MooseApp.h" 15 : #include "FileMeshGenerator.h" 16 : 17 : #include "libmesh/exodusII_io.h" 18 : #include "libmesh/mesh_tools.h" 19 : #include "libmesh/nemesis_io.h" 20 : #include "libmesh/parallel_mesh.h" 21 : 22 : using libMesh::ExodusII_IO; 23 : using libMesh::Nemesis_IO; 24 : 25 : registerMooseObject("MooseApp", FileMesh); 26 : 27 : InputParameters 28 43204 : FileMesh::validParams() 29 : { 30 43204 : InputParameters params = MooseMesh::validParams(); 31 172816 : params.addRequiredParam<MeshFileName>("file", "The name of the mesh file to read"); 32 172816 : MooseEnum dims("1=1 2 3", "1"); 33 172816 : params.addParam<MooseEnum>("dim", 34 : dims, 35 : "This is only required for certain mesh formats where " 36 : "the dimension of the mesh cannot be autodetected. " 37 : "In particular you must supply this for GMSH meshes. " 38 : "Note: This is completely ignored for ExodusII meshes!"); 39 129612 : params.addParam<bool>("clear_spline_nodes", 40 86408 : false, 41 : "If clear_spline_nodes=true, IsoGeometric Analyis spline nodes " 42 : "and constraints are removed from an IGA mesh, after which only " 43 : "C^0 Rational-Bernstein-Bezier elements will remain."); 44 216020 : params.addDeprecatedParam<bool>("nemesis", 45 86408 : false, 46 : "If nemesis=true and file=foo.n, actually reads " 47 : "foo.n.N.0, foo.n.N.1, ... foo.n.N.N-1, " 48 : "where N = # CPUs, with NemesisIO.", 49 : "This parameter should no longer be necessary if you use the " 50 : "'.n' or '.nem' file extension for Nemesis files"); 51 43204 : params.addClassDescription("Read a mesh from a file."); 52 86408 : return params; 53 43204 : } 54 : 55 5853 : FileMesh::FileMesh(const InputParameters & parameters) 56 17559 : : MooseMesh(parameters), _file_name(getParam<MeshFileName>("file")) 57 : { 58 : // Detect nemesis files from the extension or the parameter (deprecated) 59 17559 : if (isParamSetByUser("nemesis")) 60 186 : _is_nemesis = getParam<bool>("nemesis"); 61 : else 62 28955 : _is_nemesis = (MooseUtils::hasExtension(_file_name, "n", /*strip_exodus_ext =*/true) || 63 17373 : MooseUtils::hasExtension(_file_name, "nem", true)); 64 : 65 : // We may have determined this is a nemesis file from the extension, which MooseMesh cannot do 66 5853 : MooseMesh::determineUseDistributedMesh(); 67 5853 : } 68 : 69 761 : FileMesh::FileMesh(const FileMesh & other_mesh) 70 761 : : MooseMesh(other_mesh), _file_name(other_mesh._file_name) 71 : { 72 761 : } 73 : 74 7215 : FileMesh::~FileMesh() {} 75 : 76 : std::unique_ptr<MooseMesh> 77 753 : FileMesh::safeClone() const 78 : { 79 753 : return _app.getFactory().copyConstruct(*this); 80 : } 81 : 82 : void 83 3843 : FileMesh::buildMesh() 84 : { 85 19215 : TIME_SECTION("buildMesh", 2, "Reading Mesh"); 86 : 87 : // This dimension should get overridden if the mesh reader can determine the dimension 88 7686 : getMesh().set_mesh_dimension(getParam<MooseEnum>("dim")); 89 : 90 3843 : if (_is_nemesis) 91 : { 92 : // Nemesis_IO only takes a reference to DistributedMesh, so we can't be quite so short here. 93 52 : DistributedMesh & pmesh = cast_ref<DistributedMesh &>(getMesh()); 94 52 : Nemesis_IO(pmesh).read(_file_name); 95 : 96 52 : getMesh().allow_renumbering(false); 97 : 98 : // Even if we want repartitioning when load balancing later, we'll 99 : // begin with the default partitioning defined by the Nemesis 100 : // file. 101 52 : bool skip_partitioning_later = getMesh().skip_partitioning(); 102 52 : getMesh().skip_partitioning(true); 103 52 : getMesh().prepare_for_use(); 104 52 : getMesh().skip_partitioning(skip_partitioning_later); 105 : } 106 : else // not reading Nemesis files 107 : { 108 : // See if the user has requested reading a solution from the file. If so, we'll need to read 109 : // the mesh with the exodus reader instead of using mesh.read(). This will read the mesh on 110 : // every processor 111 : 112 3931 : if (_app.getExodusFileRestart() && (_file_name.rfind(".exo") < _file_name.size() || 113 140 : _file_name.rfind(".e") < _file_name.size())) 114 : { 115 140 : MooseUtils::checkFileReadable(_file_name); 116 : 117 140 : auto exreader = std::make_shared<ExodusII_IO>(getMesh()); 118 140 : _app.setExReaderForRestart(std::move(exreader)); 119 140 : exreader->read(_file_name); 120 : 121 140 : getMesh().allow_renumbering(false); 122 140 : getMesh().prepare_for_use(); 123 140 : } 124 : else 125 : { 126 3651 : _file_name = FileMeshGenerator::deduceCheckpointPath(*this, _file_name); 127 : 128 : // If we are reading a mesh while restarting, then we might have 129 : // a solution file that relies on that mesh partitioning and/or 130 : // numbering. In that case, we need to turn off repartitioning 131 : // and renumbering, at least at first. 132 3651 : bool restarting = _file_name.rfind(".cpa.gz") < _file_name.size(); 133 : 134 3651 : const bool skip_partitioning_later = restarting && getMesh().skip_partitioning(); 135 3651 : const bool allow_renumbering_later = restarting && getMesh().allow_renumbering(); 136 : 137 3651 : if (restarting) 138 : { 139 216 : getMesh().skip_partitioning(true); 140 216 : getMesh().allow_renumbering(false); 141 : } 142 : 143 3651 : MooseUtils::checkFileReadable(_file_name); 144 3645 : getMesh().read(_file_name); 145 : 146 10935 : if (getParam<bool>("clear_spline_nodes")) 147 0 : MeshTools::clear_spline_nodes(getMesh()); 148 : 149 3645 : _app.possiblyLoadRestartableMetaData(MooseApp::MESH_META_DATA, _file_name); 150 : 151 3645 : if (restarting) 152 : { 153 213 : getMesh().allow_renumbering(allow_renumbering_later); 154 213 : getMesh().skip_partitioning(skip_partitioning_later); 155 : } 156 : } 157 : } 158 3837 : } 159 : 160 : void 161 0 : FileMesh::read(const std::string & file_name) 162 : { 163 0 : if (dynamic_cast<DistributedMesh *>(&getMesh()) && !_is_nemesis) 164 0 : getMesh().read(file_name, /*mesh_data=*/NULL, /*skip_renumber=*/false); 165 : else 166 0 : getMesh().read(file_name, /*mesh_data=*/NULL, /*skip_renumber=*/true); 167 0 : }