Skip to content

Commit df323de

Browse files
authored
some BackwardEuler fixes (#1977)
we were not always rolling back the solution on a single step failure. Now we do this for all errors. we were possibly using a fine-step solution in the error estimator even if we were not successful in the fine step advance.
1 parent 94778b8 commit df323de

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

integration/BackwardEuler/be_integrator.H

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -171,17 +171,14 @@ int single_step (BurnT& state, BeT& be, const amrex::Real dt)
171171
if (! converged) {
172172

173173
if (ierr == IERR_SUCCESS) {
174-
175174
// if we didn't set another error, then we probably ran
176175
// out of iterations, so set nonconvergence
177-
178176
ierr = IERR_CORRECTOR_CONVERGENCE;
177+
}
179178

180-
// reset the solution to the original
181-
for (int n = 1; n <= int_neqs; n++) {
182-
be.y(n) = y_old(n);
183-
}
184-
179+
// reset the solution to the original on any failure
180+
for (int n = 1; n <= int_neqs; n++) {
181+
be.y(n) = y_old(n);
185182
}
186183

187184
}
@@ -206,7 +203,9 @@ int be_integrator (BurnT& state, BeT& be)
206203
// Do a single step to the final time
207204
const amrex::Real dt_single_step = be.tout - be.t;
208205
ierr = single_step(state, be, dt_single_step);
209-
be.t = be.tout;
206+
if (ierr == IERR_SUCCESS) {
207+
be.t = be.tout;
208+
}
210209
++be.n_step;
211210
return ierr;
212211
}
@@ -240,50 +239,55 @@ int be_integrator (BurnT& state, BeT& be)
240239
// our strategy is to take 2 steps at dt/2 and one at dt and
241240
// to compute the error from those
242241

243-
244-
// try to take a step dt
245-
246242
// first do 2 (fine) dt/2 steps
247243

248244
amrex::Array1D<amrex::Real, 1, int_neqs> y_fine;
249245

246+
// keep track of whether we have a valid fine solution
247+
// this means no errors from either half step
248+
bool have_fine_solution = false;
249+
250250
ierr = single_step(state, be, dt_sub/2);
251251
if (ierr == IERR_SUCCESS) {
252252
ierr = single_step(state, be, dt_sub/2);
253253

254-
// store the fine dt solution
255-
256-
for (int n = 1; n <= int_neqs; ++n) {
257-
y_fine(n) = be.y(n);
258-
}
254+
if (ierr == IERR_SUCCESS) {
255+
// store the fine dt solution
256+
for (int n = 1; n <= int_neqs; ++n) {
257+
y_fine(n) = be.y(n);
258+
}
259+
have_fine_solution = true;
259260

260-
// now that single (coarse) dt step
261-
// first reset the solution
262-
for (int n = 1; n <= int_neqs; ++n) {
263-
be.y(n) = y_old(n);
261+
// now do a single (coarse) dt step
262+
// first reset the solution
263+
for (int n = 1; n <= int_neqs; ++n) {
264+
be.y(n) = y_old(n);
265+
}
266+
ierr = single_step(state, be, dt_sub);
264267
}
265-
ierr = single_step(state, be, dt_sub);
266268
}
267269

268-
// define a weight for each variable to use in checking the error
270+
amrex::Real rel_error = 0.0_rt;
271+
bool step_success = false;
272+
if (ierr == IERR_SUCCESS && have_fine_solution) {
273+
// define a weight for each variable to use in checking the error
269274

270-
amrex::Array1D<amrex::Real, 1, int_neqs> w;
271-
for (int n = 1; n <= NumSpec; n++) {
272-
w(n) = 1.0_rt / (be.rtol_spec * std::abs(y_fine(n)) + be.atol_spec);
273-
}
274-
w(net_ienuc) = 1.0_rt / (be.rtol_enuc * std::abs(y_fine(net_ienuc)) + be.atol_enuc);
275+
amrex::Array1D<amrex::Real, 1, int_neqs> w;
276+
for (int n = 1; n <= NumSpec; n++) {
277+
w(n) = 1.0_rt / (be.rtol_spec * std::abs(y_fine(n)) + be.atol_spec);
278+
}
279+
w(net_ienuc) = 1.0_rt / (be.rtol_enuc * std::abs(y_fine(net_ienuc)) + be.atol_enuc);
275280

276-
// now look for w |y_fine - y_coarse| < 1
281+
// now look for w |y_fine - y_coarse| < 1
277282

278-
amrex::Real rel_error = 0.0_rt;
279-
for (int n = 1; n <= NumSpec; n++) {
280-
rel_error = amrex::max(rel_error, w(n) * std::abs(y_fine(n) - be.y(n)));
281-
}
282-
rel_error = amrex::max(rel_error, w(net_ienuc) * std::abs(y_fine(net_ienuc) - be.y(net_ienuc)));
283+
for (int n = 1; n <= NumSpec; n++) {
284+
rel_error = amrex::max(rel_error, w(n) * std::abs(y_fine(n) - be.y(n)));
285+
}
286+
rel_error = amrex::max(rel_error, w(net_ienuc) * std::abs(y_fine(net_ienuc) - be.y(net_ienuc)));
283287

284-
bool step_success = false;
285-
if (rel_error < 1.0_rt) {
286-
step_success = true;
288+
if (rel_error < 1.0_rt) {
289+
step_success = true;
290+
}
287291
}
288292

289293
if (ierr == IERR_SUCCESS && step_success) {

0 commit comments

Comments
 (0)