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