https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PhysicsVariableCoordinator.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
11#include "ActionWarehouse.h"
12#include "ActionFactory.h"
13#include "FEProblemBase.h"
14#include "MooseMesh.h"
15
16registerMooseAction("MooseApp", PhysicsVariableCoordinator, "flush_shared_physics_variables");
17
18namespace
19{
22std::map<std::string, std::string>
23comparableValues(const InputParameters & params)
24{
25 std::map<std::string, std::string> values;
26 for (const auto & [name, value] : params)
27 if (name != "block" && !params.isPrivate(name) && params.isParamValid(name))
28 {
29 std::stringstream ss;
30 value->print(ss);
31 values.emplace(name, ss.str());
32 }
33 return values;
34}
35
37std::vector<std::string>
38differingParameters(const InputParameters & a, const InputParameters & b)
39{
40 const auto a_values = comparableValues(a);
41 const auto b_values = comparableValues(b);
42 std::set<std::string> names;
43 for (const auto & [name, _] : a_values)
44 names.insert(name);
45 for (const auto & [name, _] : b_values)
46 names.insert(name);
47
48 std::vector<std::string> differing;
49 for (const auto & name : names)
50 {
51 const auto a_it = a_values.find(name);
52 const auto b_it = b_values.find(name);
53 if (a_it == a_values.end() || b_it == b_values.end() || a_it->second != b_it->second)
54 differing.push_back(name);
55 }
56 return differing;
57}
58}
59
62{
65 "Merges the requests of multiple Physics for the same shared variable into a single "
66 "variable spanning the union of their blocks. Created on demand; not meant to be declared "
67 "in an input file.");
68 return params;
69}
70
75
76void
78 const std::string & var_type,
79 const VariableName & var_name,
80 const InputParameters & params,
81 const std::vector<SubdomainName> & blocks,
82 const std::string & requester)
83{
84 const auto it = _requests.find(var_name);
85 if (it == _requests.end())
86 {
87 _requests.emplace(var_name, MergedRequest{nl, var_type, params, {{requester, blocks}}});
88 return;
89 }
90
91 auto & merged = it->second;
92 const auto & first_requester = merged._requester_blocks.front().first;
93 if (merged._nl != nl)
94 mooseError("Physics '",
95 requester,
96 "' requests the shared variable '",
97 var_name,
98 "' as ",
99 nl ? "a solver" : "an auxiliary",
100 " variable, but Physics '",
101 first_requester,
102 "' requested it as ",
103 merged._nl ? "a solver" : "an auxiliary",
104 " variable.");
105 if (merged._type != var_type)
106 mooseError("Physics '",
107 requester,
108 "' requests the shared variable '",
109 var_name,
110 "' with type '",
111 var_type,
112 "', but Physics '",
113 first_requester,
114 "' requested it with type '",
115 merged._type,
116 "'.");
117 const auto differing = differingParameters(params, merged._params);
118 if (!differing.empty())
119 mooseError("Physics '",
120 requester,
121 "' requests the shared variable '",
122 var_name,
123 "' with different values for parameter(s) ",
124 Moose::stringify(differing),
125 " than Physics '",
126 first_requester,
127 "' did.");
128
129 merged._requester_blocks.emplace_back(requester, blocks);
130}
131
132void
134{
135 for (const auto & [var_name, req] : _requests)
136 {
137 // ANY_BLOCK_ID cannot be passed to addVariable(); leaving 'block' unset has the same meaning
138 std::vector<SubdomainName> blocks;
139 bool any_block = false;
140 for (const auto & [_, requested_blocks] : req._requester_blocks)
141 for (const auto & block : requested_blocks)
142 if (block == "ANY_BLOCK_ID")
143 any_block = true;
144 else if (std::find(blocks.begin(), blocks.end(), block) == blocks.end())
145 blocks.push_back(block);
146
147 InputParameters params = req._params;
148 if (!any_block)
149 params.set<std::vector<SubdomainName>>("block") = blocks;
150 // As done by AddVariableAction for variables declared in the input
151 if (params.get<bool>("fv"))
152 _problem->needFV();
153 if (req._nl)
154 _problem->addVariable(req._type, var_name, params);
155 else
156 _problem->addAuxVariable(req._type, var_name, params);
157
158 // After adding the variable so that invalid block names are reported by the variable
159 checkFVAdjacency(var_name, req);
160 }
161}
162
163void
165 const MergedRequest & req) const
166{
167 if (!req._params.get<bool>("fv") || req._requester_blocks.size() < 2)
168 return;
169
170 // Indices of the requesters covering each subdomain, with ANY_BLOCK_ID covering every subdomain
171 std::map<SubdomainID, std::set<std::size_t>> sub_to_requesters;
172 for (const auto i : index_range(req._requester_blocks))
173 {
174 const auto & blocks = req._requester_blocks[i].second;
175 const std::set<SubdomainID> ids =
176 std::find(blocks.begin(), blocks.end(), "ANY_BLOCK_ID") != blocks.end()
177 ? _mesh->meshSubdomains()
178 : _mesh->getSubdomainIDs(std::set<SubdomainName>(blocks.begin(), blocks.end()));
179 for (const auto id : ids)
180 sub_to_requesters[id].insert(i);
181 }
182
183 const auto sub_name = [this](const SubdomainID id)
184 {
185 const auto & name = _mesh->getSubdomainName(id);
186 return name.empty() ? std::to_string(id) : name;
187 };
188
189 // Every face between two of the variable's subdomains must be interior to some requester;
190 // otherwise each requester's flux kernels treat that face as a boundary of their own blocks
191 for (const auto & [sub_a, requesters_a] : sub_to_requesters)
192 for (const auto sub_b : _mesh->getBlockConnectedBlocks(sub_a))
193 {
194 const auto it_b = sub_to_requesters.find(sub_b);
195 // Each pair of subdomains is only examined once
196 if (sub_b < sub_a || it_b == sub_to_requesters.end())
197 continue;
198 const auto & requesters_b = it_b->second;
199
200 const bool some_requester_covers_both =
201 std::any_of(requesters_a.begin(),
202 requesters_a.end(),
203 [&requesters_b](const auto i) { return requesters_b.count(i); });
204 if (!some_requester_covers_both)
205 mooseError("Physics '",
206 req._requester_blocks[*requesters_a.begin()].first,
207 "' and '",
208 req._requester_blocks[*requesters_b.begin()].first,
209 "' share the finite volume variable '",
210 var_name,
211 "' on the adjacent subdomains '",
212 sub_name(sub_a),
213 "' and '",
214 sub_name(sub_b),
215 "', but neither is defined on both. Their flux kernels would treat the faces "
216 "between these subdomains as boundaries, so no flux would cross them. Define a "
217 "single Physics on both subdomains instead.");
218 }
219}
220
223{
224 const auto existing = awh.getActions<PhysicsVariableCoordinator>();
225 if (!existing.empty())
226 return *const_cast<PhysicsVariableCoordinator *>(existing[0]);
227
228 const std::string class_name = "PhysicsVariableCoordinator";
229 InputParameters params = action_factory.getValidParams(class_name);
230 params.set<bool>("_built_by_moose") = true;
231 params.set<std::string>("registered_identifier") = "(AutoBuilt)";
232
233 auto action = action_factory.create(class_name, "physics_variable_coordinator", params);
234 auto * coordinator = dynamic_cast<PhysicsVariableCoordinator *>(action.get());
235 if (!coordinator)
236 ::mooseError("Internal error: failed to create the PhysicsVariableCoordinator");
237 awh.addActionBlock(action);
238 return *coordinator;
239}
subdomain_id_type SubdomainID
std::array< Real, 2 > values
Definition MortarUtils.C:52
if(!dmm->_nl) SETERRQ(PETSC_COMM_WORLD
char ** blocks
registerMooseAction("MooseApp", PhysicsVariableCoordinator, "flush_shared_physics_variables")
Specialized factory for generic Action System objects.
std::shared_ptr< Action > create(const std::string &action, const std::string &action_name, InputParameters &parameters)
InputParameters getValidParams(const std::string &name)
Storage for action instances.
std::vector< const T * > getActions()
Retrieve all actions in a specific type ordered by their names.
void addActionBlock(std::shared_ptr< Action > blk)
This method add an Action instance to the warehouse.
Base class for actions.
Definition Action.h:38
std::shared_ptr< MooseMesh > & _mesh
Definition Action.h:174
static InputParameters validParams()
Definition Action.C:26
std::shared_ptr< FEProblemBase > & _problem
Convenience reference to a problem this action works on.
Definition Action.h:178
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
T & set(const std::string &name, bool quiet_mode=false)
Returns a writable reference to the named parameters.
std::map< std::string, Metadata > _params
The actual parameter data.
const std::string & name() const
Get the name of the class.
Definition MooseBase.h:103
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition MooseBase.h:271
Lets multiple Physics instances (for example one per component) share a single variable across all of...
static PhysicsVariableCoordinator & findOrCreate(ActionWarehouse &awh, ActionFactory &action_factory)
Finds this simulation's coordinator, creating it and adding it to awh (using action_factory) if it do...
void checkFVAdjacency(const VariableName &var_name, const MergedRequest &req) const
Errors if req is a finite volume variable on two adjacent subdomains that no single requester is defi...
virtual void act() override
Method to add objects to the simulation or perform other setup tasks.
PhysicsVariableCoordinator(const InputParameters &params)
std::map< VariableName, MergedRequest > _requests
Pending variable requests, keyed by variable name.
void requestVariable(bool nl, const std::string &var_type, const VariableName &var_name, const InputParameters &params, const std::vector< SubdomainName > &blocks, const std::string &requester)
Requests that a shared variable be created on blocks, in addition to any blocks already requested for...
static InputParameters validParams()
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:65
std::string name(const ElemQuality q)
The merged requests for one shared variable.
std::vector< std::pair< std::string, std::vector< SubdomainName > > > _requester_blocks
Name of each requesting Physics, in request order, with the blocks it requested.
InputParameters _params
Parameters of the variable, from the first request.