https://mooseframework.inl.gov
Loading...
Searching...
No Matches
TorchStressDivergence.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// MOOSE includes
14#include "TorchFEMUtils.h"
15
17
20{
23 "This user object calculates the stress divergence for a given set of displacement "
24 "variables and assembles the contribution into the residual vector.");
25 params.addRequiredParam<std::vector<NonlinearVariableName>>(
26 "displacements",
27 "The displacements variables whose function space will be used to define the test "
28 "functions.");
29 params.addRequiredParam<std::string>("stress",
30 "The name of the NEML2 variable to use as the stress.");
31 params.addRequiredParam<std::string>("residual", "The tag for the residual");
32 return params;
33}
34
36 : TorchPostKernel(parameters),
37 _residual(dynamic_cast<libMesh::PetscVector<Real> *>(&_sys.system().add_vector(
38 getParam<std::string>("residual"), false, libMesh::ParallelType::GHOSTED))),
39 _stress(_constitutive.getOutput(getParam<std::string>("stress"))),
40 _disp_vars(getParam<std::vector<NonlinearVariableName>>("displacements")),
41 _ndisp(_disp_vars.size())
42{
43 mooseAssert(_residual, "Failed to cast residual to PetscVector<Real>");
44
45 if (_disp_vars.size() < 1 || _disp_vars.size() > 3)
46 mooseError("TorchStressDivergence requires 1 to 3 displacement variables, got ",
47 _disp_vars.size());
48
50 _grad_test_y = _ndisp >= 2 ? &_fe.getPhiGradient(_disp_vars[1]) : nullptr;
51 _grad_test_z = _ndisp >= 3 ? &_fe.getPhiGradient(_disp_vars[2]) : nullptr;
52}
53
54void
56{
58 return;
59
60 torch::InferenceMode guard;
61 using at::indexing::Slice;
62
63 // test function gradients, each (nelem, ndofe, nqp, 3)
64 auto dphix = *_grad_test_x;
65 auto dphiy = _ndisp >= 2 ? *_grad_test_y : at::zeros_like(dphix);
66 auto dphiz = _ndisp >= 3 ? *_grad_test_z : at::zeros_like(dphix);
67 // stack along the displacement-component axis: dphi[e, a, q, i, j] = d phi_a / d x_j for
68 // component i, shape (nelem, ndofe, nqp, 3, 3)
69 auto dphi = at::stack({dphix, dphiy, dphiz}, 3);
70 // full stress sigma[e, q, i, j], broadcast over the dof axis: (nelem, 1, nqp, 3, 3)
71 auto stress = TorchFEM::mandelToFull(_stress).unsqueeze(1);
72
73 // weak form: re_qp[e, a, q, i] = sum_j dphi_ij * sigma_ij, shape (nelem, ndofe, nqp, 3)
74 auto re_qp = (dphi * stress).sum(-1);
75
76 // element integration over quadrature points
77 auto JxWxT = _assembly.JxWxT().unsqueeze(1).unsqueeze(-1); // (nelem, 1, nqp, 1)
78 auto re = (re_qp * JxWxT).sum(2); // (nelem, ndofe, 3)
79
80 // assemble residual, one displacement component at a time
81 for (auto i : make_range(_ndisp))
82 {
83 auto re_i = re.select(-1, i).contiguous().cpu(); // (nelem, ndofe)
84 const auto & dofmap_i = _fe.getGlobalDofMap(_disp_vars[i]);
85 _residual->add_vector(re_i.data_ptr<Real>(), dofmap_i);
86 }
88}
89
90#endif // NEML2_ENABLED
registerMooseObject("SolidMechanicsApp", TorchStressDivergence)
void addRequiredParam(const std::string &name, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
void mooseError(Args &&... args) const
bool outputReady() const
const at::Tensor & JxWxT() const
const std::vector< dof_id_type > & getGlobalDofMap(const std::string &var_name)
const at::Tensor & getPhiGradient(const std::string &var_name)
TorchFEInterpolation & _fe
TorchAssembly & _assembly
const NEML2ModelExecutor & _constitutive
static InputParameters validParams()
const at::Tensor * _grad_test_x
test function gradients
const std::vector< NonlinearVariableName > _disp_vars
Displacement variables.
const at::Tensor * _grad_test_z
static InputParameters validParams()
const int64_t _ndisp
the number of displacement variables
void forward() override
calculate residual contribution corresponding to the weak form $\phi_{i,J} P_{iJ}$
libMesh::PetscVector< Real > * _residual
The residual vector.
const at::Tensor * _grad_test_y
const at::Tensor & _stress
stress (a NEML2 model output, 6-component Mandel)
TorchStressDivergence(const InputParameters &parameters)
virtual void add_vector(const T *v, const std::vector< numeric_index_type > &dof_indices) override
virtual void close() override
at::Tensor mandelToFull(const at::Tensor &mandel)
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...