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 4185 : MeshOnlyAction::validParams() 30 : { 31 4185 : return Action::validParams(); 32 : } 33 : 34 4185 : MeshOnlyAction::MeshOnlyAction(const InputParameters & params) : Action(params) {} 35 : 36 : void 37 3744 : MeshOnlyAction::act() 38 : { 39 : // Run error checking on input file first before trying to generate a mesh 40 3744 : bool warn = _app.unusedFlagIsWarning(); 41 3744 : bool err = _app.unusedFlagIsError(); 42 3744 : _app.builder().errorCheck(comm(), warn, err); 43 : 44 3741 : std::string mesh_file = _app.parameters().get<std::string>("mesh_only"); 45 3741 : auto & mesh_ptr = _app.actionWarehouse().mesh(); 46 : 47 : // Print information about the mesh 48 3741 : _console << mesh_ptr->getMesh().get_info(/* verbosity = */ 2) << std::endl; 49 : 50 3741 : if (mesh_file.empty()) 51 : { 52 2434 : mesh_file = _app.builder().getPrimaryFileName(); 53 2434 : size_t pos = mesh_file.find_last_of('.'); 54 : 55 : // Default to writing out an ExodusII mesh base on the input filename. 56 2434 : 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 3741 : if (mesh_file.find(".e") + 2 == mesh_file.size()) 65 : { 66 18600 : TIME_SECTION("act", 1, "Writing Exodus"); 67 : 68 3720 : auto & output_mesh = mesh_ptr->getMesh(); 69 3720 : ExodusII_IO exio(output_mesh); 70 : 71 : // Default to the maximum name length allowed by libMesh ExodusII 72 3720 : exio.set_max_name_length(80); 73 : 74 : // Extract the Output action to look for a non-default name 75 : // length, e.g. truncation to 32 to match gold files 76 7440 : const auto & output_actions = _app.actionWarehouse().getActionListByName("add_output"); 77 20032 : for (const auto & act : output_actions) 78 : { 79 16312 : AddOutputAction * action = dynamic_cast<AddOutputAction *>(act); 80 16312 : if (!action) 81 3720 : continue; 82 : 83 12592 : InputParameters & params = action->getObjectParams(); 84 25184 : if (params.isParamSetByUser("max_output_name_length")) 85 : { 86 : const int max_output_name_length = 87 0 : action->getObjectParams().get<unsigned int>("max_output_name_length"); 88 : 89 0 : exio.set_max_name_length(max_output_name_length); 90 : 91 0 : break; 92 : } 93 : } 94 : 95 3720 : Exodus::setOutputDimensionInExodusWriter(exio, *mesh_ptr); 96 : 97 : // Default to non-HDF5 output for wider compatibility 98 3720 : exio.set_hdf5_writing(false); 99 : 100 3720 : exio.write(mesh_file); 101 : 102 : // Check if extra element integers should be outputted to Exodus file 103 3717 : unsigned int n_eeid = output_mesh.n_elem_integers(); 104 : 105 : // Iterate through all actions and see if `Outputs/output_extra_element_ids = true` in input 106 : // file 107 : 108 : // Truth of whether to output extra element ids is initially determined by whether 109 : // there are extra element ids defined on the mesh 110 3717 : bool output_extra_ids = (n_eeid > 0); 111 3717 : bool restrict_element_id_names = false; 112 3717 : std::vector<std::string> element_id_names; 113 19806 : for (const auto & act : output_actions) 114 : { 115 : // Extract the Output action 116 16141 : AddOutputAction * action = dynamic_cast<AddOutputAction *>(act); 117 16141 : if (!action) 118 3717 : continue; 119 : 120 12424 : InputParameters & params = action->getObjectParams(); 121 24848 : if (params.isParamSetByUser("output_extra_element_ids")) 122 : { 123 : // User has set output_extra_element_ids, truth of output_extra_ids determined by value of 124 : // parameter 125 52 : output_extra_ids = params.get<bool>("output_extra_element_ids"); 126 52 : if (output_extra_ids) 127 : { 128 : // `Outputs/extra_element_ids_to_output` sets a subset of extra element ids that should 129 : // be outputted to Exodus 130 13 : restrict_element_id_names = params.isParamValid("extra_element_ids_to_output"); 131 13 : if (restrict_element_id_names) 132 : { 133 13 : element_id_names = params.get<std::vector<std::string>>("extra_element_ids_to_output"); 134 : // Check which element id names actually are defined on the mesh, remove from 135 : // element_id_names if they don't belong 136 23 : for (auto it = element_id_names.begin(); it != element_id_names.end();) 137 : { 138 : // Erase contents of iterator and return iterator if element integer does not exist 139 13 : if (!output_mesh.has_elem_integer(*it)) 140 : { 141 3 : it = element_id_names.erase(it); 142 3 : mooseWarning("Extra element id ", 143 3 : *it, 144 : " defined in Outputs/extra_element_ids_to_output " 145 : "is not defined on the mesh and will be ignored."); 146 : } 147 : // Increment iterator if element integer exists 148 : else 149 10 : ++it; 150 : } 151 : } 152 : } 153 49 : break; 154 : } 155 : } 156 : 157 3714 : if (output_extra_ids) 158 : { 159 : // Retrieve extra element id names and associated data 160 60 : const auto n_elem = output_mesh.n_elem(); 161 60 : std::vector<std::string> eeid_vars; 162 60 : const auto n_eeid_to_output = restrict_element_id_names ? element_id_names.size() : n_eeid; 163 60 : std::vector<Number> eeid_soln(n_elem * n_eeid_to_output); 164 60 : unsigned int soln_index = 0; 165 120 : for (unsigned int i = 0; i < n_eeid; i++) 166 : { 167 60 : const auto eeid_name = output_mesh.get_elem_integer_name(i); 168 : // If `Outputs/extra_element_ids_to_output` is not set, output all ids to Exodus 169 : // Otherwise only output if the extra id name is contained within 170 : // `Outputs/extra_element_ids_to_output` 171 70 : if (!restrict_element_id_names || 172 10 : (std::find(element_id_names.begin(), element_id_names.end(), eeid_name) != 173 70 : element_id_names.end())) 174 : { 175 60 : eeid_vars.push_back(output_mesh.get_elem_integer_name(i)); 176 2246 : for (const auto & elem : output_mesh.element_ptr_range()) 177 : { 178 2186 : eeid_soln[soln_index] = (int)elem->get_extra_integer(i); 179 2186 : ++soln_index; 180 60 : } 181 : } 182 60 : } 183 : 184 : // Check size of output variables just in case none of the variables in 185 : // `Outpus/extra_element_ids_to_output` are specified on the actual mesh 186 60 : if (eeid_vars.size() > 0) 187 : { 188 : // Invoke ExodusII_IO_Helper to output extra element ids to Exodus file 189 60 : auto & exio_helper = exio.get_exio_helper(); 190 : 191 : // Output empty timestep to Exodus file 192 60 : int empty_timestep = 1; 193 60 : Real default_time = 1.0; 194 60 : exio_helper.write_timestep(empty_timestep, default_time); 195 : 196 : // Write extra element id data to Exodus file 197 60 : std::vector<std::set<subdomain_id_type>> vars_active_subdomains; 198 60 : vars_active_subdomains.resize(n_eeid_to_output); 199 60 : exio_helper.initialize_element_variables(eeid_vars, vars_active_subdomains); 200 60 : exio_helper.write_element_values( 201 : output_mesh, eeid_soln, empty_timestep, vars_active_subdomains); 202 60 : } 203 : else 204 0 : mooseWarning( 205 : "Outputs/output_extra_element_ids is set to true but no extra element ids are being " 206 : "outputted. Please check extra element ids are properly defined on the mesh and any " 207 : "variables specified in Outputs/extra_element_ids_to_output are spelled correctly."); 208 60 : } 209 3720 : } 210 : 211 21 : else if (mesh_file.find(".cpa.gz") + 7 == mesh_file.size()) 212 : { 213 105 : TIME_SECTION("act", 1, "Writing Checkpoint"); 214 : 215 21 : CheckpointIO io(mesh_ptr->getMesh(), false); 216 21 : io.write(mesh_file); 217 : 218 : // Write mesh metadata 219 21 : if (processor_id() == 0) 220 : { 221 7 : const auto filenames = _app.writeRestartableMetaData(MooseApp::MESH_META_DATA, mesh_file); 222 7 : Moose::out << "Mesh meta data written into " 223 7 : << std::filesystem::absolute(filenames[0].parent_path()) << "." << std::endl; 224 7 : } 225 21 : } 226 : else 227 : { 228 : // Just write the file using the name requested by the user. 229 0 : mesh_ptr->getMesh().write(mesh_file); 230 : } 231 3738 : }