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