https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SetupMeshAction.C
Go to the documentation of this file.
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 "SetupMeshAction.h"
11#include "MooseApp.h"
12#include "MooseMesh.h"
13#include "FileMesh.h"
14#include "FEProblem.h"
15#include "ActionWarehouse.h"
16#include "Factory.h"
18
19#include <functional>
20#include <algorithm>
21
22registerMooseAction("MooseApp", SetupMeshAction, "setup_mesh");
23registerMooseAction("MooseApp", SetupMeshAction, "set_mesh_base");
24registerMooseAction("MooseApp", SetupMeshAction, "init_mesh");
25
28{
30 params.addClassDescription("Add or create Mesh object to the simulation.");
31
32 // Here we are setting the default type of the mesh to construct to "FileMesh". This is to support
33 // the very long-running legacy syntax where only a file parameter is required to determine the
34 // type of the "Mesh" block. We are re-adding it though so that we can detect whether or not the
35 // user has explicitly set the type in an input file. We do this because we want to support
36 // automatically building a "MeshGeneratorMesh" type when MeshGenerators are added to the
37 // simulation.
38 params.addParam<std::string>(
39 "type",
40 "FileMesh",
41 "A string representing the Moose Object that will be built by this Action");
42
43 params.addParam<bool>("second_order",
44 false,
45 "Converts a first order mesh to a second order "
46 "mesh. Note: This is NOT needed if you are reading "
47 "an actual first order mesh.");
48
49 params.addParam<std::vector<SubdomainID>>("block_id", "IDs of the block id/name pairs");
50 params.addParam<std::vector<SubdomainName>>(
51 "block_name", "Names of the block id/name pairs (must correspond with \"block_id\"");
52
53 params.addParam<std::vector<BoundaryID>>("boundary_id", {}, "IDs of the boundary id/name pairs");
54 params.addParam<std::vector<BoundaryName>>(
55 "boundary_name",
56 {},
57 "Names of the boundary id/name pairs (must correspond with \"boundary_id\"");
58
59 params.addParam<bool>("construct_side_list_from_node_list",
60 false,
61 "If true, construct side lists from the nodesets in the mesh (i.e. if "
62 "every node on a give side is in a nodeset then add that side to a "
63 "sideset");
64
65 params.addParam<std::vector<BoundaryName>>(
66 "ghosted_boundaries", {}, "Boundaries to be ghosted if using Nemesis");
67 params.addParam<std::vector<Real>>("ghosted_boundaries_inflation",
68 "If you are using ghosted boundaries you will want to set "
69 "this value to a vector of amounts to inflate the bounding "
70 "boxes by. ie if you are running a 3D problem you might set "
71 "it to '0.2 0.1 0.4'");
72
73 params.addParam<unsigned int>(
74 "uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
75
76 params.addParam<bool>("skip_deletion_repartition_after_refine",
77 false,
78 "If the flag is true, uniform refinements will run more efficiently, "
79 "but at the same time, there might be extra ghosting elements. "
80 "The number of layers of additional ghosting elements depends "
81 "on the number of uniform refinement levels. This flag "
82 "should be used only when you have a 'fine enough' coarse mesh and want "
83 "to refine the mesh by a few levels. Otherwise, it might introduce an "
84 "unbalanced workload and too large ghosting domain. ");
85
86 params.addParam<bool>("skip_partitioning",
87 false,
88 "If true the mesh won't be partitioned. This may cause large load "
89 "imbalances.");
90
91 params.addParam<bool>(
92 "use_split",
93 false,
94 "Use split distributed mesh files; is overriden by the --use-split command line option");
95 params.addParam<std::string>("split_file",
96 "",
97 "Optional name of split mesh file(s) to write/read; is overridden "
98 "by the --split-file command line option");
99
100 // groups
101 params.addParamNamesToGroup("ghosted_boundaries ghosted_boundaries_inflation", "Advanced");
102 params.addParamNamesToGroup("second_order construct_side_list_from_node_list skip_partitioning",
103 "Advanced");
104 params.addParamNamesToGroup("block_id block_name boundary_id boundary_name", "Add Names");
105 params.addParamNamesToGroup("use_split split_file", "Split Mesh");
106
107 return params;
108}
109
111 : MooseObjectAction(params),
112 _use_split(getParam<bool>("use_split") || _app.getParam<bool>("use_split")),
113 _split_file(_app.isParamSetByUser("split_file") ? _app.getParam<std::string>("split_file")
114 : getParam<std::string>("split_file"))
115{
116}
117
118void
120{
121 if (isParamValid("ghosted_boundaries"))
122 for (const auto & bnd_name : getParam<std::vector<BoundaryName>>("ghosted_boundaries"))
123 mesh->addGhostedBoundary(mesh->getBoundaryID(bnd_name));
124
125 if (isParamValid("ghosted_boundaries_inflation"))
126 {
127 std::vector<Real> ghosted_boundaries_inflation =
128 getParam<std::vector<Real>>("ghosted_boundaries_inflation");
129 mesh->setGhostedBoundaryInflation(ghosted_boundaries_inflation);
130 }
131
132 mesh->ghostGhostedBoundaries();
133
134 if (getParam<bool>("second_order"))
135 mesh->getMesh().all_second_order(true);
136
137#ifdef LIBMESH_ENABLE_AMR
138 unsigned int level = getParam<unsigned int>("uniform_refine");
139
140 // Did they specify extra refinement levels on the command-line?
141 if (_app.isParamSetByUser("refinements"))
142 level += _app.getParam<unsigned int>("refinements");
143
144 mesh->setUniformRefineLevel(level, getParam<bool>("skip_deletion_repartition_after_refine"));
145#endif // LIBMESH_ENABLE_AMR
146
147 // Add entity names to the mesh
148 if (_pars.isParamValid("block_id") && _pars.isParamValid("block_name"))
149 {
150 std::vector<SubdomainID> ids = getParam<std::vector<SubdomainID>>("block_id");
151 std::vector<SubdomainName> names = getParam<std::vector<SubdomainName>>("block_name");
152 std::set<SubdomainName> seen_it;
153
154 if (ids.size() != names.size())
155 mooseError("You must supply the same number of block ids and names parameters");
156
157 for (unsigned int i = 0; i < ids.size(); ++i)
158 {
159 if (seen_it.find(names[i]) != seen_it.end())
160 mooseError("The following dynamic block name is not unique: " + names[i]);
161 seen_it.insert(names[i]);
162 mesh->setSubdomainName(ids[i], names[i]);
163 }
164 }
165 if (_pars.isParamValid("boundary_id") && _pars.isParamValid("boundary_name"))
166 {
167 std::vector<BoundaryID> ids = getParam<std::vector<BoundaryID>>("boundary_id");
168 std::vector<BoundaryName> names = getParam<std::vector<BoundaryName>>("boundary_name");
169 std::set<SubdomainName> seen_it;
170
171 if (ids.size() != names.size())
172 mooseError("You must supply the same number of boundary ids and names parameters");
173
174 for (unsigned int i = 0; i < ids.size(); ++i)
175 {
176 if (seen_it.find(names[i]) != seen_it.end())
177 mooseError("The following dynamic boundary name is not unique: " + names[i]);
178 mesh->setBoundaryName(ids[i], names[i]);
179 seen_it.insert(names[i]);
180 }
181 }
182
183 if (getParam<bool>("construct_side_list_from_node_list"))
184 mesh->getMesh().get_boundary_info().build_side_list_from_node_list();
185
186 // Here we can override the partitioning for special cases
187 if (getParam<bool>("skip_partitioning"))
188 mesh->getMesh().skip_partitioning(getParam<bool>("skip_partitioning"));
189}
190
191std::string
193{
194 // Get the split_file extension, if there is one, and use that to decide
195 // between .cpr and .cpa.gz
196 auto split_file = _split_file;
197 std::string split_file_ext = MooseUtils::getExtension(split_file);
198
199 // If split_file already has the .cpr or .cpa.gz extension, we go with
200 // that, otherwise we strip off the extension and append ".cpa.gz".
201 if (split_file != "" && split_file_ext != "cpr" && split_file_ext != "cpa.gz")
202 split_file = MooseUtils::stripExtension(split_file) + ".cpa.gz";
203
204 if (_type != "FileMesh")
205 {
206 if (split_file.empty())
207 mooseError("Cannot use split mesh for a non-file mesh without specifying --split-file on "
208 "command line or the Mesh/split_file parameter");
209
210 auto new_pars = FileMesh::validParams();
211
212 // Keep existing parameters where possible
213 new_pars.applyParameters(_moose_object_pars);
214
215 new_pars.set<MeshFileName>("file") = split_file;
216 new_pars.set<MooseApp *>(MooseBase::app_param) =
217 moose_object_params.get<MooseApp *>(MooseBase::app_param);
218 moose_object_params = new_pars;
219 }
220 else
221 {
222 if (!split_file.empty())
223 moose_object_params.set<MeshFileName>("file") = split_file;
224 else
225 moose_object_params.set<MeshFileName>("file") =
226 MooseUtils::stripExtension(moose_object_params.get<MeshFileName>("file")) + ".cpa.gz";
227 }
228
229 moose_object_params.set<bool>("_is_split") = true;
230
231 return "FileMesh";
232}
233
234void
236{
237 // Create the mesh object and tell it to build itself
238 if (_current_task == "setup_mesh")
239 {
240 TIME_SECTION("SetupMeshAction::act::setup_mesh", 1, "Setting Up Mesh", true);
241
242 if (_app.useMasterMesh())
244 else
245 {
246 const auto & generator_actions = _awh.getActionListByName("add_mesh_generator");
247
248 // If we trigger any actions that can build MeshGenerators, whether through input file
249 // syntax or through custom actions, change the default type to construct. We can't yet
250 // check whether there are any actual MeshGenerator objects because those are added after
251 // setup_mesh
252 if (!generator_actions.empty())
253 {
254 // Check for whether type has been set or whether for the default type (FileMesh) a file has
255 // been provided
256 if (!_pars.isParamSetByUser("type") && !_moose_object_pars.isParamValid("file"))
257 {
258 // Auto-select MFEMMeshGeneratorMesh when a generator carries the MFEM flag.
259 // Guarded at compile time so non-MFEM builds incur zero overhead.
260 bool has_mfem_generator = false;
261#ifdef MOOSE_MFEM_ENABLED
262 // We'll have to do something smarter when people add actions other than
263 // AddMeshGeneratorAction that add MFEM mesh generators
264 if (const auto * const mesh_generator_action =
265 dynamic_cast<AddMeshGeneratorAction *>(generator_actions.front()))
266 if (const auto * const is_mfem =
267 mesh_generator_action->getObjectParams().queryParam<bool>(
268 "_mfem_mesh_generator"))
269 has_mfem_generator = *is_mfem;
270#endif
271
272 _type = has_mfem_generator ? "MFEMMeshGeneratorMesh" : "MeshGeneratorMesh";
273 auto original_params = _moose_object_pars;
275
276 // Since we changing the type on the fly, we'll have to manually extract parameters again
277 // from the input file object.
279 }
280 else if (!_moose_object_pars.get<bool>("_mesh_generator_mesh"))
281 {
282 // There are cases where a custom action may register the "add_mesh_generator" task, but
283 // may not actually add any mesh generators depending on user input. We don't want to risk
284 // giving false warnings in this case. However, if we triggered the "add_mesh_generator"
285 // task through explicit input file syntax, then it is definitely safe to warn
286 for (auto generator_action_ptr : generator_actions)
287 if (dynamic_cast<AddMeshGeneratorAction *>(generator_action_ptr))
288 {
289 mooseError("Mesh Generators present but the [Mesh] block is set to construct a \"",
290 _type,
291 "\" mesh, which does not use Mesh Generators in constructing the mesh. ");
292 }
293 }
294 }
295
296 // switch non-file meshes to be a file-mesh if using a pre-split mesh configuration.
297 if (_use_split)
299
301 }
302 }
303
304 else if (_current_task == "set_mesh_base")
305 {
306 TIME_SECTION("SetupMeshAction::act::set_mesh_base", 1, "Setting Mesh", true);
307
308 if (!_app.useMasterMesh() && !_mesh->hasMeshBase())
309 {
310 // We want to set the MeshBase object to that coming from mesh generators when the following
311 // conditions are met:
312 // 1. We have mesh generators
313 // 2. We are not using the pre-split mesh
314 // 3. We are not: recovering/restarting and we are the master application
315 if (!_app.getMeshGeneratorNames().empty() && !_use_split &&
317 {
318 auto & mesh_generator_system = _app.getMeshGeneratorSystem();
319 auto mesh_base =
320 mesh_generator_system.getSavedMesh(mesh_generator_system.mainMeshGeneratorName());
321 if (_mesh->allowRemoteElementRemoval() != mesh_base->allow_remote_element_removal())
322 mooseError("The MooseMesh and libmesh::MeshBase object coming from mesh generators are "
323 "out of sync with respect to whether remote elements can be deleted");
324 mooseAssert(mesh_base, "Null mesh");
325 _mesh->setMeshBase(std::move(mesh_base));
326 }
327 else
328 {
329 const auto & mg_names = _app.getMeshGeneratorNames();
330 std::vector<bool> use_dm;
331 for (const auto & mg_name : mg_names)
332 if (hasMeshProperty<bool>("use_distributed_mesh", mg_name))
333 use_dm.push_back(getMeshProperty<bool>("use_distributed_mesh", mg_name));
334
335 if (!use_dm.empty())
336 {
337 if (std::adjacent_find(use_dm.begin(), use_dm.end(), std::not_equal_to<bool>()) !=
338 use_dm.end())
339 mooseError("You cannot use mesh generators that set different values of the mesh "
340 "property 'use_distributed_mesh' within the same simulation.");
341
342 const auto ptype = use_dm.front() ? MooseMesh::ParallelType::DISTRIBUTED
344 _mesh->setParallelType(ptype);
345 }
346
347 _mesh->setMeshBase(_mesh->buildMeshBaseObject());
348 }
349 }
350 }
351
352 else if (_current_task == "init_mesh")
353 {
354 TIME_SECTION("SetupMeshAction::act::set_mesh_base", 1, "Initializing Mesh", true);
355
356 if (!_app.useMasterMesh())
357 {
358 _mesh->init();
359 setupMesh(_mesh.get());
360 }
361 }
362}
registerMooseAction("MooseApp", SetupMeshAction, "setup_mesh")
const std::list< Action * > & getActionListByName(const std::string &task) const
Retrieve a constant list of Action pointers associated with the passed in task.
std::string _registered_identifier
Definition Action.h:151
std::shared_ptr< MooseMesh > & _mesh
Definition Action.h:174
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
const std::string & _current_task
The current action (even though we have separate instances for each action)
Definition Action.h:172
ActionWarehouse & _awh
Reference to ActionWarehouse where we store object build by actions.
Definition Action.h:169
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters &parameters, THREAD_ID tid=0, bool print_deprecated=true)
Definition Factory.C:142
InputParameters getValidParams(const std::string &name) const
Get valid parameters for the object.
Definition Factory.C:68
static InputParameters validParams()
Definition FileMesh.C:27
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
std::unique_ptr< libMesh::MeshBase > getSavedMesh(const std::string &name)
Get the saved mesh by name.
Base class for MOOSE-based applications.
Definition MooseApp.h:110
std::vector< std::string > getMeshGeneratorNames() const
Definition MooseApp.h:938
bool isRestarting() const
Whether or not this is a "restart" calculation.
Definition MooseApp.C:1680
const MooseMesh * masterMesh() const
Returns a pointer to the master mesh.
Definition MooseApp.h:876
bool isUltimateMaster() const
Whether or not this app is the ultimate master app.
Definition MooseApp.h:866
Moose::Builder & builder()
Returns a writable reference to the builder.
Definition MooseApp.h:226
bool isRecovering() const
Whether or not this is a "recover" calculation.
Definition MooseApp.C:1674
MeshGeneratorSystem & getMeshGeneratorSystem()
Gets the system that manages the MeshGenerators.
Definition MooseApp.h:886
bool useMasterMesh() const
Returns whether to use the parent app mesh as the mesh for this app.
Definition MooseApp.h:871
bool isParamSetByUser(const std::string &name) const
Test if the supplied parameter is set by a user, as opposed to not set or set to default.
Definition MooseBase.h:205
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
const InputParameters & _pars
The object's parameters.
Definition MooseBase.h:384
const T & getParam(const std::string &name) const
Retrieve a parameter for the object.
Definition MooseBase.h:406
bool isParamValid(const std::string &name) const
Test if the supplied parameter is valid.
Definition MooseBase.h:199
static const std::string app_param
The name of the parameter that contains the MooseApp.
Definition MooseBase.h:59
MooseMesh wraps a libMesh::Mesh object and enhances its capabilities by caching additional data and s...
Definition MooseMesh.h:95
virtual std::unique_ptr< MooseMesh > safeClone() const =0
A safer version of the clone() method that hands back an allocated object wrapped in a smart pointer.
InputParameters _moose_object_pars
The parameters for the object to be created.
static InputParameters validParams()
std::string _type
The Object type that is being created.
void extractParams(const hit::Node *const section_node, InputParameters &p)
Attempt to extract values from input starting with the section in input in section_node based on the ...
Definition Builder.C:664
Factory & _factory
The Factory associated with the MooseApp.
std::string modifyParamsForUseSplit(InputParameters &moose_object_params) const
Modifies the MooseObject's parameters to build the right type of Mesh when using splits.
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
const std::string _split_file
The split mesh file (if any); comes from either Mesh/split_file or –split-file.
const bool _use_split
Whether or not to use a split mesh; comes from either Mesh/use_split or –use-split.
void setupMesh(MooseMesh *mesh)
static InputParameters validParams()
SetupMeshAction(const InputParameters &params)
MeshBase & mesh
std::string getExtension(const std::string &filename, const bool rfind)
Definition MooseUtils.C:422
std::string stripExtension(const std::string &s, const bool rfind)
Definition MooseUtils.C:438