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