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 : }