Alamo
Solid.H
Go to the documentation of this file.
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#include <type_traits>
19
20#include "Set/Set.H"
21#include "Set/Matrix4.H"
23#include "Set/Matrix4_Full.H"
25#include "Set/Matrix4_Major.H"
27#include "Util/Util.H"
28
29namespace Model
30{
31namespace Solid
32{
33
35
36template<Set::Sym SYM>
37class Solid
38{
39public:
40 Solid() = default;
41
42 ~Solid() = default;
43
44 static constexpr Set::Sym sym = SYM;
45
46 Set::Scalar W(const Set::Matrix &) const
47 {Util::Abort(INFO,"W not implemented"); return 0.0;};
48 Set::Matrix DW(const Set::Matrix &) const
49 {Util::Abort(INFO,"DW not implemented"); return Set::Matrix::Zero();};
52
53 void Advance(Set::Scalar /*dt*/, Set::Matrix /*strain*/, Set::Matrix /*stress*/, Set::Scalar /*time*/) {}
54
55 // Todo: implement for all models and make this pure virtual
56 bool ContainsNan() {return true;};
57
58
59public:
61
62
63 friend std::ostream& operator<<(std::ostream &out, const Solid &a)
64 {
65 a.Print(out);
66 return out;
67 }
68 void Print(std::ostream &out) const
69 {
70 out << "No print function written for this model.";
71 }
72
73public:
74 template <class T>
75 static int PODTest(int verbose = 0)
76 {
77 int ret = 0;
78 if (!std::is_trivially_copyable<T>::value)
79 {
80 if (verbose) Util::Test::SubWarning("Model is not trivially copyable");
81 }
82 if (std::has_virtual_destructor<T>::value)
83 {
84 if (verbose) Util::Test::SubWarning("Model has a virtual destructor");
85 }
86 if (std::is_polymorphic<T>::value)
87 {
88 if (verbose) Util::Test::SubWarning("Model is polymorphic");
89 }
90 if (!std::is_standard_layout<T>::value)
91 {
92 if (verbose) Util::Test::SubWarning("Model does not have standard layout.");
93 }
94 return ret;
95 }
96
97
98 template <class T>
99 static int ArithmeticTest(int verbose = 0)
100 {
101 const T z = T::Zero();
102 if (!(z==z) && verbose)
103 {
104 Util::Message(INFO,"Zero() failed: z = \n",z); return 1;
105 }
106
107 const T a = T::Random();
108 if (!(a==a) && verbose)
109 {
110 Util::Message(INFO,"Random() failed: a = \n",a); return 1;
111 }
112
113 T c = a;
114 if (!(c==a) && verbose) {Util::Message(INFO); return 1;}
115 c = 1.0 * a;
116 if (!(c==a) && verbose) {Util::Message(INFO); return 1;}
117 c = 0.0 * a;
118 if (!(c==z) && verbose)
119 {
120 Util::Message(INFO,"0.0*a = \n",c);
121 Util::Message(INFO,"Zero() returns \n",z);
122 return 1;
123 }
124
125 // Todo: add some more arithmetic checks in here
126
127 return 0;
128 }
129
130 template <class T>
131 static int DerivativeTest1(int verbose = 0)
132 {
133 for (int iter = 0; iter < 10; iter++)
134 {
135 T model = T::Random();
136
137 Set::Scalar dx = 1E-8, tol = 1E-6;
138
139 Set::Matrix F = Set::Matrix::Random();
140 while (F.determinant() < 0.1) F = Set::Matrix::Random(); // Ensure that F in GL(3)
141
142 Set::Matrix dw_exact = model.DW(F);
143 Set::Matrix dw_numeric = Set::Matrix::Zero();
144 for (int i = 0; i < AMREX_SPACEDIM; i++)
145 for (int j = 0; j < AMREX_SPACEDIM; j++)
146 {
147 Set::Matrix dF = Set::Matrix::Zero();
148 dF(i,j) = dx;
149 dw_numeric(i,j) = (model.W(F+dF) - model.W(F-dF)) / (2.0 * dx);
150 }
151 Set::Scalar relnorm = (dw_numeric-dw_exact).norm()/(dw_numeric.norm());
152 if (relnorm > tol || std::isnan(relnorm) || std::isinf(relnorm))
153 {
154 if (verbose)
155 {
156 Util::Message(INFO,"F \n",F);
157 Util::Message(INFO,"det(F) = ",F.determinant());
158 Util::Message(INFO,"dw exact \n",dw_exact);
159 Util::Message(INFO,"dw numeric \n",dw_numeric);
160 Util::Message(INFO,"error norm \n",relnorm);
161 }
162 return 1;
163 }
164 }
165 return 0;
166 }
167
168 template <class T>
169 static int DerivativeTest2(int verbose = 0)
170 {
171 for (int iter = 0; iter < 10; iter++)
172 {
173 T model = T::Random();
174
175 Set::Scalar dx = 1E-8, tol = 1E-4;
176 Set::Matrix F = Set::Matrix::Random();
177 while (F.determinant() < 0.1) F = Set::Matrix::Random(); // Ensure that F in GL(3)
178
179 Set::Matrix4<AMREX_SPACEDIM,Set::Sym::Major> ddw_exact = model.DDW(F);
181 for (int i = 0; i < AMREX_SPACEDIM; i++)
182 for (int j = 0; j < AMREX_SPACEDIM; j++)
183 for (int k = 0; k < AMREX_SPACEDIM; k++)
184 for (int l = 0; l < AMREX_SPACEDIM; l++)
185 {
186 Set::Matrix dF = Set::Matrix::Zero();
187 dF(k,l) = dx;
188 ddw_numeric(i,j,k,l) = (model.DW(F+dF) - model.DW(F-dF))(i,j) / (2.0 * dx);
189 }
190 Set::Matrix4<AMREX_SPACEDIM,Set::Sym::Major> error = ddw_numeric-ddw_exact;
191 Set::Scalar relnorm = error.Norm()/ddw_numeric.Norm();
192 if (relnorm > tol || std::isnan(relnorm) || std::isinf(relnorm))
193 {
194 if (verbose)
195 {
196 Util::Message(INFO,"F \n",F);
197 Util::Message(INFO,"det(F) = ",F.determinant());
198 Util::Message(INFO,"ddw exact \n",ddw_exact);
199 Util::Message(INFO,"ddw numeric \n",ddw_numeric);
200 Util::Message(INFO,"ddw difference \n",ddw_exact - ddw_numeric);
201 Util::Message(INFO,"error norm \n",relnorm);
202 }
203 return 1;
204 }
205 }
206 return 0;
207 }
208
209 template <class T>
210 static int MaterialFrameIndifference(int verbose = 0)
211 {
212 if (T::kinvar != Model::Solid::KinematicVariable::F)
213 Util::Abort(INFO,"Attempting to test material frame indifference in a non-finite-kinematics model will fail");
214
215 for (int iter = 0; iter < 10; iter++)
216 {
217 T model = T::Random();
218
219 Set::Scalar tol = 1E-4;
220 Set::Matrix F = Set::Matrix::Random();
221 while (
222 F.determinant() < 0.5 || // skip if determinant negative or too small
223 F.determinant() > 2 // also skip if determinant too large
224 )
225 F = Set::Matrix::Random(); // Ensure that F is reasonably well-behaved.
226
227 Set::Scalar W_unrotated = model.W(F);
228
229 for (int jter = 0; jter < 10; jter++)
230 {
231 #if AMREX_SPACEDIM == 2
233 Set::Matrix R;
234 R(0,0) = cos(theta);
235 R(0,1) = sin(theta);
236 R(1,0) = -sin(theta);
237 R(1,1) = cos(theta);
238 #elif AMREX_SPACEDIM == 3
239 Set::Scalar phi1 = 2.0 * Set::Constant::Pi *(Util::Random() - 0.5);
241 Set::Scalar phi2 = 2.0 * Set::Constant::Pi *(Util::Random() - 0.5);
242 Eigen::Matrix3d R;
243 R = Eigen::AngleAxisd(phi2, Eigen::Vector3d::UnitX()) *
244 Eigen::AngleAxisd(Phi, Eigen::Vector3d::UnitZ()) *
245 Eigen::AngleAxisd(phi1, Eigen::Vector3d::UnitX());
246 #endif
247
248 Util::Assert(INFO,TEST( fabs(R.determinant() - 1.0) < tol ));
249 Util::Assert(INFO,TEST( fabs((R.transpose() * R - Set::Matrix::Identity()).norm()) < tol ));
250
251 Set::Scalar W_rotated = model.W(R*F);
252 Set::Scalar error = fabs(W_rotated - W_unrotated) / fabs(W_rotated + W_unrotated + tol);
253
254 if (error > tol)
255 {
256 if (verbose)
257 {
258 Util::Message(INFO,"F = \n",F);
259 Util::Message(INFO,"R = \n",R);
260 Util::Message(INFO,"W unrotated = ",W_unrotated);
261 Util::Message(INFO,"W rotated = ",W_rotated);
262 }
263 return 1;
264 }
265 }
266 }
267 return 0;
268 }
269
270};
271
272}
273}
274
275
276#endif
#define TEST(x)
Definition Util.H:24
#define INFO
Definition Util.H:23
void Advance(Set::Scalar, Set::Matrix, Set::Matrix, Set::Scalar)
Definition Solid.H:53
bool ContainsNan()
Definition Solid.H:56
static int MaterialFrameIndifference(int verbose=0)
Definition Solid.H:210
Set::Scalar W(const Set::Matrix &) const
Definition Solid.H:46
static int PODTest(int verbose=0)
Definition Solid.H:75
static int DerivativeTest2(int verbose=0)
Definition Solid.H:169
Set::Matrix4< AMREX_SPACEDIM, SYM > DDW(const Set::Matrix &) const
Definition Solid.H:50
static int ArithmeticTest(int verbose=0)
Definition Solid.H:99
Set::Matrix DW(const Set::Matrix &) const
Definition Solid.H:48
friend std::ostream & operator<<(std::ostream &out, const Solid &a)
Definition Solid.H:63
void Print(std::ostream &out) const
Definition Solid.H:68
static const KinematicVariable kinvar
Definition Solid.H:60
static constexpr Set::Sym sym
Definition Solid.H:44
static int DerivativeTest1(int verbose=0)
Definition Solid.H:131
KinematicVariable
Definition Solid.H:34
const Set::Scalar Pi
Definition Set.cpp:13
Sym
Definition Matrix4.H:12
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:22
void SubWarning(std::string testname)
Definition Util.cpp:346
void Abort(const char *msg)
Definition Util.cpp:243
AMREX_FORCE_INLINE void Assert(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:57
Set::Scalar Random()
Definition Set.cpp:34
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:128