35 BL_PROFILE(
"PhaseFieldMicrostructure::Advance");
39 std::swap(eta_old_mf[lev], eta_mf[lev]);
42 Set::Scalar df_max = std::numeric_limits<Set::Scalar>::min();
46 for (amrex::MFIter mfi(*eta_mf[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
48 amrex::Box bx = mfi.tilebox();
57 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
62 for (
int m = 0; m < number_of_grains; m++)
68 if (pf.threshold.on) driving_force_threshold = 0.0;
83 if (!anisotropy.on || time < anisotropy.tstart)
85 kappa = pf.l_gb * 0.75 * pf.sigma0;
86 mu = 0.75 * (1.0 / 0.23) * pf.sigma0 / pf.l_gb;
87 if (pf.threshold.boundary) driving_force_threshold += -kappa * laplacian;
88 else driving_force += -kappa * laplacian;
93 auto anisotropic_df = boundary->DrivingForce(Deta, DDeta, DDDDEta);
94 if (pf.threshold.boundary) driving_force_threshold += pf.l_gb * 0.75 * std::get<0>(anisotropic_df);
95 else driving_force += pf.l_gb * 0.75 * std::get<0>(anisotropic_df);
97 if (pf.threshold.boundary) driving_force_threshold += anisotropy.beta * std::get<1>(anisotropic_df);
98 else driving_force += anisotropy.beta * std::get<1>(anisotropic_df);
100 mu = 0.75 * (1.0 / 0.23) * boundary->W(Deta) / pf.l_gb;
108 for (
int n = 0; n < number_of_grains; n++)
112 sum_of_squares += eta(i, j, k, n) * eta(i, j, k, n);
114 if (pf.threshold.chempot)
115 driving_force_threshold += mu * (eta(i, j, k, m) * eta(i, j, k, m) - 1.0 + 2.0 * pf.gamma * sum_of_squares) * eta(i, j, k, m);
117 driving_force += mu * (eta(i, j, k, m) * eta(i, j, k, m) - 1.0 + 2.0 * pf.gamma * sum_of_squares) * eta(i, j, k, m);
123 if (lagrange.on && m == 0 && time > lagrange.tstart)
125 if (pf.threshold.lagrange)
126 driving_force_threshold += lagrange.lambda * (volume - lagrange.vol0);
128 driving_force += lagrange.lambda * (volume - lagrange.vol0);
134 if (sdf.on && time > sdf.tstart)
136 if (pf.threshold.sdf)
137 driving_force_threshold += sdf.val[m](time);
139 driving_force += sdf.val[m](time);
152 for (
int n = 0; n < number_of_grains; n++)
159 sumsq = sumsq * sumsq;
165 Set::Matrix Fgbn = shearcouple.Fgb[n*number_of_grains + m];
170 Set::Matrix::Identity() +
175 elastic_df_m += (sig.transpose() * Fgbn).trace() * dgn;
182 for (
int n = 0; n < number_of_grains; n++)
183 F0avg += eta(i, j, k, n) * mechanics.model[n].F0;
187 for (
int n = 0; n < number_of_grains; n++)
189 if (n == m)
continue;
190 Set::Scalar normsq = eta(i, j, k, m) * eta(i, j, k, m) + eta(i, j, k, n) * eta(i, j, k, n);
191 dF0deta += (2.0 * eta(i, j, k, m) * eta(i, j, k, n) * eta(i, j, k, n) *
192 (mechanics.model[m].F0 - mechanics.model[n].F0))
196 elastic_df_m += (dF0deta.transpose() * sig).trace();
200 if (pf.threshold.mechanics)
201 driving_force_threshold -= pf.elastic_mult * elastic_df_m;
203 driving_force -= pf.elastic_mult * elastic_df_m;
212 if (!anisotropic_kinetics.on || time < anisotropic_kinetics.tstart)
215 threshold = pf.threshold.value;
221 L = (4. / 3.) * anisotropic_kinetics.mobility(theta) / pf.l_gb;
222 threshold = anisotropic_kinetics.threshold(theta);
228 if (driving_force_threshold > threshold)
230 if (pf.threshold.type == ThresholdType::Continuous)
231 totaldf -= L * (driving_force_threshold - threshold);
232 else if (pf.threshold.type == ThresholdType::Chop)
233 totaldf -= L * (driving_force_threshold);
235 else if (driving_force_threshold < -threshold)
237 if (pf.threshold.type == ThresholdType::Continuous)
238 totaldf -= L * (driving_force_threshold + threshold);
239 else if (pf.threshold.type == ThresholdType::Chop)
240 totaldf -= L * (driving_force_threshold);
243 totaldf -= L * driving_force;
246 etanew(i, j, k, m) = eta(i,j,k,m) + dt * totaldf;
247 *df_max_handle = std::max(df_max, std::fabs(totaldf));
252 if (shearcouple.on && time >= mechanics.tstart) UpdateEigenstrain(lev);
335 BL_PROFILE(
"PhaseFieldMicrostructure::UpdateModel");
336 if (a_step % this->m_interval)
return;
338 for (
int lev = 0; lev <= this->finest_level; ++lev)
340 amrex::Box domain = this->geom[lev].Domain();
341 domain.convert(amrex::IntVect::TheNodeVector());
343 eta_mf[lev]->FillBoundary();
345 for (MFIter mfi(*this->model_mf[lev],
false); mfi.isValid(); ++mfi)
347 amrex::Box bx = mfi.grownnodaltilebox() & domain;
349 amrex::Array4<model_type>
const& model = this->model_mf[lev]->array(mfi);
350 amrex::Array4<const Set::Scalar>
const& eta = eta_mf[lev]->array(mfi);
352 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
354 std::vector<Set::Scalar> etas(number_of_grains);
355 for (
int n = 0; n < number_of_grains; n++)
357 model_type mix = model_type::Combine(mechanics.model, etas, mechanics.model_mix_order);
358 if (a_step == 0 || !shearcouple.on)
364 model(i,j,k).F0 = F0;
369 if (mechanics.model_neumann_boundary)
372 for (MFIter mfi(*this->model_mf[lev],
false); mfi.isValid(); ++mfi)
374 amrex::Box bx = mfi.grownnodaltilebox() & domain;
375 amrex::Array4<model_type>
const& model = this->model_mf[lev]->array(mfi);
376 const Dim3 lo = amrex::lbound(domain), hi = amrex::ubound(domain);
378 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k)
380 if (i==lo.x && j==lo.y)
381 model(i,j,k) = 0.5*(model(i+1,j,k)+model(i,j+1,k));
382 else if (i==lo.x && j==hi.y)
383 model(i,j,k) = 0.5*(model(i+1,j,k)+model(i,j-1,k));
384 else if (i==hi.x && j==lo.y)
385 model(i,j,k) = 0.5*(model(i-1,j,k)+model(i,j+1,k));
386 else if (i==hi.x && j==hi.y)
387 model(i,j,k) = 0.5*(model(i-1,j,k)+model(i,j-1,k));
390 model(i,j,k) = model(i+1,j,k);
392 model(i,j,k) = model(i-1,j,k);
394 model(i,j,k) = model(i,j+1,k);
396 model(i,j,k) = model(i,j-1,k);
433 const amrex::MFIter& mfi,
const amrex::Box& box)
435 BL_PROFILE(
"PhaseFieldMicrostructure::Integrate");
439 const amrex::Real* DX = this->geom[amrlev].CellSize();
440 Set::Scalar dv = AMREX_D_TERM(DX[0], *DX[1], *DX[2]);
442 amrex::Array4<amrex::Real>
const& eta = (*eta_mf[amrlev]).array(mfi);
443 amrex::ParallelFor(box, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
444#if AMREX_SPACEDIM == 2
448 volume += eta(i, j, k, 0) * dv;
460 if (!anisotropy.on || time < anisotropy.tstart)
462 gbenergy += pf.sigma0 * da;
464 realgbenergy += 0.5 * k * normgrad * normgrad * dv;
469#if AMREX_SPACEDIM == 2
472 gbenergy += sigma * da;
475 realgbenergy += 0.5 * k * normgrad * normgrad * dv;
480 regenergy += 0.5 * anisotropy.beta * k2 * k2;
481#elif AMREX_SPACEDIM == 3
482 gbenergy += gbmodel.
W(normal) * da;