LCOV - code coverage report
Current view: top level - src/neml2/userobjects - CauchyStressFromNEML2UO.C (source / functions) Hit Total Coverage
Test: idaholab/moose tensor_mechanics: d6b47a Lines: 0 13 0.0 %
Date: 2024-02-27 11:53:14 Functions: 0 2 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://www.mooseframework.org
       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             : #include "CauchyStressFromNEML2UO.h"
      11             : #include "NEML2Utils.h"
      12             : 
      13             : registerMooseObject("TensorMechanicsApp", CauchyStressFromNEML2UO);
      14             : 
      15             : InputParameters
      16           0 : CauchyStressFromNEML2UO::validParams()
      17             : {
      18           0 :   auto params = NEML2SolidMechanicsInterface<CauchyStressFromNEML2UOParent>::validParams();
      19           0 :   NEML2Utils::addClassDescription(
      20             :       params,
      21             :       "Gather input variables required for an objective stress integration "
      22             :       "from all quadrature points. The batched input vector is sent through "
      23             :       "a NEML2 material model to perform the constitutive update.");
      24           0 :   params.addCoupledVar("temperature", "The temperature");
      25             : 
      26             :   // Since we use the NEML2 model to evaluate the residual AND the Jacobian at the same time, we
      27             :   // want to execute this user object only at execute_on = LINEAR (i.e. during residual evaluation).
      28           0 :   ExecFlagEnum execute_options = MooseUtils::getDefaultExecFlagEnum();
      29           0 :   execute_options = {EXEC_INITIAL, EXEC_LINEAR};
      30           0 :   params.set<ExecFlagEnum>("execute_on") = execute_options;
      31             : 
      32           0 :   return params;
      33           0 : }
      34             : 
      35             : #ifndef NEML2_ENABLED
      36             : 
      37           0 : CauchyStressFromNEML2UO::CauchyStressFromNEML2UO(const InputParameters & params)
      38             :   : NEML2SolidMechanicsInterface<CauchyStressFromNEML2UOParent>(
      39           0 :         params, "mechanical_strain", "temperature")
      40             : {
      41           0 :   NEML2Utils::libraryNotEnabledError(params);
      42           0 : }
      43             : 
      44             : #else
      45             : 
      46             : CauchyStressFromNEML2UO::CauchyStressFromNEML2UO(const InputParameters & params)
      47             :   : NEML2SolidMechanicsInterface<CauchyStressFromNEML2UOParent>(
      48             :         params, "mechanical_strain", "temperature")
      49             : {
      50             :   validateModel();
      51             : }
      52             : 
      53             : void
      54             : CauchyStressFromNEML2UO::batchCompute()
      55             : {
      56             :   try
      57             :   {
      58             :     // Allocate the input and output
      59             :     if (_t_step == 0)
      60             :     {
      61             :       _in = neml2::LabeledVector::zeros(_input_data.size(), {&model().input()});
      62             :       _out = neml2::LabeledVector::zeros(_input_data.size(), {&model().output()});
      63             :     }
      64             : 
      65             :     updateForces();
      66             : 
      67             :     if (_t_step > 0)
      68             :     {
      69             :       if (model().implicit())
      70             :         applyPredictor();
      71             : 
      72             :       solve();
      73             : 
      74             :       // Fill the NEML2 output back into the MOOSE output data
      75             :       for (const neml2::TorchSize i : index_range(_output_data))
      76             :       {
      77             :         std::get<0>(_output_data[i]) =
      78             :             NEML2Utils::toMOOSE<SymmetricRankTwoTensor>(_out(stress()).batch_index({i}));
      79             :         std::get<1>(_output_data[i]) = RankFourTensor(NEML2Utils::toMOOSE<SymmetricRankFourTensor>(
      80             :             _dout_din(stress(), strain()).batch_index({i})));
      81             :       }
      82             :     }
      83             :   }
      84             :   catch (neml2::NEMLException & e)
      85             :   {
      86             :     mooseException("An error occurred during the evaluation of a NEML2 model:\n",
      87             :                    e.what(),
      88             :                    NEML2Utils::NEML2_help_message);
      89             :   }
      90             :   catch (std::runtime_error & e)
      91             :   {
      92             :     mooseException("An unknown error occurred during the evaluation of a NEML2 model:\n",
      93             :                    e.what(),
      94             :                    "\nIt is possible that this error is related to NEML2.",
      95             :                    NEML2Utils::NEML2_help_message);
      96             :   }
      97             : }
      98             : 
      99             : void
     100             : CauchyStressFromNEML2UO::timestepSetup()
     101             : {
     102             :   if (_t_step > 0)
     103             :     advanceStep();
     104             : }
     105             : 
     106             : void
     107             : CauchyStressFromNEML2UO::advanceStep()
     108             : {
     109             :   // Set old state variables and old forces
     110             :   if (model().input().has_subaxis("old_state") && model().output().has_subaxis("state"))
     111             :     _in.slice("old_state").fill(_out.slice("state"));
     112             :   if (model().input().has_subaxis("old_forces") && model().input().has_subaxis("forces"))
     113             :     _in.slice("old_forces").fill(_in.slice("forces"));
     114             : }
     115             : 
     116             : void
     117             : CauchyStressFromNEML2UO::updateForces()
     118             : {
     119             :   // Homogenize the input data
     120             :   auto input = NEML2Utils::homogenizeBatchedTuple(_input_data);
     121             : 
     122             :   // Update forces
     123             :   NEML2Utils::setBatched(
     124             :       // The input LabeledVector
     125             :       _in,
     126             :       // NEML2 variable accessors
     127             :       {strain(), temperature()},
     128             :       // Pointer to the batched data
     129             :       model().input().has_variable(strain()) ? &std::get<0>(input) : nullptr,
     130             :       model().input().has_variable(temperature()) ? &std::get<1>(input) : nullptr);
     131             : 
     132             :   NEML2Utils::set(
     133             :       // The input LabeledVector
     134             :       _in,
     135             :       // NEML2 variable accessors
     136             :       {time()},
     137             :       // Pointer to the unbatched data
     138             :       model().input().has_variable(time()) ? &_t : nullptr);
     139             : }
     140             : 
     141             : void
     142             : CauchyStressFromNEML2UO::applyPredictor()
     143             : {
     144             :   // Set trial state variables (i.e., initial guesses).
     145             :   // Right now we hard-code to use the old state as the trial state.
     146             :   // TODO: implement other predictors
     147             :   _in.slice("state").fill(_in.slice("old_state"));
     148             : }
     149             : 
     150             : void
     151             : CauchyStressFromNEML2UO::solve()
     152             : {
     153             :   // 1. Sync input onto the model's device
     154             :   // 2. Evaluate the NEML2 material model
     155             :   // 3. Sync output back onto CPU
     156             :   auto res = model().value_and_dvalue(_in.to(device()));
     157             :   _out = std::get<0>(res).to(torch::kCPU);
     158             :   _dout_din = std::get<1>(res).to(torch::kCPU);
     159             : }
     160             : 
     161             : #endif // NEML2_ENABLED

Generated by: LCOV version 1.14