LCOV - code coverage report
Current view: top level - src/Model/Solid - Solid.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 81 117 69.2 %
Date: 2024-11-18 05:28:54 Functions: 51 93 54.8 %

          Line data    Source code
       1             : //
       2             : // Solid models are used with the :ref:`Integrator::Mechanics` integrator, which
       3             : // implements the :ref:`Solver::Nonlocal::Newton` elasticity solver.
       4             : // All solid models inherit from the :code:`Model::Solid` base class, which requires
       5             : // all of the necessary components to be used in a mechanics solve.
       6             : // Model classes have basically two functions:
       7             : // 
       8             : // #. Provide energy (W), stress (DW), and modulus (DDW) based on a kinematic variable
       9             : // #. Evolve internal variables in time.
      10             : //
      11             : 
      12             : #ifndef MODEL_SOLID_H_
      13             : #define MODEL_SOLID_H_
      14             : 
      15             : #include <AMReX.H>
      16             : #include <AMReX_REAL.H>
      17             : #include <eigen3/Eigen/Core>
      18             : 
      19             : #include "Set/Set.H"
      20             : 
      21             : namespace Model
      22             : {
      23             : namespace Solid
      24             : {
      25             : 
      26             : enum KinematicVariable{gradu,epsilon,F};
      27             : 
      28             : template<Set::Sym SYM>
      29             : class Solid
      30             : {
      31             : public:
      32      519875 :     Solid() {} ;
      33             : 
      34      734239 :     virtual ~Solid() {};
      35             : 
      36             :     static constexpr Set::Sym sym = SYM;
      37             : 
      38           0 :     virtual Set::Scalar W(const Set::Matrix &) const      
      39           0 :     {Util::Abort(INFO,"W not implemented"); return 0.0;};
      40           0 :     virtual Set::Matrix DW(const Set::Matrix &) const         
      41           0 :     {Util::Abort(INFO,"DW not implemented"); return Set::Matrix::Zero();};
      42           0 :     virtual Set::Matrix4<AMREX_SPACEDIM,SYM> DDW(const Set::Matrix &) const 
      43           0 :     {Util::Abort(INFO,"DDW not implemented"); return Set::Matrix4<AMREX_SPACEDIM,SYM>::Zero();};
      44             :     
      45     1762263 :     virtual void Advance(Set::Scalar /*dt*/, Set::Matrix /*strain*/, Set::Matrix /*stress*/, Set::Scalar /*time*/) {}
      46             : 
      47             :     // Todo: implement for all models and make this pure virtual
      48           0 :     virtual bool ContainsNan() {return true;};
      49             : 
      50             : 
      51             : public:
      52             :     static const KinematicVariable kinvar = KinematicVariable::F;
      53             : 
      54             : 
      55           7 :         friend std::ostream& operator<<(std::ostream &out, const Solid &a)
      56             :     {
      57           7 :         a.Print(out);
      58           7 :         return out;
      59             :     }
      60           0 :     virtual void Print(std::ostream &out) const
      61             :     {
      62           0 :         out << "No print function written for this model.";
      63           0 :     }
      64             : 
      65             : public: 
      66             :     template <class T>
      67          22 :     static int ArithmeticTest(int verbose = 0)
      68             :     {
      69          44 :         const T z = T::Zero();
      70          44 :         if (!(z==z) && verbose) 
      71             :         {
      72           0 :             Util::Message(INFO,"Zero() failed: z = \n",z); return 1;
      73             :         }
      74             :         
      75          44 :         const T a = T::Random();
      76          44 :         if (!(a==a) && verbose) 
      77             :         {
      78           0 :             Util::Message(INFO,"Random() failed: a = \n",a); return 1;
      79             :         }
      80             : 
      81          44 :         const T b = T::Random();
      82             : 
      83          44 :         T c = a;
      84          44 :         if (!(c==a) && verbose) {Util::Message(INFO); return 1;}
      85          44 :         c = 1.0 * a;
      86          44 :         if (!(c==a) && verbose) {Util::Message(INFO); return 1;}
      87          44 :         c = 0.0 * a;
      88          44 :         if (!(c==z) && verbose) 
      89             :         {
      90           0 :             Util::Message(INFO,"0.0*a = \n",c); 
      91           0 :             Util::Message(INFO,"Zero() returns \n",z); 
      92           0 :             return 1;
      93             :         }
      94             : 
      95             :         // Todo: add some more arithmetic checks in here
      96             : 
      97          22 :         return 0;
      98             :     }
      99             : 
     100             :     template <class T>
     101          22 :     static int DerivativeTest1(int verbose = 0)
     102             :     {
     103         242 :         for (int iter = 0; iter < 10; iter++)
     104             :         {
     105         220 :             T model = T::Random();
     106             : 
     107         220 :             Set::Scalar dx = 1E-8, tol = 1E-6;
     108             : 
     109         220 :             Set::Matrix F = Set::Matrix::Random();
     110         610 :             while (F.determinant() < 0.1) F = Set::Matrix::Random(); // Ensure that F in GL(3)
     111             : 
     112         220 :             Set::Matrix dw_exact = model.DW(F);
     113         220 :             Set::Matrix dw_numeric = Set::Matrix::Zero();
     114         770 :             for (int i = 0; i < AMREX_SPACEDIM; i++)
     115        1980 :                 for (int j = 0; j < AMREX_SPACEDIM; j++)
     116             :                 {
     117        1430 :                     Set::Matrix dF = Set::Matrix::Zero();
     118        1430 :                     dF(i,j) = dx;
     119        1430 :                     dw_numeric(i,j) = (model.W(F+dF) - model.W(F-dF)) / (2.0 * dx);
     120             :                 }
     121         220 :             Set::Scalar relnorm = (dw_numeric-dw_exact).norm()/(dw_numeric.norm());
     122         220 :             if (relnorm > tol || std::isnan(relnorm) || std::isinf(relnorm))
     123             :             {
     124           0 :                 if (verbose)
     125             :                 {
     126           0 :                     Util::Message(INFO,"F \n",F);
     127           0 :                     Util::Message(INFO,"det(F) = ",F.determinant());
     128           0 :                     Util::Message(INFO,"dw exact \n",dw_exact);
     129           0 :                     Util::Message(INFO,"dw numeric \n",dw_numeric);
     130           0 :                     Util::Message(INFO,"error norm \n",relnorm);
     131             :                 }
     132           0 :                 return 1;
     133             :             }   
     134             :         }
     135          22 :         return 0;
     136             :     }
     137             : 
     138             :     template <class T>
     139          22 :     static int DerivativeTest2(int verbose = 0)
     140             :     {
     141         242 :         for (int iter = 0; iter < 10; iter++)
     142             :         {
     143         220 :             T model = T::Random();
     144             : 
     145         220 :             Set::Scalar dx = 1E-8, tol = 1E-4;
     146         220 :             Set::Matrix F = Set::Matrix::Random();
     147         565 :             while (F.determinant() < 0.1) F = Set::Matrix::Random(); // Ensure that F in GL(3)
     148             : 
     149         220 :             Set::Matrix4<AMREX_SPACEDIM,Set::Sym::Major> ddw_exact = model.DDW(F);
     150         220 :             Set::Matrix4<AMREX_SPACEDIM,Set::Sym::Major> ddw_numeric = Set::Matrix4<AMREX_SPACEDIM,T::sym>::Zero();
     151         770 :             for (int i = 0; i < AMREX_SPACEDIM; i++)
     152        1980 :                 for (int j = 0; j < AMREX_SPACEDIM; j++)
     153        5280 :                     for (int k = 0; k < AMREX_SPACEDIM; k++)
     154       14520 :                         for (int l = 0; l < AMREX_SPACEDIM; l++)
     155             :                         {
     156       10670 :                             Set::Matrix dF = Set::Matrix::Zero();
     157       10670 :                             dF(k,l) = dx;
     158       21340 :                             ddw_numeric(i,j,k,l) = (model.DW(F+dF) - model.DW(F-dF))(i,j) / (2.0 * dx);
     159             :                         }
     160             :             Set::Matrix4<AMREX_SPACEDIM,Set::Sym::Major> error = ddw_numeric-ddw_exact;
     161         220 :             Set::Scalar relnorm = error.Norm()/ddw_numeric.Norm();
     162         220 :             if (relnorm > tol || std::isnan(relnorm) || std::isinf(relnorm))
     163             :             {
     164           0 :                 if (verbose)
     165             :                 {
     166           0 :                     Util::Message(INFO,"F \n",F);
     167           0 :                     Util::Message(INFO,"det(F) = ",F.determinant());
     168           0 :                     Util::Message(INFO,"ddw exact \n",ddw_exact);
     169           0 :                     Util::Message(INFO,"ddw numeric \n",ddw_numeric);
     170           0 :                     Util::Message(INFO,"ddw difference \n",ddw_exact - ddw_numeric);
     171           0 :                     Util::Message(INFO,"error norm \n",relnorm);
     172             :                 }
     173           0 :                 return 1;
     174             :             }   
     175             :         }
     176          22 :         return 0;
     177             :     }
     178             : 
     179             :     template <class T>
     180           8 :     static int MaterialFrameIndifference(int verbose = 0)
     181             :     {
     182             :         if (T::kinvar != Model::Solid::KinematicVariable::F)
     183             :             Util::Abort(INFO,"Attempting to test material frame indifference in a non-finite-kinematics model will fail");
     184             : 
     185          88 :         for (int iter = 0; iter < 10; iter++)
     186             :         {
     187          80 :             T model = T::Random();
     188             : 
     189          80 :             Set::Scalar tol = 1E-4;
     190          80 :             Set::Matrix F = Set::Matrix::Random();
     191         586 :             while (
     192         746 :                 F.determinant() < 0.5 || // skip if determinant negative or too small
     193          80 :                 F.determinant() > 2 // also skip if determinant too large
     194             :                 )
     195         586 :                 F = Set::Matrix::Random(); // Ensure that F is reasonably well-behaved.
     196             : 
     197          80 :             Set::Scalar W_unrotated = model.W(F);
     198             : 
     199         880 :             for (int jter = 0; jter < 10; jter++)
     200             :             {
     201             :                 #if AMREX_SPACEDIM == 2
     202         400 :                 Set::Scalar theta = 2.0 * Set::Constant::Pi * Util::Random();
     203         400 :                 Set::Matrix R;
     204         400 :                 R(0,0) =  cos(theta);
     205         400 :                 R(0,1) =  sin(theta);
     206         400 :                 R(1,0) = -sin(theta);
     207         400 :                 R(1,1) =  cos(theta);
     208             :                 #elif AMREX_SPACEDIM == 3
     209         400 :                 Set::Scalar phi1 = 2.0 * Set::Constant::Pi *(Util::Random() - 0.5);
     210         400 :                 Set::Scalar Phi  = Set::Constant::Pi * Util::Random();
     211         400 :                 Set::Scalar phi2 = 2.0 * Set::Constant::Pi *(Util::Random() - 0.5);
     212         400 :                 Eigen::Matrix3d R;
     213         400 :                 R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
     214             :                     Eigen::AngleAxisd(Phi,  Eigen::Vector3d::UnitZ()) *
     215             :                     Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
     216             :                 #endif
     217             : 
     218        1600 :                 Util::Assert(INFO,TEST( fabs(R.determinant() - 1.0) < tol ));
     219        1600 :                 Util::Assert(INFO,TEST( fabs((R.transpose() * R - Set::Matrix::Identity()).norm()) < tol ));
     220             :                 
     221         800 :                 Set::Scalar W_rotated = model.W(R*F);
     222         800 :                 Set::Scalar error = fabs(W_rotated - W_unrotated) / fabs(W_rotated + W_unrotated + tol);
     223             : 
     224         800 :                 if (error > tol)
     225             :                 {
     226           0 :                     if (verbose)
     227             :                     {
     228           0 :                         Util::Message(INFO,"F = \n",F);
     229           0 :                         Util::Message(INFO,"R = \n",R);
     230           0 :                         Util::Message(INFO,"W unrotated = ",W_unrotated);
     231           0 :                         Util::Message(INFO,"W rotated = ",W_rotated);
     232             :                     }
     233           0 :                     return 1;
     234             :                 }
     235             :             }
     236             :         }
     237           8 :         return 0;
     238             :     }
     239             : 
     240             : };
     241             : 
     242             : }
     243             : }
     244             : 
     245             : 
     246             : #endif

Generated by: LCOV version 1.14