diff --git a/framework/doc/content/source/actions/BatchMeshGeneratorAction.md b/framework/doc/content/source/actions/BatchMeshGeneratorAction.md new file mode 100644 index 000000000000..2afc0332942c --- /dev/null +++ b/framework/doc/content/source/actions/BatchMeshGeneratorAction.md @@ -0,0 +1,49 @@ +# BatchMeshGeneratorAction + +## Overview + +This Action is capable of batch generating a series of meshes using a single type of mesh generator with variation in one or multiple input parameters. + +The type of mesh generator to be used for batch generation is provided by [!param](/Mesh/BatchMeshGeneratorAction/mesh_generator_name). To batch generate meshes using the selected type of mesh generator, users need to provide both `fixed` input parameters, which keep constant throughout the batch generator, and `batch` input parameters, which vary among generated meshes. For both `fixed` anf `batch` input parameters, they are either be scalar or vector type. + +## Specifying Input Parameters + +### Fixed Input Parameters + +Both `scalar` and `vector` types of fixed input parameters are supported by this Action. + +Names of multiple fixed `scalar` input parameters can be defined by [!param](/Mesh/BatchMeshGeneratorAction/fixed_scalar_input_param_names), with their corresponding types defined by [!param](/Mesh/BatchMeshGeneratorAction/fixed_scalar_input_param_types). In the meantime, the values of these fixed `scalar` input parameters need to be provided through [!param](/Mesh/BatchMeshGeneratorAction/fixed_scalar_input_param_values). + +On the other hand, names and the corresponding types of multiple fixed `vector` input parameters can be specified by [!param](/Mesh/BatchMeshGeneratorAction/fixed_vector_input_param_names) and [!param](/Mesh/BatchMeshGeneratorAction/fixed_vector_input_param_types), respectively. The values of these fixed `vector` input parameters are provided through [!param](/Mesh/BatchMeshGeneratorAction/fixed_vector_input_param_values). + +### Batch Input Parameters + +Likewise, both `scalar` and `vector` types of batch input parameters are supported by this Action. + +Similar to the `scalar` and `vector` types of fixed input parameters, the names, types, and values of the batch `scalar` and `vector` input parameters can be specified using [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_param_names), [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_param_types), [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_params); as well as [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_param_names), [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_param_types), [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_params), respectively. Note that for the batch input parameters, because variation is needed, the dimensions of [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_params) and [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_params) are higher than their fixed counterparts by 1. + +### Types of Input Parameters + +The supported input parameter types are summarized in [supported_types] for both `scalar` and `vector` types. + +!table id=supported_types caption=Summary of the symbols used for supported types of input parameters. +| C++ Vector Data Type | C++ Scalar Data Type | Syntax | +| - | - | - | +| `vector` | `Real` | `REAL` | +| `vector` | `short` | `SHORT` | +| `vector` | `unsigned short` | `USHORT` | +| `vector` | `int` | `INT` | +| `vector` | `unsigned int` | `UINT` | +| `vector` | `string` | `STRING` | +| `MultiMooseEnum` | `MooseEnum` | `ENUM` | +| `vector` | `bool` | `BOOL` | + +## Multiple Batch Input Parameter Processing Methods + +If more than one batch input parameters (either `scalar` or `vector`) are provided, two methods can be selected using [!param](/Mesh/BatchMeshGeneratorAction/multi_batch_params_method). + +The default method is `cartesian_product`, which batch generates mesh generators based on the Cartessian product of all the batch input parameters. For example, if `m` scalar input parameters are specified using [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_param_names), with the corresponding [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_params) containing $N_{s,1}$, $N_{s,2}$,..., and $N_{s,m}$ variations, respectively. Meanwhile, if `n` vector input parameters are specified using [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_param_names), with the corresponding [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_params) containing $N_{v,1}$, $N_{v,2}$,..., and $N_{v,n}$ variations. Using the Cartesian product approach leads to a total of $\prod_{i=0}^{m} N_{s,i}\prod_{j=0}^{n} N_{v,j}$ mesh generators. + +On the other hand, an alternative method is `corresponding`, which requires the numbers of variations for all [!param](/Mesh/BatchMeshGeneratorAction/batch_scalar_input_param_names) and [!param](/Mesh/BatchMeshGeneratorAction/batch_vector_input_param_names) to be the same (e.g., $N$). In that case, only $N$ mesh generators are created. + +!syntax parameters /Mesh/BatchMeshGeneratorAction diff --git a/framework/doc/content/syntax/Mesh/BatchMeshGeneratorAction/index.md b/framework/doc/content/syntax/Mesh/BatchMeshGeneratorAction/index.md new file mode 100644 index 000000000000..23d5a5503765 --- /dev/null +++ b/framework/doc/content/syntax/Mesh/BatchMeshGeneratorAction/index.md @@ -0,0 +1,9 @@ +# BatchMeshGeneratorAction + +This [Action.md] can batch generate meshes using one type of mesh generators with variation in one or multiple input parameters. + +!syntax list /Mesh/BatchMeshGeneratorAction objects=True actions=False subsystems=False + +!syntax list /Mesh/BatchMeshGeneratorAction objects=False actions=False subsystems=True + +!syntax list /Mesh/BatchMeshGeneratorAction objects=False actions=True subsystems=False diff --git a/framework/include/actions/BatchMeshGeneratorAction.h b/framework/include/actions/BatchMeshGeneratorAction.h new file mode 100644 index 000000000000..f50b46d59632 --- /dev/null +++ b/framework/include/actions/BatchMeshGeneratorAction.h @@ -0,0 +1,123 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +// MOOSE includes +#include "Action.h" +#include "ActionWarehouse.h" + +class BatchMeshGeneratorAction : public Action +{ +public: + static InputParameters validParams(); + + BatchMeshGeneratorAction(const InputParameters & params); + + virtual void act() override final; + + enum class MultiBatchParamsMethod + { + corresponding, + cartesian_product + }; + + enum class ParameterType + { + BOOL, + REAL, + SHORT, + USHORT, + INT, + UINT, + STRING, + ENUM + }; + +protected: + virtual void addMeshGenerators(); + /// Name of the mesh generator to use for batch generation + const std::string _mesh_generator_name; + /// Prefix to use for naming the batch generated meshes + const std::string _mesh_name_prefix; + /// Names of the scalar input parameters to vary in the batch generation + const std::vector _batch_scalar_input_param_names; + /// Types of the scalar input parameters to vary in the batch generation + const std::vector _batch_scalar_input_param_types; + /// Values of the scalar input parameters to vary in the batch generation + const std::vector> _batch_scalar_input_params; + /// Names of the vector input parameters to vary in the batch generation + const std::vector _batch_vector_input_param_names; + /// Types of the vector input parameters to vary in the batch generation + const std::vector _batch_vector_input_param_types; + /// Values of the vector input parameters to vary in the batch generation + const std::vector>> _batch_vector_input_params; + /// Method to use for generating the batch parameters + const MultiBatchParamsMethod _multi_batch_params_method; + /// Names of the vector input parameters to keep fixed in the batch generation + const std::vector _fixed_scalar_input_param_names; + /// Types of the vector input parameters to keep fixed in the batch generation + const std::vector _fixed_scalar_input_param_types; + /// Values of the vector input parameters to keep fixed in the batch generation + const std::vector _fixed_scalar_input_param_values; + /// Names of the vector input parameters to keep fixed in the batch generation + const std::vector _fixed_vector_input_param_names; + /// Types of the vector input parameters to keep fixed in the batch generation + const std::vector _fixed_vector_input_param_types; + /// Values of the vector input parameters to keep fixed in the batch generation + const std::vector> _fixed_vector_input_param_values; + + /** + * Set the scalar input parameters for a unit mesh generator + * @param params InputParameters object to set the parameters + * @param param_name Name of the parameter to set + * @param param_type Type of the parameter to set + * @param param_value Value of the parameter to set in string format + */ + void setScalarParams(InputParameters & params, + const std::string & param_name, + const ParameterType & param_type, + const std::string & param_value); + + /** + * Set the vector input parameters for a unit mesh generator + * @param params InputParameters object to set the parameters + * @param param_name Name of the parameter to set + * @param param_type Type of the parameter to set + * @param param_value Value of the parameter to set in string format + */ + void setVectorParams(InputParameters & params, + const std::string & param_name, + const ParameterType & param_type, + const std::vector & param_value); + + /** + * Convert a string to a numeric scalar and set it in the InputParameters object + * @param params InputParameters object to set the parameter + * @param param_name Name of the parameter to set + * @param param_value Value of the parameter to set in string format + * @param is_integer Flag to indicate if the parameter is an integer + */ + template + void convertAndSetNumericScalar(InputParameters & params, + const std::string & param_name, + const std::string & param_value); + + /** + * Convert a vector of strings to a numeric vector and set it in the InputParameters object + * @param params InputParameters object to set the parameter + * @param param_name Name of the parameter to set + * @param param_value Value of the parameter to set in string format + * @param is_integer Flag to indicate if the parameter is an integer + */ + template + void convertAndSetNumericVector(InputParameters & params, + const std::string & param_name, + const std::vector & param_value); +}; diff --git a/framework/src/actions/BatchMeshGeneratorAction.C b/framework/src/actions/BatchMeshGeneratorAction.C new file mode 100644 index 000000000000..2d9db5d6f43a --- /dev/null +++ b/framework/src/actions/BatchMeshGeneratorAction.C @@ -0,0 +1,448 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +// MOOSE includes +#include "BatchMeshGeneratorAction.h" +#include "ActionFactory.h" + +#include "MooseMesh.h" +#include "MeshGenerator.h" +#include "Factory.h" +#include "MooseApp.h" + +#include "hit/hit.h" + +registerMooseAction("MooseApp", BatchMeshGeneratorAction, "add_mesh_generator"); + +InputParameters +BatchMeshGeneratorAction::validParams() +{ + InputParameters params = Action::validParams(); + + params.set("type") = "BatchMeshGeneratorAction"; + + params.addClassDescription("Batch generate meshes using actions."); + params.addRequiredParam("mesh_generator_name", + "Names of the mesh generator to be batch generated."); + params.addRequiredParam("mesh_name_prefix", + "Prefix name of the meshes to be batch generated."); + + params.addParam>("batch_scalar_input_param_names", + std::vector(), + "Names of the scalar input parameters to be altered."); + MultiMooseEnum default_types("BOOL REAL SHORT USHORT INT UINT STRING ENUM", ""); + params.addParam("batch_scalar_input_param_types", + default_types, + "Types of the scalar input parameters to be altered."); + params.addParam>>( + "batch_scalar_input_params", {}, "Values of the scalar input parameters to be assigned."); + + params.addParam>("batch_vector_input_param_names", + std::vector(), + "Name of the vector input parameters to be altered."); + params.addParam("batch_vector_input_param_types", + default_types, + "Type of the vector input parameters to be altered."); + params.addParam>>>( + "batch_vector_input_params", {}, "Values of the vector input parameters to be assigned."); + + MooseEnum multi_batch_params_method("corresponding cartesian_product", "cartesian_product"); + params.addParam("multi_batch_params_method", + multi_batch_params_method, + "Method to generate multiple batch parameters.Options: " + + multi_batch_params_method.getRawNames()); + + params.addParam>( + "fixed_scalar_input_param_names", {}, "Names of the input parameters to be fixed."); + params.addParam("fixed_scalar_input_param_types", + default_types, + "Types of the input parameters to be fixed."); + params.addParam>( + "fixed_scalar_input_param_values", {}, "Values of the input parameters to be fixed."); + params.addParam>( + "fixed_vector_input_param_names", {}, "Names of the input vector parameters to be fixed."); + params.addParam("fixed_vector_input_param_types", + default_types, + "Types of the input vector parameters to be fixed."); + params.addParam>>( + "fixed_vector_input_param_values", {}, "Values of the input vector parameters to be fixed."); + + params.addParamNamesToGroup( + "batch_scalar_input_param_names batch_scalar_input_param_types batch_scalar_input_params " + "batch_vector_input_param_names batch_vector_input_param_types batch_vector_input_params", + "Batch Input"); + params.addParamNamesToGroup("fixed_scalar_input_param_names fixed_scalar_input_param_types " + "fixed_scalar_input_param_values " + "fixed_vector_input_param_names fixed_vector_input_param_types " + "fixed_vector_input_param_values", + "Fixed Input"); + + return params; +} + +BatchMeshGeneratorAction::BatchMeshGeneratorAction(const InputParameters & params) + : Action(params), + _mesh_generator_name(getParam("mesh_generator_name")), + _mesh_name_prefix(getParam("mesh_name_prefix")), + _batch_scalar_input_param_names( + getParam>("batch_scalar_input_param_names")), + _batch_scalar_input_param_types(isParamValid("batch_scalar_input_param_types") + ? getParam("batch_scalar_input_param_types") + .template getSetValueIDs() + : std::vector()), + _batch_scalar_input_params( + getParam>>("batch_scalar_input_params")), + _batch_vector_input_param_names( + getParam>("batch_vector_input_param_names")), + _batch_vector_input_param_types(isParamValid("batch_vector_input_param_types") + ? getParam("batch_vector_input_param_types") + .template getSetValueIDs() + : std::vector()), + _batch_vector_input_params( + getParam>>>("batch_vector_input_params")), + _multi_batch_params_method(getParam("multi_batch_params_method") + .template getEnum()), + _fixed_scalar_input_param_names( + getParam>("fixed_scalar_input_param_names")), + _fixed_scalar_input_param_types(isParamValid("fixed_scalar_input_param_types") + ? getParam("fixed_scalar_input_param_types") + .template getSetValueIDs() + : std::vector()), + _fixed_scalar_input_param_values( + getParam>("fixed_scalar_input_param_values")), + _fixed_vector_input_param_names( + getParam>("fixed_vector_input_param_names")), + _fixed_vector_input_param_types(isParamValid("fixed_vector_input_param_types") + ? getParam("fixed_vector_input_param_types") + .template getSetValueIDs() + : std::vector()), + _fixed_vector_input_param_values( + getParam>>("fixed_vector_input_param_values")) +{ + if (_fixed_scalar_input_param_names.size() != _fixed_scalar_input_param_types.size() || + _fixed_scalar_input_param_names.size() != _fixed_scalar_input_param_values.size()) + { + mooseError("BatchMeshGeneratorAction: fixed_scalar_input_param_names, " + "fixed_scalar_input_param_types, and " + "fixed_scalar_input_param_values must have the same size."); + } + + // Sanity check for the batch input parameters + if (_batch_scalar_input_param_names.size() != _batch_scalar_input_param_types.size() || + _batch_scalar_input_param_names.size() != _batch_scalar_input_params.size()) + { + mooseError("BatchMeshGeneratorAction: batch_scalar_input_param_names, " + "batch_scalar_input_param_types, and " + "batch_scalar_input_params must have the same size."); + } + if (_batch_vector_input_param_names.size() != _batch_vector_input_param_types.size() || + _batch_vector_input_param_names.size() != _batch_vector_input_params.size()) + { + mooseError("BatchMeshGeneratorAction: batch_vector_input_param_names, " + "batch_vector_input_param_types, and " + "batch_vector_input_params must have the same size."); + } + // If the corresponding method is used, the number of batch parameters must be the same + std::set batch_params_sizes; + if (_multi_batch_params_method == MultiBatchParamsMethod::corresponding) + { + for (const auto & unit_batch_scalar_params : _batch_scalar_input_params) + { + batch_params_sizes.emplace(unit_batch_scalar_params.size()); + } + for (const auto & unit_batch_vector_params : _batch_vector_input_params) + { + batch_params_sizes.emplace(unit_batch_vector_params.size()); + } + // The parameters should not be empty + if (batch_params_sizes.empty()) + { + mooseError("BatchMeshGeneratorAction: batch_scalar_input_params and " + "batch_vector_input_params cannot be empty."); + } + else if (batch_params_sizes.size() > 1) + { + mooseError("BatchMeshGeneratorAction: batch_scalar_input_params and " + "batch_vector_input_params must have the same size."); + } + } +} + +void +BatchMeshGeneratorAction::act() +{ + if (_current_task == "add_mesh_generator") + addMeshGenerators(); +} + +void +BatchMeshGeneratorAction::addMeshGenerators() +{ + std::vector> processed_batch_scalar_input_params; + std::vector>> processed_batch_vector_input_params; + if (_multi_batch_params_method == MultiBatchParamsMethod::corresponding) + { + processed_batch_scalar_input_params = _batch_scalar_input_params; + processed_batch_vector_input_params = _batch_vector_input_params; + } + else // cartesian_product + { + // We basically need to reconstruct the corresponding parameters based on the cartesian product + // algorithm + for (const auto i : index_range(_batch_scalar_input_params)) + { + // For the first element, just copy the parameters + if (processed_batch_scalar_input_params.empty()) + processed_batch_scalar_input_params.push_back(_batch_scalar_input_params[i]); + else + { + const unsigned int num_new_batch_params = _batch_scalar_input_params[i].size(); + const unsigned int num_processed_batch_params = + processed_batch_scalar_input_params.front().size(); + // All the elements in the processed_batch_scalar_input_params need to be duplicated for + // num_new_batch_params times + for (auto & unit_processed_batch_scalar_input_params : processed_batch_scalar_input_params) + { + auto temp_params = unit_processed_batch_scalar_input_params; + for (unsigned int j = 1; j < num_new_batch_params; j++) + { + unit_processed_batch_scalar_input_params.insert( + unit_processed_batch_scalar_input_params.end(), + temp_params.begin(), + temp_params.end()); + } + } + // Then, add a new element to the processed_batch_scalar_input_params by repeating each + // element in _batch_scalar_input_params[i] for num_processed_batch_params times + processed_batch_scalar_input_params.push_back({}); + for (const auto & unit_batch_scalar_input_params : _batch_scalar_input_params[i]) + for (unsigned int j = 0; j < num_processed_batch_params; j++) + processed_batch_scalar_input_params.back().push_back(unit_batch_scalar_input_params); + } + } + for (const auto i : index_range(_batch_vector_input_params)) + { + // For the first element, just copy the parameters + if (processed_batch_vector_input_params.empty()) + if (processed_batch_scalar_input_params.empty()) + // if no batch scalar input parameters are used + // we just need to initiate the processed_batch_vector_input_params as the first one to + // fill + processed_batch_vector_input_params.push_back(_batch_vector_input_params[i]); + else + { + processed_batch_vector_input_params.push_back({}); + // if there are batch scalar input parameters, then each element needs to be duplicated + // for that amount of times + for (const auto & unit_batch_vector_input_params : _batch_vector_input_params[i]) + for (unsigned int j = 0; j < processed_batch_scalar_input_params.front().size(); j++) + processed_batch_vector_input_params.back().push_back(unit_batch_vector_input_params); + // Then the scalar input parameters need to be duplicated for the number of elements in + // the processed_batch_vector_input_params + for (auto & unit_processed_batch_scalar_input_params : + processed_batch_scalar_input_params) + { + auto temp_params = unit_processed_batch_scalar_input_params; + for (unsigned int j = 1; j < processed_batch_vector_input_params.back().size(); j++) + { + unit_processed_batch_scalar_input_params.insert( + unit_processed_batch_scalar_input_params.end(), + temp_params.begin(), + temp_params.end()); + } + } + } + else + { + const unsigned int num_new_batch_params = _batch_vector_input_params[i].size(); + const unsigned int num_processed_batch_params = + processed_batch_vector_input_params.front().size(); + // All the elements in the processed_batch_vector_input_params need to be duplicated for + // num_new_batch_params times + for (auto & unit_processed_batch_vector_input_params : processed_batch_vector_input_params) + { + auto temp_params = unit_processed_batch_vector_input_params; + for (unsigned int j = 1; j < num_new_batch_params; j++) + { + unit_processed_batch_vector_input_params.insert( + unit_processed_batch_vector_input_params.end(), + temp_params.begin(), + temp_params.end()); + } + } + // if there are also batch scalar input parameters, it also needs to be duplicated + for (auto & unit_processed_batch_scalar_input_params : processed_batch_scalar_input_params) + { + auto temp_params = unit_processed_batch_scalar_input_params; + for (unsigned int j = 1; j < num_new_batch_params; j++) + { + unit_processed_batch_scalar_input_params.insert( + unit_processed_batch_scalar_input_params.end(), + temp_params.begin(), + temp_params.end()); + } + } + // Then, add a new element to the processed_batch_vector_input_params by repeating each + // element in _batch_vector_input_params[i] for num_processed_batch_params times + processed_batch_vector_input_params.push_back({}); + for (const auto & unit_batch_vector_input_params : _batch_vector_input_params[i]) + for (unsigned int j = 0; j < num_processed_batch_params; j++) + processed_batch_vector_input_params.back().push_back(unit_batch_vector_input_params); + } + } + } + + // Now, we can add the mesh generators by looping through the processed params + const unsigned int num_batch_params = processed_batch_vector_input_params.empty() + ? processed_batch_scalar_input_params.front().size() + : processed_batch_vector_input_params.front().size(); + for (const auto i : make_range(num_batch_params)) + { + auto params = _app.getFactory().getValidParams(_mesh_generator_name); + for (const auto j : index_range(_batch_scalar_input_params)) + setScalarParams(params, + _batch_scalar_input_param_names[j], + _batch_scalar_input_param_types[j], + processed_batch_scalar_input_params[j][i]); + for (const auto j : index_range(_batch_vector_input_params)) + setVectorParams(params, + _batch_vector_input_param_names[j], + _batch_vector_input_param_types[j], + processed_batch_vector_input_params[j][i]); + for (const auto j : index_range(_fixed_scalar_input_param_names)) + setScalarParams(params, + _fixed_scalar_input_param_names[j], + _fixed_scalar_input_param_types[j], + _fixed_scalar_input_param_values[j]); + for (const auto j : index_range(_fixed_vector_input_param_names)) + setVectorParams(params, + _fixed_vector_input_param_names[j], + _fixed_vector_input_param_types[j], + _fixed_vector_input_param_values[j]); + _app.getMeshGeneratorSystem().addMeshGenerator( + _mesh_generator_name, _mesh_name_prefix + "_" + std::to_string(i), params); + } +} + +void +BatchMeshGeneratorAction::setScalarParams(InputParameters & params, + const std::string & param_name, + const ParameterType & param_type, + const std::string & param_value) +{ + switch (param_type) + { + case (ParameterType::REAL): + convertAndSetNumericScalar(params, param_name, param_value); + break; + case (ParameterType::SHORT): + convertAndSetNumericScalar(params, param_name, param_value); + break; + case (ParameterType::USHORT): + convertAndSetNumericScalar(params, param_name, param_value); + break; + case (ParameterType::INT): + convertAndSetNumericScalar(params, param_name, param_value); + break; + case (ParameterType::UINT): + convertAndSetNumericScalar(params, param_name, param_value); + break; + case (ParameterType::ENUM): + if (params.isType(param_name)) + params.set(param_name) = param_value; + break; + case (ParameterType::STRING): + if (params.isType(param_name)) + params.set(param_name) = param_value; + break; + case (ParameterType::BOOL): + if (params.isType(param_name)) + hit::toBool(param_value, ¶ms.set(param_name)); + break; + default: + mooseError("impossible situation."); // as we use MultiMooseEnum to ensure the type is valid + } +} + +void +BatchMeshGeneratorAction::setVectorParams(InputParameters & params, + const std::string & param_name, + const ParameterType & param_type, + const std::vector & param_value) +{ + switch (param_type) + { + case (ParameterType::REAL): + convertAndSetNumericVector(params, param_name, param_value); + break; + case (ParameterType::SHORT): + convertAndSetNumericVector(params, param_name, param_value); + break; + case (ParameterType::USHORT): + convertAndSetNumericVector(params, param_name, param_value); + break; + case (ParameterType::INT): + convertAndSetNumericVector(params, param_name, param_value); + break; + case (ParameterType::UINT): + convertAndSetNumericVector(params, param_name, param_value); + break; + case (ParameterType::ENUM): + if (params.isType>(param_name)) + params.set(param_name) = param_value; + break; + case (ParameterType::STRING): + if (params.isType>(param_name)) + params.set>(param_name) = param_value; + break; + case (ParameterType::BOOL): + if (params.isType>(param_name)) + { + std::vector values(param_value.size()); + std::transform(param_value.begin(), + param_value.end(), + values.begin(), + [](const std::string & val) + { + bool tmp; + hit::toBool(val, &tmp); + return tmp; + }); + params.set>(param_name) = values; + } + break; + default: + mooseError("impossible situation."); // as we use MultiMooseEnum to ensure the type is valid + } +} + +template +void +BatchMeshGeneratorAction::convertAndSetNumericScalar(InputParameters & params, + const std::string & param_name, + const std::string & param_value) +{ + if (params.isType(param_name)) + params.set(param_name) = MooseUtils::convert(param_value); +} + +template +void +BatchMeshGeneratorAction::convertAndSetNumericVector(InputParameters & params, + const std::string & param_name, + const std::vector & param_value) +{ + std::vector values(param_value.size()); + std::transform(param_value.begin(), + param_value.end(), + values.begin(), + [](const std::string & val) { return MooseUtils::convert(val); }); + if (params.isType>(param_name)) + params.set>(param_name) = values; +} diff --git a/framework/src/base/Moose.C b/framework/src/base/Moose.C index 5a56fd5a5acd..24b0820ae6ed 100644 --- a/framework/src/base/Moose.C +++ b/framework/src/base/Moose.C @@ -497,6 +497,8 @@ associateSyntaxInner(Syntax & syntax, ActionFactory & /*action_factory*/) registerSyntax("CreateDisplacedProblemAction", "Mesh"); registerSyntax("DisplayGhostingAction", "Mesh"); registerSyntax("AddMeshGeneratorAction", "Mesh/*"); + registerSyntaxTask("EmptyAction", "Mesh/BatchMeshGeneratorAction", "no_action"); + registerSyntax("BatchMeshGeneratorAction", "Mesh/BatchMeshGeneratorAction/*"); registerSyntax("ElementIDOutputAction", "Mesh"); syntax.registerSyntaxType("Mesh/*", "MeshGeneratorName"); diff --git a/modules/reactor/include/meshgenerators/PatternedHexMeshGenerator.h b/modules/reactor/include/meshgenerators/PatternedHexMeshGenerator.h index 19ea50f19be8..7a086e71a2a6 100644 --- a/modules/reactor/include/meshgenerators/PatternedHexMeshGenerator.h +++ b/modules/reactor/include/meshgenerators/PatternedHexMeshGenerator.h @@ -28,7 +28,7 @@ class PatternedHexMeshGenerator : public PolygonMeshGeneratorBase protected: /// The input meshes - const std::vector *> _mesh_ptrs; + std::vector *> _mesh_ptrs; /// Names of input meshes const std::vector & _input_names; diff --git a/modules/reactor/src/meshgenerators/PatternedHexMeshGenerator.C b/modules/reactor/src/meshgenerators/PatternedHexMeshGenerator.C index f7421af35de9..c17795699724 100644 --- a/modules/reactor/src/meshgenerators/PatternedHexMeshGenerator.C +++ b/modules/reactor/src/meshgenerators/PatternedHexMeshGenerator.C @@ -145,7 +145,6 @@ PatternedHexMeshGenerator::validParams() PatternedHexMeshGenerator::PatternedHexMeshGenerator(const InputParameters & parameters) : PolygonMeshGeneratorBase(parameters), - _mesh_ptrs(getMeshes("inputs")), _input_names(getParam>("inputs")), _pattern(getParam>>("pattern")), _pattern_boundary(getParam("pattern_boundary")), @@ -193,6 +192,8 @@ PatternedHexMeshGenerator::PatternedHexMeshGenerator(const InputParameters & par declareMeshProperty("hexagon_center_trimmability", true); declareMeshProperty("peripheral_modifier_compatible", _pattern_boundary == "hexagon"); + _mesh_ptrs = getMeshes("inputs"); + const unsigned int n_pattern_layers = _pattern.size(); declareMeshProperty("pattern_size", n_pattern_layers); if (n_pattern_layers % 2 == 0) diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_corr.i b/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_corr.i new file mode 100644 index 000000000000..df8138e23ace --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_corr.i @@ -0,0 +1,23 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + multi_batch_params_method = corresponding + mesh_name_prefix = 'gmg' + batch_scalar_input_param_names = 'nx ny' + batch_scalar_input_param_types = 'UINT UINT' + batch_scalar_input_params = '1 2 3 4; 1 2 3 4' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_cp.i b/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_cp.i new file mode 100644 index 000000000000..2e73e4b0b357 --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/double_scalar_cp.i @@ -0,0 +1,22 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + mesh_name_prefix = 'gmg' + batch_scalar_input_param_names = 'nx ny' + batch_scalar_input_param_types = 'UINT UINT' + batch_scalar_input_params = '1 2; 1 2' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_corr_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_corr_in.e new file mode 100644 index 000000000000..43793dd2e643 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_corr_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_cp_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_cp_in.e new file mode 100644 index 000000000000..83e527d8ba01 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/double_scalar_cp_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_enum_test_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_enum_test_in.e new file mode 100644 index 000000000000..821761dd0f39 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_enum_test_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_corr_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_corr_in.e new file mode 100644 index 000000000000..86eeb14ec182 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_corr_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_cp_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_cp_in.e new file mode 100644 index 000000000000..ba099712f5f6 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/scalar_vector_cp_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_scalar_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_scalar_in.e new file mode 100644 index 000000000000..b01c84fc47d6 Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_scalar_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_vector_in.e b/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_vector_in.e new file mode 100644 index 000000000000..bc2956d1cf8e Binary files /dev/null and b/test/tests/meshgenerators/batch_mesh_generation_action/gold/single_vector_in.e differ diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/scalar_enum_test.i b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_enum_test.i new file mode 100644 index 000000000000..2a59d5ac5788 --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_enum_test.i @@ -0,0 +1,26 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'ConcentricCircleMeshGenerator' + multi_batch_params_method = corresponding + mesh_name_prefix = 'gmg' + batch_vector_input_param_names = 'radii rings' + batch_vector_input_param_types = 'REAL UINT' + batch_vector_input_params = '0.5;0.8;1.2;1.5|1;2;3;4' + batch_scalar_input_param_names = 'num_sectors' + batch_scalar_input_param_types = 'UINT' + batch_scalar_input_params = '6 8 10 12' + fixed_scalar_input_param_names = 'portion has_outer_square preserve_volumes' + fixed_scalar_input_param_types = 'ENUM BOOL BOOL' + fixed_scalar_input_param_values = 'left_half off off' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 3 0 0 + 0 3 0 + 3 3 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_corr.i b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_corr.i new file mode 100644 index 000000000000..12d44561d157 --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_corr.i @@ -0,0 +1,26 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + multi_batch_params_method = corresponding + mesh_name_prefix = 'gmg' + batch_scalar_input_param_names = 'nx' + batch_scalar_input_param_types = 'UINT' + batch_scalar_input_params = '1 2 3 4' + batch_vector_input_param_names = 'subdomain_ids' + batch_vector_input_param_types = 'USHORT' + batch_vector_input_params = '1;2;3;4' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_cp.i b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_cp.i new file mode 100644 index 000000000000..445214492991 --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/scalar_vector_cp.i @@ -0,0 +1,26 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + multi_batch_params_method = cartesian_product + mesh_name_prefix = 'gmg' + batch_scalar_input_param_names = 'nx' + batch_scalar_input_param_types = 'UINT' + batch_scalar_input_params = '1 2' + batch_vector_input_param_names = 'subdomain_ids' + batch_vector_input_param_types = 'USHORT' + batch_vector_input_params = '1;2' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/single_scalar.i b/test/tests/meshgenerators/batch_mesh_generation_action/single_scalar.i new file mode 100644 index 000000000000..1bd265c05e7d --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/single_scalar.i @@ -0,0 +1,22 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + mesh_name_prefix = 'gmg' + batch_scalar_input_param_names = 'nx' + batch_scalar_input_param_types = 'UINT' + batch_scalar_input_params = '1 2 3 4' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/single_vector.i b/test/tests/meshgenerators/batch_mesh_generation_action/single_vector.i new file mode 100644 index 000000000000..1a343de762be --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/single_vector.i @@ -0,0 +1,23 @@ +[Mesh] + [BatchMeshGeneratorAction] + [batch1] + mesh_generator_name = 'GeneratedMeshGenerator' + #multi_batch_params_method = cartesian_product + mesh_name_prefix = 'gmg' + batch_vector_input_param_names = 'subdomain_ids' + batch_vector_input_param_types = 'USHORT' + batch_vector_input_params = '1;2;3;4' + fixed_scalar_input_param_names = 'dim' + fixed_scalar_input_param_types = 'ENUM' + fixed_scalar_input_param_values = '2' + [] + [] + [cmbn] + type = CombinerGenerator + inputs = 'gmg_0 gmg_1 gmg_2 gmg_3' + positions = '0 0 0 + 2 0 0 + 0 2 0 + 2 2 0' + [] +[] diff --git a/test/tests/meshgenerators/batch_mesh_generation_action/tests b/test/tests/meshgenerators/batch_mesh_generation_action/tests new file mode 100644 index 000000000000..662cfa84892b --- /dev/null +++ b/test/tests/meshgenerators/batch_mesh_generation_action/tests @@ -0,0 +1,58 @@ +[Tests] + [single_scalar] + type = 'Exodiff' + input = 'single_scalar.i' + exodiff = 'single_scalar_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in one single scalar parameter' + [] + [double_scalar_corr] + type = 'Exodiff' + input = 'double_scalar_corr.i' + exodiff = 'double_scalar_corr_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in two corresponding scalar parameters' + [] + [double_scalar_cp] + type = 'Exodiff' + input = 'double_scalar_cp.i' + exodiff = 'double_scalar_cp_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in two scalar parameters using a Cartesian product' + [] + [single_vector] + type = 'Exodiff' + input = 'single_vector.i' + exodiff = 'single_vector_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in one single vector parameter' + [] + [scalar_vector_corr] + type = 'Exodiff' + input = 'scalar_vector_corr.i' + exodiff = 'scalar_vector_corr_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in one scalar and one corresponding vector parameter' + [] + [scalar_vector_cp] + type = 'Exodiff' + input = 'scalar_vector_cp.i' + exodiff = 'scalar_vector_cp_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should batch generate meshes of the same type with variation in one scalar and one vector parameter using a Cartesian product' + [] + [enum_batch] + type = 'Exodiff' + input = 'scalar_enum_test.i' + exodiff = 'scalar_enum_test_in.e' + cli_args = '--mesh-only' + recover = false + requirement = 'The system should ' + [] +[] \ No newline at end of file