Alamo
TopOp.H
Go to the documentation of this file.
1#ifndef INTEGRATOR_TOPOP_H
2#define INTEGRATOR_TOPOP_H
3#include <iostream>
4#include <fstream>
5#include <iomanip>
6#include <numeric>
7
8#include "AMReX.H"
9#include "AMReX_ParallelDescriptor.H"
10#include "AMReX_ParmParse.H"
11
12#include "IO/ParmParse.H"
14
15
16#include "IC/IC.H"
17#include "BC/BC.H"
21
22#include "IC/Ellipse.H"
23#include "IC/Voronoi.H"
24#include "IC/Constant.H"
25#include "IC/BMP.H"
26#include "BC/Constant.H"
27#include "Numeric/Stencil.H"
28
29#include "Model/Solid/Solid.H"
32
33#include "Operator/Operator.H"
34
35
36namespace Integrator
37{
38template<class MODEL>
39class TopOp: virtual public Base::Mechanics<MODEL>
40{
41public:
42
43 TopOp(): Base::Mechanics<MODEL>() {}
44 TopOp(IO::ParmParse& pp): Base::Mechanics<MODEL>()
45 {
46 Parse(*this, pp);
47 }
48
50 {
51 delete ic_psi;
52 delete bc_psi;
53 }
54
55 // The mechanics integrator manages the solution of an elastic
56 // solve using the MLMG solver.
57 static void Parse(TopOp& value, IO::ParmParse& pp)
58 {
60
61 pp.queryclass<MODEL>("model", value.model);
62
63 // Read in IC for psi
64 if (pp.contains("psi.ic.type"))
65 {
66 value.psi_on = true;
67 value.bc_psi = new BC::Constant(1, pp, "psi.bc");
68 value.RegisterNewFab(value.psi_mf, value.bc_psi, 1, 2, "psi", true);
69 value.RegisterNewFab(value.psi_old_mf, value.bc_psi, 1, 2, "psiold", false);
70 }
71
72 // Initial condition for psi field
74
75 pp_query_default("eta_ref_threshold", value.m_eta_ref_threshold, 0.01); // Refinement threshold based on eta
76 pp_query_default("alpha", value.alpha, 1.0); // :math:`\alpha` parameter
77 pp_query_default("beta", value.beta, 1.0); // :math:`\beta` parameter
78 pp_query_default("gamma", value.gamma, 1.0); // :math:`\gamma` parameter
79 pp_queryclass("L", value.L); // Mobility
80 if (pp.contains("volume0frac"))
81 {
82 if (pp.contains("volume0")) Util::Abort(INFO, "Cannot specify volume0frac and volume0");
83 Set::Scalar volumefrac;
84 pp_query_default("volume0frac", volumefrac, 0.5); // Prescribed volume fraction
85 value.volume0 = volumefrac *
86 AMREX_D_TERM((value.geom[0].ProbHi()[0] - value.geom[0].ProbLo()[0]),
87 *(value.geom[0].ProbHi()[1] - value.geom[0].ProbLo()[1]),
88 *(value.geom[0].ProbHi()[2] - value.geom[0].ProbLo()[2]));
89 }
90 else
91 pp_query_default("volume0", value.volume0, 0.5); // Prescribed total vlume
92
93 pp_queryclass("lambda", value.lambda); // Lagrange multiplier (can be interplated)
94
95
96 value.RegisterIntegratedVariable(&value.volume, "volume");
97 value.RegisterIntegratedVariable(&value.w_chem_potential, "chem_potential");
98 value.RegisterIntegratedVariable(&value.w_bndry, "bndry");
99 value.RegisterIntegratedVariable(&value.w_elastic, "elastic");
100 }
101
102 void Initialize(int lev) override
103 {
105 if (psi_on) ic_psi->Initialize(lev, psi_mf);
107 }
108
109 virtual void UpdateModel(int a_step, Set::Scalar /*a_time*/) override
110 {
112
113 if (a_step > 0) return;
114
115 for (int lev = 0; lev <= finest_level; ++lev)
116 {
117 model_mf[lev]->setVal(model);
118 Util::RealFillBoundary(*model_mf[lev], geom[lev]);
119 Util::RealFillBoundary(*psi_mf[lev], geom[lev]);
120 Util::RealFillBoundary(*psi_old_mf[lev], geom[lev]);
121 }
122
123 }
124
125
126 void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
127 {
128 BL_PROFILE("TopOp::Advance");
130 std::swap(psi_old_mf[lev], psi_mf[lev]);
131 const Set::Scalar* DX = geom[lev].CellSize();
132 amrex::Box domain = geom[lev].Domain();
133
134 Set::Scalar Lnow = L(time);
135 Set::Scalar lambdaT = lambda(time);
136
137 for (amrex::MFIter mfi(*psi_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
138 {
139 amrex::Box bx = mfi.tilebox();
140 bx.grow(1);
141 bx = bx & domain;
142 amrex::Array4<const Set::Matrix> const& sig = (*stress_mf[lev]).array(mfi);
143 amrex::Array4<const Set::Matrix> const& eps = (*strain_mf[lev]).array(mfi);
144 amrex::Array4<const Set::Scalar> const& psi = (*psi_old_mf[lev]).array(mfi);
145 amrex::Array4<Set::Scalar> const& psinew = (*psi_mf[lev]).array(mfi);
146
147 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
148 {
149 Set::Scalar driving_force = 0.0;
150
151 driving_force += alpha * 2.0 * psi(i, j, k) * (2.0 * psi(i, j, k) * psi(i, j, k) - 3.0 * psi(i, j, k) + 1.0);
152 driving_force += -beta * Numeric::Laplacian(psi, i, j, k, 0, DX);
153
154 Set::Matrix sig_avg = Numeric::Interpolate::NodeToCellAverage(sig, i, j, k, 0);
155 Set::Matrix eps_avg = Numeric::Interpolate::NodeToCellAverage(eps, i, j, k, 0);
156
157 driving_force += -gamma * 0.5 * (sig_avg.transpose() * eps_avg).trace() * psi(i, j, k);
158
159 driving_force += lambdaT * (volume - volume0);
160
161 psinew(i, j, k) = psi(i, j, k) - Lnow * dt * driving_force;
162 if (psinew(i, j, k) < 0.0) psinew(i, j, k) = 0.0;
163 if (psinew(i, j, k) > 1.0) psinew(i, j, k) = 1.0;
164 });
165 }
166 }
167
168 void Integrate(int amrlev, Set::Scalar time, int step,
169 const amrex::MFIter& mfi, const amrex::Box& box) override
170 {
171 BL_PROFILE("TopOp::Integrate");
172 Base::Mechanics<MODEL>::Integrate(amrlev, time, step, mfi, box);
173
174 const amrex::Real* DX = geom[amrlev].CellSize();
175 Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
176
177 amrex::Array4<amrex::Real> const& psi = (*psi_mf[amrlev]).array(mfi);
178 amrex::Array4<const Set::Matrix> const& sig = (*stress_mf[amrlev]).array(mfi);
179 amrex::Array4<const Set::Matrix> const& eps = (*strain_mf[amrlev]).array(mfi);
180 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(int i, int j, int k)
181 {
182 volume += psi(i, j, k, 0) * dv;
183 w_chem_potential += alpha * psi(i, j, k, 0) * psi(i, j, k, 0) * (1. - psi(i, j, k, 0) * psi(i, j, k, 0)) * dv;
184 w_bndry += beta * 0.5 * Numeric::Gradient(psi, i, j, k, 0, DX).squaredNorm() * dv;
185
186 Set::Matrix sig_avg = Numeric::Interpolate::NodeToCellAverage(sig, i, j, k, 0);
187 Set::Matrix eps_avg = Numeric::Interpolate::NodeToCellAverage(eps, i, j, k, 0);
188 w_elastic += gamma * 0.5 * (sig_avg.transpose() * eps_avg).trace() * psi(i, j, k) * dv;
189 });
190 }
191
192
193 void TagCellsForRefinement(int lev, amrex::TagBoxArray& a_tags, Set::Scalar a_time, int a_ngrow) override
194 {
196 Base::Mechanics<MODEL>::TagCellsForRefinement(lev, a_tags, a_time, a_ngrow);
197
198 Set::Vector DX(geom[lev].CellSize());
199 Set::Scalar DXnorm = DX.lpNorm<2>();
200 for (amrex::MFIter mfi(*model_mf[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
201 {
202 amrex::Box bx = mfi.tilebox();
203 amrex::Array4<char> const& tags = a_tags.array(mfi);
204 if (psi_on)
205 {
206 amrex::Array4<Set::Scalar> const& psi = psi_mf[lev]->array(mfi);
207 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
208 {
209 auto sten = Numeric::GetStencil(i, j, k, bx);
210 {
211 Set::Vector gradpsi = Numeric::Gradient(psi, i, j, k, 0, DX.data(), sten);
212 if (gradpsi.lpNorm<2>() * DXnorm > m_eta_ref_threshold)
213 tags(i, j, k) = amrex::TagBox::SET;
214 }
215 });
216 }
217 }
218 }
219
220
221protected:
222 MODEL model;
227
228
229 using Base::Mechanics<MODEL>::m_type;
230 using Base::Mechanics<MODEL>::finest_level;
231 using Base::Mechanics<MODEL>::geom;
232 using Base::Mechanics<MODEL>::model_mf;
233 using Base::Mechanics<MODEL>::psi_mf;
234 using Base::Mechanics<MODEL>::psi_on;
235 using Base::Mechanics<MODEL>::stress_mf;
236 using Base::Mechanics<MODEL>::strain_mf;
237
238
242 //Set::Scalar L = 1.0;
245 //Set::Scalar lambda = 1.0;
247
252};
253
254
255
256
257
258
259
260
261
262
263} // namespace Integrator
264#endif
#define pp_query_default(...)
Definition ParmParse.H:120
#define pp_queryclass(...)
Definition ParmParse.H:130
#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
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, 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
static ForwardArgs< ForwardArgStorage< Args >... > forward_args(Args &&... args)
Definition ParmParse.H:153
bool contains(std::string name, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:318
Set::Field< Set::Matrix > strain_mf
Definition Mechanics.H:513
void Integrate(int amrlev, Set::Scalar, int, const amrex::MFIter &mfi, const amrex::Box &a_box) override
Definition Mechanics.H:418
static void Parse(Mechanics &value, IO::ParmParse &pp)
Definition Mechanics.H:42
void Initialize(int lev) override
Use the #ic object to initialize::Temp.
Definition Mechanics.H:171
void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
Definition Mechanics.H:278
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int) override
Definition Mechanics.H:477
Set::Field< Set::Matrix > stress_mf
Definition Mechanics.H:512
Set::Field< Set::Scalar > psi_mf
Definition Mechanics.H:503
Set::Field< MODEL > model_mf
Definition Mechanics.H:501
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.
std::vector< amrex::Box > box
Definition Integrator.H:465
amrex::Vector< amrex::Real > dt
Timesteps for each level of refinement.
Definition Integrator.H:394
void RegisterIntegratedVariable(Set::Scalar *integrated_variable, std::string name, bool extensive=true)
Register a variable to be integrated over the spatial domain using the Integrate function.
Set::Scalar w_bndry
Definition TopOp.H:250
void Integrate(int amrlev, Set::Scalar time, int step, const amrex::MFIter &mfi, const amrex::Box &box) override
Definition TopOp.H:168
BC::BC< Set::Scalar > * bc_psi
Definition TopOp.H:224
Set::Scalar volume
Definition TopOp.H:248
Set::Scalar m_eta_ref_threshold
Definition TopOp.H:225
Set::Scalar volume0
Definition TopOp.H:244
void Advance(int lev, Set::Scalar time, Set::Scalar dt) override
Definition TopOp.H:126
Set::Scalar alpha
Definition TopOp.H:239
Set::Scalar w_chem_potential
Definition TopOp.H:249
virtual void UpdateModel(int a_step, Set::Scalar) override
Definition TopOp.H:109
Set::Scalar w_elastic
Definition TopOp.H:251
Set::Scalar gamma
Definition TopOp.H:241
Set::Field< Set::Scalar > psi_old_mf
Definition TopOp.H:226
void Initialize(int lev) override
Definition TopOp.H:102
Numeric::Interpolator::Linear< Set::Scalar > lambda
Definition TopOp.H:246
Numeric::Interpolator::Linear< Set::Scalar > L
Definition TopOp.H:243
Set::Scalar beta
Definition TopOp.H:240
static void Parse(TopOp &value, IO::ParmParse &pp)
Definition TopOp.H:57
TopOp(IO::ParmParse &pp)
Definition TopOp.H:44
IC::IC< Set::Scalar > * ic_psi
Definition TopOp.H:223
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar a_time, int a_ngrow) override
Definition TopOp.H:193
Collection of numerical integrator objects.
Definition AllenCahn.H:43
static AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE std::array< StencilType, AMREX_SPACEDIM > GetStencil(const int i, const int j, const int k, const amrex::Box domain)
Definition Stencil.H:51
AMREX_GPU_HOST_DEVICE 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:687
AMREX_GPU_HOST_DEVICE 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:561
amrex::Real Scalar
Definition Base.H:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, AMREX_SPACEDIM > Matrix
Definition Base.H:24
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:406
AMREX_FORCE_INLINE void RealFillBoundary(amrex::FabArray< amrex::BaseFab< T > > &a_mf, const amrex::Geometry &, const int nghost=2)
Definition Util.H:350
static AMREX_FORCE_INLINE T NodeToCellAverage(const amrex::Array4< const T > &f, const int &i, const int &j, const int &k, const int &m)
Definition Stencil.H:1483