Alamo
Dendrite.H
Go to the documentation of this file.
1//
2// This is a BASIC phase field method for dendritic growth as described in
3// "A Numerical Approach to Three-Dimensional Dendritic Solidification" by Ryo Kobayashi (1994)
4// Reference: https://doi.org/10.1080/10586458.1994.10504577
5//
6
7#ifndef INTEGRATOR_DENDRITE_H // Include guards
8#define INTEGRATOR_DENDRITE_H //
9
10#include <iostream>
11#include <fstream>
12#include <iomanip>
13
14#include "AMReX.H"
15#include "AMReX_ParallelDescriptor.H"
16#include "AMReX_ParmParse.H"
17
18#include "IO/ParmParse.H"
20#include "BC/Constant.H"
21#include "IC/IC.H"
22#include "IC/Sphere.H"
23#include "IC/Constant.H"
24#include "IC/Expression.H"
25#include "Numeric/Stencil.H"
26
27namespace Integrator
28{
29class Dendrite : virtual public Integrator
30{
31public:
32 static constexpr const char* name = "dendrite";
33
34 // Empty constructor
36 {}
37
38 // Constructor that triggers parse
40 {
41 Parse(*this, pp);
42 }
43
45 {
46 delete ic_temp;
47 delete ic_phi;
48 delete bc_temp;
49 delete bc_phi;
50 }
51
52 static void Parse(Dendrite& value, IO::ParmParse& pp)
53 {
54 pp_query_required("alpha", value.alpha); // Pre-multiplier of "m" barrier height
55 pp_query_required("delta", value.delta); // Anisotropy factor
56 pp_query_required("gamma", value.gamma); // Anisotropic temperature coupling factor
57 pp_query_default("diffusion", value.diffusion,1.0); // Thermal constant
58
59 pp_query_required("eps", value.eps); // Diffuse boundary width
60 pp_query_required("tau", value.tau); // Diffusive timescale
61
62 pp_query_default("theta", value.theta, 0.0); // Orientation about z axis (Deg)
63
64 Eigen::Matrix3d R3d;
65 R3d = Eigen::AngleAxisd(value.theta*Set::Constant::Pi/180.0, Eigen::Vector3d::UnitZ());
66 value.R = Set::reduce(R3d);
67
68 // Refinement criteria for temperature
69 pp_query_default("heat.refinement_threshold", value.refinement_threshold_temp, 0.01);
70 // Refinement criteria for phi
71 pp_query_default("phi.refinement_threshold", value.refinement_threshold_phi, 0.01);
72
73 // Expressions for ICs
74 value.ic_temp = new IC::Expression(value.geom, pp, "ic.temp");
75 value.ic_phi = new IC::Expression(value.geom, pp, "ic.phi");
76
77 // boundary conditions for temperature field
78 pp.select_default<BC::Constant>("bc.temp", value.bc_temp, 1);
79 // boundary conditions for :math:`\phi` field
80 pp.select_default<BC::Constant>("bc.phi", value.bc_phi, 1);
81
82 value.RegisterNewFab(value.temp_mf, value.bc_temp, value.number_of_components, value.number_of_ghost_cells, "Temp", true);
83 value.RegisterNewFab(value.temp_old_mf, value.bc_temp, value.number_of_components, value.number_of_ghost_cells, "Temp_old", false);
84 value.RegisterNewFab(value.phi_mf, value.bc_phi, value.number_of_components, value.number_of_ghost_cells, "phi", true);
85 value.RegisterNewFab(value.phi_old_mf, value.bc_phi, value.number_of_components, value.number_of_ghost_cells, "phi_old", false);
86 }
87protected:
88
89 // Use the ic object to initialize the temperature field
90 void Initialize(int lev)
91 {
96 }
97
98
99 // Integrate the heat equation
100 void Advance(int lev, Set::Scalar /*time*/, Set::Scalar dt)
101 {
102 // Swap the old temp fab and the new temp fab so we use
103 // the new one.
104 std::swap(*temp_mf[lev], *temp_old_mf[lev]);
105 std::swap(*phi_mf[lev], *phi_old_mf[lev]);
106
107 // Get the cell size corresponding to this level
108 const Set::Scalar* DX = geom[lev].CellSize();
109
110 // Iterate over all of the patches on this level
111 for (amrex::MFIter mfi(*temp_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
112 {
113 // Get the box (index dimensions) for this patch
114 const amrex::Box& bx = mfi.tilebox();
115
116 // Get an array-accessible handle to the data on this patch.
117 amrex::Array4<const Set::Scalar> const& temp = (*temp_old_mf[lev]).array(mfi);
118 amrex::Array4<Set::Scalar> const& temp_new = (*temp_mf[lev]).array(mfi);
119 amrex::Array4<const Set::Scalar> const& phi = (*phi_old_mf[lev]).array(mfi);
120 amrex::Array4<Set::Scalar> const& phi_new = (*phi_mf[lev]).array(mfi);
121
122 // Iterate over the grid on this patch
123 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
124 {
125
126 Set::Vector gradphi = Numeric::Gradient(phi, i, j, k, 0, DX);
127
128 gradphi = R * gradphi;
129
130 //
131 // Calculate anisotropy function
132 // [ equation 2.12 in reference]
133 //
134 Set::Scalar v44 = AMREX_D_TERM(
135 gradphi(0) * gradphi(0) * gradphi(0) * gradphi(0),
136 +gradphi(1) * gradphi(1) * gradphi(1) * gradphi(1),
137 +gradphi(2) * gradphi(2) * gradphi(2) * gradphi(2));
138 Set::Scalar v22 = gradphi.squaredNorm(); v22 *= v22;
139 Set::Scalar sigma = 1.0 - delta * (1.0 - v44 / (v22 + 1E-12));
140
141 //
142 // Calculate anisotropic barrier height
143 // [ unnumbered equation on page 67 in the reference ]
144 //
145 Set::Scalar m = -(alpha / Set::Constant::Pi) * std::atan(gamma * sigma * temp(i, j, k));
146
147
148 //
149 // Evolve order paramter
150 // [ equation 2.10 in the reference ]
151 //
152 Set::Scalar lapphi = Numeric::Laplacian(phi, i, j, k, 0, DX);
153 Set::Scalar Dphi = (eps * eps * lapphi + phi(i, j, k) * (1.0 - phi(i, j, k)) * (phi(i, j, k) - 0.5 + m)) / tau;
154 phi_new(i, j, k) = phi(i, j, k) + dt * Dphi;
155
156 //
157 // Evolve temperature
158 // [ equation 2.11 in the reference ]
159 //
160 Set::Scalar laptemp = Numeric::Laplacian(temp, i, j, k, 0, DX);
161 temp_new(i, j, k) = temp(i, j, k) + dt * (diffusion*laptemp + Dphi);
162 });
163 }
164 }
165
166 // Tag cells for mesh refinement based on temperature gradient
167 void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar /*time*/, int /*ngrow*/)
168 {
169 // Get cell dimensions as done above.
170 const Set::Scalar* DX = geom[lev].CellSize();
171 // Calculate the diagonal.
172 Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
173
174 // Iterate over the patches on this level
175 for (amrex::MFIter mfi(*temp_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
176 {
177 // Get the box and handles as done above.
178 const amrex::Box& bx = mfi.tilebox();
179 amrex::Array4<char> const& tags = a_tags.array(mfi);
180 amrex::Array4<Set::Scalar> const& temp = (*temp_mf[lev]).array(mfi);
181 amrex::Array4<Set::Scalar> const& phi = (*phi_mf[lev]).array(mfi);
182
183 // Iterate over the grid as done above.
184 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
185 {
186 // Calculate the temperature gradient.
187 Set::Vector grad_temp = Numeric::Gradient(temp, i, j, k, 0, DX);
188 Set::Vector grad_phi = Numeric::Gradient(phi, i, j, k, 0, DX);
189
190 // Is the gradient * cell_size too big? If so, then
191 // mark this cell as needing refinement.
192 if (grad_temp.lpNorm<2>() * dr > refinement_threshold_temp)
193 tags(i, j, k) = amrex::TagBox::SET;
194 if (grad_phi.lpNorm<2>() * dr > refinement_threshold_phi)
195 tags(i, j, k) = amrex::TagBox::SET;
196 });
197 }
198 }
199
200protected:
205
208
209private:
210 int number_of_components = 1; // Number of components
211 int number_of_ghost_cells = 1; // Number of ghost cells
212
213 // calculation of m
215 // evolution of p
217 // orientation
219 Set::Matrix R = Set::Matrix::Identity();
220
221 Set::Scalar refinement_threshold_temp = NAN; // Criterion for cell refinement
222 Set::Scalar refinement_threshold_phi = NAN; // Criterion for cell refinement
223
226};
227} // namespace Integrator
228#endif
#define pp_query_required(...)
Definition ParmParse.H:99
#define pp_query_default(...)
Definition ParmParse.H:100
Definition BC.H:42
Pure abstract IC object from which all other IC objects inherit.
Definition IC.H:23
void Initialize(const int &a_lev, Set::Field< T > &a_field, Set::Scalar a_time=0.0)
Definition IC.H:39
void select_default(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:720
Set::Field< Set::Scalar > temp_old_mf
Definition Dendrite.H:202
Set::Scalar tau
Definition Dendrite.H:216
Set::Scalar alpha
Definition Dendrite.H:214
Dendrite(IO::ParmParse &pp)
Definition Dendrite.H:39
Set::Scalar refinement_threshold_temp
Definition Dendrite.H:221
Set::Field< Set::Scalar > phi_mf
Definition Dendrite.H:203
IC::IC< Set::Scalar > * ic_phi
Definition Dendrite.H:224
Set::Field< Set::Scalar > phi_old_mf
Definition Dendrite.H:204
Set::Scalar refinement_threshold_phi
Definition Dendrite.H:222
Set::Field< Set::Scalar > temp_mf
Definition Dendrite.H:201
static void Parse(Dendrite &value, IO::ParmParse &pp)
Definition Dendrite.H:52
void Initialize(int lev)
Definition Dendrite.H:90
static constexpr const char * name
Definition Dendrite.H:32
IC::IC< Set::Scalar > * ic_temp
Definition Dendrite.H:224
Set::Field< Set::Scalar > & eta_mf
Definition Dendrite.H:206
BC::BC< Set::Scalar > * bc_phi
Definition Dendrite.H:225
Set::Scalar gamma
Definition Dendrite.H:214
void Advance(int lev, Set::Scalar, Set::Scalar dt)
Definition Dendrite.H:100
BC::BC< Set::Scalar > * bc_temp
Definition Dendrite.H:225
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int)
Definition Dendrite.H:167
Set::Scalar theta
Definition Dendrite.H:218
Set::Scalar delta
Definition Dendrite.H:214
Set::Scalar diffusion
Definition Dendrite.H:214
Set::Field< Set::Scalar > & eta_old_mf
Definition Dendrite.H:207
Set::Scalar eps
Definition Dendrite.H:216
void RegisterNewFab(Set::Field< Set::Scalar > &new_fab, BC::BC< Set::Scalar > *new_bc, int ncomp, int nghost, std::string name, bool writeout, std::vector< std::string > suffix={})
Add a new cell-based scalar field.
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
Definition Integrator.H:381
Collection of numerical integrator objects.
Definition AllenCahn.H:41
AMREX_FORCE_INLINE Set::Scalar Laplacian(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > &stencil=DefaultType)
Definition Stencil.H:546
AMREX_FORCE_INLINE Set::Vector Gradient(const amrex::Array4< const Set::Scalar > &f, const int &i, const int &j, const int &k, const int &m, const Set::Scalar dx[AMREX_SPACEDIM], std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType)
Definition Stencil.H:672
static const Set::Scalar Pi
Definition Set.H:286
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
AMREX_FORCE_INLINE Set::Matrix reduce(const Set::Matrix3d &in)
Definition Base.H:28