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(_constitutive.getOutput(getParam<std::string>("stress"))),
43  _disp_vars(getParam<std::vector<NonlinearVariableName>>("displacements")),
44  _ndisp(_disp_vars.size())
45 {
46  mooseAssert(_residual, "Failed to cast residual to PetscVector<Real>");
47 
48  if (_disp_vars.size() < 1 || _disp_vars.size() > 3)
49  mooseError("NEML2StressDivergence requires 1 to 3 displacement variables, got ",
50  _disp_vars.size());
51 
53  _grad_test_y = _ndisp >= 2 ? &_fe.getPhiGradient(_disp_vars[1]) : nullptr;
54  _grad_test_z = _ndisp >= 3 ? &_fe.getPhiGradient(_disp_vars[2]) : nullptr;
55 }
56 
57 void
59 {
61  return;
62 
63  torch::InferenceMode guard;
64 
65  auto dphix = neml2::Tensor(*_grad_test_x, 3);
66  auto dphiy = _ndisp >= 2 ? neml2::Tensor(*_grad_test_y, 3) : neml2::Tensor::zeros_like(dphix);
67  auto dphiz = _ndisp >= 3 ? neml2::Tensor(*_grad_test_z, 3) : neml2::Tensor::zeros_like(dphix);
68  auto dphi = neml2::base_stack({dphix, dphiy, dphiz}, 0); // (nelem, ndofe, nqp; 3, 3)
69  auto stress = neml2::R2(neml2::SR2(_stress)).dynamic_unsqueeze(-2); // (nelem, 1, nqp; 3, 3)
70 
71  // weak form
72  auto re_qp = neml2::base_sum(dphi * neml2::Tensor(stress), -1); // (nelem, ndofe, nqp; 3)
73 
74  // element integration
75  auto JxWxT =
76  _neml2_assembly.JxWxT().dynamic_unsqueeze(-2).base_unsqueeze(0); // (nelem, 1, nqp; 1)
77  auto re = neml2::dynamic_sum(re_qp * JxWxT, -1)
78  .base_index({neml2::indexing::Slice(0, _ndisp)}); // (nelem, ndofe; ndisp)
79 
80  // assemble residual
81  for (auto i : make_range(_ndisp))
82  {
83  auto re_i = re.base_index({i}).contiguous().cpu();
84  const auto & dofmap_i = _fe.getGlobalDofMap(_disp_vars[i]);
85  _residual->add_vector(re_i.data_ptr<Real>(), dofmap_i);
86  }
87  _residual->close();
88 }
89 
90 #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
const neml2::Tensor * _grad_test_z
const NEML2ModelExecutor & _constitutive
ParallelType