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)),
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;
272 if (fe_type.family != SCALAR)
273 mooseError(
"This method should only be used for scalar variables.");
281 vi._var_type =
"MooseVariableScalar";
285 family = Utility::enum_to_string(fe_type.family);
289 order = Utility::enum_to_string<Order>(fe_type.order);
293 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
294 else if (!MooseUtils::absoluteFuzzyEqual(scaling_factor, 1.0))
295 mooseError(
"Aux variables cannot be provided a residual scaling factor.");
312 const VariableName &
name,
314 const std::vector<SubdomainName> & subdomain_names,
319 if (fe_type.family == SCALAR)
321 "The version of Simulation::addSimVariable() with subdomain names can no longer be used "
322 "with scalar variables since scalar variables cannot be block-restricted. Use the version "
323 "of Simulation::addSimVariable() without subdomain names instead.");
326 for (
const auto & subdomain_name : subdomain_names)
327 mooseAssert(subdomain_name !=
"ANY_BLOCK_ID",
328 "'ANY_BLOCK_ID' cannot be used for adding field variables in components.");
337 vi._var_type =
"MooseVariable";
339 params.
set<std::vector<SubdomainName>>(
"block") = subdomain_names;
342 family = Utility::enum_to_string(fe_type.family);
346 order = Utility::enum_to_string<Order>(fe_type.order);
350 params.
set<std::vector<Real>>(
"scaling") = {scaling_factor};
351 else if (!MooseUtils::absoluteFuzzyEqual(scaling_factor, 1.0))
352 mooseError(
"Aux variables cannot be provided a residual scaling factor.");
364 "' has already been added in a different system (nonlinear or aux).");
366 if (vi._var_type !=
"MooseVariable")
369 "' has already been added with a different type than 'MooseVariable'.");
372 family = Utility::enum_to_string(fe_type.family);
374 mooseError(
"The variable '",
name,
"' has already been added with a different FE family.");
377 order = Utility::enum_to_string<Order>(fe_type.order);
379 mooseError(
"The variable '",
name,
"' has already been added with a different FE order.");
384 auto blocks = params.
get<std::vector<SubdomainName>>(
"block");
385 for (
const auto & subdomain_name : subdomain_names)
387 blocks.push_back(subdomain_name);
388 params.
set<std::vector<SubdomainName>>(
"block") = blocks;
391 params.
set<std::vector<SubdomainName>>(
"block") = subdomain_names;
394 if (!MooseUtils::absoluteFuzzyEqual(params.
get<std::vector<Real>>(
"scaling")[0],
397 "The variable '",
name,
"' has already been added with a different scaling factor.");
403 const std::string & var_type,
404 const VariableName &
name,
426 "' has already been added in a different system (nonlinear or aux).");
431 "' has already been added with a different type than '",
436 for (
auto it = params.
begin(); it != params.
end(); it++)
438 const std::string param_name = it->first;
439 if (param_name ==
"block")
443 auto blocks = vi_params.
get<std::vector<SubdomainName>>(
"block");
444 const auto new_blocks = params.
get<std::vector<SubdomainName>>(
"block");
445 for (
const auto & subdomain_name : new_blocks)
447 blocks.push_back(subdomain_name);
448 vi_params.
set<std::vector<SubdomainName>>(
"block") =
blocks;
451 mooseError(
"The variable '",
name,
"' was added previously without block restriction.");
460 "' was added previously with a different value for the parameter '",
467 "' was added previously without the parameter '",
493 const std::string &
name,
505 mooseError(
"Initial condition with name '",
name,
"' already exists.");
511 const std::vector<SubdomainName> & block_names)
516 std::string blk_str = block_names[0];
517 for (
unsigned int i = 1; i < block_names.size(); i++)
518 blk_str +=
":" + block_names[i];
520 std::string class_name =
"ConstantIC";
522 params.
set<VariableName>(
"variable") = var_name;
523 params.
set<Real>(
"value") = value;
524 params.
set<std::vector<SubdomainName>>(
"block") = block_names;
530 const std::string & func_name,
531 const std::vector<SubdomainName> & block_names)
536 std::string blk_str = block_names[0];
537 for (
unsigned int i = 1; i < block_names.size(); i++)
538 blk_str +=
":" + block_names[i];
540 std::string class_name =
"FunctionIC";
542 params.
set<VariableName>(
"variable") = var_name;
543 params.
set<std::vector<SubdomainName>>(
"block") = block_names;
544 params.
set<FunctionName>(
"function") = func_name;
554 std::string class_name =
"ScalarConstantIC";
556 params.
set<VariableName>(
"variable") = var_name;
557 params.
set<Real>(
"value") = value;
567 std::string class_name =
"ScalarComponentIC";
569 params.
set<VariableName>(
"variable") = var_name;
570 params.
set<std::vector<Real>>(
"values") = value;
574std::vector<VariableName>
579 std::set<int> indices;
580 std::vector<std::pair<VariableName, int>> registered_var_index_pairs;
583 registered_var_index_pairs.push_back(var_and_index);
585 const auto ind = var_and_index.second;
586 auto insert_return = indices.insert(ind);
587 if (!insert_return.second)
588 mooseError(
"The index ", ind,
" was used for multiple component variables.");
592 std::vector<VariableName> vars_unsorted;
593 for (
const auto & var_and_data :
_vars)
594 vars_unsorted.push_back(var_and_data.first);
602 std::sort(registered_var_index_pairs.begin(),
603 registered_var_index_pairs.end(),
604 [](
const std::pair<VariableName, int> &
a,
const std::pair<VariableName, int> &
b)
605 { return a.second < b.second; });
610 std::vector<VariableName> vars_sorted;
611 for (
const auto & var_index_pair : registered_var_index_pairs)
613 const auto & var = var_index_pair.first;
614 if (std::find(vars_unsorted.begin(), vars_unsorted.end(), var) != vars_unsorted.end())
616 vars_sorted.push_back(var);
617 vars_unsorted.erase(std::remove(vars_unsorted.begin(), vars_unsorted.end(), var),
618 vars_unsorted.end());
624 std::sort(vars_unsorted.begin(), vars_unsorted.end());
625 vars_sorted.insert(vars_sorted.end(), vars_unsorted.begin(), vars_unsorted.end());
650 comp->addVariables();
658 std::stringstream ss;
659 ss <<
"The system ordering of variables added by Components is as follows:\n";
660 for (
const auto & var : var_names)
661 ss <<
" " << var <<
"\n";
666 for (
const auto &
name : var_names)
685 const UserObjectName suo_name =
genName(
"thm",
"suo");
687 const std::string class_name =
"SolutionUserObject";
689 params.
set<MeshFileName>(
"mesh") =
_thm_pars.
get<FileName>(
"initial_from_file");
690 params.
set<std::string>(
"timestep") =
_thm_pars.
get<std::string>(
"initial_from_file_timestep");
696 const VariableName & var_name =
v.first;
699 if (vi.
_var_type ==
"MooseVariableScalar")
701 std::string class_name =
"ScalarSolutionIC";
703 params.
set<VariableName>(
"variable") = var_name;
704 params.
set<VariableName>(
"from_variable") = var_name;
705 params.
set<UserObjectName>(
"solution_uo") = suo_name;
710 std::string class_name =
"SolutionIC";
712 params.
set<VariableName>(
"variable") = var_name;
713 params.
set<VariableName>(
"from_variable") = var_name;
714 params.
set<UserObjectName>(
"solution_uo") = suo_name;
716 params.
set<std::vector<SubdomainName>>(
"block") =
717 vi.
_params.
get<std::vector<SubdomainName>>(
"block");
726 for (
auto && i :
_ics)
728 const std::string &
name = i.first;
738 comp->addMooseObjects();
745 const std::string class_name =
"AugmentSparsityBetweenElements";
748 Moose::RelationshipManagerType::COUPLING | Moose::RelationshipManagerType::ALGEBRAIC |
749 Moose::RelationshipManagerType::GEOMETRIC;
752 params.
set<std::map<dof_id_type, std::vector<dof_id_type>> *>(
"_elem_map") =
761 comp->addRelationshipManagers(Moose::RelationshipManagerType::COUPLING |
762 Moose::RelationshipManagerType::ALGEBRAIC |
763 Moose::RelationshipManagerType::GEOMETRIC);
770 std::vector<SubdomainName>
blocks;
774 if (comp->parent() ==
nullptr)
776 const auto & subdomains = comp->getSubdomainNames();
777 const auto & coord_sys = comp->getCoordSysTypes();
779 for (
unsigned int i = 0; i < subdomains.size(); i++)
781 blocks.push_back(subdomains[i]);
810 const auto & time_integrators =
812 if (!time_integrators.empty())
813 ti = time_integrators.front().get();
817 (
dynamic_cast<const ExplicitRK2 *
>(ti) !=
nullptr) ||
823 mooseError(
"Coupling matrix does not exists. Something really bad happened.");
826 for (
unsigned int i = 0; i < cm->size(); i++)
827 for (
unsigned int j = 0; j < cm->size(); j++)
832 "Single matrix preconditioning with full coupling is required to run. Please, check that "
833 "your input file has the following preconditioning block:\n\n"
834 "[Preconditioning]\n"
852 std::vector<Component *> flow_channels;
856 if (flow_channel !=
nullptr)
857 flow_channels.push_back(flow_channel);
861 std::map<std::string, unsigned int> flow_channel_inlets;
862 std::map<std::string, unsigned int> flow_channel_outlets;
863 for (
auto && comp : flow_channels)
865 flow_channel_inlets[comp->name()] = 0;
866 flow_channel_outlets[comp->name()] = 0;
873 if (pc_comp !=
nullptr)
875 for (
const auto & connection : pc_comp->getConnections())
878 flow_channel_inlets[connection._component_name]++;
880 flow_channel_outlets[connection._component_name]++;
886 for (
auto && comp : flow_channels)
888 if (flow_channel_inlets[comp->name()] == 0)
889 logError(
"Component '", comp->name(),
"' does not have connected inlet.");
890 else if (flow_channel_inlets[comp->name()] > 1)
891 logError(
"Multiple inlets specified for component '", comp->name(),
"'.");
893 if (flow_channel_outlets[comp->name()] == 0)
894 logError(
"Component '", comp->name(),
"' does not have connected outlet.");
895 else if (flow_channel_outlets[comp->name()] > 1)
896 logError(
"Multiple outlets specified for component '", comp->name(),
"'.");
916 if (!i.second->getDeclared())
919 "' was requested, but was not declared by any active control object.");
927 for (
auto && i : ctrl_wh.getObjects())
934 for (
auto && i : ctrl_wh.getObjects())
942 for (
auto && cd_name : cd_deps)
949 auto it = std::find(deps.begin(), deps.end(), dep_name);
950 if (it == deps.end())
951 deps.push_back(dep_name);
960 for (
auto && i : ctrl_wh.getObjects())
964 std::list<const THMControl *> l;
970 for (
auto && cd_name : cd_deps)
994 logError(
"Component with name '",
name,
"' already exists");
1012 logError(
"A closures object with the name '",
name,
"' already exists.");
1021std::shared_ptr<ClosuresBase>
1028 mooseError(
"The requested closures object '",
name,
"' does not exist.");
1045std::vector<OutputName>
1048 std::string key_lowercase = key;
1049 std::transform(key_lowercase.begin(), key_lowercase.end(), key_lowercase.begin(), ::tolower);
1051 std::vector<OutputName> outputs;
1052 if (key_lowercase ==
"none")
1053 outputs.push_back(
"none");
1054 else if (key_lowercase ==
"screen")
1056 else if (key_lowercase ==
"file")
1058 else if (key_lowercase ==
"both")
1061 mooseError(
"The outputs vector key '" + key_lowercase +
"' is invalid");
1076 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.
void addSimVariable(bool nl, const VariableName &name, libMesh::FEType fe_type, Real scaling_factor=1.0)
Queues a variable of type MooseVariableScalar to be added to the nonlinear or aux system.
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' and 'initial_from_fil...
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)
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.