LCOV - code coverage report
Current view: top level - src/Model/Interface/Crack - PFCZM.H (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 0.0 % 92 0
Test Date: 2025-07-10 18:14:14 Functions: 0.0 % 20 0

            Line data    Source code
       1              : #ifndef MODEL_INTERFACE_CRACK_PFCZM_H
       2              : #define MODEL_INTERFACE_CRACK_PFCZM_H
       3              : 
       4              : #include <iostream>
       5              : #include <fstream>
       6              : #include <cmath>
       7              : 
       8              : #include "AMReX.H"
       9              : #include "Crack.H"
      10              : #include "Set/Set.H"
      11              : #include "Util/Util.H"
      12              : 
      13              : namespace Model
      14              : {
      15              : namespace Interface
      16              : {
      17              : namespace Crack
      18              : {
      19              : class PFCZM : public Crack
      20              : {
      21              : public:
      22              :     enum FSType {WANG2023, MC};
      23              : 
      24            0 :     PFCZM() = default;
      25            0 :     virtual ~PFCZM() = default;
      26              : 
      27              :     // In Wu 2024 formulation, Gc is scaled by a constant C_alpha.
      28              :     // $C_\alpha = 4 \int_0^1 \sqrt{\alpha(\beta)} d\beta$
      29              :     // where $\alpha$ is the geometric function defined in the code as w_phi
      30              :     // For the optimal function chosen in Wu 2024, $C_\alpha = \pi$ 
      31            0 :     Set::Scalar Gc (Set::Scalar /*ratio*/) { return _Gc / _c_alpha; }
      32            0 :     Set::Scalar c_alpha ()      { return _c_alpha; }
      33            0 :     Set::Scalar l_w()           { return _l_w; }
      34              : 
      35              :     // this hould check if we need to do mixed mode loading.
      36            0 :     bool mixed_mode()           { return _mixed_mode; }
      37            0 :     FSType failure_surface()    { return _failure_surface; }
      38              : 
      39              :     // added functions for mixed mode - Wang 2023 surface
      40              :     Set::Scalar GcI_bar ()      { return _GcI_bar / _c_alpha; }
      41              :     Set::Scalar GcII_bar ()     { return _GcII_bar / _c_alpha; }
      42            0 :     Set::Scalar chi()           { return _chi; }
      43            0 :     Set::Scalar beta_bar()      { return _beta_bar; }
      44            0 :     Set::Scalar sig_t()         { return _sig_t; }
      45            0 :     Set::Scalar tau_s()         { return _tau_s; }
      46              : 
      47              :     // added functions for mixed mode - mohr columb surface
      48            0 :     Set::Scalar cohesion()      { return _cohesion; }
      49            0 :     Set::Scalar friction()      { return _friction; }
      50              : 
      51              :     // For now, we are storing things like youngs modulus stuff here.
      52              :     // ideally, they should be moved to Material -> Solid -> Affine.
      53            0 :     Set::Scalar DGc (Set::Scalar /*theta*/) { return 0.0; }
      54            0 :     Set::Scalar DDGc (Set::Scalar /*theta*/) { return 0.0; }
      55            0 :     Set::Scalar Zeta(Set::Scalar /*theta*/) { return zeta; }
      56            0 :     Set::Scalar Mobility (Set::Scalar /*theta*/) {return mobility;}
      57            0 :     Set::Scalar DrivingForceThreshold (Set::Scalar /*theta*/) {return threshold;}
      58              : 
      59              : private:
      60              :     Set::Scalar _Gc = NAN; 
      61              :     Set::Scalar _c_alpha = pi; // scaling factor.
      62              :     Set::Scalar _l_w = 1.e-5; //irwing length
      63              :     Set::Scalar zeta = NAN;
      64              :     Set::Scalar mobility = NAN;
      65              :     Set::Scalar threshold = NAN;
      66              : 
      67              :     Set::Scalar czm_a0 = 1.0;
      68              :     Set::Scalar czm_order = NAN;
      69              :     
      70              :     bool _mixed_mode = false;
      71              :     FSType _failure_surface = FSType::WANG2023;
      72              : 
      73              :     Set::Scalar _GcI_bar = 1.e3;
      74              :     Set::Scalar _GcII_bar = 1.e3;
      75              : 
      76              :     // Parameters specific to WANG 2023 failure surface
      77              :     Set::Scalar _chi = NAN;
      78              :     Set::Scalar k1 = 1.0;
      79              :     Set::Scalar _beta_bar = -1.0;
      80              :     Set::Scalar _sig_t = 1.0;
      81              :     Set::Scalar _tau_s = 1.0;
      82              : 
      83              :     // Parameters specific to MC failure surface
      84              :     Set::Scalar _cohesion = NAN;
      85              :     Set::Scalar _friction = NAN;
      86              : 
      87              : public:
      88            0 :     static void Parse(PFCZM & value, IO::ParmParse & pp)
      89              :     {
      90            0 :         pp.query_default("czm_order", value.czm_order, 1.0); //Order 1, 1.5, or 2 (Wu 2024, JMPS)
      91            0 :         pp.query_default("G_c",value._Gc,1.0e3); // Fracture energy in N/m
      92            0 :         pp.query_default("zeta",value.zeta,1.e-5); // Lengthscale regularization in m
      93              : 
      94            0 :         Set::Scalar fracture_strength = NAN;
      95              :         
      96            0 :         Set::Scalar youngs = NAN;
      97            0 :         Set::Scalar nu = NAN;
      98            0 :         Set::Scalar tensile_strength = 2.e8;
      99            0 :         Set::Scalar shear_strength = 1.41e8;
     100            0 :         Set::Scalar compressive_strength = NAN;
     101              : 
     102              :         // Toggle to determine mixed mode
     103            0 :         pp.query_default("mixed_mode", value._mixed_mode, false);
     104              : 
     105            0 :         if (value._mixed_mode)
     106              :         {
     107              :             // Young's modulus
     108            0 :             pp.query_default("E", youngs, 2.e11);
     109              :             
     110              :             // Poisson's ratio $\nu$
     111            0 :             pp.query_default("nu", nu, 0.3);
     112              : 
     113              :             // shear modulus
     114            0 :             Set::Scalar mu = 0.5 * youngs / (1. + nu);
     115              :             
     116            0 :             std::string fail_surf_type = "";
     117              :             // type of failure surface
     118            0 :             pp.query_validate("failure_surface", fail_surf_type, {"wang2023", "mohr", "mc", "columb"}); // degradation function. For now, we only have linear softening
     119            0 :             std::map<std::string,FSType>  fs_map;
     120            0 :             fs_map["wang2023"]   = FSType::WANG2023;
     121            0 :             fs_map["mohr"]       = FSType::MC;
     122            0 :             fs_map["mc"]         = FSType::MC;
     123            0 :             fs_map["columb"]     = FSType::MC;
     124            0 :             value._failure_surface = fs_map[fail_surf_type];
     125              : 
     126            0 :             if (value._failure_surface == FSType::WANG2023)
     127              :             {
     128              :                 // Fracture strength
     129            0 :                 pp.query_default("fracture_strength", fracture_strength, 1.e6);
     130              :                 
     131              :                 // $\chi$ value
     132            0 :                 pp.query_default("chi", value._chi, 1.0);
     133              :                 
     134              :                 // Compressive strength
     135            0 :                 pp.query_default("compressive_strength", compressive_strength,4.e8);
     136            0 :                 value.k1 = ( value._chi < 1/std::sqrt(2) ) ? ( 2 * value._chi * std::sqrt(1.0 - value._chi*value._chi) ) : 1.0;
     137              : 
     138            0 :                 tensile_strength = fracture_strength / value.k1;
     139            0 :                 shear_strength = value._chi * tensile_strength;
     140            0 :                 value._beta_bar = (1.0 / (value._chi * value._chi)) - (compressive_strength * compressive_strength / (4.0 * value._chi * value._chi * shear_strength * shear_strength));
     141              : 
     142            0 :                 value._GcI_bar = value._Gc/(value.k1*value.k1);
     143            0 :                 value._GcII_bar = value._GcI_bar * youngs * value._chi * value._chi / mu ;
     144            0 :                 fracture_strength = tensile_strength * value.k1;
     145              : 
     146            0 :                 Util::Message(INFO, "Chi = ", value._chi);
     147            0 :                 Util::Message(INFO, "mu = ", mu);
     148            0 :                 Util::Message(INFO, "k1 = ", value.k1);
     149            0 :                 Util::Message(INFO, "beta_bar = ", value._beta_bar);
     150            0 :                 Util::Message(INFO, "GcI_bar = ", value._GcI_bar);
     151            0 :                 Util::Message(INFO, "GcII_bar = ", value._GcII_bar);
     152            0 :                 Util::Message(INFO, "f_t = ", fracture_strength);
     153            0 :                 Util::Message(INFO, "f_c = ", compressive_strength);
     154            0 :                 Util::Message(INFO, "sig_t = ", tensile_strength);
     155            0 :                 Util::Message(INFO, "tau_s = ", shear_strength);
     156              : 
     157            0 :                 value._sig_t = tensile_strength;
     158            0 :                 value._tau_s = shear_strength;
     159              :             }
     160            0 :             else if (value._failure_surface == FSType::MC)
     161              :             {
     162              :                 // cohesion coefficient for MC FS type
     163            0 :                 pp.query_default("cohesion", value._cohesion, 1.0);
     164              :                 // friction coefficient for MC FS type
     165            0 :                 pp.query_default("friction", value._friction, 0.5);
     166              :                 
     167            0 :                 Set::Scalar phi = std::atan(value._friction);
     168            0 :                 fracture_strength = 2.0 * value._cohesion * std::cos(phi) / (1.0 + std::sin(phi));
     169              :             }
     170              : 
     171            0 :         }
     172              :         else
     173              :         {
     174              :             // Young's modulus
     175            0 :             pp.query_default("E", youngs, 2.e11);
     176              :             // fracture strength beyond which softening starts [Pa]
     177            0 :             pp.query_default("fracture_strength", fracture_strength,1.e6);   
     178              :         }
     179              :         
     180            0 :         Set::Scalar irwing_length = youngs * value._Gc / (fracture_strength * fracture_strength);
     181            0 :         value.czm_a0 = 4.0 * irwing_length / (pi * value.zeta);
     182            0 :         Util::Message(INFO, "irwing_length = ", irwing_length, ", a0 = ", value.czm_a0);
     183            0 :         value._l_w = irwing_length;
     184              : 
     185            0 :         if (value.zeta > 0.33 * irwing_length) Util::Warning(INFO, "Zeta value is greater than irwing length. Consider reducing it.");
     186              : 
     187            0 :         pp.query_default("mobility",value.mobility,1.0e-2); // Mobility (speed)
     188            0 :         pp.query_default("threshold", value.threshold,0.0); // Threshold
     189              : 
     190            0 :         std::string gtype = "";
     191            0 :         std::string wtype = "";
     192            0 :         pp.query_validate("gtype", gtype, {"wu_linear"}); // degradation function. For now, we only have linear softening
     193            0 :         pp.query_validate("wtype", wtype, {"wu"}); // geometric function. no choice except for the optimal one for now.
     194              :         
     195            0 :         std::map<std::string,Model::Interface::Crack::Crack::GType>  g_map;
     196            0 :         g_map["wu_linear"] = Model::Interface::Crack::Crack::GType::GWULINEAR;
     197              :         
     198            0 :         std::map<std::string,Model::Interface::Crack::Crack::WType>  w_map;
     199            0 :         w_map["wu"] = Model::Interface::Crack::Crack::WType::WU;
     200              : 
     201            0 :         value.SetGType(g_map[gtype]);
     202            0 :         value.SetWType(w_map[wtype]);
     203              : 
     204            0 :         if (w_map[wtype] == Model::Interface::Crack::Crack::WType::WU) value._c_alpha = pi;
     205              : 
     206            0 :         value.SetPFCZMConstants(value.czm_order, value.czm_a0);
     207            0 :     }
     208              : };
     209              : }
     210              : }
     211              : }
     212              : #endif
        

Generated by: LCOV version 2.0-1