Alamo
AllenCahn.H
Go to the documentation of this file.
1//
2// This is a simple implementation of an Allen-Cahn equation governed by
3//
4// .. math::
5//
6// \frac{\partial\alpha}{\partial t} =
7// - L \Big(\frac{\lambda}{\epsilon}(2.0\alpha
8// - 6\alpha^2 + 4\alpha^3) + \epsilon\,\kappa\,\Delta \alpha \Big)
9//
10// where :math:`\alpha(x,t)` is the order parameter.
11//
12
13#ifndef INTEGRATOR_ALLENCAHN_H // Include guards
14#define INTEGRATOR_ALLENCAHN_H //
15
16// Standard library includes
17#include <iostream>
18#include <fstream>
19#include <iomanip>
20
21// AMReX Includes
22#include "AMReX.H"
23#include "AMReX_ParallelDescriptor.H"
24#include "AMReX_ParmParse.H"
25
26// Alamo Includes
27#include "IO/ParmParse.H"
29#include "BC/Constant.H"
30#include "IC/IC.H"
31#include "IC/Sphere.H"
32#include "IC/Constant.H"
33#include "IC/Expression.H"
34#include "IC/BMP.H"
35#include "IC/PNG.H"
36#include "IC/PSRead.H"
37#include "Numeric/Stencil.H"
38#include "IC/Random.H"
39#include "Unit/Unit.H"
40
41namespace Integrator
42{
43
44/// This is the definition of the Allen Cahn class
45class AllenCahn : virtual public Integrator
46{
47public:
48 static constexpr const char* name = "allencahn";
49
50 // Empty constructor
52 {}
53
54 // Constructor that triggers parse
56 {
57 Parse(*this, pp);
58 }
59
61 {
62 delete ic;
63 delete bc;
64 }
65
66 // The Parse function initializes the AllenCahn object using
67 // a parser, pp.
68 // Note that this is a static function, which means it does not have
69 // direct access to member variables. Instead, it initializes the variables
70 // inside the argument, "value", and so all references to member items are
71 // prefixed by "value."
72 static void Parse(AllenCahn& value, IO::ParmParse& pp)
73 {
74 // Criterion for mesh refinement [0.01]
75 pp_query_default("refinement_threshold", value.refinement_threshold, 0.01);
76
77 // Value for :math:`L` (mobility)
78 pp.query_default("ch.L",value.ch.L, "1.0", 1/ Unit::Pressure()/Unit::Time());
79 // Value for :math:`\epsilon` (diffuse boundary width)
80 // pp.query_default("ch.eps",value.ch.eps, "0.1", Unit::Length());
81 // Value for :math:`\kappa` (Interface energy parameter)
82 pp.query_default("ch.grad",value.ch.kappa, "1.0", Unit::Energy()/Unit::Length());
83 // Value for :math:`\lambda` (Chemical potential coefficient)
84 pp_query_default("ch.chempot",value.ch.lambda, "1.0", Unit::Pressure());
85 // Force directional growth: 0=no growth, 1=only positive, -1=only negative
86 pp_query_validate("ch.direction",value.ch.direction, {0,1,-1});
87 // Time to start forcing directional growth
88 pp_query_default("ch.direction_tstart",value.ch.direction_tstart, 0.0);
89
90
91 std::pair<std::string,Set::Scalar> ch_coeffs[2];
92 pp.query_exactly<2>({"ch.lambda","ch.kappa","ch.sigma","ch.eps"}, ch_coeffs,
94
95 if (ch_coeffs[0].first == "ch.lambda" && ch_coeffs[1].first == "ch.kappa")
96 {
97 value.ch.lambda = ch_coeffs[0].second;
98 value.ch.kappa = ch_coeffs[1].second;
99 }
100 else if (ch_coeffs[0].first == "ch.sigma" && ch_coeffs[1].first == "ch.eps")
101 {
102 Set::Scalar sigma = ch_coeffs[0].second, eps = ch_coeffs[1].second;
103 value.ch.lambda = 4.0 * sigma / eps;
104 value.ch.kappa = sigma * eps / 2.0;
105 }
106
107
108 // Set the initial condition for the alpha field
110
111
112 // Use a constant BC object for temperature
113 // value.bc = new BC::Constant(1);
114 // :ref:`BC::Constant` parameters
115 pp.select_default<BC::Constant>("alpha.bc", value.bc, 1);
116
117 // Register the temperature and old temperature fields.
118 // alpha_mf and alpha_old_mf are defined near the bottom of this Header file.
119 value.RegisterNewFab(value.alpha_mf, value.bc, value.number_of_components, value.number_of_ghost_cells, "alpha", true);
120 value.RegisterNewFab(value.alpha_old_mf, value.bc, value.number_of_components, value.number_of_ghost_cells, "alpha_old", false);
121 }
122
123protected:
124
125 // Use the ic object to initialize the order parameter
126 void Initialize(int lev)
127 {
128 ic->Initialize(lev, alpha_mf);
130 }
131
132 // Integrate the Allen Cahn equation
133 void Advance(int lev, Set::Scalar time, Set::Scalar dt)
134 {
135 std::swap(*alpha_mf[lev], *alpha_old_mf[lev]);
136
137 const Set::Scalar *DX = this->geom[lev].CellSize();
138 // Evolve alpha
139 for (amrex::MFIter mfi(*alpha_mf[lev], true); mfi.isValid(); ++mfi)
140 {
141 const amrex::Box& bx = mfi.tilebox();
142 Set::Patch<Set::Scalar> alpha_new = alpha_mf.Patch(lev,mfi);
144
145 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
146 {
147 Set::Scalar driving_force = 0.0;
148
149 // Chemical potential
150 Set::Scalar alpha_2 = alpha(i, j, k) * alpha(i, j, k);
151 Set::Scalar alpha_3 = alpha_2 * alpha(i, j, k);
152 driving_force += ch.lambda * (2.0 * alpha(i, j, k) - 6.0 * alpha_2 + 4.0 * alpha_3);
153
154 // Gradient
155 Set::Scalar alpha_lap = Numeric::Laplacian(alpha, i, j, k, 0, DX);
156 driving_force -= ch.kappa * alpha_lap;
157
158 if (time >= ch.direction_tstart)
159 {
160 if (ch.direction == 1)
161 driving_force = std::min(0.0, driving_force);
162 else if (ch.direction == -1)
163 driving_force = std::max(0.0, driving_force);
164 }
165
166 // Update
167 alpha_new(i, j, k) =
168 alpha(i, j, k) - ch.L * dt * driving_force;
169 });
170 }
171 }
172
173 // Tag cells for mesh refinement based on temperature gradient
174 void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar /*time*/, int /*ngrow*/)
175 {
176 // Get cell dimensions as done above.
177 const Set::Scalar* DX = geom[lev].CellSize();
178 // Calculate the diagonal.
179 Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
180
181 // Iterate over the patches on this level
182 for (amrex::MFIter mfi(*alpha_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
183 {
184 // Get the box and handles as done above.
185 const amrex::Box& bx = mfi.tilebox();
186 amrex::Array4<char> const& tags = a_tags.array(mfi);
187 amrex::Array4<Set::Scalar> const& alpha = (*alpha_mf[lev]).array(mfi);
188
189 // Iterate over the grid as done above.
190 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
191 {
192 // Calculate the temperature gradient.
193 Set::Vector grad = Numeric::Gradient(alpha, i, j, k, 0, DX);
194
195 // Is the gradient * cell_size too big? If so, then
196 // mark this cell as needing refinement.
197 if (grad.lpNorm<2>() * dr > refinement_threshold)
198 tags(i, j, k) = amrex::TagBox::SET;
199 });
200 }
201 }
202
203protected:
204 Set::Field<Set::Scalar> alpha_mf; /// Temperature field variable (current timestep)
205 Set::Field<Set::Scalar> alpha_old_mf; /// Temperature field variable (previous timestep)
206 IC::IC<Set::Scalar>* ic; /// Object used to initialize temperature field
207
210
211 struct {
217 int direction = 0;
218 } ch;
219
220private:
221 int number_of_components = 1; // Number of components
222 int number_of_ghost_cells = 2; // Number of ghost cells
223
224 Set::Scalar refinement_threshold = NAN; // Criterion for cell refinement
225
226 BC::BC<Set::Scalar>* bc; // Object used to update temp field boundary ghost cells
227};
228} // namespace Integrator
229#endif
#define pp_query_validate(...)
Definition ParmParse.H:103
#define pp_query_default(...)
Definition ParmParse.H:102
Definition BC.H:43
Definition BMP.H:22
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
Definition PNG.H:26
Set each point to a random value.
Definition Random.H:20
void select_default(std::string name, PTRTYPE *&ic_eta, Args &&... args)
Definition ParmParse.H:1069
int query_default(std::string name, T &value, T defaultvalue)
Definition ParmParse.H:293
void query_exactly(std::vector< std::string > names, std::pair< std::string, Set::Scalar > values[N], std::vector< Unit > units=std::vector< Unit >())
Definition ParmParse.H:1253
This is the definition of the Allen Cahn class.
Definition AllenCahn.H:46
Set::Scalar refinement_threshold
Definition AllenCahn.H:224
IC::IC< Set::Scalar > * ic
Temperature field variable (previous timestep)
Definition AllenCahn.H:206
void Advance(int lev, Set::Scalar time, Set::Scalar dt)
Definition AllenCahn.H:133
AllenCahn(IO::ParmParse &pp)
Definition AllenCahn.H:55
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int)
Definition AllenCahn.H:174
struct Integrator::AllenCahn::@0 ch
static void Parse(AllenCahn &value, IO::ParmParse &pp)
Definition AllenCahn.H:72
static constexpr const char * name
Definition AllenCahn.H:48
Set::Field< Set::Scalar > alpha_old_mf
Temperature field variable (current timestep)
Definition AllenCahn.H:205
void Initialize(int lev)
Definition AllenCahn.H:126
Set::Scalar direction_tstart
Definition AllenCahn.H:216
Set::Field< Set::Scalar > & eta_old_mf
Definition AllenCahn.H:209
BC::BC< Set::Scalar > * bc
Definition AllenCahn.H:226
Set::Field< Set::Scalar > alpha_mf
Definition AllenCahn.H:204
Set::Field< Set::Scalar > & eta_mf
Object used to initialize temperature field.
Definition AllenCahn.H:208
void RegisterNewFab(Set::Field< Set::Scalar > &new_fab, BC::BC< Set::Scalar > *new_bc, int ncomp, int nghost, std::string name, bool writeout, bool evolving=true, 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
amrex::Array4< Set::Scalar > Patch(const int lev, const amrex::MFIter &mfi) const &
Definition Set.H:263
Collection of numerical integrator objects.
Definition AllenCahn.H:42
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
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
static Unit Area()
Definition Unit.H:197
static Unit Energy()
Definition Unit.H:206
static Unit Time()
Definition Unit.H:189
static Unit Pressure()
Definition Unit.H:205
static Unit Length()
Definition Unit.H:188