LCOV - code coverage report
Current view: top level - models/solid_mechanics - KocksMeckingFlowSwitch.cxx (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.6 % 42 41
Test Date: 2025-06-29 01:25:44 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/KocksMeckingFlowSwitch.h"
      26              : #include "neml2/tensors/Scalar.h"
      27              : #include "neml2/tensors/functions/pow.h"
      28              : #include "neml2/tensors/functions/tanh.h"
      29              : #include "neml2/tensors/functions/cosh.h"
      30              : 
      31              : namespace neml2
      32              : {
      33              : register_NEML2_object(KocksMeckingFlowSwitch);
      34              : 
      35              : OptionSet
      36            2 : KocksMeckingFlowSwitch::expected_options()
      37              : {
      38            2 :   OptionSet options = Model::expected_options();
      39            2 :   options.doc() = "Switches between rate independent and rate dependent flow rules based on the "
      40              :                   "value of the Kocks-Mecking normalized activation energy.  For activation "
      41              :                   "energies less than the threshold use the rate independent flow rule, for values "
      42              :                   "greater than the threshold use the rate dependent flow rule.  This version uses "
      43            2 :                   "a soft switch between the models, based on a tanh sigmoid function.";
      44              : 
      45            4 :   options.set_parameter<TensorName<Scalar>>("g0");
      46            2 :   options.set("g0").doc() = "Critical value of activation energy";
      47              : 
      48            6 :   options.set_input("activation_energy") = VariableName(FORCES, "g");
      49            4 :   options.set("activation_energy").doc() = "The input name of the activation energy";
      50              : 
      51            4 :   options.set<double>("sharpness") = 1.0;
      52            4 :   options.set("sharpness").doc() = "A steepness parameter that controls the tanh mixing of the "
      53            2 :                                    "models.  Higher values gives a sharper transition.";
      54              : 
      55            6 :   options.set_input("rate_independent_flow_rate") = VariableName(STATE, "internal", "ri_rate");
      56            2 :   options.set("rate_independent_flow_rate").doc() = "Input name of the rate independent flow rate";
      57            6 :   options.set_input("rate_dependent_flow_rate") = VariableName(STATE, "internal", "rd_rate");
      58            2 :   options.set("rate_dependent_flow_rate").doc() = "Input name of the rate dependent flow rate";
      59              : 
      60            6 :   options.set_output("flow_rate") = VariableName(STATE, "internal", "gamma_rate");
      61            2 :   options.set("flow_rate").doc() = "Output name for the mixed flow rate";
      62            2 :   return options;
      63            0 : }
      64              : 
      65            2 : KocksMeckingFlowSwitch::KocksMeckingFlowSwitch(const OptionSet & options)
      66              :   : Model(options),
      67            6 :     _g0(declare_parameter<Scalar>("g0", "g0", /*allow_nonlinear=*/true)),
      68            2 :     _g(declare_input_variable<Scalar>("activation_energy")),
      69            2 :     _sharp(options.get<double>("sharpness")),
      70            2 :     _ri_flow(declare_input_variable<Scalar>("rate_independent_flow_rate")),
      71            2 :     _rd_flow(declare_input_variable<Scalar>("rate_dependent_flow_rate")),
      72            4 :     _gamma_dot(declare_output_variable<Scalar>("flow_rate"))
      73              : {
      74            2 : }
      75              : 
      76              : void
      77            4 : KocksMeckingFlowSwitch::set_value(bool out, bool dout_din, bool /*d2out_din2*/)
      78              : {
      79            4 :   auto sig = (tanh(_sharp * (_g - _g0)) + 1.0) / 2.0;
      80              : 
      81            4 :   if (out)
      82            3 :     _gamma_dot = sig * _rd_flow + (1.0 - sig) * _ri_flow;
      83              : 
      84            4 :   if (dout_din)
      85              :   {
      86            2 :     _gamma_dot.d(_rd_flow) = sig;
      87            2 :     _gamma_dot.d(_ri_flow) = 1.0 - sig;
      88              : 
      89            2 :     auto partial = 0.5 * _sharp * pow(1.0 / cosh(_sharp * (_g - _g0)), 2.0);
      90            2 :     auto deriv = partial * (_rd_flow - _ri_flow);
      91              : 
      92            2 :     if (_g.is_dependent())
      93            2 :       _gamma_dot.d(_g) = deriv;
      94              : 
      95            6 :     if (const auto * const g0 = nl_param("g0"))
      96            1 :       _gamma_dot.d(*g0) = -deriv;
      97            2 :   }
      98            4 : }
      99              : 
     100              : } // namespace neml2
        

Generated by: LCOV version 2.0-1