https://mooseframework.inl.gov
NEML2StressDivergence.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 #ifdef NEML2_ENABLED
11 
12 // NEML2 includes
13 #include "neml2/tensors/functions/stack.h"
14 #include "neml2/tensors/functions/sum.h"
15 
16 // MOOSE includes
17 #include "NEML2StressDivergence.h"
18 
19 registerMooseObject("SolidMechanicsApp", NEML2StressDivergence);
20 
23 {
25  params.addClassDescription(
26  "This user object calculates the stress divergence for a given set of displacement "
27  "variables and assemble the contribution into the residual vector.");
28  params.addRequiredParam<std::vector<NonlinearVariableName>>(
29  "displacements",
30  "The displacements variables whose function space will be used to define the test "
31  "functions.");
32  params.addRequiredParam<std::string>("stress",
33  "The name of the NEML2 variable to use as the stress.");
34  params.addRequiredParam<std::string>("residual", "The tag for the residual");
35  return params;
36 }
37 
39  : NEML2PostKernel(parameters),
40  _residual(dynamic_cast<PetscVector<Real> *>(&_sys.system().add_vector(
41  getParam<std::string>("residual"), false, libMesh::ParallelType::GHOSTED))),
42  _stress(
43  _constitutive.getOutput(NEML2Utils::parseVariableName(getParam<std::string>("stress")))),
44  _disp_vars(getParam<std::vector<NonlinearVariableName>>("displacements")),
45  _ndisp(_disp_vars.size())
46 {
47  mooseAssert(_residual, "Failed to cast residual to PetscVector<Real>");
48 
49  if (_disp_vars.size() < 1 || _disp_vars.size() > 3)
50  mooseError("NEML2StressDivergence requires 1 to 3 displacement variables, got ",
51  _disp_vars.size());
52 
54  _grad_test_y = _ndisp >= 2 ? &_fe.getPhiGradient(_disp_vars[1]) : nullptr;
55  _grad_test_z = _ndisp >= 3 ? &_fe.getPhiGradient(_disp_vars[2]) : nullptr;
56 }
57 
58 void
60 {
62  return;
63 
64  torch::InferenceMode guard;
65 
66  auto dphix = neml2::Tensor(*_grad_test_x, 3);
67  auto dphiy = _ndisp >= 2 ? neml2::Tensor(*_grad_test_y, 3) : neml2::Tensor::zeros_like(dphix);
68  auto dphiz = _ndisp >= 3 ? neml2::Tensor(*_grad_test_z, 3) : neml2::Tensor::zeros_like(dphix);
69  auto dphi = neml2::base_stack({dphix, dphiy, dphiz}, 0); // (nelem, ndofe, nqp; 3, 3)
70  auto stress = neml2::R2(neml2::SR2(_stress)).dynamic_unsqueeze(-2); // (nelem, 1, nqp; 3, 3)
71 
72  // weak form
73  auto re_qp = neml2::base_sum(dphi * neml2::Tensor(stress), -1); // (nelem, ndofe, nqp; 3)
74 
75  // element integration
76  auto JxWxT =
77  _neml2_assembly.JxWxT().dynamic_unsqueeze(-2).base_unsqueeze(0); // (nelem, 1, nqp; 1)
78  auto re = neml2::dynamic_sum(re_qp * JxWxT, -1)
79  .base_index({neml2::indexing::Slice(0, _ndisp)}); // (nelem, ndofe; ndisp)
80 
81  // assemble residual
82  for (auto i : make_range(_ndisp))
83  {
84  auto re_i = re.base_index({i}).contiguous().cpu();
85  const auto & dofmap_i = _fe.getGlobalDofMap(_disp_vars[i]);
86  _residual->add_vector(re_i.data_ptr<Real>(), dofmap_i);
87  }
88  _residual->close();
89 }
90 
91 #endif
const neml2::Tensor & getPhiGradient(const std::string &var_name)
const std::vector< dof_id_type > & getGlobalDofMap(const std::string &var_name)
bool outputReady() const
const neml2::Tensor * _grad_test_y
const std::vector< NonlinearVariableName > _disp_vars
Displacement variables.
const neml2::Tensor * _grad_test_x
test function gradients
void forward() override
calculate residual contribution corresponding to the weak form ${i,J} P_{iJ}$
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
void addRequiredParam(const std::string &name, const std::string &doc_string)
static InputParameters validParams()
const neml2::Tensor & JxWxT() const
GHOSTED
NEML2StressDivergence(const InputParameters &parameters)
const int64_t _ndisp
the number of displacement variables
const neml2::Tensor & _stress
stress
PetscVector< Real > * _residual
The residual vector.
NEML2FEInterpolation & _fe
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
static InputParameters validParams()
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
registerMooseObject("SolidMechanicsApp", NEML2StressDivergence)
NEML2Assembly & _neml2_assembly
neml2::VariableName parseVariableName(const std::string &)
const neml2::Tensor * _grad_test_z
const NEML2ModelExecutor & _constitutive
ParallelType