xref: /petsc/src/ts/interface/tshistory.c (revision 115dd874ad11c2dfdfe8de0e926d279faa2e2e8e)
189818f9dSStefano Zampini #include <petsc/private/tshistoryimpl.h>
289818f9dSStefano Zampini 
389818f9dSStefano Zampini /* These macros can be moved to petscimpl.h eventually */
489818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG)
589818f9dSStefano Zampini 
689818f9dSStefano Zampini #define PetscValidLogicalCollectiveIntComm(a,b,c)                       \
789818f9dSStefano Zampini   do {                                                                  \
889818f9dSStefano Zampini     PetscErrorCode _7_ierr;                                             \
989818f9dSStefano Zampini     PetscInt b1[2],b2[2];                                               \
1089818f9dSStefano Zampini     b1[0] = -b; b1[1] = b;                                              \
11820f2d46SBarry Smith     _7_ierr = MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,a);CHKERRMPI(_7_ierr); \
122c71b3e2SJacob Faibussowitsch     PetscCheckFalse(-b2[0] != b2[1],a,PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",c); \
1389818f9dSStefano Zampini   } while (0)
1489818f9dSStefano Zampini 
1589818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c)                      \
1689818f9dSStefano Zampini   do {                                                                  \
1789818f9dSStefano Zampini     PetscErrorCode _7_ierr;                                             \
1889818f9dSStefano Zampini     PetscMPIInt b1[2],b2[2];                                            \
1989818f9dSStefano Zampini     b1[0] = -(PetscMPIInt)b; b1[1] = (PetscMPIInt)b;                    \
20820f2d46SBarry Smith     _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,a);CHKERRMPI(_7_ierr); \
212c71b3e2SJacob Faibussowitsch     PetscCheckFalse(-b2[0] != b2[1],a,PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",c); \
2289818f9dSStefano Zampini   } while (0)
2389818f9dSStefano Zampini 
2489818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c)                      \
2589818f9dSStefano Zampini   do {                                                                  \
2689818f9dSStefano Zampini     PetscErrorCode _7_ierr;                                             \
2789818f9dSStefano Zampini     PetscReal b1[3],b2[3];                                              \
2889818f9dSStefano Zampini     if (PetscIsNanReal(b)) {b1[2] = 1;} else {b1[2] = 0;};              \
2989818f9dSStefano Zampini     b1[0] = -b; b1[1] = b;                                              \
30ffc4695bSBarry Smith     _7_ierr = MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,a);CHKERRMPI(_7_ierr); \
312c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!(b2[2] > 0) && !PetscEqualReal(-b2[0],b2[1]),a,PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",c); \
3289818f9dSStefano Zampini   } while (0)
3389818f9dSStefano Zampini 
3489818f9dSStefano Zampini #else
3589818f9dSStefano Zampini 
3689818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c) do {} while (0)
3789818f9dSStefano Zampini #define PetscValidLogicalCollectiveIntComm(a,b,c) do {} while (0)
3889818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c) do {} while (0)
3989818f9dSStefano Zampini 
4089818f9dSStefano Zampini #endif
4189818f9dSStefano Zampini 
4289818f9dSStefano Zampini struct _n_TSHistory {
4389818f9dSStefano Zampini   MPI_Comm  comm;     /* used for runtime collective checks */
4489818f9dSStefano Zampini   PetscReal *hist;    /* time history */
4589818f9dSStefano Zampini   PetscInt  *hist_id; /* stores the stepid in time history */
46*115dd874SBarry Smith   size_t    n;        /* current number of steps registered */
4789818f9dSStefano Zampini   PetscBool sorted;   /* if the history is sorted in ascending order */
48*115dd874SBarry Smith   size_t    c;        /* current capacity of history */
49*115dd874SBarry Smith   size_t    s;        /* reallocation size */
5089818f9dSStefano Zampini };
5189818f9dSStefano Zampini 
5289818f9dSStefano Zampini PetscErrorCode TSHistoryGetNumSteps(TSHistory tsh, PetscInt *n)
5389818f9dSStefano Zampini {
5489818f9dSStefano Zampini   PetscFunctionBegin;
5589818f9dSStefano Zampini   PetscValidPointer(n,2);
5689818f9dSStefano Zampini   *n = tsh->n;
5789818f9dSStefano Zampini   PetscFunctionReturn(0);
5889818f9dSStefano Zampini }
5989818f9dSStefano Zampini 
6089818f9dSStefano Zampini PetscErrorCode TSHistoryUpdate(TSHistory tsh, PetscInt id, PetscReal time)
6189818f9dSStefano Zampini {
6289818f9dSStefano Zampini   PetscErrorCode ierr;
6389818f9dSStefano Zampini 
6489818f9dSStefano Zampini   PetscFunctionBegin;
6589818f9dSStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm,id,2);
6689818f9dSStefano Zampini   PetscValidLogicalCollectiveRealComm(tsh->comm,time,3);
6789818f9dSStefano Zampini   if (tsh->n == tsh->c) { /* reallocation */
6889818f9dSStefano Zampini     tsh->c += tsh->s;
6989818f9dSStefano Zampini     ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist),&tsh->hist);CHKERRQ(ierr);
7089818f9dSStefano Zampini     ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist_id),&tsh->hist_id);CHKERRQ(ierr);
7189818f9dSStefano Zampini   }
7289818f9dSStefano Zampini   tsh->sorted = (PetscBool)(tsh->sorted && (tsh->n ? time >= tsh->hist[tsh->n-1] : PETSC_TRUE));
7389818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG)
7489818f9dSStefano Zampini   if (tsh->n) { /* id should be unique */
7589818f9dSStefano Zampini     PetscInt loc,*ids;
7689818f9dSStefano Zampini 
7789818f9dSStefano Zampini     ierr = PetscMalloc1(tsh->n,&ids);CHKERRQ(ierr);
78580bdb30SBarry Smith     ierr = PetscArraycpy(ids,tsh->hist_id,tsh->n);CHKERRQ(ierr);
7989818f9dSStefano Zampini     ierr = PetscSortInt(tsh->n,ids);CHKERRQ(ierr);
8089818f9dSStefano Zampini     ierr = PetscFindInt(id,tsh->n,ids,&loc);CHKERRQ(ierr);
8189818f9dSStefano Zampini     ierr = PetscFree(ids);CHKERRQ(ierr);
822c71b3e2SJacob Faibussowitsch     PetscCheckFalse(loc >=0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"History id should be unique");
8389818f9dSStefano Zampini   }
8489818f9dSStefano Zampini #endif
8589818f9dSStefano Zampini   tsh->hist[tsh->n]    = time;
8689818f9dSStefano Zampini   tsh->hist_id[tsh->n] = id;
8789818f9dSStefano Zampini   tsh->n += 1;
8889818f9dSStefano Zampini   PetscFunctionReturn(0);
8989818f9dSStefano Zampini }
9089818f9dSStefano Zampini 
918a32c442SStefano Zampini PetscErrorCode TSHistoryGetTime(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *t)
928a32c442SStefano Zampini {
938a32c442SStefano Zampini   PetscFunctionBegin;
948a32c442SStefano Zampini   PetscValidLogicalCollectiveBoolComm(tsh->comm,backward,2);
958a32c442SStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm,step,3);
968a32c442SStefano Zampini   if (!t) PetscFunctionReturn(0);
978a32c442SStefano Zampini   PetscValidRealPointer(t,4);
988a32c442SStefano Zampini   if (!tsh->sorted) {
998a32c442SStefano Zampini     PetscErrorCode ierr;
1008a32c442SStefano Zampini 
1018a32c442SStefano Zampini     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
1028a32c442SStefano Zampini     tsh->sorted = PETSC_TRUE;
1038a32c442SStefano Zampini   }
104*115dd874SBarry Smith   PetscCheck(step >= 0 && step < (PetscInt)tsh->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Given time step %D does not match any in history [0,%D]",step,(PetscInt)tsh->n);
1058a32c442SStefano Zampini   if (!backward) *t = tsh->hist[step];
1068a32c442SStefano Zampini   else           *t = tsh->hist[tsh->n-step-1];
1078a32c442SStefano Zampini   PetscFunctionReturn(0);
1088a32c442SStefano Zampini }
1098a32c442SStefano Zampini 
11089818f9dSStefano Zampini PetscErrorCode TSHistoryGetTimeStep(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *dt)
11189818f9dSStefano Zampini {
11289818f9dSStefano Zampini   PetscFunctionBegin;
11389818f9dSStefano Zampini   PetscValidLogicalCollectiveBoolComm(tsh->comm,backward,2);
11489818f9dSStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm,step,3);
1158a32c442SStefano Zampini   if (!dt) PetscFunctionReturn(0);
11689818f9dSStefano Zampini   PetscValidRealPointer(dt,4);
11789818f9dSStefano Zampini   if (!tsh->sorted) {
11889818f9dSStefano Zampini     PetscErrorCode ierr;
11989818f9dSStefano Zampini 
12089818f9dSStefano Zampini     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
12189818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
12289818f9dSStefano Zampini   }
123*115dd874SBarry Smith   PetscCheck(step >= 0 && step <= (PetscInt)tsh->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Given time step %D does not match any in history [0,%D]",step,(PetscInt)tsh->n);
124*115dd874SBarry Smith   if (!backward) *dt = tsh->hist[PetscMin(step+1,(PetscInt)tsh->n-1)] - tsh->hist[PetscMin(step,(PetscInt)tsh->n-1)];
125*115dd874SBarry Smith   else           *dt = tsh->hist[PetscMax((PetscInt)tsh->n-step-1,0)] - tsh->hist[PetscMax((PetscInt)tsh->n-step-2,0)];
12689818f9dSStefano Zampini   PetscFunctionReturn(0);
12789818f9dSStefano Zampini }
12889818f9dSStefano Zampini 
12989818f9dSStefano Zampini PetscErrorCode TSHistoryGetLocFromTime(TSHistory tsh, PetscReal time, PetscInt *loc)
13089818f9dSStefano Zampini {
13189818f9dSStefano Zampini   PetscErrorCode ierr;
13289818f9dSStefano Zampini 
13389818f9dSStefano Zampini   PetscFunctionBegin;
13489818f9dSStefano Zampini   PetscValidLogicalCollectiveRealComm(tsh->comm,time,2);
13589818f9dSStefano Zampini   PetscValidIntPointer(loc,3);
13689818f9dSStefano Zampini   if (!tsh->sorted) {
13789818f9dSStefano Zampini     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
13889818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
13989818f9dSStefano Zampini   }
14089818f9dSStefano Zampini   ierr = PetscFindReal(time,tsh->n,tsh->hist,PETSC_SMALL,loc);CHKERRQ(ierr);
14189818f9dSStefano Zampini   PetscFunctionReturn(0);
14289818f9dSStefano Zampini }
14389818f9dSStefano Zampini 
14489818f9dSStefano Zampini PetscErrorCode TSHistorySetHistory(TSHistory tsh, PetscInt n, PetscReal hist[], PetscInt hist_id[], PetscBool sorted)
14589818f9dSStefano Zampini {
14689818f9dSStefano Zampini   PetscInt       i;
14789818f9dSStefano Zampini   PetscErrorCode ierr;
14889818f9dSStefano Zampini 
14989818f9dSStefano Zampini   PetscFunctionBegin;
15089818f9dSStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm,n,2);
151*115dd874SBarry Smith   if (n < 0) SETERRQ(tsh->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot request a negative size for history storage");
15289818f9dSStefano Zampini   if (n) PetscValidRealPointer(hist,3);
15389818f9dSStefano Zampini   ierr = PetscFree(tsh->hist);CHKERRQ(ierr);
15489818f9dSStefano Zampini   ierr = PetscFree(tsh->hist_id);CHKERRQ(ierr);
155*115dd874SBarry Smith   tsh->n = (size_t) n;
156*115dd874SBarry Smith   tsh->c = (size_t) n;
15789818f9dSStefano Zampini   ierr = PetscMalloc1(tsh->n,&tsh->hist);CHKERRQ(ierr);
15889818f9dSStefano Zampini   ierr = PetscMalloc1(tsh->n,&tsh->hist_id);CHKERRQ(ierr);
159*115dd874SBarry Smith   for (i = 0; i < (PetscInt)tsh->n; i++) {
16089818f9dSStefano Zampini     tsh->hist[i]    = hist[i];
16189818f9dSStefano Zampini     tsh->hist_id[i] = hist_id ? hist_id[i] : i;
16289818f9dSStefano Zampini   }
16389818f9dSStefano Zampini   if (!sorted) {
16489818f9dSStefano Zampini     ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr);
16589818f9dSStefano Zampini   }
16689818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
16789818f9dSStefano Zampini   PetscFunctionReturn(0);
16889818f9dSStefano Zampini }
16989818f9dSStefano Zampini 
17089818f9dSStefano Zampini PetscErrorCode TSHistoryGetHistory(TSHistory tsh, PetscInt *n, const PetscReal* hist[], const PetscInt* hist_id[], PetscBool *sorted)
17189818f9dSStefano Zampini {
17289818f9dSStefano Zampini   PetscFunctionBegin;
17389818f9dSStefano Zampini   if (n)             *n = tsh->n;
17489818f9dSStefano Zampini   if (hist)       *hist = tsh->hist;
17589818f9dSStefano Zampini   if (hist_id) *hist_id = tsh->hist_id;
17689818f9dSStefano Zampini   if (sorted)   *sorted = tsh->sorted;
17789818f9dSStefano Zampini   PetscFunctionReturn(0);
17889818f9dSStefano Zampini }
17989818f9dSStefano Zampini 
18089818f9dSStefano Zampini PetscErrorCode TSHistoryDestroy(TSHistory *tsh)
18189818f9dSStefano Zampini {
18289818f9dSStefano Zampini   PetscErrorCode ierr;
18389818f9dSStefano Zampini 
18489818f9dSStefano Zampini   PetscFunctionBegin;
18589818f9dSStefano Zampini   if (!*tsh) PetscFunctionReturn(0);
18689818f9dSStefano Zampini   ierr = PetscFree((*tsh)->hist);CHKERRQ(ierr);
18789818f9dSStefano Zampini   ierr = PetscFree((*tsh)->hist_id);CHKERRQ(ierr);
18889818f9dSStefano Zampini   ierr = PetscCommDestroy(&((*tsh)->comm));CHKERRQ(ierr);
18989818f9dSStefano Zampini   ierr = PetscFree((*tsh));CHKERRQ(ierr);
19089818f9dSStefano Zampini   *tsh = NULL;
19189818f9dSStefano Zampini   PetscFunctionReturn(0);
19289818f9dSStefano Zampini }
19389818f9dSStefano Zampini 
19489818f9dSStefano Zampini PetscErrorCode TSHistoryCreate(MPI_Comm comm, TSHistory *hst)
19589818f9dSStefano Zampini {
19689818f9dSStefano Zampini   TSHistory      tsh;
19789818f9dSStefano Zampini   PetscErrorCode ierr;
19889818f9dSStefano Zampini 
19989818f9dSStefano Zampini   PetscFunctionBegin;
20089818f9dSStefano Zampini   PetscValidPointer(hst,2);
20189818f9dSStefano Zampini   *hst = NULL;
20289818f9dSStefano Zampini   ierr = PetscNew(&tsh);CHKERRQ(ierr);
20389818f9dSStefano Zampini   ierr = PetscCommDuplicate(comm,&tsh->comm,NULL);CHKERRQ(ierr);
20489818f9dSStefano Zampini 
20589818f9dSStefano Zampini   tsh->c      = 1024; /* capacity */
20689818f9dSStefano Zampini   tsh->s      = 1024; /* reallocation size */
20789818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
20889818f9dSStefano Zampini 
20989818f9dSStefano Zampini   ierr = PetscMalloc1(tsh->c,&tsh->hist);CHKERRQ(ierr);
21089818f9dSStefano Zampini   ierr = PetscMalloc1(tsh->c,&tsh->hist_id);CHKERRQ(ierr);
21189818f9dSStefano Zampini   *hst = tsh;
21289818f9dSStefano Zampini   PetscFunctionReturn(0);
21389818f9dSStefano Zampini }
214