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