1*89818f9dSStefano Zampini #include <petsc/private/tshistoryimpl.h> 2*89818f9dSStefano Zampini 3*89818f9dSStefano Zampini /* These macros can be moved to petscimpl.h eventually */ 4*89818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG) 5*89818f9dSStefano Zampini 6*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveIntComm(a,b,c) \ 7*89818f9dSStefano Zampini do { \ 8*89818f9dSStefano Zampini PetscErrorCode _7_ierr; \ 9*89818f9dSStefano Zampini PetscInt b1[2],b2[2]; \ 10*89818f9dSStefano Zampini b1[0] = -b; b1[1] = b; \ 11*89818f9dSStefano Zampini _7_ierr = MPIU_Allreduce(b1,b2,2,MPIU_INT,MPI_MAX,a);CHKERRQ(_7_ierr); \ 12*89818f9dSStefano Zampini if (-b2[0] != b2[1]) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Int value must be same on all processes, argument # %d",c); \ 13*89818f9dSStefano Zampini } while (0) 14*89818f9dSStefano Zampini 15*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c) \ 16*89818f9dSStefano Zampini do { \ 17*89818f9dSStefano Zampini PetscErrorCode _7_ierr; \ 18*89818f9dSStefano Zampini PetscMPIInt b1[2],b2[2]; \ 19*89818f9dSStefano Zampini b1[0] = -(PetscMPIInt)b; b1[1] = (PetscMPIInt)b; \ 20*89818f9dSStefano Zampini _7_ierr = MPIU_Allreduce(b1,b2,2,MPI_INT,MPI_MAX,a);CHKERRQ(_7_ierr); \ 21*89818f9dSStefano Zampini if (-b2[0] != b2[1]) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Bool value must be same on all processes, argument # %d",c); \ 22*89818f9dSStefano Zampini } while (0) 23*89818f9dSStefano Zampini 24*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c) \ 25*89818f9dSStefano Zampini do { \ 26*89818f9dSStefano Zampini PetscErrorCode _7_ierr; \ 27*89818f9dSStefano Zampini PetscReal b1[3],b2[3]; \ 28*89818f9dSStefano Zampini if (PetscIsNanReal(b)) {b1[2] = 1;} else {b1[2] = 0;}; \ 29*89818f9dSStefano Zampini b1[0] = -b; b1[1] = b; \ 30*89818f9dSStefano Zampini _7_ierr = MPI_Allreduce(b1,b2,3,MPIU_REAL,MPIU_MAX,a);CHKERRQ(_7_ierr); \ 31*89818f9dSStefano Zampini if (!(b2[2] > 0) && !PetscEqualReal(-b2[0],b2[1])) SETERRQ1(a,PETSC_ERR_ARG_WRONG,"Real value must be same on all processes, argument # %d",c); \ 32*89818f9dSStefano Zampini } while (0) 33*89818f9dSStefano Zampini 34*89818f9dSStefano Zampini #else 35*89818f9dSStefano Zampini 36*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveRealComm(a,b,c) do {} while (0) 37*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveIntComm(a,b,c) do {} while (0) 38*89818f9dSStefano Zampini #define PetscValidLogicalCollectiveBoolComm(a,b,c) do {} while (0) 39*89818f9dSStefano Zampini 40*89818f9dSStefano Zampini #endif 41*89818f9dSStefano Zampini 42*89818f9dSStefano Zampini struct _n_TSHistory { 43*89818f9dSStefano Zampini MPI_Comm comm; /* used for runtime collective checks */ 44*89818f9dSStefano Zampini PetscReal *hist; /* time history */ 45*89818f9dSStefano Zampini PetscInt *hist_id; /* stores the stepid in time history */ 46*89818f9dSStefano Zampini PetscInt n; /* current number of steps registered */ 47*89818f9dSStefano Zampini PetscBool sorted; /* if the history is sorted in ascending order */ 48*89818f9dSStefano Zampini PetscInt c; /* current capacity of hist */ 49*89818f9dSStefano Zampini PetscInt s; /* reallocation size */ 50*89818f9dSStefano Zampini }; 51*89818f9dSStefano Zampini 52*89818f9dSStefano Zampini PetscErrorCode TSHistoryGetNumSteps(TSHistory tsh, PetscInt *n) 53*89818f9dSStefano Zampini { 54*89818f9dSStefano Zampini PetscFunctionBegin; 55*89818f9dSStefano Zampini PetscValidPointer(n,2); 56*89818f9dSStefano Zampini *n = tsh->n; 57*89818f9dSStefano Zampini PetscFunctionReturn(0); 58*89818f9dSStefano Zampini } 59*89818f9dSStefano Zampini 60*89818f9dSStefano Zampini PetscErrorCode TSHistoryUpdate(TSHistory tsh, PetscInt id, PetscReal time) 61*89818f9dSStefano Zampini { 62*89818f9dSStefano Zampini PetscErrorCode ierr; 63*89818f9dSStefano Zampini 64*89818f9dSStefano Zampini PetscFunctionBegin; 65*89818f9dSStefano Zampini PetscValidLogicalCollectiveIntComm(tsh->comm,id,2); 66*89818f9dSStefano Zampini PetscValidLogicalCollectiveRealComm(tsh->comm,time,3); 67*89818f9dSStefano Zampini if (tsh->n == tsh->c) { /* reallocation */ 68*89818f9dSStefano Zampini tsh->c += tsh->s; 69*89818f9dSStefano Zampini ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist),&tsh->hist);CHKERRQ(ierr); 70*89818f9dSStefano Zampini ierr = PetscRealloc(tsh->c*sizeof(*tsh->hist_id),&tsh->hist_id);CHKERRQ(ierr); 71*89818f9dSStefano Zampini } 72*89818f9dSStefano Zampini tsh->sorted = (PetscBool)(tsh->sorted && (tsh->n ? time >= tsh->hist[tsh->n-1] : PETSC_TRUE)); 73*89818f9dSStefano Zampini #if defined(PETSC_USE_DEBUG) 74*89818f9dSStefano Zampini if (tsh->n) { /* id should be unique */ 75*89818f9dSStefano Zampini PetscInt loc,*ids; 76*89818f9dSStefano Zampini 77*89818f9dSStefano Zampini ierr = PetscMalloc1(tsh->n,&ids);CHKERRQ(ierr); 78*89818f9dSStefano Zampini ierr = PetscMemcpy(ids,tsh->hist_id,tsh->n*sizeof(PetscInt));CHKERRQ(ierr); 79*89818f9dSStefano Zampini ierr = PetscSortInt(tsh->n,ids);CHKERRQ(ierr); 80*89818f9dSStefano Zampini ierr = PetscFindInt(id,tsh->n,ids,&loc);CHKERRQ(ierr); 81*89818f9dSStefano Zampini ierr = PetscFree(ids);CHKERRQ(ierr); 82*89818f9dSStefano Zampini if (loc >=0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"History id should be unique"); 83*89818f9dSStefano Zampini } 84*89818f9dSStefano Zampini #endif 85*89818f9dSStefano Zampini tsh->hist[tsh->n] = time; 86*89818f9dSStefano Zampini tsh->hist_id[tsh->n] = id; 87*89818f9dSStefano Zampini tsh->n += 1; 88*89818f9dSStefano Zampini PetscFunctionReturn(0); 89*89818f9dSStefano Zampini } 90*89818f9dSStefano Zampini 91*89818f9dSStefano Zampini PetscErrorCode TSHistoryGetTimeStep(TSHistory tsh, PetscBool backward, PetscInt step, PetscReal *dt) 92*89818f9dSStefano Zampini { 93*89818f9dSStefano Zampini PetscFunctionBegin; 94*89818f9dSStefano Zampini PetscValidLogicalCollectiveBoolComm(tsh->comm,backward,2); 95*89818f9dSStefano Zampini PetscValidLogicalCollectiveIntComm(tsh->comm,step,3); 96*89818f9dSStefano Zampini PetscValidRealPointer(dt,4); 97*89818f9dSStefano Zampini if (!tsh->sorted) { 98*89818f9dSStefano Zampini PetscErrorCode ierr; 99*89818f9dSStefano Zampini 100*89818f9dSStefano Zampini ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr); 101*89818f9dSStefano Zampini tsh->sorted = PETSC_TRUE; 102*89818f9dSStefano Zampini } 103*89818f9dSStefano Zampini if (step < 0 || step > tsh->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Given time step %D does not match any in history [0,%D]",step,tsh->n); 104*89818f9dSStefano Zampini if (!backward) *dt = tsh->hist[PetscMin(step+1,tsh->n-1)] - tsh->hist[PetscMin(step,tsh->n-1)]; 105*89818f9dSStefano Zampini else *dt = tsh->hist[PetscMax(tsh->n-step-1,0)] - tsh->hist[PetscMax(tsh->n-step-2,0)]; 106*89818f9dSStefano Zampini PetscFunctionReturn(0); 107*89818f9dSStefano Zampini } 108*89818f9dSStefano Zampini 109*89818f9dSStefano Zampini PetscErrorCode TSHistoryGetLocFromTime(TSHistory tsh, PetscReal time, PetscInt *loc) 110*89818f9dSStefano Zampini { 111*89818f9dSStefano Zampini PetscErrorCode ierr; 112*89818f9dSStefano Zampini 113*89818f9dSStefano Zampini PetscFunctionBegin; 114*89818f9dSStefano Zampini PetscValidLogicalCollectiveRealComm(tsh->comm,time,2); 115*89818f9dSStefano Zampini PetscValidIntPointer(loc,3); 116*89818f9dSStefano Zampini if (!tsh->sorted) { 117*89818f9dSStefano Zampini ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr); 118*89818f9dSStefano Zampini tsh->sorted = PETSC_TRUE; 119*89818f9dSStefano Zampini } 120*89818f9dSStefano Zampini ierr = PetscFindReal(time,tsh->n,tsh->hist,PETSC_SMALL,loc);CHKERRQ(ierr); 121*89818f9dSStefano Zampini PetscFunctionReturn(0); 122*89818f9dSStefano Zampini } 123*89818f9dSStefano Zampini 124*89818f9dSStefano Zampini PetscErrorCode TSHistorySetHistory(TSHistory tsh, PetscInt n, PetscReal hist[], PetscInt hist_id[], PetscBool sorted) 125*89818f9dSStefano Zampini { 126*89818f9dSStefano Zampini PetscInt i; 127*89818f9dSStefano Zampini PetscErrorCode ierr; 128*89818f9dSStefano Zampini 129*89818f9dSStefano Zampini PetscFunctionBegin; 130*89818f9dSStefano Zampini PetscValidLogicalCollectiveIntComm(tsh->comm,n,2); 131*89818f9dSStefano Zampini if (n) PetscValidRealPointer(hist,3); 132*89818f9dSStefano Zampini ierr = PetscFree(tsh->hist);CHKERRQ(ierr); 133*89818f9dSStefano Zampini ierr = PetscFree(tsh->hist_id);CHKERRQ(ierr); 134*89818f9dSStefano Zampini tsh->n = n; 135*89818f9dSStefano Zampini tsh->c = n; 136*89818f9dSStefano Zampini ierr = PetscMalloc1(tsh->n,&tsh->hist);CHKERRQ(ierr); 137*89818f9dSStefano Zampini ierr = PetscMalloc1(tsh->n,&tsh->hist_id);CHKERRQ(ierr); 138*89818f9dSStefano Zampini for (i = 0; i < tsh->n; i++) { 139*89818f9dSStefano Zampini tsh->hist[i] = hist[i]; 140*89818f9dSStefano Zampini tsh->hist_id[i] = hist_id ? hist_id[i] : i; 141*89818f9dSStefano Zampini } 142*89818f9dSStefano Zampini if (!sorted) { 143*89818f9dSStefano Zampini ierr = PetscSortRealWithArrayInt(tsh->n,tsh->hist,tsh->hist_id);CHKERRQ(ierr); 144*89818f9dSStefano Zampini } 145*89818f9dSStefano Zampini tsh->sorted = PETSC_TRUE; 146*89818f9dSStefano Zampini PetscFunctionReturn(0); 147*89818f9dSStefano Zampini } 148*89818f9dSStefano Zampini 149*89818f9dSStefano Zampini PetscErrorCode TSHistoryGetHistory(TSHistory tsh, PetscInt *n, const PetscReal* hist[], const PetscInt* hist_id[], PetscBool *sorted) 150*89818f9dSStefano Zampini { 151*89818f9dSStefano Zampini PetscFunctionBegin; 152*89818f9dSStefano Zampini if (n) *n = tsh->n; 153*89818f9dSStefano Zampini if (hist) *hist = tsh->hist; 154*89818f9dSStefano Zampini if (hist_id) *hist_id = tsh->hist_id; 155*89818f9dSStefano Zampini if (sorted) *sorted = tsh->sorted; 156*89818f9dSStefano Zampini PetscFunctionReturn(0); 157*89818f9dSStefano Zampini } 158*89818f9dSStefano Zampini 159*89818f9dSStefano Zampini PetscErrorCode TSHistoryDestroy(TSHistory *tsh) 160*89818f9dSStefano Zampini { 161*89818f9dSStefano Zampini PetscErrorCode ierr; 162*89818f9dSStefano Zampini 163*89818f9dSStefano Zampini PetscFunctionBegin; 164*89818f9dSStefano Zampini if (!*tsh) PetscFunctionReturn(0); 165*89818f9dSStefano Zampini ierr = PetscFree((*tsh)->hist);CHKERRQ(ierr); 166*89818f9dSStefano Zampini ierr = PetscFree((*tsh)->hist_id);CHKERRQ(ierr); 167*89818f9dSStefano Zampini ierr = PetscCommDestroy(&((*tsh)->comm));CHKERRQ(ierr); 168*89818f9dSStefano Zampini ierr = PetscFree((*tsh));CHKERRQ(ierr); 169*89818f9dSStefano Zampini *tsh = NULL; 170*89818f9dSStefano Zampini PetscFunctionReturn(0); 171*89818f9dSStefano Zampini } 172*89818f9dSStefano Zampini 173*89818f9dSStefano Zampini PetscErrorCode TSHistoryCreate(MPI_Comm comm, TSHistory *hst) 174*89818f9dSStefano Zampini { 175*89818f9dSStefano Zampini TSHistory tsh; 176*89818f9dSStefano Zampini PetscErrorCode ierr; 177*89818f9dSStefano Zampini 178*89818f9dSStefano Zampini PetscFunctionBegin; 179*89818f9dSStefano Zampini PetscValidPointer(hst,2); 180*89818f9dSStefano Zampini *hst = NULL; 181*89818f9dSStefano Zampini ierr = PetscNew(&tsh);CHKERRQ(ierr); 182*89818f9dSStefano Zampini ierr = PetscCommDuplicate(comm,&tsh->comm,NULL);CHKERRQ(ierr); 183*89818f9dSStefano Zampini 184*89818f9dSStefano Zampini tsh->c = 1024; /* capacity */ 185*89818f9dSStefano Zampini tsh->s = 1024; /* reallocation size */ 186*89818f9dSStefano Zampini tsh->sorted = PETSC_TRUE; 187*89818f9dSStefano Zampini 188*89818f9dSStefano Zampini ierr = PetscMalloc1(tsh->c,&tsh->hist);CHKERRQ(ierr); 189*89818f9dSStefano Zampini ierr = PetscMalloc1(tsh->c,&tsh->hist_id);CHKERRQ(ierr); 190*89818f9dSStefano Zampini *hst = tsh; 191*89818f9dSStefano Zampini PetscFunctionReturn(0); 192*89818f9dSStefano Zampini } 193