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<std::string>>(
66 "displacements",
67 "The variables corresponding to the x y z displacements of the mesh. If "
68 "this is provided then the displacements will be taken into account during "
69 "the computation. Creation of the displaced mesh can be suppressed even if "
70 "this is set by setting 'use_displaced_mesh = false'.");
71 params.addParam<bool>(
72 "use_displaced_mesh",
73 true,
74 "Create the displaced mesh if the 'displacements' "
75 "parameter is set. If this is 'false', a displaced mesh will not be created, "
76 "regardless of whether 'displacements' is set.");
77 params.addParam<std::vector<BoundaryName>>(
78 "ghosted_boundaries", {}, "Boundaries to be ghosted if using Nemesis");
79 params.addParam<std::vector<Real>>("ghosted_boundaries_inflation",
80 "If you are using ghosted boundaries you will want to set "
81 "this value to a vector of amounts to inflate the bounding "
82 "boxes by. ie if you are running a 3D problem you might set "
83 "it to '0.2 0.1 0.4'");
84
85 params.addParam<unsigned int>(
86 "uniform_refine", 0, "Specify the level of uniform refinement applied to the initial mesh");
87
88 params.addParam<bool>("skip_deletion_repartition_after_refine",
89 false,
90 "If the flag is true, uniform refinements will run more efficiently, "
91 "but at the same time, there might be extra ghosting elements. "
92 "The number of layers of additional ghosting elements depends "
93 "on the number of uniform refinement levels. This flag "
94 "should be used only when you have a 'fine enough' coarse mesh and want "
95 "to refine the mesh by a few levels. Otherwise, it might introduce an "
96 "unbalanced workload and too large ghosting domain. ");
97
98 params.addParam<bool>("skip_partitioning",
99 false,
100 "If true the mesh won't be partitioned. This may cause large load "
101 "imbalances.");
102
103 params.addParam<bool>(
104 "use_split",
105 false,
106 "Use split distributed mesh files; is overriden by the --use-split command line option");
107 params.addParam<std::string>("split_file",
108 "",
109 "Optional name of split mesh file(s) to write/read; is overridden "
110 "by the --split-file command line option");
111
112 // groups
113 params.addParamNamesToGroup("displacements ghosted_boundaries ghosted_boundaries_inflation",
114 "Advanced");
115 params.addParamNamesToGroup("second_order construct_side_list_from_node_list skip_partitioning",
116 "Advanced");
117 params.addParamNamesToGroup("block_id block_name boundary_id boundary_name", "Add Names");
118 params.addParamNamesToGroup("use_split split_file", "Split Mesh");
119
120 return params;
121}
122
124 : MooseObjectAction(params),
125 _use_split(getParam<bool>("use_split") || _app.getParam<bool>("use_split")),
126 _split_file(_app.isParamSetByUser("split_file") ? _app.getParam<std::string>("split_file")
127 : getParam<std::string>("split_file"))
128{
129}
130
131void
133{
134 if (isParamValid("ghosted_boundaries"))
135 for (const auto & bnd_name : getParam<std::vector<BoundaryName>>("ghosted_boundaries"))
136 mesh->addGhostedBoundary(mesh->getBoundaryID(bnd_name));
137
138 if (isParamValid("ghosted_boundaries_inflation"))
139 {
140 std::vector<Real> ghosted_boundaries_inflation =
141 getParam<std::vector<Real>>("ghosted_boundaries_inflation");
142 mesh->setGhostedBoundaryInflation(ghosted_boundaries_inflation);
143 }
144
145 mesh->ghostGhostedBoundaries();
146
147 if (getParam<bool>("second_order"))
148 mesh->getMesh().all_second_order(true);
149
150#ifdef LIBMESH_ENABLE_AMR
151 unsigned int level = getParam<unsigned int>("uniform_refine");
152
153 // Did they specify extra refinement levels on the command-line?
154 if (_app.isParamSetByUser("refinements"))
155 level += _app.getParam<unsigned int>("refinements");
156
157 mesh->setUniformRefineLevel(level, getParam<bool>("skip_deletion_repartition_after_refine"));
158#endif // LIBMESH_ENABLE_AMR
159
160 // Add entity names to the mesh
161 if (_pars.isParamValid("block_id") && _pars.isParamValid("block_name"))
162 {
163 std::vector<SubdomainID> ids = getParam<std::vector<SubdomainID>>("block_id");
164 std::vector<SubdomainName> names = getParam<std::vector<SubdomainName>>("block_name");
165 std::set<SubdomainName> seen_it;
166
167 if (ids.size() != names.size())
168 mooseError("You must supply the same number of block ids and names parameters");
169
170 for (unsigned int i = 0; i < ids.size(); ++i)
171 {
172 if (seen_it.find(names[i]) != seen_it.end())
173 mooseError("The following dynamic block name is not unique: " + names[i]);
174 seen_it.insert(names[i]);
175 mesh->setSubdomainName(ids[i], names[i]);
176 }
177 }
178 if (_pars.isParamValid("boundary_id") && _pars.isParamValid("boundary_name"))
179 {
180 std::vector<BoundaryID> ids = getParam<std::vector<BoundaryID>>("boundary_id");
181 std::vector<BoundaryName> names = getParam<std::vector<BoundaryName>>("boundary_name");
182 std::set<SubdomainName> seen_it;
183
184 if (ids.size() != names.size())
185 mooseError("You must supply the same number of boundary ids and names parameters");
186
187 for (unsigned int i = 0; i < ids.size(); ++i)
188 {
189 if (seen_it.find(names[i]) != seen_it.end())
190 mooseError("The following dynamic boundary name is not unique: " + names[i]);
191 mesh->setBoundaryName(ids[i], names[i]);
192 seen_it.insert(names[i]);
193 }
194 }
195
196 if (getParam<bool>("construct_side_list_from_node_list"))
197 mesh->getMesh().get_boundary_info().build_side_list_from_node_list();
198
199 // Here we can override the partitioning for special cases
200 if (getParam<bool>("skip_partitioning"))
201 mesh->getMesh().skip_partitioning(getParam<bool>("skip_partitioning"));
202}
203
204std::string
206{
207 // Get the split_file extension, if there is one, and use that to decide
208 // between .cpr and .cpa.gz
209 auto split_file = _split_file;
210 std::string split_file_ext = MooseUtils::getExtension(split_file);
211
212 // If split_file already has the .cpr or .cpa.gz extension, we go with
213 // that, otherwise we strip off the extension and append ".cpa.gz".
214 if (split_file != "" && split_file_ext != "cpr" && split_file_ext != "cpa.gz")
215 split_file = MooseUtils::stripExtension(split_file) + ".cpa.gz";
216
217 if (_type != "FileMesh")
218 {
219 if (split_file.empty())
220 mooseError("Cannot use split mesh for a non-file mesh without specifying --split-file on "
221 "command line or the Mesh/split_file parameter");
222
223 auto new_pars = FileMesh::validParams();
224
225 // Keep existing parameters where possible
226 new_pars.applyParameters(_moose_object_pars);
227
228 new_pars.set<MeshFileName>("file") = split_file;
229 new_pars.set<MooseApp *>(MooseBase::app_param) =
230 moose_object_params.get<MooseApp *>(MooseBase::app_param);
231 moose_object_params = new_pars;
232 }
233 else
234 {
235 if (!split_file.empty())
236 moose_object_params.set<MeshFileName>("file") = split_file;
237 else
238 moose_object_params.set<MeshFileName>("file") =
239 MooseUtils::stripExtension(moose_object_params.get<MeshFileName>("file")) + ".cpa.gz";
240 }
241
242 moose_object_params.set<bool>("_is_split") = true;
243
244 return "FileMesh";
245}
246
247void
249{
250 // Create the mesh object and tell it to build itself
251 if (_current_task == "setup_mesh")
252 {
253 TIME_SECTION("SetupMeshAction::act::setup_mesh", 1, "Setting Up Mesh", true);
254
255 if (_app.useMasterMesh())
257 else
258 {
259 const auto & generator_actions = _awh.getActionListByName("add_mesh_generator");
260
261 // If we trigger any actions that can build MeshGenerators, whether through input file
262 // syntax or through custom actions, change the default type to construct. We can't yet
263 // check whether there are any actual MeshGenerator objects because those are added after
264 // setup_mesh
265 if (!generator_actions.empty())
266 {
267 // Check for whether type has been set or whether for the default type (FileMesh) a file has
268 // been provided
269 if (!_pars.isParamSetByUser("type") && !_moose_object_pars.isParamValid("file"))
270 {
271 _type = "MeshGeneratorMesh";
272 auto original_params = _moose_object_pars;
273 _moose_object_pars = _factory.getValidParams("MeshGeneratorMesh");
274
275 // Since we changing the type on the fly, we'll have to manually extract parameters again
276 // from the input file object.
278 }
279 else if (!_moose_object_pars.get<bool>("_mesh_generator_mesh"))
280 {
281 // There are cases where a custom action may register the "add_mesh_generator" task, but
282 // may not actually add any mesh generators depending on user input. We don't want to risk
283 // giving false warnings in this case. However, if we triggered the "add_mesh_generator"
284 // task through explicit input file syntax, then it is definitely safe to warn
285 for (auto generator_action_ptr : generator_actions)
286 if (dynamic_cast<AddMeshGeneratorAction *>(generator_action_ptr))
287 {
288 mooseError("Mesh Generators present but the [Mesh] block is set to construct a \"",
289 _type,
290 "\" mesh, which does not use Mesh Generators in constructing the mesh. ");
291 }
292 }
293 }
294
295 // switch non-file meshes to be a file-mesh if using a pre-split mesh configuration.
296 if (_use_split)
298
300 }
301 }
302
303 else if (_current_task == "set_mesh_base")
304 {
305 TIME_SECTION("SetupMeshAction::act::set_mesh_base", 1, "Setting Mesh", true);
306
307 if (!_app.useMasterMesh() && !_mesh->hasMeshBase())
308 {
309 // We want to set the MeshBase object to that coming from mesh generators when the following
310 // conditions are met:
311 // 1. We have mesh generators
312 // 2. We are not using the pre-split mesh
313 // 3. We are not: recovering/restarting and we are the master application
314 if (!_app.getMeshGeneratorNames().empty() && !_use_split &&
316 {
317 auto & mesh_generator_system = _app.getMeshGeneratorSystem();
318 auto mesh_base =
319 mesh_generator_system.getSavedMesh(mesh_generator_system.mainMeshGeneratorName());
320 if (_mesh->allowRemoteElementRemoval() != mesh_base->allow_remote_element_removal())
321 mooseError("The MooseMesh and libmesh::MeshBase object coming from mesh generators are "
322 "out of sync with respect to whether remote elements can be deleted");
323 mooseAssert(mesh_base, "Null mesh");
324 _mesh->setMeshBase(std::move(mesh_base));
325 }
326 else
327 {
328 const auto & mg_names = _app.getMeshGeneratorNames();
329 std::vector<bool> use_dm;
330 for (const auto & mg_name : mg_names)
331 if (hasMeshProperty<bool>("use_distributed_mesh", mg_name))
332 use_dm.push_back(getMeshProperty<bool>("use_distributed_mesh", mg_name));
333
334 if (!use_dm.empty())
335 {
336 if (std::adjacent_find(use_dm.begin(), use_dm.end(), std::not_equal_to<bool>()) !=
337 use_dm.end())
338 mooseError("You cannot use mesh generators that set different values of the mesh "
339 "property 'use_distributed_mesh' within the same simulation.");
340
341 const auto ptype = use_dm.front() ? MooseMesh::ParallelType::DISTRIBUTED
343 _mesh->setParallelType(ptype);
344 }
345
346 _mesh->setMeshBase(_mesh->buildMeshBaseObject());
347 }
348 }
349 }
350
351 else if (_current_task == "init_mesh")
352 {
353 TIME_SECTION("SetupMeshAction::act::set_mesh_base", 1, "Initializing Mesh", true);
354
355 if (_app.useMasterMesh())
356 {
359 }
360 else
361 {
362 _mesh->init();
363
364 if (isParamValid("displacements") && getParam<bool>("use_displaced_mesh"))
365 {
366 _displaced_mesh = _mesh->safeClone();
367 _displaced_mesh->isDisplaced(true);
368 _displaced_mesh->getMesh().allow_remote_element_removal(
369 _mesh->getMesh().allow_remote_element_removal());
370
371 std::vector<std::string> displacements =
372 getParam<std::vector<std::string>>("displacements");
373 if (displacements.size() < _displaced_mesh->dimension())
374 mooseError("Number of displacements must be greater than or equal to the dimension of "
375 "the mesh!");
376 }
377
378 setupMesh(_mesh.get());
379
380 if (_displaced_mesh)
382 }
383 }
384}
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
std::shared_ptr< MooseMesh > & _displaced_mesh
Definition Action.h:175
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:28
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:1675
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:1669
const MooseMesh * masterDisplacedMesh() const
Returns a pointer to the master displaced mesh.
Definition MooseApp.h:881
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