LCOV - code coverage report
Current view: top level - models/solid_mechanics - FredrickArmstrongPlasticHardening.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.7 % 44 43
Test Date: 2025-10-02 16:03:03 Functions: 100.0 % 3 3

            Line data    Source code
       1              : // Copyright 2024, UChicago Argonne, LLC
       2              : // All Rights Reserved
       3              : // Software Name: NEML2 -- the New Engineering material Model Library, version 2
       4              : // By: Argonne National Laboratory
       5              : // OPEN SOURCE LICENSE (MIT)
       6              : //
       7              : // Permission is hereby granted, free of charge, to any person obtaining a copy
       8              : // of this software and associated documentation files (the "Software"), to deal
       9              : // in the Software without restriction, including without limitation the rights
      10              : // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      11              : // copies of the Software, and to permit persons to whom the Software is
      12              : // furnished to do so, subject to the following conditions:
      13              : //
      14              : // The above copyright notice and this permission notice shall be included in
      15              : // all copies or substantial portions of the Software.
      16              : //
      17              : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18              : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19              : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      20              : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      21              : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      22              : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      23              : // THE SOFTWARE.
      24              : 
      25              : #include "neml2/models/solid_mechanics/FredrickArmstrongPlasticHardening.h"
      26              : #include "neml2/tensors/Scalar.h"
      27              : #include "neml2/tensors/SR2.h"
      28              : #include "neml2/tensors/SSR4.h"
      29              : 
      30              : namespace neml2
      31              : {
      32              : register_NEML2_object(FredrickArmstrongPlasticHardening);
      33              : 
      34              : OptionSet
      35            4 : FredrickArmstrongPlasticHardening::expected_options()
      36              : {
      37            4 :   OptionSet options = FlowRule::expected_options();
      38            4 :   options.doc() +=
      39              :       " This object defines the non-associative Fredrick-Armstrong kinematic hardening. In the "
      40              :       "model, back stress is directly treated as an internal variable. Rate of back stress is "
      41              :       "given as \\f$ \\dot{\\boldsymbol{X}} = \\left( \\frac{2}{3} C \\frac{\\partial f}{\\partial "
      42              :       "\\boldsymbol{M}} - g \\boldsymbol{X} \\right) \\dot{\\gamma} \\f$."
      43              :       "\\f$ \\frac{\\partial f}{\\partial \\boldsymbol{M}} \\f$ is the flow "
      44              :       "direction, \\f$ \\dot{\\gamma} \\f$ is the flow rate, and \\f$ C \\f$ and \\f$ g \\f$ are "
      45            4 :       "material parameters.";
      46              : 
      47           12 :   options.set_input("back_stress") = VariableName(STATE, "internal", "X");
      48            8 :   options.set("back_stress").doc() = "Back stress";
      49              : 
      50            8 :   options.set_output("back_stress_rate");
      51            4 :   options.set("back_stress_rate").doc() = "Back stress rate, defaults to back_stress + _rate";
      52              : 
      53           12 :   options.set_input("flow_direction") = VariableName(STATE, "internal", "NM");
      54            8 :   options.set("flow_direction").doc() = "Flow direction";
      55              : 
      56            8 :   options.set_parameter<TensorName<Scalar>>("C");
      57            8 :   options.set("C").doc() = "Kinematic hardening coefficient";
      58              : 
      59            8 :   options.set_parameter<TensorName<Scalar>>("g");
      60            4 :   options.set("g").doc() = "Dynamic recovery coefficient";
      61              : 
      62            4 :   return options;
      63            0 : }
      64              : 
      65            6 : FredrickArmstrongPlasticHardening::FredrickArmstrongPlasticHardening(const OptionSet & options)
      66              :   : FlowRule(options),
      67            6 :     _X(declare_input_variable<SR2>("back_stress")),
      68            6 :     _NM(declare_input_variable<SR2>("flow_direction")),
      69           24 :     _X_dot(declare_output_variable<SR2>(options.get<VariableName>("back_stress_rate").empty()
      70           24 :                                             ? _X.name().with_suffix("_rate")
      71              :                                             : options.get<VariableName>("back_stress_rate"))),
      72           24 :     _C(declare_parameter<Scalar>("C", "C", true)),
      73           30 :     _g(declare_parameter<Scalar>("g", "g", true))
      74              : {
      75            6 : }
      76              : 
      77              : void
      78            4 : FredrickArmstrongPlasticHardening::set_value(bool out, bool dout_din, bool /*d2out_din2*/)
      79              : {
      80            4 :   auto eps = machine_precision(_X.scalar_type());
      81              :   // The effective stress
      82            4 :   auto s = SR2(_X).norm(eps);
      83              :   // The part that's proportional to the plastic strain rate
      84            4 :   auto g_term = 2.0 / 3.0 * _C * _NM - _g * _X;
      85              : 
      86            4 :   if (out)
      87            3 :     _X_dot = g_term * _gamma_dot;
      88              : 
      89            4 :   if (dout_din)
      90              :   {
      91            2 :     auto I = SR2::identity_map(_X.options());
      92              : 
      93            2 :     if (_gamma_dot.is_dependent())
      94            2 :       _X_dot.d(_gamma_dot) = g_term;
      95              : 
      96            2 :     if (_NM.is_dependent())
      97            2 :       _X_dot.d(_NM) = 2.0 / 3.0 * _C * _gamma_dot * I;
      98              : 
      99            2 :     if (_X.is_dependent())
     100            2 :       _X_dot.d(_X) = -_g * _gamma_dot * I;
     101              : 
     102            6 :     if (const auto * const C = nl_param("C"))
     103            1 :       _X_dot.d(*C) = 2.0 / 3.0 * _NM * _gamma_dot;
     104              : 
     105            6 :     if (const auto * const g = nl_param("g"))
     106            1 :       _X_dot.d(*g) = -_X * _gamma_dot;
     107            2 :   }
     108            4 : }
     109              : 
     110              : } // namespace neml2
        

Generated by: LCOV version 2.0-1