Alamo
GB.H
Go to the documentation of this file.
1#ifndef MODEL_INTERFACE_GB_H
2#define MODEL_INTERFACE_GB_H
3
4#include <AMReX.H>
5#include <AMReX_AmrCore.H>
6
7#include <eigen3/Eigen/Eigenvalues>
8
9#include <iostream>
10#include <fstream>
11
12namespace Model
13{
14namespace Interface
15{
16namespace GB
17{
18class GB
19{
20public:
21 GB() {};
22 virtual ~GB() {};
23 virtual Set::Scalar W(const Set::Scalar theta) const = 0;
24 virtual Set::Scalar DW(const Set::Scalar theta) const = 0;
25 virtual Set::Scalar DDW(const Set::Scalar theta) const = 0;
26 virtual Set::Scalar W(const Set::Vector& a_n) const { return W(atan2(a_n(1), a_n(0))); };
27 virtual Set::Scalar DW(const Set::Vector&, const Set::Vector&) const { return NAN; };
28 virtual Set::Scalar DDW(const Set::Vector&, const Set::Vector&) const { return NAN; };
29
30 void ExportToFile(std::string filename, amrex::Real dTheta)
31 {
32 std::ofstream outFile;
33 outFile.open(filename);
34
35 for (amrex::Real theta = 0; theta < 2 * pi; theta = theta + dTheta)
36 {
37 outFile << theta << " " << W(theta) << std::endl;
38 }
39 outFile.close();
40 }
41
43
44 // Return anisotropic driving force, regularization
45 std::tuple<Set::Scalar, Set::Scalar>
47 {
48#if AMREX_SPACEDIM == 2
49 Set::Scalar Theta = atan2(Deta(1), Deta(0));
50 Set::Scalar sigma = /*pf.l_gb*0.75**/W(Theta);
51 Set::Scalar Dsigma = /*pf.l_gb*0.75**/DW(Theta);
52 Set::Scalar DDsigma = /*pf.l_gb*0.75**/DDW(Theta);
53 Set::Scalar sinTheta = sin(Theta);
54 Set::Scalar cosTheta = cos(Theta);
55 Set::Scalar sin2Theta = sinTheta * sinTheta;
56 Set::Scalar cos2Theta = cosTheta * cosTheta;
57 Set::Scalar cosThetasinTheta = cosTheta * sinTheta;
58
59 Set::Scalar boundary_term =
60 -(sigma * DDeta.trace() +
61 Dsigma * (cos(2.0 * Theta) * DDeta(0, 1) + 0.5 * sin(2.0 * Theta) * (DDeta(1, 1) - DDeta(0, 0))) +
62 0.5 * DDsigma * (sin2Theta * DDeta(0, 0) - 2. * cosThetasinTheta * DDeta(0, 1) + cos2Theta * DDeta(1, 1)));
63
64 Set::Scalar curvature_term =
65 DDDDeta(0, 0, 0, 0) * (sin2Theta * sin2Theta) +
66 DDDDeta(0, 0, 0, 1) * (4.0 * sin2Theta * cosThetasinTheta) +
67 DDDDeta(0, 0, 1, 1) * (6.0 * sin2Theta * cos2Theta) +
68 DDDDeta(0, 1, 1, 1) * (4.0 * cosThetasinTheta * cos2Theta) +
69 DDDDeta(1, 1, 1, 1) * (cos2Theta * cos2Theta);
70 return std::make_tuple(boundary_term, curvature_term);
71
72#elif AMREX_SPACEDIM == 3
73
74 Set::Vector normal = Deta / Deta.lpNorm<2>();
75
76 // GRAHM-SCHMIDT PROCESS to get orthonormal basis
77 const Set::Vector e1(1, 0, 0), e2(0, 1, 0), e3(0, 0, 1);
78 Set::Vector _t2, _t3;
79 if (fabs(normal(0)) > fabs(normal(1)) && fabs(normal(0)) > fabs(normal(2)))
80 {
81 _t2 = e2 - normal.dot(e2) * normal; _t2 /= _t2.lpNorm<2>();
82 _t3 = e3 - normal.dot(e3) * normal - _t2.dot(e3) * _t2; _t3 /= _t3.lpNorm<2>();
83 }
84 else if (fabs(normal(1)) > fabs(normal(0)) && fabs(normal(1)) > fabs(normal(2)))
85 {
86 _t2 = e1 - normal.dot(e1) * normal; _t2 /= _t2.lpNorm<2>();
87 _t3 = e3 - normal.dot(e3) * normal - _t2.dot(e3) * _t2; _t3 /= _t3.lpNorm<2>();
88 }
89 else
90 {
91 _t2 = e1 - normal.dot(e1) * normal; _t2 /= _t2.lpNorm<2>();
92 _t3 = e2 - normal.dot(e2) * normal - _t2.dot(e2) * _t2; _t3 /= _t3.lpNorm<2>();
93 }
94
95 // Compute Hessian projected into tangent space (spanned by _t1,_t2)
96 Eigen::Matrix2d DDeta2D;
97 DDeta2D <<
98 _t2.dot(DDeta * _t2), _t2.dot(DDeta * _t3),
99 _t3.dot(DDeta * _t2), _t3.dot(DDeta * _t3);
100 Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver(2);
101 eigensolver.computeDirect(DDeta2D);
102 Eigen::Matrix2d eigenvecs = eigensolver.eigenvectors();
103
104 // Compute tangent vectors embedded in R^3
105 Set::Vector t2 = _t2 * eigenvecs(0, 0) + _t3 * eigenvecs(0, 1),
106 t3 = _t2 * eigenvecs(1, 0) + _t3 * eigenvecs(1, 1);
107
108 // Compute components of second Hessian in t2,t3 directions
109 Set::Scalar DH2 = 0.0, DH3 = 0.0;
110 Set::Scalar DH23 = 0.0;
111 for (int p = 0; p < 3; p++)
112 for (int q = 0; q < 3; q++)
113 for (int r = 0; r < 3; r++)
114 for (int s = 0; s < 3; s++)
115 {
116 DH2 += DDDDeta(p, q, r, s) * t2(p) * t2(q) * t2(r) * t2(s);
117 DH3 += DDDDeta(p, q, r, s) * t3(p) * t3(q) * t3(r) * t3(s);
118 DH23 += DDDDeta(p, q, r, s) * t2(p) * t2(q) * t3(r) * t3(s);
119 }
120
121 Set::Scalar sigma = W(normal);
122 Set::Scalar DDK2 = DDW(normal, _t2);
123 Set::Scalar DDK3 = DDW(normal, _t3);
124
125 // GB energy anisotropy term
126 Set::Scalar gbenergy_df = -sigma * DDeta.trace() - DDK2 * DDeta2D(0, 0) - DDK3 * DDeta2D(1, 1);
127
128 // Second order curvature term
129 Set::Scalar reg_df = NAN;
130 if (regularization == Regularization::Wilhelm) reg_df = DH2 + DH3 + 2.0 * DH23;
131 else if (regularization == Regularization::K23) reg_df = DH2 + DH3;
132
133 return std::make_tuple(gbenergy_df, reg_df);
134
135#endif
136 }
137
138
139protected:
140 static constexpr amrex::Real pi = 3.14159265359;
142};
143}
144}
145}
146
147#endif
virtual Set::Scalar W(const Set::Scalar theta) const =0
virtual Set::Scalar W(const Set::Vector &a_n) const
Definition GB.H:26
Regularization regularization
Definition GB.H:141
virtual ~GB()
Definition GB.H:22
std::tuple< Set::Scalar, Set::Scalar > DrivingForce(const Set::Vector &Deta, const Set::Matrix &DDeta, const Set::Matrix4< AMREX_SPACEDIM, Set::Sym::Full > &DDDDeta)
Definition GB.H:46
void ExportToFile(std::string filename, amrex::Real dTheta)
Definition GB.H:30
virtual Set::Scalar DW(const Set::Scalar theta) const =0
virtual Set::Scalar DDW(const Set::Scalar theta) const =0
static constexpr amrex::Real pi
Definition GB.H:140
virtual Set::Scalar DW(const Set::Vector &, const Set::Vector &) const
Definition GB.H:27
virtual Set::Scalar DDW(const Set::Vector &, const Set::Vector &) const
Definition GB.H:28
amrex::Real Scalar
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:20
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:23