1af0996ceSBarry Smith #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/
286e171c2SStefano Zampini #include <petscdm.h>
384df9cb4SJed Brown
TSAdaptChoose_Basic(TSAdapt adapt,TS ts,PetscReal h,PetscInt * next_sc,PetscReal * next_h,PetscBool * accept,PetscReal * wlte,PetscReal * wltea,PetscReal * wlter)4d71ae5a4SJacob Faibussowitsch static PetscErrorCode TSAdaptChoose_Basic(TSAdapt adapt, TS ts, PetscReal h, PetscInt *next_sc, PetscReal *next_h, PetscBool *accept, PetscReal *wlte, PetscReal *wltea, PetscReal *wlter)
5d71ae5a4SJacob Faibussowitsch {
686e171c2SStefano Zampini Vec Y;
786e171c2SStefano Zampini DM dm;
8b1f5bccaSLisandro Dalcin PetscInt order = PETSC_DECIDE;
9b1f5bccaSLisandro Dalcin PetscReal enorm = -1;
107453f775SEmil Constantinescu PetscReal enorma, enormr;
111917a363SLisandro Dalcin PetscReal safety = adapt->safety;
12b1f5bccaSLisandro Dalcin PetscReal hfac_lte, h_lte;
1384df9cb4SJed Brown
1484df9cb4SJed Brown PetscFunctionBegin;
151566a47fSLisandro Dalcin *next_sc = 0; /* Reuse the same order scheme */
16bf997491SLisandro Dalcin *wltea = -1; /* Weighted absolute local truncation error is not used */
17bf997491SLisandro Dalcin *wlter = -1; /* Weighted relative local truncation error is not used */
181566a47fSLisandro Dalcin
191ebf93c6SLisandro Dalcin if (ts->ops->evaluatewlte) {
209566063dSJacob Faibussowitsch PetscCall(TSEvaluateWLTE(ts, adapt->wnormtype, &order, &enorm));
21cad9d221SBarry Smith PetscCheck(enorm < 0 || order >= 1, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Computed error order %" PetscInt_FMT " must be positive", order);
221566a47fSLisandro Dalcin } else if (ts->ops->evaluatestep) {
2308401ef6SPierre Jolivet PetscCheck(adapt->candidates.n >= 1, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_WRONGSTATE, "No candidate has been registered");
2463a3b9bcSJacob Faibussowitsch PetscCheck(adapt->candidates.inuse_set, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_WRONGSTATE, "The current in-use scheme is not among the %" PetscInt_FMT " candidates", adapt->candidates.n);
251566a47fSLisandro Dalcin order = adapt->candidates.order[0];
269566063dSJacob Faibussowitsch PetscCall(TSGetDM(ts, &dm));
279566063dSJacob Faibussowitsch PetscCall(DMGetGlobalVector(dm, &Y));
289566063dSJacob Faibussowitsch PetscCall(TSEvaluateStep(ts, order - 1, Y, NULL));
299566063dSJacob Faibussowitsch PetscCall(TSErrorWeightedNorm(ts, ts->vec_sol, Y, adapt->wnormtype, &enorm, &enorma, &enormr));
309566063dSJacob Faibussowitsch PetscCall(DMRestoreGlobalVector(dm, &Y));
311ebf93c6SLisandro Dalcin }
321c3436cfSJed Brown
331566a47fSLisandro Dalcin if (enorm < 0) {
341566a47fSLisandro Dalcin *accept = PETSC_TRUE;
351566a47fSLisandro Dalcin *next_h = h; /* Reuse the old step */
361566a47fSLisandro Dalcin *wlte = -1; /* Weighted local truncation error was not evaluated */
373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
381566a47fSLisandro Dalcin }
391566a47fSLisandro Dalcin
401566a47fSLisandro Dalcin /* Determine whether the step is accepted of rejected */
411566a47fSLisandro Dalcin if (enorm > 1) {
421917a363SLisandro Dalcin if (!*accept) safety *= adapt->reject_safety; /* The last attempt also failed, shorten more aggressively */
43fd94acc0SJed Brown if (h < (1 + PETSC_SQRT_MACHINE_EPSILON) * adapt->dt_min) {
449566063dSJacob Faibussowitsch PetscCall(PetscInfo(adapt, "Estimated scaled local truncation error %g, accepting because step size %g is at minimum\n", (double)enorm, (double)h));
45fd94acc0SJed Brown *accept = PETSC_TRUE;
46bf997491SLisandro Dalcin } else if (adapt->always_accept) {
479566063dSJacob Faibussowitsch PetscCall(PetscInfo(adapt, "Estimated scaled local truncation error %g, accepting step of size %g because always_accept is set\n", (double)enorm, (double)h));
487e1ba4dcSJed Brown *accept = PETSC_TRUE;
491c3436cfSJed Brown } else {
509566063dSJacob Faibussowitsch PetscCall(PetscInfo(adapt, "Estimated scaled local truncation error %g, rejecting step of size %g\n", (double)enorm, (double)h));
51fd94acc0SJed Brown *accept = PETSC_FALSE;
52fd94acc0SJed Brown }
53fd94acc0SJed Brown } else {
549566063dSJacob Faibussowitsch PetscCall(PetscInfo(adapt, "Estimated scaled local truncation error %g, accepting step of size %g\n", (double)enorm, (double)h));
55fd94acc0SJed Brown *accept = PETSC_TRUE;
561c3436cfSJed Brown }
571c3436cfSJed Brown
581c3436cfSJed Brown /* The optimal new step based purely on local truncation error for this step. */
599371c9d4SSatish Balay if (enorm > 0) hfac_lte = safety * PetscPowReal(enorm, ((PetscReal)-1) / order);
609371c9d4SSatish Balay else hfac_lte = safety * PETSC_INFINITY;
61de50f1caSBarry Smith if (adapt->timestepjustdecreased) {
62a191cbb8SBarry Smith hfac_lte = PetscMin(hfac_lte, 1.0);
63de50f1caSBarry Smith adapt->timestepjustdecreased--;
64a191cbb8SBarry Smith }
651917a363SLisandro Dalcin h_lte = h * PetscClipInterval(hfac_lte, adapt->clip[0], adapt->clip[1]);
661c3436cfSJed Brown
671c3436cfSJed Brown *next_h = PetscClipInterval(h_lte, adapt->dt_min, adapt->dt_max);
680b99f514SJed Brown *wlte = enorm;
693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
7084df9cb4SJed Brown }
7184df9cb4SJed Brown
7284df9cb4SJed Brown /*MC
7384df9cb4SJed Brown TSADAPTBASIC - Basic adaptive controller for time stepping
7484df9cb4SJed Brown
7584df9cb4SJed Brown Level: intermediate
7684df9cb4SJed Brown
77*efa39862SBarry Smith .seealso: [](ch_ts), [](sec_ts_error_control), `TS`, `TSAdapt`, `TSGetAdapt()`, `TSAdaptType`
7884df9cb4SJed Brown M*/
TSAdaptCreate_Basic(TSAdapt adapt)79d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt adapt)
80d71ae5a4SJacob Faibussowitsch {
8184df9cb4SJed Brown PetscFunctionBegin;
821c3436cfSJed Brown adapt->ops->choose = TSAdaptChoose_Basic;
833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
841b9b13dfSLisandro Dalcin }
85