xref: /petsc/src/ts/adapt/impls/glee/adaptglee.c (revision fc8a9adeb7fcdc98711d755fa2dc544ddccf0f3e)
1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/
2 
3 typedef struct {
4   Vec E,Y;
5 } TSAdapt_GLEE;
6 
7 static PetscErrorCode TSAdaptChoose_GLEE(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept,PetscReal *wlte,PetscReal *wltea,PetscReal *wlter)
8 {
9   TSAdapt_GLEE  *glee = (TSAdapt_GLEE*)adapt->data;
10   TSType         time_scheme;      /* Type of time-integration scheme        */
11   PetscErrorCode ierr;
12   Vec            X,Y,E;
13   PetscReal      enorm,enorma,enormr,hfac_lte,hfac_ltea,hfac_lter,h_lte,safety;
14   PetscInt       order;
15   PetscBool      bGTEMethod=PETSC_FALSE;
16 
17   PetscFunctionBegin;
18 
19   *next_sc = 0; /* Reuse the same order scheme */
20   safety = adapt->safety;
21   ierr = TSGetType(ts,&time_scheme);CHKERRQ(ierr);
22   if (!strcmp(time_scheme,TSGLEE)) bGTEMethod=PETSC_TRUE;
23   order = adapt->candidates.order[0];
24 
25   if (bGTEMethod){/* the method is of GLEE type */
26     ierr = TSGetSolution(ts,&X);CHKERRQ(ierr);
27     if (!glee->Y && adapt->glee_use_local) {
28       ierr = VecDuplicate(X,&glee->Y);CHKERRQ(ierr);/*create vector to store previous step global error*/
29       ierr = VecZeroEntries(glee->Y);CHKERRQ(ierr); /*set error to zero on the first step - may not work if error is not zero initially*/
30     }
31     if (!glee->E) {ierr = VecDuplicate(X,&glee->E);CHKERRQ(ierr);}
32     E    = glee->E;
33     ierr = TSGetTimeError(ts,0,&E);CHKERRQ(ierr);
34 
35     if (adapt->glee_use_local) {ierr = VecAXPY(E,-1.0,glee->Y);CHKERRQ(ierr);} /* local error = current error - previous step error */
36 
37     /* this should be called with the solution at the beginning of the step too*/
38     ierr = TSErrorWeightedENorm(ts,E,X,X,adapt->wnormtype,&enorm,&enorma,&enormr);CHKERRQ(ierr);
39   } else {
40     /* the method is NOT of GLEE type; use the stantard basic augmented by separate atol and rtol */
41     ierr = TSGetSolution(ts,&X);CHKERRQ(ierr);
42     if (!glee->Y) {ierr = VecDuplicate(X,&glee->Y);CHKERRQ(ierr);}
43     Y     = glee->Y;
44     ierr  = TSEvaluateStep(ts,order-1,Y,NULL);CHKERRQ(ierr);
45     ierr  = TSErrorWeightedNorm(ts,X,Y,adapt->wnormtype,&enorm,&enorma,&enormr);CHKERRQ(ierr);
46   }
47 
48   if (enorm < 0) {
49     *accept  = PETSC_TRUE;
50     *next_h  = h;            /* Reuse the old step */
51     *wlte    = -1;           /* Weighted error was not evaluated */
52     *wltea   = -1;           /* Weighted absolute error was not evaluated */
53     *wlter   = -1;           /* Weighted relative error was not evaluated */
54     PetscFunctionReturn(0);
55   }
56 
57   if (enorm > 1. || enorma > 1. || enormr > 1.) {
58     if (!*accept) safety *= adapt->reject_safety; /* The last attempt also failed, shorten more aggressively */
59     if (h < (1 + PETSC_SQRT_MACHINE_EPSILON)*adapt->dt_min) {
60       ierr    = PetscInfo4(adapt,"Estimated scaled truncation error [combined, absolute, relative]] [%g, %g, %g], accepting because step size %g is at minimum\n",(double)enorm,(double)enorma,(double)enormr,(double)h);CHKERRQ(ierr);
61       *accept = PETSC_TRUE;
62     } else if (adapt->always_accept) {
63       ierr    = PetscInfo4(adapt,"Estimated scaled truncation error [combined, absolute, relative]] [%g, %g, %g], accepting step of size %g because always_accept is set\n",(double)enorm,(double)enorma,(double)enormr,(double)h);CHKERRQ(ierr);
64       *accept = PETSC_TRUE;
65     } else {
66       ierr    = PetscInfo4(adapt,"Estimated scaled truncation error [combined, absolute, relative]] [%g, %g, %g], rejecting step of size %g\n",(double)enorm,(double)enorma,(double)enormr,(double)h);CHKERRQ(ierr);
67       *accept = PETSC_FALSE;
68     }
69   } else {
70     ierr    = PetscInfo4(adapt,"Estimated scaled truncation error [combined, absolute, relative] [%g, %g, %g], accepting step of size %g\n",(double)enorm,(double)enorma,(double)enormr,(double)h);CHKERRQ(ierr);
71     *accept = PETSC_TRUE;
72   }
73 
74   if (bGTEMethod){
75     if (*accept == PETSC_TRUE && adapt->glee_use_local) {
76       /* If step is accepted, then overwrite previous step error with the current error to be used on the next step */
77       /* WARNING: if the adapters are composable, then the accept test will not be reliable*/
78       ierr = TSGetTimeError(ts,0,&(glee->Y));CHKERRQ(ierr);
79     }
80 
81     /* The optimal new step based on the current global truncation error. */
82     if (enorm > 0) {
83       /* factor based on the absolute tolerance */
84       hfac_ltea = safety * PetscPowReal(1./enorma,((PetscReal)1)/(order+1));
85       /* factor based on the relative tolerance */
86       hfac_lter = safety * PetscPowReal(1./enormr,((PetscReal)1)/(order+1));
87       /* pick the minimum time step among the relative and absolute tolerances */
88       hfac_lte  = PetscMin(hfac_ltea,hfac_lter);
89     } else {
90       hfac_lte = safety * PETSC_INFINITY;
91     }
92     h_lte = h * PetscClipInterval(hfac_lte,adapt->clip[0],adapt->clip[1]);
93     *next_h = PetscClipInterval(h_lte,adapt->dt_min,adapt->dt_max);
94   } else {
95     /* The optimal new step based purely on local truncation error for this step. */
96     if (enorm > 0) {
97       /* factor based on the absolute tolerance */
98       hfac_ltea = safety * PetscPowReal(enorma,((PetscReal)-1)/order);
99       /* factor based on the relative tolerance */
100       hfac_lter = safety * PetscPowReal(enormr,((PetscReal)-1)/order);
101       /* pick the minimum time step among the relative and absolute tolerances */
102       hfac_lte  = PetscMin(hfac_ltea,hfac_lter);
103     } else {
104       hfac_lte = safety * PETSC_INFINITY;
105     }
106     h_lte = h * PetscClipInterval(hfac_lte,adapt->clip[0],adapt->clip[1]);
107     *next_h = PetscClipInterval(h_lte,adapt->dt_min,adapt->dt_max);
108   }
109   *wlte   = enorm;
110   *wltea  = enorma;
111   *wlter  = enormr;
112   PetscFunctionReturn(0);
113 }
114 
115 static PetscErrorCode TSAdaptReset_GLEE(TSAdapt adapt)
116 {
117   TSAdapt_GLEE  *glee = (TSAdapt_GLEE*)adapt->data;
118   PetscErrorCode ierr;
119 
120   PetscFunctionBegin;
121   ierr = VecDestroy(&glee->Y);CHKERRQ(ierr);
122   ierr = VecDestroy(&glee->E);CHKERRQ(ierr);
123   PetscFunctionReturn(0);
124 }
125 
126 static PetscErrorCode TSAdaptDestroy_GLEE(TSAdapt adapt)
127 {
128   PetscErrorCode ierr;
129 
130   PetscFunctionBegin;
131   ierr = TSAdaptReset_GLEE(adapt);CHKERRQ(ierr);
132   ierr = PetscFree(adapt->data);CHKERRQ(ierr);
133   PetscFunctionReturn(0);
134 }
135 
136 /*MC
137    TSADAPTGLEE - GLEE adaptive controller for time stepping
138 
139    Level: intermediate
140 
141 .seealso: TS, TSAdapt, TSGetAdapt()
142 M*/
143 PETSC_EXTERN PetscErrorCode TSAdaptCreate_GLEE(TSAdapt adapt)
144 {
145   PetscErrorCode ierr;
146   TSAdapt_GLEE  *glee;
147 
148   PetscFunctionBegin;
149   ierr = PetscNewLog(adapt,&glee);CHKERRQ(ierr);
150   adapt->data         = (void*)glee;
151   adapt->ops->choose  = TSAdaptChoose_GLEE;
152   adapt->ops->reset   = TSAdaptReset_GLEE;
153   adapt->ops->destroy = TSAdaptDestroy_GLEE;
154   PetscFunctionReturn(0);
155 }
156