32#include "libmesh/string_to_enum.h"
43 : ParallelObject(fe_problem.comm()),
45 _thm_mesh(*pars.get<
MooseMesh *>(
"mesh")),
46 _fe_problem(fe_problem),
48 _thm_factory(_thm_app.getFactory()),
50 _flow_fe_type(FEType(CONSTANT, MONOMIAL).set_p_refinement(false)),
51 _implicit_time_integration(true),
52 _check_jacobian(false),
53 _output_vector_velocity(true),
56 bool second_order_mesh = pars.
get<
bool>(
"2nd_order_mesh");
58 second_order_mesh ? FEType(SECOND, LAGRANGE) : FEType(FIRST, LAGRANGE);
73 {elem_id1, std::vector<dof_id_type>()});
74 it->second.push_back(elem_id2);
79 {elem_id2, std::vector<dof_id_type>()});
80 it->second.push_back(elem_id1);
91 comp->executeSetupMesh();
100 Order order = CONSTANT;
101 unsigned int n_flow_channels = 0;
102 unsigned int n_heat_structures = 0;
107 if (flow_channel !=
nullptr)
115 if (n_flow_channels > 0)
118 if (fe_type.default_quadrature_order() > order)
119 order = fe_type.default_quadrature_order();
121 if (n_heat_structures > 0)
124 if (fe_type.default_quadrature_order() > order)
125 order = fe_type.default_quadrature_order();
138 dependency_resolver.
addNode(comp);
139 for (
const auto & dep : comp->getDependencies())
157 comp->executeInitSecondary();
166 const auto flow_connection =
167 MooseSharedNamespace::dynamic_pointer_cast<Component1DConnection>(component);
172 std::vector<std::string> names = flow_connection->getConnectedComponentNames();
173 names.push_back(component->name());
174 std::sort(names.begin(), names.end());
177 std::string proposed_loop_name = names[0];
179 for (
const std::string &
name : names)
193 if (proposed_loop_name > current_loop_name)
196 if (entry.second == proposed_loop_name)
197 entry.second = current_loop_name;
198 proposed_loop_name = current_loop_name;
202 else if (proposed_loop_name < current_loop_name)
205 if (entry.second == current_loop_name)
206 entry.second = proposed_loop_name;
214 std::vector<std::string> loops;
216 if (std::find(loops.begin(), loops.end(), entry.second) == loops.end())
217 loops.push_back(entry.second);
220 for (
const auto & loop : loops)
224 bool found_model_id =
false;
227 const auto flow_chan_base_component =
228 MooseSharedNamespace::dynamic_pointer_cast<FlowChannelBase>(component);
231 model_id = flow_chan_base_component->getFlowModelID();
232 found_model_id =
true;
240 logError(
"No FlowChannelBase-derived components were found in loop '", loop,
"'");
248 std::vector<std::string> loops;
250 if (std::find(loops.begin(), loops.end(), entry.second) == loops.end())
251 loops.push_back(entry.second);
254 Moose::out <<
"\nListing of component loops:" << std::endl;
255 for (
unsigned int i = 0; i < loops.size(); i++)
257 Moose::out <<
"\n Loop " << i + 1 <<
":" << std::endl;
261 if (entry.second == loops[i])
262 Moose::out <<
" " << entry.first << std::endl;
264 Moose::out << std::endl;
269 const VariableName &
name,
272 const SolverSystemName & solver_sys)
276 if (fe_type.family != SCALAR)
277 mooseError(
"This method should only be used for scalar variables.");
285 vi._var_type =
"MooseVariableScalar";
289 family = Utility::enum_to_string(fe_type.family);
293 order = Utility::enum_to_string<Order>(fe_type.order);
297 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
298 else if (!MooseUtils::absoluteFuzzyEqual(scaling_factor, 1.0))
299 mooseError(
"Aux variables cannot be provided a residual scaling factor.");
301 params.
set<SolverSystemName>(
"solver_sys") = solver_sys;
318 const VariableName &
name,
320 const std::vector<SubdomainName> & subdomain_names,
322 const SolverSystemName & solver_sys)
326 if (fe_type.family == SCALAR)
328 "The version of Simulation::addSimVariable() with subdomain names can no longer be used "
329 "with scalar variables since scalar variables cannot be block-restricted. Use the version "
330 "of Simulation::addSimVariable() without subdomain names instead.");
333 for (
const auto & subdomain_name : subdomain_names)
334 mooseAssert(subdomain_name !=
"ANY_BLOCK_ID",
335 "'ANY_BLOCK_ID' cannot be used for adding field variables in components.");
344 vi._var_type =
"MooseVariable";
346 params.
set<std::vector<SubdomainName>>(
"block") = subdomain_names;
349 family = Utility::enum_to_string(fe_type.family);
353 order = Utility::enum_to_string<Order>(fe_type.order);
357 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
358 else if (!MooseUtils::absoluteFuzzyEqual(scaling_factor, 1.0))
359 mooseError(
"Aux variables cannot be provided a residual scaling factor.");
361 params.
set<SolverSystemName>(
"solver_sys") = solver_sys;
373 "' has already been added in a different system (nonlinear or aux).");
375 if (vi._var_type !=
"MooseVariable")
378 "' has already been added with a different type than 'MooseVariable'.");
380 if (params.
get<SolverSystemName>(
"solver_sys") != solver_sys)
381 mooseError(
"The variable '",
name,
"' has already been added to a different solver system.");
384 family = Utility::enum_to_string(fe_type.family);
386 mooseError(
"The variable '",
name,
"' has already been added with a different FE family.");
389 order = Utility::enum_to_string<Order>(fe_type.order);
391 mooseError(
"The variable '",
name,
"' has already been added with a different FE order.");
396 auto blocks = params.
get<std::vector<SubdomainName>>(
"block");
397 for (
const auto & subdomain_name : subdomain_names)
399 blocks.push_back(subdomain_name);
400 params.
set<std::vector<SubdomainName>>(
"block") = blocks;
403 params.
set<std::vector<SubdomainName>>(
"block") = subdomain_names;
406 if (!MooseUtils::absoluteFuzzyEqual(params.
get<std::vector<Real>>(
"scaling")[0],
409 "The variable '",
name,
"' has already been added with a different scaling factor.");
415 const std::string & var_type,
416 const VariableName &
name,
438 "' has already been added in a different system (nonlinear or aux).");
443 "' has already been added with a different type than '",
448 for (
auto it = params.
begin(); it != params.
end(); it++)
450 const std::string param_name = it->first;
451 if (param_name ==
"block")
455 auto blocks = vi_params.
get<std::vector<SubdomainName>>(
"block");
456 const auto new_blocks = params.
get<std::vector<SubdomainName>>(
"block");
457 for (
const auto & subdomain_name : new_blocks)
459 blocks.push_back(subdomain_name);
460 vi_params.
set<std::vector<SubdomainName>>(
"block") =
blocks;
463 mooseError(
"The variable '",
name,
"' was added previously without block restriction.");
472 "' was added previously with a different value for the parameter '",
479 "' was added previously without the parameter '",
505 const std::string &
name,
517 mooseError(
"Initial condition with name '",
name,
"' already exists.");
523 const std::vector<SubdomainName> & block_names)
528 std::string blk_str = block_names[0];
529 for (
unsigned int i = 1; i < block_names.size(); i++)
530 blk_str +=
":" + block_names[i];
532 std::string class_name =
"ConstantIC";
534 params.
set<VariableName>(
"variable") = var_name;
535 params.
set<Real>(
"value") = value;
536 params.
set<std::vector<SubdomainName>>(
"block") = block_names;
542 const std::string & func_name,
543 const std::vector<SubdomainName> & block_names)
548 std::string blk_str = block_names[0];
549 for (
unsigned int i = 1; i < block_names.size(); i++)
550 blk_str +=
":" + block_names[i];
552 std::string class_name =
"FunctionIC";
554 params.
set<VariableName>(
"variable") = var_name;
555 params.
set<std::vector<SubdomainName>>(
"block") = block_names;
556 params.
set<FunctionName>(
"function") = func_name;
566 std::string class_name =
"ScalarConstantIC";
568 params.
set<VariableName>(
"variable") = var_name;
569 params.
set<Real>(
"value") = value;
579 std::string class_name =
"ScalarComponentIC";
581 params.
set<VariableName>(
"variable") = var_name;
582 params.
set<std::vector<Real>>(
"values") = value;
586std::vector<VariableName>
591 std::set<int> indices;
592 std::vector<std::pair<VariableName, int>> registered_var_index_pairs;
595 registered_var_index_pairs.push_back(var_and_index);
597 const auto ind = var_and_index.second;
598 auto insert_return = indices.insert(ind);
599 if (!insert_return.second)
600 mooseError(
"The index ", ind,
" was used for multiple component variables.");
604 std::vector<VariableName> vars_unsorted;
605 for (
const auto & var_and_data :
_vars)
606 vars_unsorted.push_back(var_and_data.first);
614 std::sort(registered_var_index_pairs.begin(),
615 registered_var_index_pairs.end(),
616 [](
const std::pair<VariableName, int> &
a,
const std::pair<VariableName, int> &
b)
617 { return a.second < b.second; });
622 std::vector<VariableName> vars_sorted;
623 for (
const auto & var_index_pair : registered_var_index_pairs)
625 const auto & var = var_index_pair.first;
626 if (std::find(vars_unsorted.begin(), vars_unsorted.end(), var) != vars_unsorted.end())
628 vars_sorted.push_back(var);
629 vars_unsorted.erase(std::remove(vars_unsorted.begin(), vars_unsorted.end(), var),
630 vars_unsorted.end());
636 std::sort(vars_unsorted.begin(), vars_unsorted.end());
637 vars_sorted.insert(vars_sorted.end(), vars_unsorted.begin(), vars_unsorted.end());
662 comp->addVariables();
670 std::stringstream ss;
671 ss <<
"The system ordering of variables added by Components is as follows:\n";
672 for (
const auto & var : var_names)
673 ss <<
" " << var <<
"\n";
678 for (
const auto &
name : var_names)
697 const UserObjectName suo_name =
genName(
"thm",
"suo");
699 const std::string class_name =
"SolutionUserObject";
701 params.
set<MeshFileName>(
"mesh") =
_thm_pars.
get<FileName>(
"initial_from_file");
702 params.
set<std::string>(
"timestep") =
_thm_pars.
get<std::string>(
"initial_from_file_timestep");
708 const VariableName & var_name =
v.first;
711 if (vi.
_var_type ==
"MooseVariableScalar")
713 std::string class_name =
"ScalarSolutionIC";
715 params.
set<VariableName>(
"variable") = var_name;
716 params.
set<VariableName>(
"from_variable") = var_name;
717 params.
set<UserObjectName>(
"solution_uo") = suo_name;
722 const std::string class_name =
"SolutionIC";
724 params.
set<VariableName>(
"variable") = var_name;
725 params.
set<VariableName>(
"from_variable") = var_name;
726 params.
set<UserObjectName>(
"solution_uo") = suo_name;
733 const auto & block_names = vi.
_params.
get<std::vector<SubdomainName>>(
"block");
735 for (
const auto & block_name : block_names)
738 block_params.
set<std::vector<SubdomainName>>(
"block") = {block_name};
739 block_params.
set<std::vector<SubdomainName>>(
"from_subdomains") = {block_name};
742 class_name,
genName(var_name, block_name,
"ic"), block_params);
754 for (
auto && i :
_ics)
756 const std::string &
name = i.first;
766 comp->addMooseObjects();
773 const std::string class_name =
"AugmentSparsityBetweenElements";
776 Moose::RelationshipManagerType::COUPLING | Moose::RelationshipManagerType::ALGEBRAIC |
777 Moose::RelationshipManagerType::GEOMETRIC;
780 params.
set<std::map<dof_id_type, std::vector<dof_id_type>> *>(
"_elem_map") =
789 comp->addRelationshipManagers(Moose::RelationshipManagerType::COUPLING |
790 Moose::RelationshipManagerType::ALGEBRAIC |
791 Moose::RelationshipManagerType::GEOMETRIC);
798 std::vector<SubdomainName>
blocks;
802 if (comp->parent() ==
nullptr)
804 const auto & subdomains = comp->getSubdomainNames();
805 const auto & coord_sys = comp->getCoordSysTypes();
807 for (
unsigned int i = 0; i < subdomains.size(); i++)
809 blocks.push_back(subdomains[i]);
838 const auto & time_integrators =
840 if (!time_integrators.empty())
841 ti = time_integrators.front().get();
845 (
dynamic_cast<const ExplicitRK2 *
>(ti) !=
nullptr) ||
851 mooseError(
"Coupling matrix does not exists. Something really bad happened.");
854 for (
unsigned int i = 0; i < cm->size(); i++)
855 for (
unsigned int j = 0; j < cm->size(); j++)
860 "Single matrix preconditioning with full coupling is required to run. Please, check that "
861 "your input file has the following preconditioning block:\n\n"
862 "[Preconditioning]\n"
880 std::vector<Component *> flow_channels;
884 if (flow_channel !=
nullptr)
885 flow_channels.push_back(flow_channel);
889 std::map<std::string, unsigned int> flow_channel_inlets;
890 std::map<std::string, unsigned int> flow_channel_outlets;
891 for (
auto && comp : flow_channels)
893 flow_channel_inlets[comp->name()] = 0;
894 flow_channel_outlets[comp->name()] = 0;
901 if (pc_comp !=
nullptr)
903 for (
const auto & connection : pc_comp->getConnections())
906 flow_channel_inlets[connection._component_name]++;
908 flow_channel_outlets[connection._component_name]++;
914 for (
auto && comp : flow_channels)
916 if (flow_channel_inlets[comp->name()] == 0)
917 logError(
"Component '", comp->name(),
"' does not have connected inlet.");
918 else if (flow_channel_inlets[comp->name()] > 1)
919 logError(
"Multiple inlets specified for component '", comp->name(),
"'.");
921 if (flow_channel_outlets[comp->name()] == 0)
922 logError(
"Component '", comp->name(),
"' does not have connected outlet.");
923 else if (flow_channel_outlets[comp->name()] > 1)
924 logError(
"Multiple outlets specified for component '", comp->name(),
"'.");
944 if (!i.second->getDeclared())
947 "' was requested, but was not declared by any active control object.");
955 for (
auto && i : ctrl_wh.getObjects())
962 for (
auto && i : ctrl_wh.getObjects())
970 for (
auto && cd_name : cd_deps)
977 auto it = std::find(deps.begin(), deps.end(), dep_name);
978 if (it == deps.end())
979 deps.push_back(dep_name);
988 for (
auto && i : ctrl_wh.getObjects())
992 std::list<const THMControl *> l;
998 for (
auto && cd_name : cd_deps)
1022 logError(
"Component with name '",
name,
"' already exists");
1040 logError(
"A closures object with the name '",
name,
"' already exists.");
1049std::shared_ptr<ClosuresBase>
1056 mooseError(
"The requested closures object '",
name,
"' does not exist.");
1073std::vector<OutputName>
1076 std::string key_lowercase = key;
1077 std::transform(key_lowercase.begin(), key_lowercase.end(), key_lowercase.begin(), ::tolower);
1079 std::vector<OutputName> outputs;
1080 if (key_lowercase ==
"none")
1081 outputs.push_back(
"none");
1082 else if (key_lowercase ==
"screen")
1084 else if (key_lowercase ==
"file")
1086 else if (key_lowercase ==
"both")
1089 mooseError(
"The outputs vector key '" + key_lowercase +
"' is invalid");
1104 i.second->copyValuesBack();
void mooseInfo(Args &&... args)
void mooseError(Args &&... args)
void mooseDeprecated(Args &&... args)
const ExecFlagType EXEC_TIMESTEP_END
const ExecFlagType EXEC_TIMESTEP_BEGIN
static MooseEnum getNonlinearVariableFamilies()
static MooseEnum getNonlinearVariableOrders()
Base class for closures implementations.
Base class for 1D component junctions and boundaries.
Base class for THM components.
void executeCheck() const
Wrapper function for check() that marks the function as being called.
Abstract definition of a ControlData value.
const THMControl * getControl() const
Get the pointer to the control object that declared this control data.
std::vector< std::string > & getDependencies()
const std::vector< T > & dfs()
void addEdge(const T &a, const T &b)
void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
virtual std::vector< std::shared_ptr< UserObject > > addUserObject(const std::string &user_object_name, const std::string &name, InputParameters ¶meters)
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters ¶ms)
void setCoordSystem(const std::vector< SubdomainName > &blocks, const MultiMooseEnum &coord_sys)
virtual void addInitialCondition(const std::string &ic_name, const std::string &name, InputParameters ¶meters)
ExecuteMooseObjectWarehouse< Control > & getControlWarehouse()
const libMesh::CouplingMatrix * couplingMatrix(const unsigned int nl_sys_num) const override
virtual void createQRules(libMesh::QuadratureType type, libMesh::Order order, libMesh::Order volume_order=libMesh::INVALID_ORDER, libMesh::Order face_order=libMesh::INVALID_ORDER, SubdomainID block=Moose::ANY_BLOCK_ID, bool allow_negative_qweights=true)
virtual void addAuxVariable(const std::string &var_type, const std::string &var_name, InputParameters ¶ms)
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
std::shared_ptr< MooseObject > create(const std::string &obj_name, const std::string &name, const InputParameters ¶meters, THREAD_ID tid=0, bool print_deprecated=true)
InputParameters getValidParams(const std::string &name) const
void releaseSharedObjects(const MooseObject &moose_object, THREAD_ID tid=0)
A base class for flow channels.
static const libMesh::FEType & feType()
Get the FE type used for heat conduction.
static libMesh::FEType _fe_type
Interface class for heat structure components.
void emitLoggedErrors() const
Calls mooseError if there are any logged errors.
void emitLoggedWarnings() const
Calls mooseWarning if there are any logged warnings.
Interface class for logging errors and warnings.
void logError(Args &&... args) const
Logs an error.
bool addRelationshipManager(std::shared_ptr< RelationshipManager > relationship_manager)
Executioner * getExecutioner() const
const std::string & name() const
const T & getParam(const std::string &name) const
bool compareCurrent(const MooseEnum &other, CompareMode mode=CompareMode::COMPARE_NAME) const
virtual void addObject(std::shared_ptr< T > object, THREAD_ID tid=0, bool recurse=true) override
void setAdditionalValue(const std::string &names)
std::string genName(const std::string &prefix, unsigned int id, const std::string &suffix="") const
Build a name from a prefix, number and possible suffix.
void printComponentLoops() const
Prints the component loops.
Simulation(FEProblemBase &fe_problem, const InputParameters ¶ms)
void addComponentScalarIC(const VariableName &var_name, const std::vector< Real > &value)
void addControl(const std::string &type, const std::string &name, InputParameters params)
Add a control.
std::map< std::string, std::shared_ptr< Component > > _comp_by_name
Map of components by their names.
bool hasInitialConditionsFromFile() const
Are initial conditions specified from a file.
std::map< VariableName, VariableInfo > _vars
variables for this simulation (name and info about the var)
std::map< std::string, ControlDataValue * > _control_data
Control data created in the control logic system.
void addConstantScalarIC(const VariableName &var_name, Real value)
MooseMesh & _thm_mesh
THM mesh.
FEProblemBase & _fe_problem
Pointer to FEProblem representing this simulation.
static std::map< VariableName, int > _component_variable_order_map
Component variable order map; see setComponentVariableOrder for more info.
std::vector< OutputName > _outputters_file
void addConstantIC(const VariableName &var_name, Real value, const std::vector< SubdomainName > &block_names)
virtual void integrityCheck() const
Check the integrity of the simulation.
virtual void advanceState()
Advance all of the state holding vectors / datastructures so that we can move to the next timestep.
virtual void addVariables()
Add variables involved in this simulation.
virtual void augmentSparsity(const dof_id_type &elem_id1, const dof_id_type &elem_id2)
Hint how to augment sparsity pattern between two elements.
const InputParameters & _thm_pars
"Global" of this simulation
void addFunctionIC(const VariableName &var_name, const std::string &func_name, const std::vector< SubdomainName > &block_names)
virtual void initComponents()
Initialize this simulation's components.
std::vector< OutputName > _outputters_all
std::map< std::string, std::string > _component_name_to_loop_name
Map of component name to component loop name.
virtual void couplingMatrixIntegrityCheck() const
Check integrity of coupling matrix used by the preconditioner.
virtual void addClosures(const std::string &type, const std::string &name, InputParameters params)
Add a closures object into this simulation.
void addRelationshipManagers()
Add additional relationship managers to run the simulation.
virtual void setupMesh()
Perform mesh setup actions such as setting up the coordinate system(s) and creating ghosted elements.
std::vector< OutputName > _outputters_screen
void checkVariableNameLength(const std::string &name) const
Reports an error if the variable name is too long.
const libMesh::FEType & getFlowFEType() const
Gets the FE type for the flow in this simulation.
bool hasComponent(const std::string &name) const
Find out if simulation has a component with the given name.
virtual void controlDataIntegrityCheck()
Check the integrity of the control data.
std::map< std::string, ICInfo > _ics
std::shared_ptr< ClosuresBase > getClosures(const std::string &name) const
Get a pointer to a closures object.
void identifyLoops()
Identifies the component loops.
virtual void initSimulation()
Initialize this simulation.
static void setComponentVariableOrder(const VariableName &var, int index)
Sets a component variable order index.
virtual void addComponent(const std::string &type, const std::string &name, InputParameters params)
Add a component into this simulation.
bool hasClosures(const std::string &name) const
Return whether the simulation has a closures object.
std::map< std::string, std::shared_ptr< ClosuresBase > > _closures_by_name
Map of closures by their names.
virtual void addMooseObjects()
Add component MOOSE objects.
bool _implicit_time_integration
true if using implicit time integration scheme
virtual void buildMesh()
Create mesh for this simulation.
MooseApp & _thm_app
The application this is associated with.
virtual void setupQuadrature()
Sets up quadrature rules.
Factory & _thm_factory
The Factory associated with the MooseApp.
std::vector< std::shared_ptr< Component > > _components
List of components in this simulation.
std::vector< VariableName > sortAddedComponentVariables() const
Returns a sorted list of the variables added by components.
void setupInitialConditionObjects()
void addFileOutputter(const std::string &name)
std::vector< OutputName > getOutputsVector(const std::string &key) const
Gets the vector of output names corresponding to a 1-word key string.
void setupCoordinateSystem()
Sets the coordinate system for each subdomain.
virtual void run()
Run the simulation.
void setupInitialConditionsFromFile()
Setup reading initial conditions from a specified file, see 'initial_from_file', 'initial_from_file_t...
std::map< std::string, THM::FlowModelID > _loop_name_to_model_id
Map of loop name to model type.
bool _check_jacobian
True if checking jacobian.
void addSimInitialCondition(const std::string &type, const std::string &name, InputParameters params)
std::map< dof_id_type, std::vector< dof_id_type > > _sparsity_elem_augmentation
Additional sparsity pattern that needs to be added into the Jacobian matrix.
void addScreenOutputter(const std::string &name)
void addSimVariable(bool nl, const VariableName &name, libMesh::FEType fe_type, Real scaling_factor=1.0, const SolverSystemName &solver_sys="nl0")
Queues a variable of type MooseVariableScalar to be added to the nonlinear or aux system.
const std::vector< std::shared_ptr< TimeIntegrator > > & getTimeIntegrators()
const std::vector< std::string > & getControlDataDependencies() const
Return the Controls that must run before this Control.
This control block will terminate a run if its input indicates so.
Moose::TimeIntegratorType getTimeScheme() const
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
static const size_t MAX_VARIABLE_LENGTH
bool _nl
True if the variable is a nonlinear (solution) variable; otherwise, aux.
InputParameters _params
Input parameters.
std::string _var_type
Type (class) of the variable.