13#ifndef INTEGRATOR_ALLENCAHN_H
14#define INTEGRATOR_ALLENCAHN_H
23#include "AMReX_ParallelDescriptor.H"
24#include "AMReX_ParmParse.H"
37#include "Numeric/Stencil.H"
48 static constexpr const char*
name =
"allencahn";
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,
95 if (ch_coeffs[0].first ==
"ch.lambda" && ch_coeffs[1].first ==
"ch.kappa")
97 value.
ch.
lambda = ch_coeffs[0].second;
98 value.
ch.
kappa = ch_coeffs[1].second;
100 else if (ch_coeffs[0].first ==
"ch.sigma" && ch_coeffs[1].first ==
"ch.eps")
102 Set::Scalar sigma = ch_coeffs[0].second,
eps = ch_coeffs[1].second;
137 const Set::Scalar *DX = this->geom[lev].CellSize();
139 for (amrex::MFIter mfi(*
alpha_mf[lev],
true); mfi.isValid(); ++mfi)
141 const amrex::Box& bx = mfi.tilebox();
145 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
150 Set::Scalar alpha_2 = alpha(i, j, k) * alpha(i, j, k);
152 driving_force +=
ch.lambda * (2.0 * alpha(i, j, k) - 6.0 * alpha_2 + 4.0 * alpha_3);
156 driving_force -=
ch.kappa * alpha_lap;
158 if (time >=
ch.direction_tstart)
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);
168 alpha(i, j, k) -
ch.L *
dt * driving_force;
179 Set::Scalar dr = sqrt(AMREX_D_TERM(DX[0] * DX[0], +DX[1] * DX[1], +DX[2] * DX[2]));
182 for (amrex::MFIter mfi(*
alpha_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
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);
190 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
198 tags(i, j, k) = amrex::TagBox::SET;
#define pp_query_validate(...)
#define pp_query_default(...)
Pure abstract IC object from which all other IC objects inherit.
void Initialize(const int &a_lev, Set::Field< T > &a_field, Set::Scalar a_time=0.0)
Set each point to a random value.
void select_default(std::string name, PTRTYPE *&ic_eta, Args &&... args)
int query_default(std::string name, T &value, T defaultvalue)
void query_exactly(std::vector< std::string > names, std::pair< std::string, Set::Scalar > values[N], std::vector< Unit > units=std::vector< Unit >())
This is the definition of the Allen Cahn class.
Set::Scalar refinement_threshold
IC::IC< Set::Scalar > * ic
Temperature field variable (previous timestep)
int number_of_ghost_cells
void Advance(int lev, Set::Scalar time, Set::Scalar dt)
AllenCahn(IO::ParmParse &pp)
void TagCellsForRefinement(int lev, amrex::TagBoxArray &a_tags, Set::Scalar, int)
struct Integrator::AllenCahn::@0 ch
static void Parse(AllenCahn &value, IO::ParmParse &pp)
static constexpr const char * name
Set::Field< Set::Scalar > alpha_old_mf
Temperature field variable (current timestep)
Set::Scalar direction_tstart
Set::Field< Set::Scalar > & eta_old_mf
BC::BC< Set::Scalar > * bc
Set::Field< Set::Scalar > alpha_mf
Set::Field< Set::Scalar > & eta_mf
Object used to initialize temperature field.
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.
amrex::Array4< Set::Scalar > Patch(const int lev, const amrex::MFIter &mfi) const &
Collection of numerical integrator objects.
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)
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)
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector