xref: /petsc/src/ts/interface/tshistory.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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     PetscInt b1[2],b2[2];                                               \
989818f9dSStefano Zampini     b1[0] = -b; b1[1] = b;                                              \
10*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,a)); \
113c633725SBarry Smith     PetscCheck(-b2[0] == b2[1],a,PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",c); \
1289818f9dSStefano Zampini   } while (0)
1389818f9dSStefano Zampini 
1489818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c)                      \
1589818f9dSStefano Zampini   do {                                                                  \
1689818f9dSStefano Zampini     PetscMPIInt b1[2],b2[2];                                            \
1789818f9dSStefano Zampini     b1[0] = -(PetscMPIInt)b; b1[1] = (PetscMPIInt)b;                    \
18*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,a)); \
193c633725SBarry Smith     PetscCheck(-b2[0] == b2[1],a,PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",c); \
2089818f9dSStefano Zampini   } while (0)
2189818f9dSStefano Zampini 
2289818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c)                      \
2389818f9dSStefano Zampini   do {                                                                  \
2489818f9dSStefano Zampini     PetscReal b1[3],b2[3];                                              \
2589818f9dSStefano Zampini     if (PetscIsNanReal(b)) {b1[2] = 1;} else {b1[2] = 0;};              \
2689818f9dSStefano Zampini     b1[0] = -b; b1[1] = b;                                              \
27*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,a)); \
283c633725SBarry Smith     PetscCheck((b2[2] == 1) || PetscEqualReal(-b2[0],b2[1]),a,PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",c); \
2989818f9dSStefano Zampini   } while (0)
3089818f9dSStefano Zampini 
3189818f9dSStefano Zampini #else
3289818f9dSStefano Zampini 
3389818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c) do {} while (0)
3489818f9dSStefano Zampini #define PetscValidLogicalCollectiveIntComm(a,b,c) do {} while (0)
3589818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c) do {} while (0)
3689818f9dSStefano Zampini 
3789818f9dSStefano Zampini #endif
3889818f9dSStefano Zampini 
3989818f9dSStefano Zampini struct _n_TSHistory {
4089818f9dSStefano Zampini   MPI_Comm  comm;     /* used for runtime collective checks */
4189818f9dSStefano Zampini   PetscReal *hist;    /* time history */
4289818f9dSStefano Zampini   PetscInt  *hist_id; /* stores the stepid in time history */
43115dd874SBarry Smith   size_t    n;        /* current number of steps registered */
4489818f9dSStefano Zampini   PetscBool sorted;   /* if the history is sorted in ascending order */
45115dd874SBarry Smith   size_t    c;        /* current capacity of history */
46115dd874SBarry Smith   size_t    s;        /* reallocation size */
4789818f9dSStefano Zampini };
4889818f9dSStefano Zampini 
4989818f9dSStefano Zampini PetscErrorCode TSHistoryGetNumSteps(TSHistory tsh, PetscInt *n)
5089818f9dSStefano Zampini {
5189818f9dSStefano Zampini   PetscFunctionBegin;
5289818f9dSStefano Zampini   PetscValidPointer(n,2);
5389818f9dSStefano Zampini   *n = tsh->n;
5489818f9dSStefano Zampini   PetscFunctionReturn(0);
5589818f9dSStefano Zampini }
5689818f9dSStefano Zampini 
5789818f9dSStefano Zampini PetscErrorCode TSHistoryUpdate(TSHistory tsh, PetscInt id, PetscReal time)
5889818f9dSStefano Zampini {
5989818f9dSStefano Zampini   PetscFunctionBegin;
6089818f9dSStefano Zampini   if (tsh->n == tsh->c) { /* reallocation */
6189818f9dSStefano Zampini     tsh->c += tsh->s;
62*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscRealloc(tsh->c*sizeof(*tsh->hist),&tsh->hist));
63*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscRealloc(tsh->c*sizeof(*tsh->hist_id),&tsh->hist_id));
6489818f9dSStefano Zampini   }
6589818f9dSStefano Zampini   tsh->sorted = (PetscBool)(tsh->sorted && (tsh->n ? time >= tsh->hist[tsh->n-1] : PETSC_TRUE));
6689818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG)
6789818f9dSStefano Zampini   if (tsh->n) { /* id should be unique */
6889818f9dSStefano Zampini     PetscInt loc,*ids;
6989818f9dSStefano Zampini 
70*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(tsh->n,&ids));
71*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(ids,tsh->hist_id,tsh->n));
72*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortInt(tsh->n,ids));
73*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFindInt(id,tsh->n,ids,&loc));
74*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(ids));
753c633725SBarry Smith     PetscCheck(loc < 0,PETSC_COMM_SELF,PETSC_ERR_PLIB,"History id should be unique");
7689818f9dSStefano Zampini   }
7789818f9dSStefano Zampini #endif
7889818f9dSStefano Zampini   tsh->hist[tsh->n]    = time;
7989818f9dSStefano Zampini   tsh->hist_id[tsh->n] = id;
8089818f9dSStefano Zampini   tsh->n += 1;
8189818f9dSStefano Zampini   PetscFunctionReturn(0);
8289818f9dSStefano Zampini }
8389818f9dSStefano Zampini 
848a32c442SStefano Zampini PetscErrorCode TSHistoryGetTime(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *t)
858a32c442SStefano Zampini {
868a32c442SStefano Zampini   PetscFunctionBegin;
878a32c442SStefano Zampini   if (!t) PetscFunctionReturn(0);
888a32c442SStefano Zampini   PetscValidRealPointer(t,4);
898a32c442SStefano Zampini   if (!tsh->sorted) {
908a32c442SStefano Zampini 
91*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id));
928a32c442SStefano Zampini     tsh->sorted = PETSC_TRUE;
938a32c442SStefano Zampini   }
94115dd874SBarry 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);
958a32c442SStefano Zampini   if (!backward) *t = tsh->hist[step];
968a32c442SStefano Zampini   else           *t = tsh->hist[tsh->n-step-1];
978a32c442SStefano Zampini   PetscFunctionReturn(0);
988a32c442SStefano Zampini }
998a32c442SStefano Zampini 
10089818f9dSStefano Zampini PetscErrorCode TSHistoryGetTimeStep(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *dt)
10189818f9dSStefano Zampini {
10289818f9dSStefano Zampini   PetscFunctionBegin;
1038a32c442SStefano Zampini   if (!dt) PetscFunctionReturn(0);
10489818f9dSStefano Zampini   PetscValidRealPointer(dt,4);
10589818f9dSStefano Zampini   if (!tsh->sorted) {
10689818f9dSStefano Zampini 
107*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id));
10889818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
10989818f9dSStefano Zampini   }
110115dd874SBarry 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);
111115dd874SBarry Smith   if (!backward) *dt = tsh->hist[PetscMin(step+1,(PetscInt)tsh->n-1)] - tsh->hist[PetscMin(step,(PetscInt)tsh->n-1)];
112115dd874SBarry Smith   else           *dt = tsh->hist[PetscMax((PetscInt)tsh->n-step-1,0)] - tsh->hist[PetscMax((PetscInt)tsh->n-step-2,0)];
11389818f9dSStefano Zampini   PetscFunctionReturn(0);
11489818f9dSStefano Zampini }
11589818f9dSStefano Zampini 
11689818f9dSStefano Zampini PetscErrorCode TSHistoryGetLocFromTime(TSHistory tsh, PetscReal time, PetscInt *loc)
11789818f9dSStefano Zampini {
11889818f9dSStefano Zampini   PetscFunctionBegin;
11989818f9dSStefano Zampini   PetscValidIntPointer(loc,3);
12089818f9dSStefano Zampini   if (!tsh->sorted) {
121*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id));
12289818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
12389818f9dSStefano Zampini   }
124*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFindReal(time,tsh->n,tsh->hist,PETSC_SMALL,loc));
12589818f9dSStefano Zampini   PetscFunctionReturn(0);
12689818f9dSStefano Zampini }
12789818f9dSStefano Zampini 
12889818f9dSStefano Zampini PetscErrorCode TSHistorySetHistory(TSHistory tsh, PetscInt n, PetscReal hist[], PetscInt hist_id[], PetscBool sorted)
12989818f9dSStefano Zampini {
13089818f9dSStefano Zampini   PetscFunctionBegin;
13189818f9dSStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm,n,2);
13254c59aa7SJacob Faibussowitsch   PetscCheck(n >= 0,tsh->comm,PETSC_ERR_ARG_OUTOFRANGE,"Cannot request a negative size for history storage");
13389818f9dSStefano Zampini   if (n) PetscValidRealPointer(hist,3);
134*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(tsh->hist));
135*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(tsh->hist_id));
136115dd874SBarry Smith   tsh->n = (size_t) n;
137115dd874SBarry Smith   tsh->c = (size_t) n;
138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(tsh->n,&tsh->hist));
139*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(tsh->n,&tsh->hist_id));
140*5f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < (PetscInt)tsh->n; i++) {
14189818f9dSStefano Zampini     tsh->hist[i]    = hist[i];
14289818f9dSStefano Zampini     tsh->hist_id[i] = hist_id ? hist_id[i] : i;
14389818f9dSStefano Zampini   }
144*5f80ce2aSJacob Faibussowitsch   if (!sorted) CHKERRQ(PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id));
14589818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
14689818f9dSStefano Zampini   PetscFunctionReturn(0);
14789818f9dSStefano Zampini }
14889818f9dSStefano Zampini 
14989818f9dSStefano Zampini PetscErrorCode TSHistoryGetHistory(TSHistory tsh, PetscInt *n, const PetscReal* hist[], const PetscInt* hist_id[], PetscBool *sorted)
15089818f9dSStefano Zampini {
15189818f9dSStefano Zampini   PetscFunctionBegin;
15289818f9dSStefano Zampini   if (n)             *n = tsh->n;
15389818f9dSStefano Zampini   if (hist)       *hist = tsh->hist;
15489818f9dSStefano Zampini   if (hist_id) *hist_id = tsh->hist_id;
15589818f9dSStefano Zampini   if (sorted)   *sorted = tsh->sorted;
15689818f9dSStefano Zampini   PetscFunctionReturn(0);
15789818f9dSStefano Zampini }
15889818f9dSStefano Zampini 
15989818f9dSStefano Zampini PetscErrorCode TSHistoryDestroy(TSHistory *tsh)
16089818f9dSStefano Zampini {
16189818f9dSStefano Zampini   PetscFunctionBegin;
16289818f9dSStefano Zampini   if (!*tsh) PetscFunctionReturn(0);
163*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*tsh)->hist));
164*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*tsh)->hist_id));
165*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCommDestroy(&((*tsh)->comm)));
166*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree((*tsh)));
16789818f9dSStefano Zampini   *tsh = NULL;
16889818f9dSStefano Zampini   PetscFunctionReturn(0);
16989818f9dSStefano Zampini }
17089818f9dSStefano Zampini 
17189818f9dSStefano Zampini PetscErrorCode TSHistoryCreate(MPI_Comm comm, TSHistory *hst)
17289818f9dSStefano Zampini {
17389818f9dSStefano Zampini   TSHistory      tsh;
17489818f9dSStefano Zampini 
17589818f9dSStefano Zampini   PetscFunctionBegin;
17689818f9dSStefano Zampini   PetscValidPointer(hst,2);
17789818f9dSStefano Zampini   *hst = NULL;
178*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&tsh));
179*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCommDuplicate(comm,&tsh->comm,NULL));
18089818f9dSStefano Zampini 
18189818f9dSStefano Zampini   tsh->c      = 1024; /* capacity */
18289818f9dSStefano Zampini   tsh->s      = 1024; /* reallocation size */
18389818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
18489818f9dSStefano Zampini 
185*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(tsh->c,&tsh->hist));
186*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(tsh->c,&tsh->hist_id));
18789818f9dSStefano Zampini   *hst = tsh;
18889818f9dSStefano Zampini   PetscFunctionReturn(0);
18989818f9dSStefano Zampini }
190