Skip to content

Commit

Permalink
Implement UO support (idaholab#22563)
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen committed Jan 31, 2023
1 parent 98f1d53 commit eaecdd9
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 21 deletions.
12 changes: 11 additions & 1 deletion framework/include/interfaces/Coupleable.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,16 @@ class Coupleable
return _fe_coupleable_matrix_tags;
}

/**
* Checks whether the object has any writable coupled variables
*/
bool hasWritableCoupledVariables() { return !_writable_coupled_variables[_c_tid].empty(); }

/**
* returns a reference to the set of writable coupled variables
*/
auto & getWritableCoupledVariables() { return _writable_coupled_variables[_c_tid]; }

protected:
/**
* A call-back function provided by the derived object for actions before coupling a variable
Expand Down Expand Up @@ -1587,7 +1597,7 @@ class Coupleable
Moose::OLDER_SOLUTION_TAG};

/// keep a set of allocated writable variable references to make sure only one object can obtain them per thread
std::vector<std::set<std::string>> _writable_copled_variables;
std::vector<std::set<MooseVariable *>> _writable_coupled_variables;
};

template <typename T>
Expand Down
1 change: 1 addition & 0 deletions framework/include/loops/ComputeNodalUserObjectsThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ class ComputeNodalUserObjectsThread

private:
const TheWarehouse::Query _query;
AuxiliarySystem & _aux_sys;
};
2 changes: 2 additions & 0 deletions framework/include/loops/ComputeUserObjectsThread.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class ComputeUserObjectsThread : public ThreadedElementLoop<ConstElemRange>
std::vector<ShapeElementUserObject *> _shape_element_objs;
std::vector<DomainUserObject *> _domain_objs;
std::vector<DomainUserObject *> _all_domain_objs;

AuxiliarySystem & _aux_sys;
};

// determine when we need to run user objects based on whether any initial conditions or aux
Expand Down
35 changes: 19 additions & 16 deletions framework/src/interfaces/Coupleable.C
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Coupleable::Coupleable(const MooseObject * moose_object, bool nodal, bool is_fv)
_coupleable_max_qps(Moose::constMaxQpsPerElem),
_is_fv(is_fv),
_obj(moose_object),
_writable_copled_variables(libMesh::n_threads())
_writable_coupled_variables(libMesh::n_threads())
{
SubProblem & problem = *_c_parameters.getCheckedPointerParam<SubProblem *>("_subproblem");
_obj->getMooseApp().registerInterfaceObject(*this);
Expand Down Expand Up @@ -809,15 +809,11 @@ Coupleable::coupledArrayValues(const std::string & var_name) const
VariableValue &
Coupleable::writableCoupledValue(const std::string & var_name, unsigned int comp)
{
// make sure only one object can access a variable

for (const auto & ci : _obj->getMooseApp().getInterfaceObjects<Coupleable>())
if (ci != this && ci->_writable_copled_variables[_c_tid].count(var_name))
mooseError("'",
ci->_obj->name(),
"' already obtained a writable reference to '",
var_name,
"'. Only one object can obtain such a reference per variable in a simulation.");
// check if the variable exists
auto * const var = getVar(var_name, comp);
if (!var)
mooseError(
"Unable to create a writable reference to '", var_name, "', is it a constant expression?");

// check that the variable type (elemental/nodal) is compatible with the object type
const auto * aux = dynamic_cast<const AuxKernel *>(this);
Expand All @@ -830,11 +826,6 @@ Coupleable::writableCoupledValue(const std::string & var_name, unsigned int comp
_obj->name(),
"' is neither of those.");

const auto * var = getVar(var_name, comp);
if (!var)
mooseError(
"Unable to create a writable reference to '", var_name, "', is it a constant expression?");

if (aux && aux->isNodal() != var->isNodal())
mooseError("The AuxKernel '",
_obj->name(),
Expand All @@ -854,7 +845,19 @@ Coupleable::writableCoupledValue(const std::string & var_name, unsigned int comp
var_name,
"'.");

_writable_copled_variables[_c_tid].insert(var_name);
// make sure only one object can access a variable
for (const auto & ci : _obj->getMooseApp().getInterfaceObjects<Coupleable>())
if (ci != this && ci->_writable_coupled_variables[_c_tid].count(var))
mooseError("'",
ci->_obj->name(),
"' already obtained a writable reference to '",
var_name,
"'. Only one object can obtain such a reference per variable in a simulation.");

// var is unique across threads, so we could forego having a separate set per thread, but we
// need qucik access to the list of all variables that need to be inserted into the solution
// vector by a given thread.
_writable_coupled_variables[_c_tid].insert(var);
return const_cast<VariableValue &>(coupledValue(var_name, comp));
}

Expand Down
18 changes: 16 additions & 2 deletions framework/src/loops/ComputeNodalUserObjectsThread.C
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@

ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(FEProblemBase & fe_problem,
const TheWarehouse::Query & query)
: ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(fe_problem), _query(query)
: ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(fe_problem),
_query(query),
_aux_sys(fe_problem.getAuxiliarySystem())
{
}

// Splitting Constructor
ComputeNodalUserObjectsThread::ComputeNodalUserObjectsThread(ComputeNodalUserObjectsThread & x,
Threads::split split)
: ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(x, split), _query(x._query)
: ThreadedNodeLoop<ConstNodeRange, ConstNodeRange::const_iterator>(x, split),
_query(x._query),
_aux_sys(x._aux_sys)
{
}

Expand All @@ -50,7 +54,17 @@ ComputeNodalUserObjectsThread::onNode(ConstNodeRange::const_iterator & node_it)
.condition<AttribBoundaries>(bnd, true)
.queryInto(objs);
for (const auto & uo : objs)
{
uo->execute();

// update the aux solution vector if writable coupled variables are used
if (uo->hasWritableCoupledVariables())
{
Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
for (auto * var : uo->getWritableCoupledVariables())
var->insert(_aux_sys.solution());
}
}
}

// Block Restricted
Expand Down
16 changes: 14 additions & 2 deletions framework/src/loops/ComputeUserObjectsThread.C
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ ComputeUserObjectsThread::ComputeUserObjectsThread(FEProblemBase & problem,
_soln(*sys.currentSolution()),
_query(query),
_query_subdomain(_query),
_query_boundary(_query)
_query_boundary(_query),
_aux_sys(problem.getAuxiliarySystem())
{
}

Expand All @@ -41,7 +42,8 @@ ComputeUserObjectsThread::ComputeUserObjectsThread(ComputeUserObjectsThread & x,
_soln(x._soln),
_query(x._query),
_query_subdomain(x._query_subdomain),
_query_boundary(x._query_boundary)
_query_boundary(x._query_boundary),
_aux_sys(x._aux_sys)
{
}

Expand Down Expand Up @@ -126,8 +128,18 @@ ComputeUserObjectsThread::onElement(const Elem * elem)
_fe_problem.reinitMaterials(_subdomain, _tid);

for (const auto & uo : _element_objs)
{
uo->execute();

// update the aux solution vector if writable coupled variables are used
if (uo->hasWritableCoupledVariables())
{
Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
for (auto * var : uo->getWritableCoupledVariables())
var->insert(_aux_sys.solution());
}
}

for (auto & uo : _domain_objs)
{
uo->preExecuteOnElement();
Expand Down

0 comments on commit eaecdd9

Please sign in to comment.