Alamo
PhaseFieldMicrostructure.H
Go to the documentation of this file.
1///
2/// \file PhaseFieldMicrostructure.H
3///
4#ifndef INTEGRATOR_PHASEFIELDMICROSTRUCTURE_H
5#define INTEGRATOR_PHASEFIELDMICROSTRUCTURE_H
6
7#include <random>
8
9#include "AMReX_ParmParse.H"
10#include <AMReX_MLMG.H>
11
12#include "IO/ParmParse.H"
14#include "BC/BC.H"
15#include "BC/Constant.H"
16#include "IC/Constant.H"
18#include "IC/Voronoi.H"
19#include "IC/Sphere.H"
20#include "IC/Expression.H"
21#include "IC/Ellipse.H"
22#include "IC/Random.H"
23#include "Model/Interface/GB/GB.H"
29#include "Base/Mechanics.H"
30#include "Set/Base.H"
31
32namespace Integrator
33{
34
38
39///
40/// Solve the Allen-Cahn evolution equation for microstructure with parameters \f$\eta_1\ldots\eta_n\f$,
41/// where n corresponds to the number of grains.
42///
43template<class model_type>
44class PhaseFieldMicrostructure : public Base::Mechanics<model_type>
45{
46public:
47 const std::string name = "phasefieldmicrostructure." + std::string(model_type::name);
48
53 {
54 delete boundary;
55 delete ic;
56 delete mybc;
57 }
59 {
60 BL_PROFILE("PhaseFieldMicrostructure::Parse");
61
62 // Number of grain fields (may be more if using different IC)
63 pp_query_default("pf.number_of_grains", value.number_of_grains,2);
64 pp_query_required("pf.M", value.pf.M); // Mobility
65 pp_query_required("pf.gamma", value.pf.gamma); // Phase field :math:`\gamma`
66 pp_query_required("pf.sigma0", value.pf.sigma0); // Initial GB energy if not using anisotropy
67 pp_query_required("pf.l_gb", value.pf.l_gb); // Mobility
68 pp_query_default("pf.elastic_df",value.pf.elastic_df,false); // Determine whether to use elastic driving force
69 pp_query_default("pf.elastic_mult",value.pf.elastic_mult,1.0); // Multiplier of elastic energy
70
71 pp_query_default("pf.threshold.value",value.pf.threshold.value,0.0); // Value used for thresholding kinetic relation
72 pp_query_default("pf.threshold.chempot",value.pf.threshold.chempot,false); // Whether to include chemical potential in threshold
73 pp_query_default("pf.threshold.boundary",value.pf.threshold.boundary,false); // Whether to include boundary energy in threshold
74 pp_query_default("pf.threshold.corner",value.pf.threshold.corner,false); // Whether to include corner regularization in threshold
75 pp_query_default("pf.threshold.lagrange",value.pf.threshold.lagrange,false); // Whether to include lagrange multiplier in threshold
76 pp_query_default("pf.threshold.mechanics",value.pf.threshold.mechanics,false);// Whether to include mechanical driving force in threshold
77
78 value.pf.threshold.on =
79 value.pf.threshold.chempot || value.pf.threshold.boundary ||
80 value.pf.threshold.corner || value.pf.threshold.lagrange ||
81 value.pf.threshold.mechanics;
82
83 // Type of threshold to use
84 pp.query_switch("pf.threshold.type", {
85 {"continuous", [&]() { value.pf.threshold.type = ThresholdType::Continuous; }},
86 {"chop", [&]() { value.pf.threshold.type = ThresholdType::Chop; }}
87 });
88
89 value.pf.L = (4./3.)*value.pf.M / value.pf.l_gb;
90
91 pp_query_required("amr.max_level", value.max_level); // Maximum AMR level
92 pp_query_default("amr.ref_threshold", value.ref_threshold, 0.1); // Phase field refinement threshold
93
94
95 std::string type_str;
96 // Reading this is redundant but necessary because of the way the code was originally structured
97 // (need to fix eventually)
98 pp.query_validate("mechanics.type", type_str, {"disable","static","dynamic"});
99 value.m_type = Base::Mechanics<model_type>::Disable; // Turn mechanics off by default
100
101 if (type_str != "disable" || IO::ParmParse::InTraversalMode()) // do this only if mechanics is activated
102 {
103 // Elasticity
104 pp_query_default("mechanics.tstart",value.mechanics.tstart, 0.0);
105
106 // Read in models - either one model for all grains, or
107 // individual models, one for each grain.
108 pp.queryclass_enumerate("mechanics.model",value.mechanics.model, value.number_of_grains);
109
110 // Mixing order
111 pp_query_validate("mechanics.mix_order",value.mechanics.model_mix_order,{1,2});
112 // Force Neumann BCs on the model
113 pp_query_default("mechanics.model_neuman_boundary",value.mechanics.model_neumann_boundary,false);
114
117 value.number_of_ghost_cells = std::max(value.number_of_ghost_cells, 3);
118 }
119
120
121 // Lagrange multiplier method for enforcing volumes
122 pp.query_if("lagrange.on", [&]() {
123 value.lagrange.on = true;
124 pp_query_required("lagrange.lambda", value.lagrange.lambda); // Lagrange multiplier value
125 pp_query_required("lagrange.vol0", value.lagrange.vol0); // Prescribed volume
126 pp_query_default("lagrange.tstart", value.lagrange.tstart,0.0); // Lagrange multipler start time
127 value.SetThermoInt(1);
128 });
129
130 // synthetic driving force (SDF)
131 pp.query_if("sdf.on", [&]() {
132 value.sdf.on = true;
133 std::vector<std::string> vals;
134 pp_queryarr("sdf.val",vals); // value of SDF for each grain
135 pp.query_default("sdf.tstart",value.sdf.tstart,0.0); // time to begin applying SDF
136
137 if (IO::ParmParse::InTraversalMode()) return;
138
139 int nvals = static_cast<int>(vals.size());
140 if (nvals == 1)
141 for (int i = 0; i < value.number_of_grains; i++)
142 value.sdf.val.push_back(Numeric::Interpolator::Linear<Set::Scalar>(vals[0]));
143 else if (nvals == value.number_of_grains)
144 for (int i = 0; i < value.number_of_grains; i++)
145 value.sdf.val.push_back(Numeric::Interpolator::Linear<Set::Scalar>(vals[i]));
146 else
147 Util::Abort(INFO,"sdf.val received ", vals.size(), " but requires 1 or ", value.number_of_grains);
148 });
149
150 // Anisotropic grain boundary energy parameters
151 pp.query_if("anisotropy.on", [&]() {
152 value.anisotropy.on = true;
153
154 // Regularization param
155 pp.query_required("anisotropy.beta", value.anisotropy.beta);
156 // Time to turn on anisotropy
157 pp.query_required("anisotropy.tstart", value.anisotropy.tstart);
158 value.anisotropy.timestep = value.timestep;
159 // Modify timestep when turned on
160 pp.query_required("anisotropy.timestep", value.anisotropy.timestep);
161 value.anisotropy.plot_int = value.plot_int;
162 // Modify plot_int when turned on
163 pp.query_default("anisotropy.plot_int", value.anisotropy.plot_int, -1);
164 value.anisotropy.plot_dt = value.plot_dt;
165 // Modify plot_dt when turned on
166 pp.query_default("anisotropy.plot_dt", value.anisotropy.plot_dt, -1.0);
167 // Modify thermo int when turned on
168 pp.query_default("anisotropy.thermo_int", value.anisotropy.thermo_int, -1);
169 // Modify thermo plot int when turned on
170 pp.query_default("anisotropy.thermo_plot_int", value.anisotropy.thermo_plot_int, -1);
171 // Frequency of elastic calculation
172 pp.query_default("anisotropy.elastic_int",value.anisotropy.elastic_int, -1);
173 if (value.anisotropy.on)
174 value.number_of_ghost_cells = std::max(value.number_of_ghost_cells,2);
175
176 // Determine the kind of regularization to use
177 pp.query_switch("anisotropy.regularization", {
178 {"k12", [&](){
179 value.regularization = RegularizationType::K12;
180 }},
181 {"wilmore", [&](){
182 value.regularization = RegularizationType::Wilmore;
183 }}
184 });
185
186 // Type of GB to use
188 });
189
190 // Thermal fluctuations
191 pp.query_if("fluctuation.on", [&]() {
192 value.fluctuation.on = true;
193 pp.query_required("fluctuation.amp",value.fluctuation.amp); // fluctuation amplitude
194 pp.query_required("fluctuation.sd",value.fluctuation.sd); // fluctuation stadard deviation
195 pp.query_required("fluctuation.tstart", value.fluctuation.tstart); // time to start applying fluctuation
196 value.fluctuation.norm_dist = std::normal_distribution<double>(0.0,value.fluctuation.sd);
197 });
198
199 // Disconnection generation
200 pp.query_if("disconnection.on", [&]() {
201 value.disconnection.on = true;
202
203 // Read in nucleation parameters from disconnection class
204 pp.queryclass<Model::Defect::Disconnection>("disconnection",value.disconnection.model);
205 });
206
207 // Define explicit shear coupling matrices
208 pp.query_if("shearcouple.on",[&](){
209 value.shearcouple.on = true;
210
211 value.shearcouple.Fgb.resize(value.number_of_grains * value.number_of_grains, Set::Matrix::Zero());
212 for (int i = 0 ; i < value.number_of_grains ; i++)
213 for (int j = 0 ; j < value.number_of_grains ; j++)
214 {
215 std::string name = "shearcouple.Fgb."+std::to_string(i)+"."+std::to_string(j);
216 std::string namerev = "shearcouple.Fgb."+std::to_string(j)+"."+std::to_string(i);
217
218 if ( i==j && pp.contains(name.data()))
219 Util::Abort(INFO,"Cannot specify self FGB ", name);
220 if (pp.contains(name.data()) && pp.contains(namerev.data()))
221 Util::Abort(INFO,"Cannot specify both ",name," and ",namerev);
222
223 if (i==j) continue;
224
225 // Shear couple matrix from grain N to grain M.
226 // (Note that N != M and you cannot specify both N,M and also M,N)
227 pp.queryarr_default(name.data(),value.shearcouple.Fgb[i*value.number_of_grains + j],Set::Matrix::Zero());
228 if (pp.contains(name.data()))
229 {
230 value.shearcouple.Fgb[j*value.number_of_grains + i] = - value.shearcouple.Fgb[i*value.number_of_grains + j];
231 }
232 }
233
234 if (IO::ParmParse::InTraversalMode()) return;
235
236 Util::AssertException(INFO,TEST(value.m_time_evolving == true), " mechanics.time_evolving must be true when using shearcouple");
237 Util::AssertException(INFO,TEST(value.mechanics.model_mix_order == 2), " mechanics.model.mix_order must be 2 when using shearcouple");
238
239 });
240
241 // Boundary condition for eta
242 pp.select<BC::Constant>("bc.eta",value.mybc,pp.forward_args(value.number_of_grains));
243
244 // Initial condition for the order parameter eta
246
247 // Anisotropic mobility
248 pp.query_if("anisotropic_kinetics.on",[&](){
249 value.anisotropic_kinetics.on = true;
250 // simulation time when anisotropic kinetics is activated
251 pp.query_default("anisotropic_kinetics.tstart",value.anisotropic_kinetics.tstart, 0.0);
252 std::string mobility_filename, threshold_filename;
253 // file containing anisotropic mobility data
254 pp.query_file("anisotropic_kinetics.mobility",mobility_filename);
255 value.anisotropic_kinetics.mobility = Numeric::Interpolator::Linear<Set::Scalar>::Read(mobility_filename);
256 // file containing anisotropic mobility data
257 pp.query_file("anisotropic_kinetics.threshold",threshold_filename);
258 value.anisotropic_kinetics.threshold = Numeric::Interpolator::Linear<Set::Scalar>::Read(threshold_filename);
259 value.RegisterNewFab(value.anisotropic_kinetics.L_mf, value.mybc, value.number_of_grains, 0, "mobility",true);
260 value.RegisterNewFab(value.anisotropic_kinetics.threshold_mf, value.mybc, value.number_of_grains, 0, "theshold",true);
261 });
262
263
264 value.RegisterNewFab(value.eta_mf, value.mybc, value.number_of_grains, value.number_of_ghost_cells, "Eta",true);
265 value.RegisterNewFab(value.eta_old_mf, value.mybc, value.number_of_grains, value.number_of_ghost_cells, "EtaOld",false);
266 //value.RegisterNewFab(value.driving_force_mf, value.mybc, value.number_of_grains, value.number_of_ghost_cells, "DrivingForce",false);
267 // if (value.pf.threshold.on)
268 // value.RegisterNewFab(value.driving_force_threshold_mf, value.mybc, value.number_of_grains, value.number_of_ghost_cells, "DrivingForceThreshold",false);
269 // if (value.disconnection.on)
270 // value.RegisterNewFab(value.disc_mf, new BC::Nothing(), 1, value.number_of_ghost_cells, "disc",true); // see box
271
272 value.RegisterIntegratedVariable(&value.volume, "volume");
273 value.RegisterIntegratedVariable(&value.area, "area");
274 value.RegisterIntegratedVariable(&value.gbenergy, "gbenergy");
275 value.RegisterIntegratedVariable(&value.realgbenergy, "realgbenergy");
276 value.RegisterIntegratedVariable(&value.regenergy, "regenergy");
277
278 }
279
280
281protected:
282
283 /// \fn Advance
284 /// \brief Evolve phase field in time
285 void Advance (int lev, Real time, Real dt) override;
286 void Initialize (int lev) override;
287
288 void TagCellsForRefinement (int lev, amrex::TagBoxArray& tags, amrex::Real time, int ngrow) override;
289
290 virtual void TimeStepBegin(amrex::Real time, int iter) override;
291 virtual void TimeStepComplete(amrex::Real time, int iter) override;
292 void Integrate(int amrlev, Set::Scalar time, int step,
293 const amrex::MFIter &mfi, const amrex::Box &box) override;
294
295 virtual void UpdateEigenstrain(int lev);
296 virtual void UpdateEigenstrain()
297 {
298 for (int lev = 0; lev <= this->max_level; lev++)
300 }
301
302 virtual void UpdateModel(int /*a_step*/, Set::Scalar /*a_time*/) override;
303
304private:
305
309
310 // Cell fab
311 Set::Field<Set::Scalar> eta_mf; // Multicomponent field variable storing \t$\eta_i\t$ for the __current__ timestep
316 //Set::Field<Set::Scalar> disc_mf; //see box
317 // Node fab
318 //Set::Field<Set::Scalar> elasticdf_mf;
320
322
323 //amrex::Real M, mu, gamma, sigma0, l_gb, beta;
328 struct {
335 bool elastic_df = false;
337 struct {
338 bool on = false;
339 bool chempot = false;
340 bool boundary = false;
341 bool corner = false;
342 bool lagrange = false;
343 bool mechanics = false;
344 bool sdf = false;
348 } pf;
349
350 struct {
351 int on = 0;
358
359 struct {
360 int on = 0;
364 int plot_int = -1;
369 int elastic_int = -1;
371
372 struct {
373 bool on = 0;
374 Set::Scalar tstart = NAN;
378
379 struct {
380 int on = 0;
381 std::vector<Numeric::Interpolator::Linear<Set::Scalar>> val;
382 Set::Scalar tstart = 0.0;
384
385 struct {
386 int on = 0;
389 Set::Scalar tstart = 0.0;
390 std::normal_distribution<double> norm_dist;
391 std::default_random_engine rand_num_gen;
393
394 struct {
395 int on = 0;
398
399 struct {
400 int on = 0;
401 std::vector<Set::Matrix> Fgb;
403
404 std::string gb_type, filename;
405
407
409
415
416 struct
417 {
418 Set::Scalar tstart = 0.0;
419 std::vector<model_type> model;
423
424 using Base::Mechanics<model_type>::model_mf;
425 using Base::Mechanics<model_type>::stress_mf;
426
427};
428}
429#endif
#define pp_query_validate(...)
Definition ParmParse.H:121
#define pp_queryarr(...)
Definition ParmParse.H:126
#define pp_query_required(...)
Definition ParmParse.H:119
#define pp_query_default(...)
Definition ParmParse.H:120
#define pp_queryclass(...)
Definition ParmParse.H:130
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
Definition BC.H:43
Pure abstract IC object from which all other IC objects inherit.
Definition IC.H:23
Set each point to a random value.
Definition Random.H:28
void select_default(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1978
void queryclass(std::string name, T *value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1767
int query_validate(std::string name, int &value, std::vector< int > possibleintvals, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:569
int queryclass_enumerate(std::string a_name, std::vector< T > &value, int number=1, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1503
static ForwardArgs< ForwardArgStorage< Args >... > forward_args(Args &&... args)
Definition ParmParse.H:153
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:961
int query_switch(std::string name, std::initializer_list< std::pair< std::string, std::function< void()> > > cases, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:714
static bool InTraversalMode()
Definition ParmParse.cpp:14
int queryarr_default(std::string name, std::vector< std::string > &value, std::vector< std::string > defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1303
bool contains(std::string name, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:318
int query_required(std::string name, T &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:421
int query_if(std::string name, Action &&action, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:817
void select(std::string name, PTRTYPE *&ic_eta, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1883
Set::Field< Set::Matrix > stress_mf
Definition Mechanics.H:512
Set::Field< model_type > model_mf
Definition Mechanics.H:501
std::vector< amrex::Box > box
Definition Integrator.H:465
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
Definition Integrator.H:394
Solve the Allen-Cahn evolution equation for microstructure with parameters , where n corresponds to t...
void Advance(int lev, Real time, Real dt) override
Evolve phase field in time.
Numeric::Interpolator::Linear< Set::Scalar > mobility
virtual void UpdateModel(int, Set::Scalar) override
struct Integrator::PhaseFieldMicrostructure::@14 pf
static void Parse(PhaseFieldMicrostructure &value, IO::ParmParse &pp)
struct Integrator::PhaseFieldMicrostructure::@14::@23 threshold
struct Integrator::PhaseFieldMicrostructure::@16 anisotropy
void TagCellsForRefinement(int lev, amrex::TagBoxArray &tags, amrex::Real time, int ngrow) override
void Integrate(int amrlev, Set::Scalar time, int step, const amrex::MFIter &mfi, const amrex::Box &box) override
struct Integrator::PhaseFieldMicrostructure::@15 anisotropic_kinetics
virtual void TimeStepBegin(amrex::Real time, int iter) override
Numeric::Interpolator::Linear< Set::Scalar > threshold
std::normal_distribution< double > norm_dist
Set::Field< Set::Scalar > driving_force_threshold_mf
struct Integrator::PhaseFieldMicrostructure::@20 disconnection
std::vector< Numeric::Interpolator::Linear< Set::Scalar > > val
virtual void TimeStepComplete(amrex::Real time, int iter) override
struct Integrator::PhaseFieldMicrostructure::@21 shearcouple
struct Integrator::PhaseFieldMicrostructure::@19 fluctuation
Reads the data from a file and computes energies and its derivates.
Definition Read.H:25
A 2D interface model class.
Definition SH.H:36
static Linear< T > Read(std::string filename, int derivative=0)
Collection of numerical integrator objects.
Definition AllenCahn.H:43
amrex::Real Scalar
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:265
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:406