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