xref: /petsc/src/ts/interface/tshistory.c (revision efa12513287cff49a2b9648ae83199dcbfaad71a)
1 #include <petsc/private/tshistoryimpl.h>
2 
3 /* These macros can be moved to petscimpl.h eventually */
4 #if defined(PETSC_USE_DEBUG)
5 
6 #define PetscValidLogicalCollectiveIntComm(a,b,c)                       \
7   do {                                                                  \
8     PetscErrorCode _7_ierr;                                             \
9     PetscInt b1[2],b2[2];                                               \
10     b1[0] = -b; b1[1] = b;                                              \
11     _7_ierr = MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,a);CHKERRQ(_7_ierr); \
12     if (-b2[0] != b2[1]) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",c); \
13   } while (0)
14 
15 #define PetscValidLogicalCollectiveBoolComm(a,b,c)                      \
16   do {                                                                  \
17     PetscErrorCode _7_ierr;                                             \
18     PetscMPIInt b1[2],b2[2];                                            \
19     b1[0] = -(PetscMPIInt)b; b1[1] = (PetscMPIInt)b;                    \
20     _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,a);CHKERRQ(_7_ierr); \
21     if (-b2[0] != b2[1]) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",c); \
22   } while (0)
23 
24 #define PetscValidLogicalCollectiveRealComm(a,b,c)                      \
25   do {                                                                  \
26     PetscErrorCode _7_ierr;                                             \
27     PetscReal b1[3],b2[3];                                              \
28     if (PetscIsNanReal(b)) {b1[2] = 1;} else {b1[2] = 0;};              \
29     b1[0] = -b; b1[1] = b;                                              \
30     _7_ierr = MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,a);CHKERRMPI(_7_ierr); \
31     if (!(b2[2] > 0) && !PetscEqualReal(-b2[0],b2[1])) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",c); \
32   } while (0)
33 
34 #else
35 
36 #define PetscValidLogicalCollectiveRealComm(a,b,c) do {} while (0)
37 #define PetscValidLogicalCollectiveIntComm(a,b,c) do {} while (0)
38 #define PetscValidLogicalCollectiveBoolComm(a,b,c) do {} while (0)
39 
40 #endif
41 
42 struct _n_TSHistory {
43   MPI_Comm  comm;     /* used for runtime collective checks */
44   PetscReal *hist;    /* time history */
45   PetscInt  *hist_id; /* stores the stepid in time history */
46   PetscInt  n;        /* current number of steps registered */
47   PetscBool sorted;   /* if the history is sorted in ascending order */
48   PetscInt  c;        /* current capacity of hist */
49   PetscInt  s;        /* reallocation size */
50 };
51 
52 PetscErrorCode TSHistoryGetNumSteps(TSHistory tsh, PetscInt *n)
53 {
54   PetscFunctionBegin;
55   PetscValidPointer(n,2);
56   *n = tsh->n;
57   PetscFunctionReturn(0);
58 }
59 
60 PetscErrorCode TSHistoryUpdate(TSHistory tsh, PetscInt id, PetscReal time)
61 {
62   PetscErrorCode ierr;
63 
64   PetscFunctionBegin;
65   PetscValidLogicalCollectiveIntComm(tsh->comm,id,2);
66   PetscValidLogicalCollectiveRealComm(tsh->comm,time,3);
67   if (tsh->n == tsh->c) { /* reallocation */
68     tsh->c += tsh->s;
69     ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist),&tsh->hist);CHKERRQ(ierr);
70     ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist_id),&tsh->hist_id);CHKERRQ(ierr);
71   }
72   tsh->sorted = (PetscBool)(tsh->sorted && (tsh->n ? time >= tsh->hist[tsh->n-1] : PETSC_TRUE));
73 #if defined(PETSC_USE_DEBUG)
74   if (tsh->n) { /* id should be unique */
75     PetscInt loc,*ids;
76 
77     ierr = PetscMalloc1(tsh->n,&ids);CHKERRQ(ierr);
78     ierr = PetscArraycpy(ids,tsh->hist_id,tsh->n);CHKERRQ(ierr);
79     ierr = PetscSortInt(tsh->n,ids);CHKERRQ(ierr);
80     ierr = PetscFindInt(id,tsh->n,ids,&loc);CHKERRQ(ierr);
81     ierr = PetscFree(ids);CHKERRQ(ierr);
82     if (loc >=0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"History id should be unique");
83   }
84 #endif
85   tsh->hist[tsh->n]    = time;
86   tsh->hist_id[tsh->n] = id;
87   tsh->n += 1;
88   PetscFunctionReturn(0);
89 }
90 
91 PetscErrorCode TSHistoryGetTime(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *t)
92 {
93   PetscFunctionBegin;
94   PetscValidLogicalCollectiveBoolComm(tsh->comm,backward,2);
95   PetscValidLogicalCollectiveIntComm(tsh->comm,step,3);
96   if (!t) PetscFunctionReturn(0);
97   PetscValidRealPointer(t,4);
98   if (!tsh->sorted) {
99     PetscErrorCode ierr;
100 
101     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
102     tsh->sorted = PETSC_TRUE;
103   }
104   if (step < 0 || step >= tsh->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Given time step %D does not match any in history [0,%D]",step,tsh->n);
105   if (!backward) *t = tsh->hist[step];
106   else           *t = tsh->hist[tsh->n-step-1];
107   PetscFunctionReturn(0);
108 }
109 
110 PetscErrorCode TSHistoryGetTimeStep(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *dt)
111 {
112   PetscFunctionBegin;
113   PetscValidLogicalCollectiveBoolComm(tsh->comm,backward,2);
114   PetscValidLogicalCollectiveIntComm(tsh->comm,step,3);
115   if (!dt) PetscFunctionReturn(0);
116   PetscValidRealPointer(dt,4);
117   if (!tsh->sorted) {
118     PetscErrorCode ierr;
119 
120     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
121     tsh->sorted = PETSC_TRUE;
122   }
123   if (step < 0 || step > tsh->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Given time step %D does not match any in history [0,%D]",step,tsh->n);
124   if (!backward) *dt = tsh->hist[PetscMin(step+1,tsh->n-1)] - tsh->hist[PetscMin(step,tsh->n-1)];
125   else           *dt = tsh->hist[PetscMax(tsh->n-step-1,0)] - tsh->hist[PetscMax(tsh->n-step-2,0)];
126   PetscFunctionReturn(0);
127 }
128 
129 PetscErrorCode TSHistoryGetLocFromTime(TSHistory tsh, PetscReal time, PetscInt *loc)
130 {
131   PetscErrorCode ierr;
132 
133   PetscFunctionBegin;
134   PetscValidLogicalCollectiveRealComm(tsh->comm,time,2);
135   PetscValidIntPointer(loc,3);
136   if (!tsh->sorted) {
137     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
138     tsh->sorted = PETSC_TRUE;
139   }
140   ierr = PetscFindReal(time,tsh->n,tsh->hist,PETSC_SMALL,loc);CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 PetscErrorCode TSHistorySetHistory(TSHistory tsh, PetscInt n, PetscReal hist[], PetscInt hist_id[], PetscBool sorted)
145 {
146   PetscInt       i;
147   PetscErrorCode ierr;
148 
149   PetscFunctionBegin;
150   PetscValidLogicalCollectiveIntComm(tsh->comm,n,2);
151   if (n) PetscValidRealPointer(hist,3);
152   ierr = PetscFree(tsh->hist);CHKERRQ(ierr);
153   ierr = PetscFree(tsh->hist_id);CHKERRQ(ierr);
154   tsh->n = n;
155   tsh->c = n;
156   ierr = PetscMalloc1(tsh->n,&tsh->hist);CHKERRQ(ierr);
157   ierr = PetscMalloc1(tsh->n,&tsh->hist_id);CHKERRQ(ierr);
158   for (i = 0; i < tsh->n; i++) {
159     tsh->hist[i]    = hist[i];
160     tsh->hist_id[i] = hist_id ? hist_id[i] : i;
161   }
162   if (!sorted) {
163     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
164   }
165   tsh->sorted = PETSC_TRUE;
166   PetscFunctionReturn(0);
167 }
168 
169 PetscErrorCode TSHistoryGetHistory(TSHistory tsh, PetscInt *n, const PetscReal* hist[], const PetscInt* hist_id[], PetscBool *sorted)
170 {
171   PetscFunctionBegin;
172   if (n)             *n = tsh->n;
173   if (hist)       *hist = tsh->hist;
174   if (hist_id) *hist_id = tsh->hist_id;
175   if (sorted)   *sorted = tsh->sorted;
176   PetscFunctionReturn(0);
177 }
178 
179 PetscErrorCode TSHistoryDestroy(TSHistory *tsh)
180 {
181   PetscErrorCode ierr;
182 
183   PetscFunctionBegin;
184   if (!*tsh) PetscFunctionReturn(0);
185   ierr = PetscFree((*tsh)->hist);CHKERRQ(ierr);
186   ierr = PetscFree((*tsh)->hist_id);CHKERRQ(ierr);
187   ierr = PetscCommDestroy(&((*tsh)->comm));CHKERRQ(ierr);
188   ierr = PetscFree((*tsh));CHKERRQ(ierr);
189   *tsh = NULL;
190   PetscFunctionReturn(0);
191 }
192 
193 PetscErrorCode TSHistoryCreate(MPI_Comm comm, TSHistory *hst)
194 {
195   TSHistory      tsh;
196   PetscErrorCode ierr;
197 
198   PetscFunctionBegin;
199   PetscValidPointer(hst,2);
200   *hst = NULL;
201   ierr = PetscNew(&tsh);CHKERRQ(ierr);
202   ierr = PetscCommDuplicate(comm,&tsh->comm,NULL);CHKERRQ(ierr);
203 
204   tsh->c      = 1024; /* capacity */
205   tsh->s      = 1024; /* reallocation size */
206   tsh->sorted = PETSC_TRUE;
207 
208   ierr = PetscMalloc1(tsh->c,&tsh->hist);CHKERRQ(ierr);
209   ierr = PetscMalloc1(tsh->c,&tsh->hist_id);CHKERRQ(ierr);
210   *hst = tsh;
211   PetscFunctionReturn(0);
212 }
213