https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Simulation.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 "Simulation.h"
11#include "FEProblemBase.h"
12#include "AddVariableAction.h"
13#include "MooseObjectAction.h"
14#include "Transient.h"
15#include "HeatConductionModel.h"
17#include "FlowChannelBase.h"
18#include "FlowJunction.h"
19
20#include "ClosuresBase.h"
21#include "FluidProperties.h"
22#include "THMControl.h"
23#include "TerminateControl.h"
24#include "RelationshipManager.h"
25#include "NonlinearSystemBase.h"
26#include "TimeIntegrator.h"
28#include "ExplicitEuler.h"
29#include "ExplicitRK2.h"
30#include "ExplicitTVDRK2.h"
31
32#include "libmesh/string_to_enum.h"
33
34std::map<VariableName, int> Simulation::_component_variable_order_map;
35
36void
37Simulation::setComponentVariableOrder(const VariableName & var, int index)
38{
40}
41
43 : ParallelObject(fe_problem.comm()),
44 LoggingInterface(_log),
45 _thm_mesh(*pars.get<MooseMesh *>("mesh")),
46 _fe_problem(fe_problem),
47 _thm_app(*pars.get<MooseApp *>(MooseBase::app_param)),
48 _thm_factory(_thm_app.getFactory()),
49 _thm_pars(pars),
50 _flow_fe_type(FEType(CONSTANT, MONOMIAL)),
51 _implicit_time_integration(true),
52 _check_jacobian(false),
53 _output_vector_velocity(true),
54 _zero(0)
55{
56 bool second_order_mesh = pars.get<bool>("2nd_order_mesh");
58 second_order_mesh ? FEType(SECOND, LAGRANGE) : FEType(FIRST, LAGRANGE);
59}
60
62{
63 for (auto && k : _control_data)
64 delete k.second;
65}
66
67void
68Simulation::augmentSparsity(const dof_id_type & elem_id1, const dof_id_type & elem_id2)
69{
70 auto it = _sparsity_elem_augmentation.find(elem_id1);
71 if (it == _sparsity_elem_augmentation.end())
73 {elem_id1, std::vector<dof_id_type>()});
74 it->second.push_back(elem_id2);
75
76 it = _sparsity_elem_augmentation.find(elem_id2);
77 if (it == _sparsity_elem_augmentation.end())
79 {elem_id2, std::vector<dof_id_type>()});
80 it->second.push_back(elem_id1);
81}
82
83void
85{
86 if (_components.size() == 0)
87 return;
88
89 // build mesh
90 for (auto && comp : _components)
91 comp->executeSetupMesh();
92}
93
94void
96{
97 if (_components.size() == 0)
98 return;
99
100 Order order = CONSTANT;
101 unsigned int n_flow_channels = 0;
102 unsigned int n_heat_structures = 0;
103
104 for (auto && comp : _components)
105 {
106 auto flow_channel = dynamic_cast<FlowChannelBase *>(comp.get());
107 if (flow_channel != nullptr)
108 n_flow_channels++;
109
110 auto hs_interface = dynamic_cast<HeatStructureInterface *>(comp.get());
111 if (hs_interface)
112 n_heat_structures++;
113 }
114
115 if (n_flow_channels > 0)
116 {
117 const FEType & fe_type = getFlowFEType();
118 if (fe_type.default_quadrature_order() > order)
119 order = fe_type.default_quadrature_order();
120 }
121 if (n_heat_structures > 0)
122 {
123 const FEType & fe_type = HeatConductionModel::feType();
124 if (fe_type.default_quadrature_order() > order)
125 order = fe_type.default_quadrature_order();
126 }
127
128 _fe_problem.createQRules(libMesh::QGAUSS, order, order, order);
129}
130
131void
133{
134 // sort the components using dependency resolver
136 for (const auto & comp : _components)
137 {
138 dependency_resolver.addNode(comp);
139 for (const auto & dep : comp->getDependencies())
140 if (hasComponent(dep))
141 dependency_resolver.addEdge(_comp_by_name[dep], comp);
142 }
143
144 _components = dependency_resolver.dfs();
145}
146
147void
149{
150 // initialize components
151 for (auto && comp : _components)
152 comp->executeInit();
153
154 // perform secondary initialization, which relies on init() being called
155 // already for all components
156 for (auto && comp : _components)
157 comp->executeInitSecondary();
158}
159
160void
162{
163 // loop over junctions and boundaries (non-geometrical components)
164 for (const auto & component : _components)
165 {
166 const auto flow_connection =
167 MooseSharedNamespace::dynamic_pointer_cast<Component1DConnection>(component);
168 if (flow_connection)
169 {
170 // create vector of names of this component and its connected flow channels, and then sort
171 // them
172 std::vector<std::string> names = flow_connection->getConnectedComponentNames();
173 names.push_back(component->name());
174 std::sort(names.begin(), names.end());
175
176 // pick first name alphabetically to be the proposed loop name
177 std::string proposed_loop_name = names[0];
178
179 for (const std::string & name : names)
180 {
181 // if the name is not yet in the map
183 // just add the new map key; nothing else needs updating
184 _component_name_to_loop_name[name] = proposed_loop_name;
185 else
186 {
187 // compare to the existing loop name for this component to make sure the
188 // proposed loop name is first alphabetically
189 const std::string current_loop_name = _component_name_to_loop_name[name];
190 // if proposed loop name comes later, change map values of the current
191 // loop name to be the proposed name, and then update the proposed name
192 // to be the current name
193 if (proposed_loop_name > current_loop_name)
194 {
195 for (auto && entry : _component_name_to_loop_name)
196 if (entry.second == proposed_loop_name)
197 entry.second = current_loop_name;
198 proposed_loop_name = current_loop_name;
199 }
200 // if proposed loop name comes earlier, change map values of the current
201 // loop name to be the proposed name
202 else if (proposed_loop_name < current_loop_name)
203 {
204 for (auto && entry : _component_name_to_loop_name)
205 if (entry.second == current_loop_name)
206 entry.second = proposed_loop_name;
207 }
208 }
209 }
210 }
211 }
212
213 // get the list of loops
214 std::vector<std::string> loops;
215 for (const auto & entry : _component_name_to_loop_name)
216 if (std::find(loops.begin(), loops.end(), entry.second) == loops.end())
217 loops.push_back(entry.second);
218
219 // fill the map of loop name to model ID
220 for (const auto & loop : loops)
221 {
222 // find a flow channel in this loop and get its model ID
223 THM::FlowModelID model_id;
224 bool found_model_id = false;
225 for (const auto & component : _components)
226 {
227 const auto flow_chan_base_component =
228 MooseSharedNamespace::dynamic_pointer_cast<FlowChannelBase>(component);
229 if (flow_chan_base_component && (_component_name_to_loop_name[component->name()] == loop))
230 {
231 model_id = flow_chan_base_component->getFlowModelID();
232 found_model_id = true;
233 break;
234 }
235 }
236 // set the value in the map or throw an error
237 if (found_model_id)
238 _loop_name_to_model_id[loop] = model_id;
239 else
240 logError("No FlowChannelBase-derived components were found in loop '", loop, "'");
241 }
242}
243
244void
246{
247 // get the list of loops
248 std::vector<std::string> loops;
249 for (auto && entry : _component_name_to_loop_name)
250 if (std::find(loops.begin(), loops.end(), entry.second) == loops.end())
251 loops.push_back(entry.second);
252
253 // for each loop
254 Moose::out << "\nListing of component loops:" << std::endl;
255 for (unsigned int i = 0; i < loops.size(); i++)
256 {
257 Moose::out << "\n Loop " << i + 1 << ":" << std::endl;
258
259 // print out each component in the loop
260 for (auto && entry : _component_name_to_loop_name)
261 if (entry.second == loops[i])
262 Moose::out << " " << entry.first << std::endl;
263 }
264 Moose::out << std::endl;
265}
266
267void
268Simulation::addSimVariable(bool nl, const VariableName & name, FEType fe_type, Real scaling_factor)
269{
271
272 if (fe_type.family != SCALAR)
273 mooseError("This method should only be used for scalar variables.");
274
275 if (_vars.find(name) == _vars.end()) // variable is new
276 {
277 VariableInfo vi;
278 InputParameters & params = vi._params;
279
280 vi._nl = nl;
281 vi._var_type = "MooseVariableScalar";
282 params = _thm_factory.getValidParams(vi._var_type);
283
285 family = Utility::enum_to_string(fe_type.family);
286 params.set<MooseEnum>("family") = family;
287
289 order = Utility::enum_to_string<Order>(fe_type.order);
290 params.set<MooseEnum>("order") = order;
291
292 if (nl)
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.");
296
297 _vars[name] = vi;
298 }
299 else
300 // One of the two cases is true:
301 // - This variable was previously added as a scalar variable, and scalar
302 // variables should not be added more than once, since there is no block
303 // restriction to extend, as there is in the field variable version of this
304 // method.
305 // - This variable was previously added as a field variable, and a variable
306 // may have only one type (this method is used for scalar variables only).
307 mooseError("The variable '", name, "' was already added.");
308}
309
310void
312 const VariableName & name,
313 FEType fe_type,
314 const std::vector<SubdomainName> & subdomain_names,
315 Real scaling_factor)
316{
318
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.");
324
325#ifdef DEBUG
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.");
329#endif
330
331 if (_vars.find(name) == _vars.end()) // variable is new
332 {
333 VariableInfo vi;
334 InputParameters & params = vi._params;
335
336 vi._nl = nl;
337 vi._var_type = "MooseVariable";
338 params = _thm_factory.getValidParams(vi._var_type);
339 params.set<std::vector<SubdomainName>>("block") = subdomain_names;
340
342 family = Utility::enum_to_string(fe_type.family);
343 params.set<MooseEnum>("family") = family;
344
346 order = Utility::enum_to_string<Order>(fe_type.order);
347 params.set<MooseEnum>("order") = order;
348
349 if (nl)
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.");
353
354 _vars[name] = vi;
355 }
356 else // variable was previously added
357 {
358 VariableInfo & vi = _vars[name];
359 InputParameters & params = vi._params;
360
361 if (vi._nl != nl)
362 mooseError("The variable '",
363 name,
364 "' has already been added in a different system (nonlinear or aux).");
365
366 if (vi._var_type != "MooseVariable")
367 mooseError("The variable '",
368 name,
369 "' has already been added with a different type than 'MooseVariable'.");
370
372 family = Utility::enum_to_string(fe_type.family);
373 if (!params.get<MooseEnum>("family").compareCurrent(family))
374 mooseError("The variable '", name, "' has already been added with a different FE family.");
375
377 order = Utility::enum_to_string<Order>(fe_type.order);
378 if (!params.get<MooseEnum>("order").compareCurrent(order))
379 mooseError("The variable '", name, "' has already been added with a different FE order.");
380
381 // If already block-restricted, extend the block restriction
382 if (params.isParamValid("block"))
383 {
384 auto blocks = params.get<std::vector<SubdomainName>>("block");
385 for (const auto & subdomain_name : subdomain_names)
386 if (std::find(blocks.begin(), blocks.end(), subdomain_name) == blocks.end())
387 blocks.push_back(subdomain_name);
388 params.set<std::vector<SubdomainName>>("block") = blocks;
389 }
390 else
391 params.set<std::vector<SubdomainName>>("block") = subdomain_names;
392
393 if (params.isParamValid("scaling"))
394 if (!MooseUtils::absoluteFuzzyEqual(params.get<std::vector<Real>>("scaling")[0],
395 scaling_factor))
397 "The variable '", name, "' has already been added with a different scaling factor.");
398 }
399}
400
401void
403 const std::string & var_type,
404 const VariableName & name,
405 const InputParameters & params)
406{
408
409 if (_vars.find(name) == _vars.end()) // variable is new
410 {
411 VariableInfo vi;
412 vi._nl = nl;
413 vi._var_type = var_type;
414 vi._params = params;
415
416 _vars[name] = vi;
417 }
418 else // variable was previously added
419 {
420 VariableInfo & vi = _vars[name];
421 InputParameters & vi_params = vi._params;
422
423 if (vi._nl != nl)
424 mooseError("The variable '",
425 name,
426 "' has already been added in a different system (nonlinear or aux).");
427
428 if (vi._var_type != var_type)
429 mooseError("The variable '",
430 name,
431 "' has already been added with a different type than '",
432 var_type,
433 "'.");
434
435 // Check that all valid parameters (other than 'block') are consistent
436 for (auto it = params.begin(); it != params.end(); it++)
437 {
438 const std::string param_name = it->first;
439 if (param_name == "block")
440 {
441 if (vi_params.isParamValid("block"))
442 {
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)
446 if (std::find(blocks.begin(), blocks.end(), subdomain_name) == blocks.end())
447 blocks.push_back(subdomain_name);
448 vi_params.set<std::vector<SubdomainName>>("block") = blocks;
449 }
450 else
451 mooseError("The variable '", name, "' was added previously without block restriction.");
452 }
453 else if (params.isParamValid(param_name))
454 {
455 if (vi_params.isParamValid(param_name))
456 {
457 if (params.rawParamVal(param_name) != vi_params.rawParamVal(param_name))
458 mooseError("The variable '",
459 name,
460 "' was added previously with a different value for the parameter '",
461 param_name,
462 "'.");
463 }
464 else
465 mooseError("The variable '",
466 name,
467 "' was added previously without the parameter '",
468 param_name,
469 "'.");
470 }
471 }
472 }
473}
474
475void
477{
478 if (name.size() > THM::MAX_VARIABLE_LENGTH)
480 "Variable name '", name, "' is too long. The limit is ", THM::MAX_VARIABLE_LENGTH, ".");
481}
482
483void
484Simulation::addControl(const std::string & type, const std::string & name, InputParameters params)
485{
486 params.addPrivateParam<FEProblemBase *>("_fe_problem_base", &_fe_problem);
487 std::shared_ptr<Control> control = _thm_factory.create<Control>(type, name, params);
489}
490
491void
492Simulation::addSimInitialCondition(const std::string & type,
493 const std::string & name,
494 InputParameters params)
495{
497 return;
498
499 if (_ics.find(name) == _ics.end())
500 {
501 ICInfo ic(type, params);
502 _ics[name] = ic;
503 }
504 else
505 mooseError("Initial condition with name '", name, "' already exists.");
506}
507
508void
509Simulation::addConstantIC(const VariableName & var_name,
510 Real value,
511 const std::vector<SubdomainName> & block_names)
512{
514 return;
515
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];
519
520 std::string class_name = "ConstantIC";
521 InputParameters params = _thm_factory.getValidParams(class_name);
522 params.set<VariableName>("variable") = var_name;
523 params.set<Real>("value") = value;
524 params.set<std::vector<SubdomainName>>("block") = block_names;
525 addSimInitialCondition(class_name, genName(var_name, blk_str, "ic"), params);
526}
527
528void
529Simulation::addFunctionIC(const VariableName & var_name,
530 const std::string & func_name,
531 const std::vector<SubdomainName> & block_names)
532{
534 return;
535
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];
539
540 std::string class_name = "FunctionIC";
541 InputParameters params = _thm_factory.getValidParams(class_name);
542 params.set<VariableName>("variable") = var_name;
543 params.set<std::vector<SubdomainName>>("block") = block_names;
544 params.set<FunctionName>("function") = func_name;
545 addSimInitialCondition(class_name, genName(var_name, blk_str, "ic"), params);
546}
547
548void
549Simulation::addConstantScalarIC(const VariableName & var_name, Real value)
550{
552 return;
553
554 std::string class_name = "ScalarConstantIC";
555 InputParameters params = _thm_factory.getValidParams(class_name);
556 params.set<VariableName>("variable") = var_name;
557 params.set<Real>("value") = value;
558 addSimInitialCondition(class_name, genName(var_name, "ic"), params);
559}
560
561void
562Simulation::addComponentScalarIC(const VariableName & var_name, const std::vector<Real> & value)
563{
565 return;
566
567 std::string class_name = "ScalarComponentIC";
568 InputParameters params = _thm_factory.getValidParams(class_name);
569 params.set<VariableName>("variable") = var_name;
570 params.set<std::vector<Real>>("values") = value;
571 addSimInitialCondition(class_name, genName(var_name, "ic"), params);
572}
573
574std::vector<VariableName>
576{
577 // Check that no index in order map is used more than once.
578 // Also, convert the map to a vector of pairs to be sorted.
579 std::set<int> indices;
580 std::vector<std::pair<VariableName, int>> registered_var_index_pairs;
581 for (const auto & var_and_index : _component_variable_order_map)
582 {
583 registered_var_index_pairs.push_back(var_and_index);
584
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.");
589 }
590
591 // Collect all of the added variable names into an unsorted vector.
592 std::vector<VariableName> vars_unsorted;
593 for (const auto & var_and_data : _vars)
594 vars_unsorted.push_back(var_and_data.first);
595
596 // The sorting works as follows. For those variables that are listed in
597 // _component_variable_order_map, these are ordered before those that are not,
598 // in the order of their indices in the map. Those not in the map are sorted
599 // alphabetically.
600
601 // Sort registered_var_index_pairs by value (index)
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; });
606
607 // Loop over the ordered, registered variable names and add a variable to the
608 // sorted list if in vars_unsorted. When this happens, delete the element from
609 // vars_unsorted, leaving only unregistered variable names after the loop.
610 std::vector<VariableName> vars_sorted;
611 for (const auto & var_index_pair : registered_var_index_pairs)
612 {
613 const auto & var = var_index_pair.first;
614 if (std::find(vars_unsorted.begin(), vars_unsorted.end(), var) != vars_unsorted.end())
615 {
616 vars_sorted.push_back(var);
617 vars_unsorted.erase(std::remove(vars_unsorted.begin(), vars_unsorted.end(), var),
618 vars_unsorted.end());
619 }
620 }
621
622 // Sort the remaining (unregistered) variables alphabetically and then add
623 // them to the end of the full list.
624 std::sort(vars_unsorted.begin(), vars_unsorted.end());
625 vars_sorted.insert(vars_sorted.end(), vars_unsorted.begin(), vars_unsorted.end());
626
627 return vars_sorted;
628}
629
630void
632{
633 TransientBase * trex = dynamic_cast<TransientBase *>(_thm_app.getExecutioner());
634 if (trex)
635 {
637 // This is only needed for the listed time integrators that are using the original approach to
638 // explicit integration in MOOSE. Currently, the new time integrators like
639 // ActuallyExplicitEuler do not need the implicit flag to be set.
640 if (ti_type == Moose::TI_EXPLICIT_TVD_RK_2 || ti_type == Moose::TI_EXPLICIT_MIDPOINT ||
641 ti_type == Moose::TI_EXPLICIT_EULER)
643 }
644
645 if (_components.size() == 0)
646 return;
647
648 // Cache the variables that components request to add
649 for (auto && comp : _components)
650 comp->addVariables();
651
652 // Sort the variables for a consistent ordering
653 const auto var_names = sortAddedComponentVariables();
654
655 // Report the ordering if the executioner is verbose
656 if (_fe_problem.getParam<MooseEnum>("verbose_setup") != "false")
657 {
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";
662 mooseInfo(ss.str());
663 }
664
665 // Add the variables to the problem
666 for (const auto & name : var_names)
667 {
668 VariableInfo & vi = _vars[name];
669
670 if (vi._nl)
672 else
674 }
675
678 else
680}
681
682void
684{
685 const UserObjectName suo_name = genName("thm", "suo");
686 {
687 const std::string class_name = "SolutionUserObject";
688 InputParameters params = _thm_factory.getValidParams(class_name);
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");
691 _fe_problem.addUserObject(class_name, suo_name, params);
692 }
693
694 for (auto && v : _vars)
695 {
696 const VariableName & var_name = v.first;
697 const VariableInfo & vi = v.second;
698
699 if (vi._var_type == "MooseVariableScalar")
700 {
701 std::string class_name = "ScalarSolutionIC";
702 InputParameters params = _thm_factory.getValidParams(class_name);
703 params.set<VariableName>("variable") = var_name;
704 params.set<VariableName>("from_variable") = var_name;
705 params.set<UserObjectName>("solution_uo") = suo_name;
706 _fe_problem.addInitialCondition(class_name, genName(var_name, "ic"), params);
707 }
708 else
709 {
710 std::string class_name = "SolutionIC";
711 InputParameters params = _thm_factory.getValidParams(class_name);
712 params.set<VariableName>("variable") = var_name;
713 params.set<VariableName>("from_variable") = var_name;
714 params.set<UserObjectName>("solution_uo") = suo_name;
715 if (vi._params.isParamValid("block"))
716 params.set<std::vector<SubdomainName>>("block") =
717 vi._params.get<std::vector<SubdomainName>>("block");
718 _fe_problem.addInitialCondition(class_name, genName(var_name, "ic"), params);
719 }
720 }
721}
722
723void
725{
726 for (auto && i : _ics)
727 {
728 const std::string & name = i.first;
729 ICInfo & ic = i.second;
731 }
732}
733
734void
736{
737 for (auto && comp : _components)
738 comp->addMooseObjects();
739}
740
741void
743{
744 {
745 const std::string class_name = "AugmentSparsityBetweenElements";
746 auto params = _thm_factory.getValidParams(class_name);
747 params.set<Moose::RelationshipManagerType>("rm_type") =
748 Moose::RelationshipManagerType::COUPLING | Moose::RelationshipManagerType::ALGEBRAIC |
749 Moose::RelationshipManagerType::GEOMETRIC;
750 params.set<std::string>("for_whom") = _fe_problem.name();
751 params.set<MooseMesh *>("mesh") = &_thm_mesh;
752 params.set<std::map<dof_id_type, std::vector<dof_id_type>> *>("_elem_map") =
754 auto rm =
755 _thm_factory.create<RelationshipManager>(class_name, "thm:sparsity_btw_elems", params);
758 }
759
760 for (auto && comp : _components)
761 comp->addRelationshipManagers(Moose::RelationshipManagerType::COUPLING |
762 Moose::RelationshipManagerType::ALGEBRAIC |
763 Moose::RelationshipManagerType::GEOMETRIC);
764}
765
766void
768{
769 MultiMooseEnum coord_types("XYZ RZ RSPHERICAL");
770 std::vector<SubdomainName> blocks;
771
772 for (auto && comp : _components)
773 {
774 if (comp->parent() == nullptr)
775 {
776 const auto & subdomains = comp->getSubdomainNames();
777 const auto & coord_sys = comp->getCoordSysTypes();
778
779 for (unsigned int i = 0; i < subdomains.size(); i++)
780 {
781 blocks.push_back(subdomains[i]);
782 // coord_types.push_back("XYZ");
783 coord_types.setAdditionalValue(coord_sys[i] == Moose::COORD_RZ ? "RZ" : "XYZ");
784 }
785 }
786 }
787 _fe_problem.setCoordSystem(blocks, coord_types);
788
789 // RZ geometries are always aligned with x-axis
790 MooseEnum rz_coord_axis("X=0 Y=1", "X");
792}
793
794void
796{
797 if (_components.size() == 0)
798 return;
799
801}
802
803void
805{
807 return;
808
809 const TimeIntegrator * ti = nullptr;
810 const auto & time_integrators =
812 if (!time_integrators.empty())
813 ti = time_integrators.front().get();
814 // Yes, this is horrible. Don't ask why...
815 if ((dynamic_cast<const ExplicitTimeIntegrator *>(ti) != nullptr) ||
816 (dynamic_cast<const ExplicitEuler *>(ti) != nullptr) ||
817 (dynamic_cast<const ExplicitRK2 *>(ti) != nullptr) ||
818 (dynamic_cast<const ExplicitTVDRK2 *>(ti) != nullptr))
819 return;
820
821 const CouplingMatrix * cm = _fe_problem.couplingMatrix(/*nl_sys_num=*/0);
822 if (cm == nullptr)
823 mooseError("Coupling matrix does not exists. Something really bad happened.");
824
825 bool full = true;
826 for (unsigned int i = 0; i < cm->size(); i++)
827 for (unsigned int j = 0; j < cm->size(); j++)
828 full &= (*cm)(i, j);
829
830 if (!full)
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"
835 " [pc]\n"
836 " type = SMP\n"
837 " full = true\n"
838 " []\n"
839 "[].\n");
840}
841
842void
844{
845 if (_components.size() == 0)
846 return;
847
848 if (_check_jacobian)
849 return;
850
851 // go over components and put flow channels into one "bucket"
852 std::vector<Component *> flow_channels;
853 for (auto && comp : _components)
854 {
855 auto flow_channel = dynamic_cast<FlowChannelBase *>(comp.get());
856 if (flow_channel != nullptr)
857 flow_channels.push_back(flow_channel);
858 }
859
860 // initialize number of connected flow channel inlets and outlets to zero
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)
864 {
865 flow_channel_inlets[comp->name()] = 0;
866 flow_channel_outlets[comp->name()] = 0;
867 }
868
869 // mark connections of any Component1DConnection components
870 for (const auto & comp : _components)
871 {
872 auto pc_comp = dynamic_cast<Component1DConnection *>(comp.get());
873 if (pc_comp != nullptr)
874 {
875 for (const auto & connection : pc_comp->getConnections())
876 {
877 if (connection._end_type == Component1DConnection::IN)
878 flow_channel_inlets[connection._component_name]++;
879 else if (connection._end_type == Component1DConnection::OUT)
880 flow_channel_outlets[connection._component_name]++;
881 }
882 }
883 }
884
885 // finally, check that each flow channel has exactly one input and one output
886 for (auto && comp : flow_channels)
887 {
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(), "'.");
892
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(), "'.");
897 }
898
899 // let components check themselves
900 for (auto && comp : _components)
901 comp->executeCheck();
902
905}
906
907void
909{
910 if (_check_jacobian)
911 return;
912
913 // check that control data are consistent
914 for (auto && i : _control_data)
915 {
916 if (!i.second->getDeclared())
917 logError("Control data '",
918 i.first,
919 "' was requested, but was not declared by any active control object.");
920 }
921
923
925
926 // initialize THM control objects
927 for (auto && i : ctrl_wh.getObjects())
928 {
929 THMControl * ctrl = dynamic_cast<THMControl *>(i.get());
930 if (ctrl != nullptr)
931 ctrl->init();
932 }
933
934 for (auto && i : ctrl_wh.getObjects())
935 {
936 THMControl * ctrl = dynamic_cast<THMControl *>(i.get());
937 // if it is a THM control
938 if (ctrl != nullptr)
939 {
940 // get its dependencies on control data
941 auto & cd_deps = ctrl->getControlDataDependencies();
942 for (auto && cd_name : cd_deps)
943 {
944 ControlDataValue * cdv = _control_data[cd_name];
945 // find out which control object built the control data
946 std::string dep_name = cdv->getControl()->name();
947 auto & deps = ctrl->getDependencies();
948 // and if it is not in its dependency list, add it
949 auto it = std::find(deps.begin(), deps.end(), dep_name);
950 if (it == deps.end())
951 deps.push_back(dep_name);
952 }
953 }
954 }
955
956 // Find all `TerminateControl`s and all their dependencies. Then add those
957 // objects into TIMESTEP_END control warehouse
958 MooseObjectWarehouse<Control> & ctrl_wh_tse =
960 for (auto && i : ctrl_wh.getObjects())
961 {
962 if (TerminateControl * ctrl = dynamic_cast<TerminateControl *>(i.get()))
963 {
964 std::list<const THMControl *> l;
965 l.push_back(ctrl);
966 while (l.size() > 0)
967 {
968 const THMControl * ctrl = l.front();
969 auto & cd_deps = ctrl->getControlDataDependencies();
970 for (auto && cd_name : cd_deps)
971 {
972 ControlDataValue * cdv = _control_data[cd_name];
973 l.push_back(cdv->getControl());
974 }
975 ctrl_wh_tse.addObject(ctrl_wh.getObject(ctrl->name()));
976 l.pop_front();
977 }
978 }
979 }
980}
981
982void
984{
985}
986
987void
988Simulation::addComponent(const std::string & type, const std::string & name, InputParameters params)
989{
990 std::shared_ptr<Component> comp = _thm_factory.create<Component>(type, name, params);
991 if (_comp_by_name.find(name) == _comp_by_name.end())
992 _comp_by_name[name] = comp;
993 else
994 logError("Component with name '", name, "' already exists");
995 _components.push_back(comp);
996}
997
998bool
999Simulation::hasComponent(const std::string & name) const
1000{
1001 auto it = _comp_by_name.find(name);
1002 return (it != _comp_by_name.end());
1003}
1004
1005void
1006Simulation::addClosures(const std::string & type, const std::string & name, InputParameters params)
1007{
1008 std::shared_ptr<ClosuresBase> obj_ptr = _thm_factory.create<ClosuresBase>(type, name, params);
1009 if (_closures_by_name.find(name) == _closures_by_name.end())
1010 _closures_by_name[name] = obj_ptr;
1011 else
1012 logError("A closures object with the name '", name, "' already exists.");
1013}
1014
1015bool
1016Simulation::hasClosures(const std::string & name) const
1017{
1018 return _closures_by_name.find(name) != _closures_by_name.end();
1019}
1020
1021std::shared_ptr<ClosuresBase>
1022Simulation::getClosures(const std::string & name) const
1023{
1024 auto it = _closures_by_name.find(name);
1025 if (it != _closures_by_name.end())
1026 return it->second;
1027 else
1028 mooseError("The requested closures object '", name, "' does not exist.");
1029}
1030
1031void
1033{
1034 _outputters_all.push_back(name);
1035 _outputters_file.push_back(name);
1036}
1037
1038void
1040{
1041 _outputters_all.push_back(name);
1042 _outputters_screen.push_back(name);
1043}
1044
1045std::vector<OutputName>
1046Simulation::getOutputsVector(const std::string & key) const
1047{
1048 std::string key_lowercase = key;
1049 std::transform(key_lowercase.begin(), key_lowercase.end(), key_lowercase.begin(), ::tolower);
1050
1051 std::vector<OutputName> outputs;
1052 if (key_lowercase == "none")
1053 outputs.push_back("none"); // provide non-existent name, so it does not get printed out
1054 else if (key_lowercase == "screen")
1055 outputs = _outputters_screen;
1056 else if (key_lowercase == "file")
1057 outputs = _outputters_file;
1058 else if (key_lowercase == "both")
1059 outputs = _outputters_all;
1060 else
1061 mooseError("The outputs vector key '" + key_lowercase + "' is invalid");
1062
1063 return outputs;
1064}
1065
1066bool
1068{
1069 return _thm_pars.isParamValid("initial_from_file");
1070}
1071
1072void
1074{
1075 for (auto && i : _control_data)
1076 i.second->copyValuesBack();
1077}
const double v
void mooseInfo(Args &&... args)
void mooseError(Args &&... args)
void mooseDeprecated(Args &&... args)
const ExecFlagType EXEC_TIMESTEP_END
const ExecFlagType EXEC_TIMESTEP_BEGIN
char ** blocks
const std::string name
Definition Setup.h:21
static MooseEnum getNonlinearVariableFamilies()
static MooseEnum getNonlinearVariableOrders()
Base class for closures implementations.
Base class for 1D component junctions and boundaries.
Base class for THM components.
Definition Component.h:32
void executeCheck() const
Wrapper function for check() that marks the function as being called.
Definition Component.C:84
Abstract definition of a ControlData value.
Definition ControlData.h:21
const THMControl * getControl() const
Get the pointer to the control object that declared this control data.
Definition ControlData.h:55
std::vector< std::string > & getDependencies()
void addNode(const T &a)
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 &parameters)
void setAxisymmetricCoordAxis(const MooseEnum &rz_coord_axis)
virtual void addVariable(const std::string &var_type, const std::string &var_name, InputParameters &params)
bool shouldSolve() const
void setCoordSystem(const std::vector< SubdomainName > &blocks, const MultiMooseEnum &coord_sys)
virtual void addInitialCondition(const std::string &ic_name, const std::string &name, InputParameters &parameters)
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 &params)
NonlinearSystemBase & getNonlinearSystemBase(const unsigned int sys_num)
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)
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 addPrivateParam(const std::string &name, const T &value)
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
std::string rawParamVal(const std::string &param) const
T & set(const std::string &name, bool quiet_mode=false)
std::map< std::string, Metadata > _params
bool isParamValid(const std::string &name) const
void emitLoggedErrors() const
Calls mooseError if there are any logged errors.
Definition Logger.C:21
void emitLoggedWarnings() const
Calls mooseWarning if there are any logged warnings.
Definition Logger.C:35
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.
Definition Simulation.C:245
Simulation(FEProblemBase &fe_problem, const InputParameters &params)
Definition Simulation.C:42
void addComponentScalarIC(const VariableName &var_name, const std::vector< Real > &value)
Definition Simulation.C:562
void addControl(const std::string &type, const std::string &name, InputParameters params)
Add a control.
Definition Simulation.C:484
std::map< std::string, std::shared_ptr< Component > > _comp_by_name
Map of components by their names.
Definition Simulation.h:397
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)
Definition Simulation.h:407
std::map< std::string, ControlDataValue * > _control_data
Control data created in the control logic system.
Definition Simulation.h:455
void addConstantScalarIC(const VariableName &var_name, Real value)
Definition Simulation.C:549
MooseMesh & _thm_mesh
THM mesh.
Definition Simulation.h:383
FEProblemBase & _fe_problem
Pointer to FEProblem representing this simulation.
Definition Simulation.h:386
static std::map< VariableName, int > _component_variable_order_map
Component variable order map; see setComponentVariableOrder for more info.
Definition Simulation.h:483
std::vector< OutputName > _outputters_file
Definition Simulation.h:451
void addConstantIC(const VariableName &var_name, Real value, const std::vector< SubdomainName > &block_names)
Definition Simulation.C:509
virtual void integrityCheck() const
Check the integrity of the simulation.
Definition Simulation.C:843
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.
Definition Simulation.C:631
virtual void augmentSparsity(const dof_id_type &elem_id1, const dof_id_type &elem_id2)
Hint how to augment sparsity pattern between two elements.
Definition Simulation.C:68
const InputParameters & _thm_pars
"Global" of this simulation
Definition Simulation.h:422
void addFunctionIC(const VariableName &var_name, const std::string &func_name, const std::vector< SubdomainName > &block_names)
Definition Simulation.C:529
virtual void initComponents()
Initialize this simulation's components.
Definition Simulation.C:148
std::vector< OutputName > _outputters_all
Definition Simulation.h:450
std::map< std::string, std::string > _component_name_to_loop_name
Map of component name to component loop name.
Definition Simulation.h:399
virtual void couplingMatrixIntegrityCheck() const
Check integrity of coupling matrix used by the preconditioner.
Definition Simulation.C:804
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.
Definition Simulation.C:742
virtual void setupMesh()
Perform mesh setup actions such as setting up the coordinate system(s) and creating ghosted elements.
Definition Simulation.C:795
std::vector< OutputName > _outputters_screen
Definition Simulation.h:452
void checkVariableNameLength(const std::string &name) const
Reports an error if the variable name is too long.
Definition Simulation.C:476
const libMesh::FEType & getFlowFEType() const
Gets the FE type for the flow in this simulation.
Definition Simulation.h:48
bool hasComponent(const std::string &name) const
Find out if simulation has a component with the given name.
Definition Simulation.C:999
virtual ~Simulation()
Definition Simulation.C:61
virtual void controlDataIntegrityCheck()
Check the integrity of the control data.
Definition Simulation.C:908
std::map< std::string, ICInfo > _ics
Definition Simulation.h:419
std::shared_ptr< ClosuresBase > getClosures(const std::string &name) const
Get a pointer to a closures object.
void identifyLoops()
Identifies the component loops.
Definition Simulation.C:161
virtual void initSimulation()
Initialize this simulation.
Definition Simulation.C:132
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.
Definition Simulation.C:37
virtual void addComponent(const std::string &type, const std::string &name, InputParameters params)
Add a component into this simulation.
Definition Simulation.C:988
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.
Definition Simulation.h:404
virtual void addMooseObjects()
Add component MOOSE objects.
Definition Simulation.C:735
bool _implicit_time_integration
true if using implicit time integration scheme
Definition Simulation.h:458
virtual void buildMesh()
Create mesh for this simulation.
Definition Simulation.C:84
MooseApp & _thm_app
The application this is associated with.
Definition Simulation.h:389
virtual void setupQuadrature()
Sets up quadrature rules.
Definition Simulation.C:95
Factory & _thm_factory
The Factory associated with the MooseApp.
Definition Simulation.h:392
std::vector< std::shared_ptr< Component > > _components
List of components in this simulation.
Definition Simulation.h:395
std::vector< VariableName > sortAddedComponentVariables() const
Returns a sorted list of the variables added by components.
Definition Simulation.C:575
void setupInitialConditionObjects()
Definition Simulation.C:724
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.
Definition Simulation.C:767
virtual void run()
Run the simulation.
Definition Simulation.C:983
Logger _log
Definition Simulation.h:460
void setupInitialConditionsFromFile()
Setup reading initial conditions from a specified file, see 'initial_from_file' and 'initial_from_fil...
Definition Simulation.C:683
std::map< std::string, THM::FlowModelID > _loop_name_to_model_id
Map of loop name to model type.
Definition Simulation.h:401
bool _check_jacobian
True if checking jacobian.
Definition Simulation.h:463
void addSimInitialCondition(const std::string &type, const std::string &name, InputParameters params)
Definition Simulation.C:492
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.
Definition Simulation.h:466
void addScreenOutputter(const std::string &name)
const std::vector< std::shared_ptr< TimeIntegrator > > & getTimeIntegrators()
virtual void init()
Definition THMControl.h:21
const std::vector< std::string > & getControlDataDependencies() const
Return the Controls that must run before this Control.
Definition THMControl.h:26
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)
TimeIntegratorType
TI_EXPLICIT_EULER
TI_EXPLICIT_TVD_RK_2
TI_EXPLICIT_MIDPOINT
RelationshipManagerType
static const size_t MAX_VARIABLE_LENGTH
unsigned int FlowModelID
if(subdm)
InputParameters _params
Definition Simulation.h:412
std::string _type
Definition Simulation.h:411
Variable information.
Definition Simulation.h:371
bool _nl
True if the variable is a nonlinear (solution) variable; otherwise, aux.
Definition Simulation.h:373
InputParameters _params
Input parameters.
Definition Simulation.h:377
std::string _var_type
Type (class) of the variable.
Definition Simulation.h:375