1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscsys.h> 3 4 #ifdef PETSC_HAVE_REVOLVE 5 #include <revolve_c.h> 6 #endif 7 8 typedef enum {NONE,TWO_LEVEL_NOREVOLVE,TWO_LEVEL_REVOLVE,REVOLVE_OFFLINE,REVOLVE_ONLINE,REVOLVE_MULTISTAGE} SchedulerType; 9 10 typedef struct _StackElement { 11 PetscInt stepnum; 12 Vec X; 13 Vec *Y; 14 PetscReal time; 15 PetscReal timeprev; 16 } *StackElement; 17 18 typedef struct _RevolveCTX { 19 PetscBool reverseonestep; 20 PetscInt where; 21 PetscInt snaps_in; 22 PetscInt stepsleft; 23 PetscInt check; 24 PetscInt oldcapo; 25 PetscInt capo; 26 PetscInt fine; 27 PetscInt info; 28 } RevolveCTX; 29 30 typedef struct _Stack { 31 SchedulerType stype; 32 PetscBool recompute; 33 MPI_Comm comm; 34 RevolveCTX *rctx; 35 PetscInt max_cps_ram; /* maximum checkpoints in RAM */ 36 PetscInt max_cps_disk; /* maximum checkpoints on disk */ 37 PetscInt stride; 38 PetscInt total_steps; /* total number of steps */ 39 PetscInt numY; 40 PetscInt stacksize; 41 PetscInt top; /* top of the stack */ 42 StackElement *stack; /* container */ 43 } Stack; 44 45 static PetscErrorCode StackCreate(MPI_Comm,Stack *,PetscInt,PetscInt); 46 static PetscErrorCode StackDestroy(Stack*); 47 static PetscErrorCode StackPush(Stack*,StackElement); 48 static PetscErrorCode StackPop(Stack*,StackElement*); 49 static PetscErrorCode StackTop(Stack*,StackElement*); 50 static PetscErrorCode StackDumpAll(TS,Stack*,PetscInt); 51 static PetscErrorCode StackLoadAll(TS,Stack*,PetscInt); 52 53 #ifdef PETSC_HAVE_REVOLVE 54 static void printwhattodo(PetscInt whattodo,RevolveCTX *rctx,PetscInt shift) 55 { 56 switch(whattodo) { 57 case 1: 58 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mAdvance from %D to %D\033[0m\n",rctx->oldcapo+shift,rctx->capo+shift); 59 break; 60 case 2: 61 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mStore in checkpoint number %D\n\033[0m",rctx->check); 62 break; 63 case 3: 64 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mFirst turn: Initialize adjoints and reverse first step\033[0m\n"); 65 break; 66 case 4: 67 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mForward and reverse one step\033[0m\n"); 68 break; 69 case 5: 70 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mRestore in checkpoint number %D\033[0m\n",rctx->check); 71 break; 72 case -1: 73 PetscPrintf(PETSC_COMM_WORLD,"\x1B[35mError!"); 74 break; 75 } 76 } 77 #endif 78 79 #undef __FUNCT__ 80 #define __FUNCT__ "StackCreate" 81 static PetscErrorCode StackCreate(MPI_Comm comm,Stack *s,PetscInt size,PetscInt ny) 82 { 83 PetscErrorCode ierr; 84 85 PetscFunctionBegin; 86 s->top = -1; 87 s->comm = comm; 88 s->numY = ny; 89 90 ierr = PetscMalloc1(size*sizeof(StackElement),&s->stack);CHKERRQ(ierr); 91 PetscFunctionReturn(0); 92 } 93 94 #undef __FUNCT__ 95 #define __FUNCT__ "StackDestroy" 96 static PetscErrorCode StackDestroy(Stack *s) 97 { 98 PetscInt i; 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 if (s->top>-1) { 103 for (i=0;i<=s->top;i++) { 104 ierr = VecDestroy(&s->stack[i]->X);CHKERRQ(ierr); 105 ierr = VecDestroyVecs(s->numY,&s->stack[i]->Y);CHKERRQ(ierr); 106 ierr = PetscFree(s->stack[i]);CHKERRQ(ierr); 107 } 108 } 109 ierr = PetscFree(s->stack);CHKERRQ(ierr); 110 if (s->stype) { 111 ierr = PetscFree(s->rctx);CHKERRQ(ierr); 112 } 113 ierr = PetscFree(s);CHKERRQ(ierr); 114 PetscFunctionReturn(0); 115 } 116 117 #undef __FUNCT__ 118 #define __FUNCT__ "StackPush" 119 static PetscErrorCode StackPush(Stack *s,StackElement e) 120 { 121 PetscFunctionBegin; 122 if (s->top+1 >= s->stacksize) SETERRQ1(s->comm,PETSC_ERR_MEMC,"Maximum stack size (%D) exceeded",s->stacksize); 123 s->stack[++s->top] = e; 124 PetscFunctionReturn(0); 125 } 126 127 #undef __FUNCT__ 128 #define __FUNCT__ "StackPop" 129 static PetscErrorCode StackPop(Stack *s,StackElement *e) 130 { 131 PetscFunctionBegin; 132 if (s->top == -1) SETERRQ(s->comm,PETSC_ERR_MEMC,"Emptry stack"); 133 *e = s->stack[s->top--]; 134 PetscFunctionReturn(0); 135 } 136 137 #undef __FUNCT__ 138 #define __FUNCT__ "StackTop" 139 static PetscErrorCode StackTop(Stack *s,StackElement *e) 140 { 141 PetscFunctionBegin; 142 *e = s->stack[s->top]; 143 PetscFunctionReturn(0); 144 } 145 146 #undef __FUNCT__ 147 #define __FUNCT__ "OutputBIN" 148 static PetscErrorCode OutputBIN(const char *filename,PetscViewer *viewer) 149 { 150 PetscErrorCode ierr; 151 152 PetscFunctionBegin; 153 ierr = PetscViewerCreate(PETSC_COMM_WORLD,viewer);CHKERRQ(ierr); 154 ierr = PetscViewerSetType(*viewer,PETSCVIEWERBINARY);CHKERRQ(ierr); 155 ierr = PetscViewerFileSetMode(*viewer,FILE_MODE_WRITE);CHKERRQ(ierr); 156 ierr = PetscViewerFileSetName(*viewer,filename);CHKERRQ(ierr); 157 PetscFunctionReturn(0); 158 } 159 160 #undef __FUNCT__ 161 #define __FUNCT__ "StackDumpAll" 162 static PetscErrorCode StackDumpAll(TS ts,Stack *s,PetscInt id) 163 { 164 PetscInt i,j; 165 StackElement e; 166 PetscViewer viewer; 167 char filename[PETSC_MAX_PATH_LEN]; 168 Vec *Y; 169 PetscErrorCode ierr; 170 171 PetscFunctionBegin; 172 if (id == 1) { 173 #if defined(PETSC_HAVE_POPEN) 174 PetscMPIInt rank; 175 ierr = MPI_Comm_rank(s->comm,&rank);CHKERRQ(ierr); 176 if (!rank) { 177 char command[PETSC_MAX_PATH_LEN]; 178 FILE *fd; 179 int err; 180 181 ierr = PetscMemzero(command,sizeof(command));CHKERRQ(ierr); 182 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"rm -fr %s","SA-data");CHKERRQ(ierr); 183 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 184 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 185 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"mkdir %s","SA-data");CHKERRQ(ierr); 186 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 187 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 188 } 189 #endif 190 } 191 ierr = PetscSNPrintf(filename,sizeof(filename),"SA-data/SA-STACK%06d.bin",id);CHKERRQ(ierr); 192 ierr = OutputBIN(filename,&viewer);CHKERRQ(ierr); 193 for (i=0;i<s->stacksize;i++) { 194 e = s->stack[i]; 195 ierr = PetscViewerBinaryWrite(viewer,&e->stepnum,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 196 ierr = VecView(e->X,viewer);CHKERRQ(ierr); 197 for (j=0;j<s->numY;j++) { 198 ierr = VecView(e->Y[j],viewer);CHKERRQ(ierr); 199 } 200 ierr = PetscViewerBinaryWrite(viewer,&e->time,1,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr); 201 ierr = PetscViewerBinaryWrite(viewer,&e->timeprev,1,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr); 202 } 203 /* dump the state inside TS from the current step */ 204 ierr = PetscViewerBinaryWrite(viewer,&ts->total_steps,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 205 ierr = VecView(ts->vec_sol,viewer);CHKERRQ(ierr); 206 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 207 for (j=0;j<s->numY;j++) { 208 ierr = VecView(Y[j],viewer);CHKERRQ(ierr); 209 } 210 ierr = PetscViewerBinaryWrite(viewer,&ts->ptime,1,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr); 211 ierr = PetscViewerBinaryWrite(viewer,&ts->ptime_prev,1,PETSC_REAL,PETSC_FALSE);CHKERRQ(ierr); 212 for (i=0;i<s->stacksize;i++) { 213 ierr = StackPop(s,&e);CHKERRQ(ierr); 214 ierr = VecDestroy(&e->X);CHKERRQ(ierr); 215 ierr = VecDestroyVecs(s->numY,&e->Y);CHKERRQ(ierr); 216 ierr = PetscFree(e);CHKERRQ(ierr); 217 } 218 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 219 PetscFunctionReturn(0); 220 } 221 222 #undef __FUNCT__ 223 #define __FUNCT__ "StackLoadAll" 224 static PetscErrorCode StackLoadAll(TS ts,Stack *s,PetscInt id) 225 { 226 Vec *Y; 227 PetscInt i,j; 228 StackElement e; 229 PetscViewer viewer; 230 char filename[PETSC_MAX_PATH_LEN]; 231 PetscErrorCode ierr; 232 233 PetscFunctionBegin; 234 ierr = PetscSNPrintf(filename,sizeof filename,"SA-data/SA-STACK%06d.bin",id);CHKERRQ(ierr); 235 ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr); 236 for (i=0;i<s->stacksize;i++) { 237 ierr = PetscCalloc1(1,&e); 238 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 239 ierr = VecDuplicate(Y[0],&e->X);CHKERRQ(ierr); 240 if (s->numY > 0) { 241 ierr = VecDuplicateVecs(Y[0],s->numY,&e->Y);CHKERRQ(ierr); 242 } 243 ierr = StackPush(s,e);CHKERRQ(ierr); 244 } 245 for (i=0;i<s->stacksize;i++) { 246 e = s->stack[i]; 247 ierr = PetscViewerBinaryRead(viewer,&e->stepnum,1,NULL,PETSC_INT);CHKERRQ(ierr); 248 ierr = VecLoad(e->X,viewer);CHKERRQ(ierr); 249 for (j=0;j<s->numY;j++) { 250 ierr = VecLoad(e->Y[j],viewer);CHKERRQ(ierr); 251 } 252 ierr = PetscViewerBinaryRead(viewer,&e->time,1,NULL,PETSC_REAL);CHKERRQ(ierr); 253 ierr = PetscViewerBinaryRead(viewer,&e->timeprev,1,NULL,PETSC_REAL);CHKERRQ(ierr); 254 } 255 /* load the additioinal state into TS */ 256 ierr = PetscViewerBinaryRead(viewer,&ts->total_steps,1,NULL,PETSC_INT);CHKERRQ(ierr); 257 ierr = VecLoad(ts->vec_sol,viewer);CHKERRQ(ierr); 258 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 259 for (j=0;j<s->numY;j++) { 260 ierr = VecLoad(Y[j],viewer);CHKERRQ(ierr); 261 } 262 ierr = PetscViewerBinaryRead(viewer,&ts->ptime,1,NULL,PETSC_REAL);CHKERRQ(ierr); 263 ierr = PetscViewerBinaryRead(viewer,&ts->ptime_prev,1,NULL,PETSC_REAL);CHKERRQ(ierr); 264 ierr = TSSetTimeStep(ts,ts->ptime-ts->ptime_prev);CHKERRQ(ierr); 265 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 266 PetscFunctionReturn(0); 267 } 268 269 #undef __FUNCT__ 270 #define __FUNCT__ "TSTrajectorySetStride_Memory" 271 PetscErrorCode TSTrajectorySetStride_Memory(TSTrajectory tj,TS ts,PetscInt stride) 272 { 273 Stack *s = (Stack*)tj->data; 274 275 PetscFunctionBegin; 276 s->stride = stride; 277 PetscFunctionReturn(0); 278 } 279 280 #undef __FUNCT__ 281 #define __FUNCT__ "TSTrajectorySetMaxCheckpoints_Memory" 282 PetscErrorCode TSTrajectorySetMaxCheckpoints_Memory(TSTrajectory tj,TS ts,PetscInt max_cps_ram) 283 { 284 Stack *s = (Stack*)tj->data; 285 286 PetscFunctionBegin; 287 s->max_cps_ram = max_cps_ram; 288 PetscFunctionReturn(0); 289 } 290 291 #undef __FUNCT__ 292 #define __FUNCT__ "TSTrajectorySetFromOptions_Memory" 293 PetscErrorCode TSTrajectorySetFromOptions_Memory(PetscOptions *PetscOptionsObject,TSTrajectory tj) 294 { 295 Stack *s = (Stack*)tj->data; 296 PetscErrorCode ierr; 297 298 PetscFunctionBegin; 299 ierr = PetscOptionsHead(PetscOptionsObject,"Memory based TS trajectory options");CHKERRQ(ierr); 300 { 301 ierr = PetscOptionsInt("-tstrajectory_max_cps_ram","Maximum number of checkpoints","TSTrajectorySetMaxCheckpoints_Memory",s->max_cps_ram,&s->max_cps_ram,NULL);CHKERRQ(ierr); 302 ierr = PetscOptionsInt("-tstrajectory_stride","Stride to save checkpoints to file","TSTrajectorySetStride_Memory",s->stride,&s->stride,NULL);CHKERRQ(ierr); 303 } 304 ierr = PetscOptionsTail();CHKERRQ(ierr); 305 PetscFunctionReturn(0); 306 } 307 308 #undef __FUNCT__ 309 #define __FUNCT__ "TSTrajectorySetUp_Memory" 310 PetscErrorCode TSTrajectorySetUp_Memory(TSTrajectory tj,TS ts) 311 { 312 Stack *s = (Stack*)tj->data; 313 RevolveCTX *rctx; 314 PetscInt numY; 315 PetscBool flg; 316 PetscErrorCode ierr; 317 318 PetscFunctionBegin; 319 PetscStrcmp(((PetscObject)ts->adapt)->type_name,TSADAPTNONE,&flg); 320 if (flg) { /* fixed time step */ 321 s->total_steps = PetscMin(ts->max_steps,(PetscInt)(ceil(ts->max_time/ts->time_step))); 322 } 323 if (s->max_cps_ram > 1) s->stacksize = s->max_cps_ram; 324 if (s->stride > 1) { /* two level mode works for both fixed time step and adaptive time step */ 325 if (s->max_cps_ram > 1 && s->max_cps_ram < s->stride-1) { /* use revolve_offline for each stride */ 326 s->stype = TWO_LEVEL_REVOLVE; 327 }else { /* checkpoint all for each stride */ 328 s->stype = TWO_LEVEL_NOREVOLVE; 329 s->stacksize = s->stride-1; 330 } 331 } else { 332 if (flg) { /* fixed time step */ 333 if (s->max_cps_ram >= s->total_steps-1 || s->max_cps_ram < 1) { /* checkpoint all */ 334 s->stype = NONE; 335 s->stacksize = s->total_steps-1; 336 } else { 337 if (s->max_cps_disk > 1) { /* disk can be used */ 338 s->stype = REVOLVE_MULTISTAGE; 339 } else { /* memory only */ 340 s->stype = REVOLVE_OFFLINE; 341 } 342 } 343 } else { /* adaptive time step */ 344 s->stype = REVOLVE_ONLINE; 345 } 346 } 347 348 if (s->stype > TWO_LEVEL_NOREVOLVE) { 349 #ifndef PETSC_HAVE_REVOLVE 350 SETERRQ(s->comm,PETSC_ERR_SUP,"revolve is needed when there is not enought memory to checkpoint all time steps according to the user's settings, please reconfigure with the additional option --download-revolve."); 351 #else 352 if (s->stype == TWO_LEVEL_REVOLVE) revolve_create_offline(s->stride,s->max_cps_ram); 353 else if (s->stype == REVOLVE_OFFLINE) revolve_create_offline(s->total_steps,s->max_cps_ram); 354 else if (s->stype == REVOLVE_ONLINE) revolve_create_online(s->max_cps_ram); 355 else if (s->stype ==REVOLVE_MULTISTAGE) revolve_create_multistage(s->total_steps,s->max_cps_ram+s->max_cps_disk,s->max_cps_ram); 356 357 ierr = PetscCalloc1(1,&rctx);CHKERRQ(ierr); 358 rctx->snaps_in = s->max_cps_ram; /* for theta methods snaps_in=2*max_cps_ram */ 359 rctx->reverseonestep = PETSC_FALSE; 360 rctx->check = -1; 361 rctx->oldcapo = 0; 362 rctx->capo = 0; 363 rctx->info = 2; 364 rctx->fine = (s->stride > 1) ? s->stride : s->total_steps; 365 366 s->rctx = rctx; 367 #endif 368 } 369 370 s->recompute = PETSC_FALSE; 371 372 ierr = TSGetStages(ts,&numY,PETSC_IGNORE);CHKERRQ(ierr); 373 ierr = StackCreate(PetscObjectComm((PetscObject)ts),s,s->stacksize,numY);CHKERRQ(ierr); 374 PetscFunctionReturn(0); 375 } 376 377 #undef __FUNCT__ 378 #define __FUNCT__ "TSTrajectorySet_Memory" 379 PetscErrorCode TSTrajectorySet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal time,Vec X) 380 { 381 PetscInt i; 382 Vec *Y; 383 PetscReal timeprev; 384 StackElement e; 385 Stack *s = (Stack*)tj->data; 386 PetscInt localstepnum,id; 387 RevolveCTX *rctx; 388 #ifdef PETSC_HAVE_REVOLVE 389 PetscInt whattodo,shift; 390 #endif 391 PetscErrorCode ierr; 392 393 PetscFunctionBegin; 394 if (!s->recompute) { /* use global stepnum in the forward sweep */ 395 ierr = TSGetTotalSteps(ts,&stepnum);CHKERRQ(ierr); 396 } 397 if (s->stype == TWO_LEVEL_REVOLVE || s->stype == TWO_LEVEL_NOREVOLVE) { /* two-level mode */ 398 localstepnum = stepnum%s->stride; 399 if (stepnum!=0 && stepnum!=s->total_steps && localstepnum==0 && !s->recompute) { /* never need to recompute localstepnum=0 */ 400 #ifdef PETSC_HAVE_REVOLVE 401 PetscPrintf(PETSC_COMM_WORLD,"\x1B[33mDump stack to file\033[0m\n"); 402 #endif 403 id = stepnum/s->stride; 404 ierr = StackDumpAll(ts,s,id);CHKERRQ(ierr); 405 s->top = -1; /* reset top */ 406 #ifdef PETSC_HAVE_REVOLVE 407 if (s->stype == TWO_LEVEL_REVOLVE) { 408 revolve_reset(); 409 revolve_create_offline(s->stride,s->max_cps_ram); 410 rctx = s->rctx; 411 rctx->check = 0; 412 rctx->capo = 0; 413 rctx->fine = s->stride; 414 } 415 #endif 416 } 417 } else { 418 localstepnum = stepnum; 419 } 420 421 if (s->stype > TWO_LEVEL_NOREVOLVE) { 422 #ifdef PETSC_HAVE_REVOLVE 423 rctx = s->rctx; 424 if (rctx->reverseonestep && stepnum==s->total_steps) { /* intermediate information is ready inside TS, this happens at last time step */ 425 rctx->reverseonestep = PETSC_FALSE; 426 PetscFunctionReturn(0); 427 } 428 if (rctx->stepsleft != 0) { /* advance the solution without checkpointing anything as Revolve requires */ 429 rctx->stepsleft--; 430 PetscFunctionReturn(0); 431 } 432 433 /* let Revolve determine what to do next */ 434 shift = stepnum-localstepnum; 435 rctx->capo = localstepnum; 436 rctx->oldcapo = rctx->capo; 437 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 438 printwhattodo(whattodo,rctx,shift); 439 if (whattodo == -1) SETERRQ(s->comm,PETSC_ERR_LIB,"Error in the Revolve library"); 440 if (whattodo == 1) { /* advance some time steps */ 441 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 442 PetscFunctionReturn(0); 443 } 444 if (whattodo == 3 || whattodo == 4) { /* ready for a reverse step */ 445 rctx->reverseonestep = PETSC_TRUE; 446 PetscFunctionReturn(0); 447 } 448 if (whattodo == 5) { /* restore a checkpoint and ask Revolve what to do next */ 449 rctx->oldcapo = rctx->capo; 450 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1*/ 451 printwhattodo(whattodo,rctx,shift); 452 rctx->stepsleft = rctx->capo-rctx->oldcapo; 453 PetscFunctionReturn(0); 454 } 455 if (whattodo == 2) { /* store a checkpoint and ask Revolve how many time steps to advance next */ 456 rctx->oldcapo = rctx->capo; 457 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1*/ 458 printwhattodo(whattodo,rctx,shift); 459 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 460 } 461 #endif 462 } else { /* Revolve is not used */ 463 /* skip the first and the last steps of each stride or the whole interval */ 464 if (localstepnum == 0 || stepnum == s->total_steps) PetscFunctionReturn(0); 465 } 466 467 /* checkpoint to memory */ 468 if (localstepnum == s->top) { /* overwrite the top checkpoint, this might happen when the time interval is split into several smaller ones, each corresponding to a call of TSSolve() */ 469 ierr = StackTop(s,&e);CHKERRQ(ierr); 470 ierr = VecCopy(X,e->X);CHKERRQ(ierr); 471 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 472 for (i=0;i<s->numY;i++) { 473 ierr = VecCopy(Y[i],e->Y[i]);CHKERRQ(ierr); 474 } 475 e->stepnum = stepnum; 476 e->time = time; 477 ierr = TSGetPrevTime(ts,&timeprev);CHKERRQ(ierr); 478 e->timeprev = timeprev; 479 } else { 480 if (localstepnum < s->top) SETERRQ(s->comm,PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 481 ierr = PetscCalloc1(1,&e);CHKERRQ(ierr); 482 ierr = VecDuplicate(X,&e->X);CHKERRQ(ierr); 483 ierr = VecCopy(X,e->X);CHKERRQ(ierr); 484 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 485 if (s->numY > 0) { 486 ierr = VecDuplicateVecs(Y[0],s->numY,&e->Y);CHKERRQ(ierr); 487 } 488 for (i=0;i<s->numY;i++) { 489 ierr = VecCopy(Y[i],e->Y[i]);CHKERRQ(ierr); 490 } 491 e->stepnum = stepnum; 492 e->time = time; 493 /* for consistency */ 494 if (stepnum == 0) { 495 e->timeprev = e->time - ts->time_step; 496 } else { 497 ierr = TSGetPrevTime(ts,&timeprev);CHKERRQ(ierr); 498 e->timeprev = timeprev; 499 } 500 ierr = StackPush(s,e);CHKERRQ(ierr); 501 } 502 PetscFunctionReturn(0); 503 } 504 505 #undef __FUNCT__ 506 #define __FUNCT__ "TSTrajectoryGet_Memory" 507 PetscErrorCode TSTrajectoryGet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal *t) 508 { 509 Vec *Y; 510 PetscInt i; 511 StackElement e; 512 Stack *s = (Stack*)tj->data; 513 PetscReal stepsize; 514 PetscInt localstepnum,id; 515 #ifdef PETSC_HAVE_REVOLVE 516 PetscInt whattodo,shift; 517 #endif 518 PetscErrorCode ierr; 519 520 PetscFunctionBegin; 521 ierr = TSGetTotalSteps(ts,&stepnum);CHKERRQ(ierr); 522 if (s->stype == TWO_LEVEL_REVOLVE || s->stype == TWO_LEVEL_NOREVOLVE) { /* two-level mode */ 523 localstepnum = stepnum%s->stride; 524 if (localstepnum == 0 && stepnum != 0 && stepnum != s->total_steps) { 525 #ifdef PETSC_HAVE_REVOLVE 526 PetscPrintf(PETSC_COMM_WORLD,"\x1B[33mLoad stack from file\033[0m\n"); 527 #endif 528 id = stepnum/s->stride; 529 ierr = StackLoadAll(ts,s,id);CHKERRQ(ierr); 530 s->top = s->stacksize-1; 531 #ifdef PETSC_HAVE_REVOLVE 532 if (s->stype == TWO_LEVEL_REVOLVE) { 533 revolve_reset(); 534 revolve_create_offline(s->stride,s->max_cps_ram); 535 s->rctx->check = 0; 536 s->rctx->capo = 0; 537 s->rctx->fine = s->stride; 538 whattodo = 0; 539 while(whattodo!=3) { /* stupid revolve */ 540 whattodo = revolve_action(&s->rctx->check,&s->rctx->capo,&s->rctx->fine,s->rctx->snaps_in,&s->rctx->info,&s->rctx->where); 541 } 542 } 543 #endif 544 } 545 } else { 546 localstepnum = stepnum; 547 } 548 #ifdef PETSC_HAVE_REVOLVE 549 if (s->stype > TWO_LEVEL_NOREVOLVE && s->rctx->reverseonestep) { /* ready for the reverse step */ 550 ierr = TSGetTimeStep(ts,&stepsize);CHKERRQ(ierr); 551 ierr = TSSetTimeStep(ts,-stepsize);CHKERRQ(ierr); 552 s->rctx->reverseonestep = PETSC_FALSE; 553 PetscFunctionReturn(0); 554 } 555 #endif 556 if (localstepnum == 0 || stepnum == s->total_steps) { 557 ierr = TSGetTimeStep(ts,&stepsize);CHKERRQ(ierr); 558 ierr = TSSetTimeStep(ts,-stepsize);CHKERRQ(ierr); 559 PetscFunctionReturn(0); 560 } 561 /* restore a checkpoint */ 562 ierr = StackTop(s,&e);CHKERRQ(ierr); 563 ierr = VecCopy(e->X,ts->vec_sol);CHKERRQ(ierr); 564 ierr = TSGetStages(ts,&s->numY,&Y);CHKERRQ(ierr); 565 for (i=0;i<s->numY;i++) { 566 ierr = VecCopy(e->Y[i],Y[i]);CHKERRQ(ierr); 567 } 568 *t = e->time; 569 570 if (e->stepnum < stepnum) { /* need recomputation */ 571 s->recompute = PETSC_TRUE; 572 shift = stepnum-localstepnum; 573 #ifdef PETSC_HAVE_REVOLVE 574 s->rctx->capo = localstepnum; 575 whattodo = revolve_action(&s->rctx->check,&s->rctx->capo,&s->rctx->fine,s->rctx->snaps_in,&s->rctx->info,&s->rctx->where); 576 printwhattodo(whattodo,s->rctx,shift); 577 #endif 578 ierr = TSSetTimeStep(ts,(*t)-e->timeprev);CHKERRQ(ierr); 579 /* reset ts context */ 580 PetscInt steps = ts->steps; 581 ts->steps = e->stepnum; 582 ts->ptime = e->time; 583 ts->ptime_prev = e->timeprev; 584 for (i=e->stepnum;i<stepnum;i++) { /* assume fixed step size */ 585 ierr = TSTrajectorySet(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 586 ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 587 ierr = TSStep(ts);CHKERRQ(ierr); 588 if (ts->event) { 589 ierr = TSEventMonitor(ts);CHKERRQ(ierr); 590 } 591 if (!ts->steprollback) { 592 ierr = TSPostStep(ts);CHKERRQ(ierr); 593 } 594 } 595 /* reverseonestep must be true after the for loop */ 596 ts->steps = steps; 597 ts->total_steps = stepnum; 598 ierr = TSGetTimeStep(ts,&stepsize);CHKERRQ(ierr); 599 ierr = TSSetTimeStep(ts,-stepsize);CHKERRQ(ierr); 600 if (stepnum-e->stepnum==1) { /* the restored checkpoint can be deleted now */ 601 ierr = StackPop(s,&e);CHKERRQ(ierr); 602 ierr = VecDestroy(&e->X);CHKERRQ(ierr); 603 ierr = VecDestroyVecs(s->numY,&e->Y);CHKERRQ(ierr); 604 ierr = PetscFree(e);CHKERRQ(ierr); 605 } 606 #ifdef PETSC_HAVE_REVOLVE 607 s->rctx->reverseonestep = PETSC_FALSE; 608 #endif 609 } else if (e->stepnum == stepnum) { /* restore the data directly from checkpoints */ 610 ierr = TSSetTimeStep(ts,-(*t)+e->timeprev);CHKERRQ(ierr); 611 ierr = StackPop(s,&e);CHKERRQ(ierr); 612 ierr = VecDestroy(&e->X);CHKERRQ(ierr); 613 ierr = VecDestroyVecs(s->numY,&e->Y);CHKERRQ(ierr); 614 ierr = PetscFree(e);CHKERRQ(ierr); 615 } else { 616 SETERRQ2(s->comm,PETSC_ERR_ARG_OUTOFRANGE,"The current step no. is %D, but the step number at top of the stack is %D",stepnum,e->stepnum); 617 } 618 619 PetscFunctionReturn(0); 620 } 621 622 #undef __FUNCT__ 623 #define __FUNCT__ "TSTrajectoryDestroy_Memory" 624 PETSC_EXTERN PetscErrorCode TSTrajectoryDestroy_Memory(TSTrajectory tj) 625 { 626 Stack *s = (Stack*)tj->data; 627 PetscErrorCode ierr; 628 629 PetscFunctionBegin; 630 if (s->stype > TWO_LEVEL_NOREVOLVE) { 631 #ifdef PETSC_HAVE_REVOLVE 632 revolve_reset(); 633 #endif 634 } 635 ierr = StackDestroy(s);CHKERRQ(ierr); 636 PetscFunctionReturn(0); 637 } 638 639 /*MC 640 TSTRAJECTORYMEMORY - Stores each solution of the ODE/ADE in memory 641 642 Level: intermediate 643 644 .seealso: TSTrajectoryCreate(), TS, TSTrajectorySetType() 645 646 M*/ 647 #undef __FUNCT__ 648 #define __FUNCT__ "TSTrajectoryCreate_Memory" 649 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory tj,TS ts) 650 { 651 Stack *s; 652 PetscErrorCode ierr; 653 654 PetscFunctionBegin; 655 tj->ops->set = TSTrajectorySet_Memory; 656 tj->ops->get = TSTrajectoryGet_Memory; 657 tj->ops->setup = TSTrajectorySetUp_Memory; 658 tj->ops->destroy = TSTrajectoryDestroy_Memory; 659 tj->ops->setfromoptions = TSTrajectorySetFromOptions_Memory; 660 661 ierr = PetscCalloc1(1,&s);CHKERRQ(ierr); 662 s->stype = NONE; 663 s->max_cps_ram = -1; /* -1 indicates that it is not set */ 664 s->max_cps_disk = -1; /* -1 indicates that it is not set */ 665 s->stride = 0; /* if not zero, two-level checkpointing will be used */ 666 tj->data = s; 667 PetscFunctionReturn(0); 668 } 669