xref: /petsc/src/ts/interface/tshistory.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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]; \
9*9371c9d4SSatish Balay     b1[0] = -b; \
10*9371c9d4SSatish Balay     b1[1] = b; \
111c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(b1, b2, 2, MPIU_INT, MPI_MAX, a)); \
123c633725SBarry Smith     PetscCheck(-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     PetscMPIInt b1[2], b2[2]; \
18*9371c9d4SSatish Balay     b1[0] = -(PetscMPIInt)b; \
19*9371c9d4SSatish Balay     b1[1] = (PetscMPIInt)b; \
201c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(b1, b2, 2, MPI_INT, MPI_MAX, a)); \
213c633725SBarry Smith     PetscCheck(-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     PetscReal b1[3], b2[3]; \
27*9371c9d4SSatish Balay     if (PetscIsNanReal(b)) { \
28*9371c9d4SSatish Balay       b1[2] = 1; \
29*9371c9d4SSatish Balay     } else { \
30*9371c9d4SSatish Balay       b1[2] = 0; \
31*9371c9d4SSatish Balay     }; \
32*9371c9d4SSatish Balay     b1[0] = -b; \
33*9371c9d4SSatish Balay     b1[1] = b; \
349566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(b1, b2, 3, MPIU_REAL, MPIU_MAX, a)); \
353c633725SBarry 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); \
3689818f9dSStefano Zampini   } while (0)
3789818f9dSStefano Zampini 
3889818f9dSStefano Zampini #else
3989818f9dSStefano Zampini 
40*9371c9d4SSatish Balay #define PetscValidLogicalCollectiveRealComm(a, b, c) \
41*9371c9d4SSatish Balay   do { \
42*9371c9d4SSatish Balay   } while (0)
43*9371c9d4SSatish Balay #define PetscValidLogicalCollectiveIntComm(a, b, c) \
44*9371c9d4SSatish Balay   do { \
45*9371c9d4SSatish Balay   } while (0)
46*9371c9d4SSatish Balay #define PetscValidLogicalCollectiveBoolComm(a, b, c) \
47*9371c9d4SSatish Balay   do { \
48*9371c9d4SSatish Balay   } while (0)
4989818f9dSStefano Zampini 
5089818f9dSStefano Zampini #endif
5189818f9dSStefano Zampini 
5289818f9dSStefano Zampini struct _n_TSHistory {
5389818f9dSStefano Zampini   MPI_Comm   comm;    /* used for runtime collective checks */
5489818f9dSStefano Zampini   PetscReal *hist;    /* time history */
5589818f9dSStefano Zampini   PetscInt  *hist_id; /* stores the stepid in time history */
56115dd874SBarry Smith   size_t     n;       /* current number of steps registered */
5789818f9dSStefano Zampini   PetscBool  sorted;  /* if the history is sorted in ascending order */
58115dd874SBarry Smith   size_t     c;       /* current capacity of history */
59115dd874SBarry Smith   size_t     s;       /* reallocation size */
6089818f9dSStefano Zampini };
6189818f9dSStefano Zampini 
62*9371c9d4SSatish Balay PetscErrorCode TSHistoryGetNumSteps(TSHistory tsh, PetscInt *n) {
6389818f9dSStefano Zampini   PetscFunctionBegin;
64dadcf809SJacob Faibussowitsch   PetscValidIntPointer(n, 2);
6589818f9dSStefano Zampini   *n = tsh->n;
6689818f9dSStefano Zampini   PetscFunctionReturn(0);
6789818f9dSStefano Zampini }
6889818f9dSStefano Zampini 
69*9371c9d4SSatish Balay PetscErrorCode TSHistoryUpdate(TSHistory tsh, PetscInt id, PetscReal time) {
7089818f9dSStefano Zampini   PetscFunctionBegin;
7189818f9dSStefano Zampini   if (tsh->n == tsh->c) { /* reallocation */
7289818f9dSStefano Zampini     tsh->c += tsh->s;
739566063dSJacob Faibussowitsch     PetscCall(PetscRealloc(tsh->c * sizeof(*tsh->hist), &tsh->hist));
749566063dSJacob Faibussowitsch     PetscCall(PetscRealloc(tsh->c * sizeof(*tsh->hist_id), &tsh->hist_id));
7589818f9dSStefano Zampini   }
7689818f9dSStefano Zampini   tsh->sorted = (PetscBool)(tsh->sorted && (tsh->n ? time >= tsh->hist[tsh->n - 1] : PETSC_TRUE));
7789818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG)
7889818f9dSStefano Zampini   if (tsh->n) { /* id should be unique */
7989818f9dSStefano Zampini     PetscInt loc, *ids;
8089818f9dSStefano Zampini 
819566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(tsh->n, &ids));
829566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(ids, tsh->hist_id, tsh->n));
839566063dSJacob Faibussowitsch     PetscCall(PetscSortInt(tsh->n, ids));
849566063dSJacob Faibussowitsch     PetscCall(PetscFindInt(id, tsh->n, ids, &loc));
859566063dSJacob Faibussowitsch     PetscCall(PetscFree(ids));
863c633725SBarry Smith     PetscCheck(loc < 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "History id should be unique");
8789818f9dSStefano Zampini   }
8889818f9dSStefano Zampini #endif
8989818f9dSStefano Zampini   tsh->hist[tsh->n]    = time;
9089818f9dSStefano Zampini   tsh->hist_id[tsh->n] = id;
9189818f9dSStefano Zampini   tsh->n += 1;
9289818f9dSStefano Zampini   PetscFunctionReturn(0);
9389818f9dSStefano Zampini }
9489818f9dSStefano Zampini 
95*9371c9d4SSatish Balay PetscErrorCode TSHistoryGetTime(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *t) {
968a32c442SStefano Zampini   PetscFunctionBegin;
978a32c442SStefano Zampini   if (!t) PetscFunctionReturn(0);
988a32c442SStefano Zampini   PetscValidRealPointer(t, 4);
998a32c442SStefano Zampini   if (!tsh->sorted) {
1009566063dSJacob Faibussowitsch     PetscCall(PetscSortRealWithArrayInt(tsh->n, tsh->hist, tsh->hist_id));
1018a32c442SStefano Zampini     tsh->sorted = PETSC_TRUE;
1028a32c442SStefano Zampini   }
10363a3b9bcSJacob Faibussowitsch   PetscCheck(step >= 0 && step < (PetscInt)tsh->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Given time step %" PetscInt_FMT " does not match any in history [0,%" PetscInt_FMT "]", step, (PetscInt)tsh->n);
1048a32c442SStefano Zampini   if (!backward) *t = tsh->hist[step];
1058a32c442SStefano Zampini   else *t = tsh->hist[tsh->n - step - 1];
1068a32c442SStefano Zampini   PetscFunctionReturn(0);
1078a32c442SStefano Zampini }
1088a32c442SStefano Zampini 
109*9371c9d4SSatish Balay PetscErrorCode TSHistoryGetTimeStep(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *dt) {
11089818f9dSStefano Zampini   PetscFunctionBegin;
1118a32c442SStefano Zampini   if (!dt) PetscFunctionReturn(0);
11289818f9dSStefano Zampini   PetscValidRealPointer(dt, 4);
11389818f9dSStefano Zampini   if (!tsh->sorted) {
1149566063dSJacob Faibussowitsch     PetscCall(PetscSortRealWithArrayInt(tsh->n, tsh->hist, tsh->hist_id));
11589818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
11689818f9dSStefano Zampini   }
11763a3b9bcSJacob Faibussowitsch   PetscCheck(step >= 0 && step <= (PetscInt)tsh->n, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Given time step %" PetscInt_FMT " does not match any in history [0,%" PetscInt_FMT "]", step, (PetscInt)tsh->n);
118115dd874SBarry Smith   if (!backward) *dt = tsh->hist[PetscMin(step + 1, (PetscInt)tsh->n - 1)] - tsh->hist[PetscMin(step, (PetscInt)tsh->n - 1)];
119115dd874SBarry Smith   else *dt = tsh->hist[PetscMax((PetscInt)tsh->n - step - 1, 0)] - tsh->hist[PetscMax((PetscInt)tsh->n - step - 2, 0)];
12089818f9dSStefano Zampini   PetscFunctionReturn(0);
12189818f9dSStefano Zampini }
12289818f9dSStefano Zampini 
123*9371c9d4SSatish Balay PetscErrorCode TSHistoryGetLocFromTime(TSHistory tsh, PetscReal time, PetscInt *loc) {
12489818f9dSStefano Zampini   PetscFunctionBegin;
12589818f9dSStefano Zampini   PetscValidIntPointer(loc, 3);
12689818f9dSStefano Zampini   if (!tsh->sorted) {
1279566063dSJacob Faibussowitsch     PetscCall(PetscSortRealWithArrayInt(tsh->n, tsh->hist, tsh->hist_id));
12889818f9dSStefano Zampini     tsh->sorted = PETSC_TRUE;
12989818f9dSStefano Zampini   }
1309566063dSJacob Faibussowitsch   PetscCall(PetscFindReal(time, tsh->n, tsh->hist, PETSC_SMALL, loc));
13189818f9dSStefano Zampini   PetscFunctionReturn(0);
13289818f9dSStefano Zampini }
13389818f9dSStefano Zampini 
134*9371c9d4SSatish Balay PetscErrorCode TSHistorySetHistory(TSHistory tsh, PetscInt n, PetscReal hist[], PetscInt hist_id[], PetscBool sorted) {
13589818f9dSStefano Zampini   PetscFunctionBegin;
13689818f9dSStefano Zampini   PetscValidLogicalCollectiveIntComm(tsh->comm, n, 2);
13754c59aa7SJacob Faibussowitsch   PetscCheck(n >= 0, tsh->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot request a negative size for history storage");
13889818f9dSStefano Zampini   if (n) PetscValidRealPointer(hist, 3);
1399566063dSJacob Faibussowitsch   PetscCall(PetscFree(tsh->hist));
1409566063dSJacob Faibussowitsch   PetscCall(PetscFree(tsh->hist_id));
141115dd874SBarry Smith   tsh->n = (size_t)n;
142115dd874SBarry Smith   tsh->c = (size_t)n;
1439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(tsh->n, &tsh->hist));
1449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(tsh->n, &tsh->hist_id));
1455f80ce2aSJacob Faibussowitsch   for (PetscInt i = 0; i < (PetscInt)tsh->n; i++) {
14689818f9dSStefano Zampini     tsh->hist[i]    = hist[i];
14789818f9dSStefano Zampini     tsh->hist_id[i] = hist_id ? hist_id[i] : i;
14889818f9dSStefano Zampini   }
1499566063dSJacob Faibussowitsch   if (!sorted) PetscCall(PetscSortRealWithArrayInt(tsh->n, tsh->hist, tsh->hist_id));
15089818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
15189818f9dSStefano Zampini   PetscFunctionReturn(0);
15289818f9dSStefano Zampini }
15389818f9dSStefano Zampini 
154*9371c9d4SSatish Balay PetscErrorCode TSHistoryGetHistory(TSHistory tsh, PetscInt *n, const PetscReal *hist[], const PetscInt *hist_id[], PetscBool *sorted) {
15589818f9dSStefano Zampini   PetscFunctionBegin;
15689818f9dSStefano Zampini   if (n) *n = tsh->n;
15789818f9dSStefano Zampini   if (hist) *hist = tsh->hist;
15889818f9dSStefano Zampini   if (hist_id) *hist_id = tsh->hist_id;
15989818f9dSStefano Zampini   if (sorted) *sorted = tsh->sorted;
16089818f9dSStefano Zampini   PetscFunctionReturn(0);
16189818f9dSStefano Zampini }
16289818f9dSStefano Zampini 
163*9371c9d4SSatish Balay PetscErrorCode TSHistoryDestroy(TSHistory *tsh) {
16489818f9dSStefano Zampini   PetscFunctionBegin;
16589818f9dSStefano Zampini   if (!*tsh) PetscFunctionReturn(0);
1669566063dSJacob Faibussowitsch   PetscCall(PetscFree((*tsh)->hist));
1679566063dSJacob Faibussowitsch   PetscCall(PetscFree((*tsh)->hist_id));
1689566063dSJacob Faibussowitsch   PetscCall(PetscCommDestroy(&((*tsh)->comm)));
1699566063dSJacob Faibussowitsch   PetscCall(PetscFree((*tsh)));
17089818f9dSStefano Zampini   *tsh = NULL;
17189818f9dSStefano Zampini   PetscFunctionReturn(0);
17289818f9dSStefano Zampini }
17389818f9dSStefano Zampini 
174*9371c9d4SSatish Balay PetscErrorCode TSHistoryCreate(MPI_Comm comm, TSHistory *hst) {
17589818f9dSStefano Zampini   TSHistory tsh;
17689818f9dSStefano Zampini 
17789818f9dSStefano Zampini   PetscFunctionBegin;
17889818f9dSStefano Zampini   PetscValidPointer(hst, 2);
17989818f9dSStefano Zampini   *hst = NULL;
1809566063dSJacob Faibussowitsch   PetscCall(PetscNew(&tsh));
1819566063dSJacob Faibussowitsch   PetscCall(PetscCommDuplicate(comm, &tsh->comm, NULL));
18289818f9dSStefano Zampini 
18389818f9dSStefano Zampini   tsh->c      = 1024; /* capacity */
18489818f9dSStefano Zampini   tsh->s      = 1024; /* reallocation size */
18589818f9dSStefano Zampini   tsh->sorted = PETSC_TRUE;
18689818f9dSStefano Zampini 
1879566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(tsh->c, &tsh->hist));
1889566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(tsh->c, &tsh->hist_id));
18989818f9dSStefano Zampini   *hst = tsh;
19089818f9dSStefano Zampini   PetscFunctionReturn(0);
19189818f9dSStefano Zampini }
192