13#include "libmesh/petsc_vector.h"
16#include <ATen/ops/from_blob.h>
19#include "neml2/tensors/functions/discretization/scatter.h"
20#include "neml2/tensors/functions/discretization/interpolate.h"
35 "This user object provides an interface to NEML2 for finite element "
36 "interpolation of variables and their gradients. It gathers the shape "
37 "functions and DOF maps for each variable in the assembly and provides "
38 "them as NEML2 tensors for use in NEML2 models.");
41 "assembly",
"The NEML2Assembly object to use to provide assembly information");
59 auto [it, success] =
_vars.emplace(var_name, neml2::Tensor());
64 _phis.emplace(var->feType(), &var->phi());
74 auto [it, success] =
_grad_vars.emplace(var_name, neml2::Tensor());
79 _grad_phis.emplace(var->feType(), &var->gradPhi());
91 const auto it =
_neml2_phi.find(var->feType());
95 _phis.emplace(var->feType(), &var->phi());
96 auto [it2, success] =
_neml2_phi.emplace(var->feType(), neml2::Tensor());
109 _grad_phis.emplace(var->feType(), &var->gradPhi());
110 auto [it2, success] =
_neml2_grad_phi.emplace(var->feType(), neml2::Tensor());
120const std::vector<dof_id_type> &
140 mooseError(
"NEML2FEInterpolation only supports variables of type MooseVariableFE<Real>");
142 if (var_fe->scalingFactor() != 1)
143 mooseError(
"Scaling factors other than unity are not yet supported");
149 "' must be defined on all blocks '",
163 mooseError(
"Only solution vectors of type PetscVector are currently supported");
206 for (
const auto & [var_name, var] : main_uo._moose_vars)
209 if (main_uo._phis.count(var->feType()))
211 if (main_uo._grad_phis.count(var->feType()))
221 "NEML2FEInterpolation becomes out of sync with other thread");
226 auto merge_map_vecs = [](
auto & map1,
const auto & map2)
228 for (
const auto & [key, map2_val] : map2)
230 auto & map1_val = map1[key];
231 map1_val.insert(map1_val.end(), map2_val.begin(), map2_val.end());
252 if (!success && std::size_t(it->second) !=
_dof_indices.size())
253 mooseError(
"DOF map size mismatch for variable ",
263 moose_dof_map.push_back(
_petsc_solution->map_global_to_local_index(dof));
264 moose_dof_map_global.push_back(dof);
269 for (
const auto & [fetype, phi] :
_phis)
274 moose_phi.push_back((*phi)[i][qp]);
278 for (
const auto & [fetype, grad_phi] :
_grad_phis)
284 moose_grad_phi.push_back((*grad_phi)[i][qp](j));
291 TIME_SECTION(
"finalize", 1,
"Updating FEM context and interpolations for NEML2");
303 TIME_SECTION(
"updateFEMContext", 2,
"Updating FEM context for NEML2");
322 auto ndofe =
_ndofe.at(var->feType());
325 if (moose_dof_map.size() != std::size_t(nelem * ndofe))
327 "dof map size mismatch, expected ", nelem * ndofe,
" but got ", moose_dof_map.size());
331 neml2::Tensor(at::from_blob(moose_dof_map.data(), {nelem, ndofe}, torch::kInt64), 2)
347 auto ndofe =
_ndofe.at(fetype);
350 if (moose_phi.size() != std::size_t(nelem * ndofe * nqp))
351 mooseError(
"shape function size mismatch, expected ",
356 neml2::Tensor(at::from_blob(moose_phi.data(), {nelem, ndofe, nqp}, torch::kFloat64), 3)
370 auto ndofe =
_ndofe.at(fetype);
373 if (moose_grad_phi.size() != std::size_t(nelem * ndofe * nqp * 3))
374 mooseError(
"shape function gradient size mismatch, expected ",
375 nelem * ndofe * nqp * 3,
377 moose_grad_phi.size());
379 neml2::Tensor(at::from_blob(moose_grad_phi.data(), {nelem, ndofe, nqp, 3}, torch::kFloat64),
388 TIME_SECTION(
"updateInterpolations", 2,
"Updating FEM interpolations for NEML2");
397 for (
auto & [var_name, val] :
_vars)
400 const auto fetype =
_moose_vars[var_name]->feType();
402 auto sol_scattered = neml2::discretization::scatter(sol, dof_map);
403 val = neml2::discretization::interpolate(sol_scattered, phi);
410 const auto fetype =
_moose_vars[var_name]->feType();
412 auto sol_scattered = neml2::discretization::scatter(sol, dof_map);
413 val = neml2::discretization::interpolate(sol_scattered, grad_phi);
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
const ExecFlagType EXEC_INITIAL
const ExecFlagType EXEC_LINEAR
registerMooseObject("MooseApp", NEML2FEInterpolation)
virtual const std::set< SubdomainID > & blockIDs() const
Return the block subdomain ids for this object Note, if this is not block restricted,...
static InputParameters validParams()
const Elem *const & _current_elem
The current element pointer (available during execute())
const MooseArray< Point > & _q_point
A MultiMooseEnum object to hold "execute_on" flags.
T & getUserObject(const std::string &name, unsigned int tid=0) const
Get the user object by its name.
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
torch::DeviceType getLibtorchDevice() const
Get the device torch is supposed to be running on.
const std::string & name() const
Get the name of the class.
MooseApp & _app
The MOOSE application this is associated with.
Class for stuff related to variables.
This user object caches assembly information from MOOSE.
int64_t numQP() const
Number of quadrature points per element.
int64_t numElem() const
Number of active elements on this rank.
This user object serves as the "interface" for interpolating MOOSE variable values and gradients from...
static InputParameters validParams()
const neml2::Tensor & getPhiGradient(const std::string &var_name)
Get the shape function gradient associated with a MOOSE variable.
const neml2::Tensor & getGradient(const std::string &var_name)
Get the variable gradient of a MOOSE nonlinear variable converted to a NEML2 tensor.
const neml2::Tensor & getDofMap(const std::string &var_name)
Get the local dof map associated with a MOOSE variable.
std::unordered_map< std::string, neml2::Tensor > _vars
coupled variables (by value) requested by other objects
const NEML2Assembly & _neml2_assembly
Assembly.
virtual void updateGradPhi()
virtual void syncWithMainThread()
std::unordered_map< std::string, neml2::Tensor > _neml2_dof_map
void invalidateFEMContext()
Invalidate the cached FEM context such as dof map, shape functions, etc.
void invalidateInterpolations()
Invalidate the cached interpolations.
bool _interp_up_to_date
Whether the current interpolations are up to date.
NEML2FEInterpolation(const InputParameters ¶meters)
std::unordered_map< std::string, std::vector< int64_t > > _moose_dof_map
const neml2::Tensor & getValue(const std::string &var_name)
Get the variable value of a MOOSE nonlinear variable converted to a NEML2 tensor.
std::vector< dof_id_type > _dof_indices
Helper vector to store local dof indices.
std::unordered_map< FEType, std::vector< Real > > _moose_phi
std::unordered_map< FEType, const VariablePhiGradient * > _grad_phis
std::unordered_map< FEType, neml2::Tensor > _neml2_phi
const MooseVariableFE< Real > * getMOOSEVariable(const std::string &var_name) const
Helper to get the MOOSE variable and check for common restrictions.
void meshChanged() override
Called on this object when the mesh changes.
void execute() override
Execute method.
void threadJoin(const UserObject &) override
Must override.
int64_t local_ndof() const
virtual void updateFEMContext()
int64_t _local_ndof
Number of local dofs (including ghost dofs)
virtual void updateDofMap()
std::unordered_map< FEType, int64_t > _ndofe
cached information on the requested function spaces
std::unordered_map< FEType, neml2::Tensor > _neml2_grad_phi
std::unordered_map< std::string, neml2::Tensor > _grad_vars
coupled variables (by gradient) requested by other objects
bool _fem_context_up_to_date
Whether the current FEM context is up to date.
virtual void updateInterpolations()
void initialSetup() override
Gets called at the beginning of the simulation before this object is asked to do its job.
std::unordered_map< std::string, const MooseVariableFE< Real > * > _moose_vars
moose variables that have been coupled
std::unordered_map< std::string, std::vector< dof_id_type > > _moose_dof_map_global
const PetscVector< Real > * _petsc_solution
PETSc solution vector.
std::unordered_map< FEType, const VariablePhiValue * > _phis
const std::vector< dof_id_type > & getGlobalDofMap(const std::string &var_name)
Similar to getDofMap, but returns the global dof map (as a flattened vector of dof_id_type)
const neml2::Tensor & getPhi(const std::string &var_name)
Get the shape function associated with a MOOSE variable.
void finalize() override
Finalize.
void initialize() override
Called before execute() is ever called so that data can be cleared.
std::unordered_map< FEType, std::vector< Real > > _moose_grad_phi
virtual const NumericVector< Number > *const & currentSolution() const =0
The solution vector that is currently being operated on.
virtual libMesh::DofMap & dofMap()
Gets writeable reference to the dof map.
FEProblemBase & _fe_problem
Reference to the FEProblemBase for this user object.
const THREAD_ID _tid
Thread ID of this postprocessor.
SystemBase & _sys
Reference to the system object for this user object.
Base class for user-specific data.
void dof_indices(const Elem *const elem, std::vector< dof_id_type > &di) const
ExecFlagEnum getDefaultExecFlagEnum()
The following methods are specializations for using the libMesh::Parallel::packed_range_* routines fo...
auto index_range(const T &sizable)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)