1 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 2 #include <petscsys.h> 3 #if defined(PETSC_HAVE_REVOLVE) 4 #include <revolve_c.h> 5 6 /* Limit Revolve to 32-bits */ 7 #define PETSC_REVOLVE_INT_MAX 2147483647 8 9 typedef int PetscRevolveInt; 10 11 static inline PetscErrorCode PetscRevolveIntCast(PetscInt a,PetscRevolveInt *b) 12 { 13 PetscFunctionBegin; 14 #if defined(PETSC_USE_64BIT_INDICES) 15 *b = 0; 16 PetscCheck(a <= PETSC_REVOLVE_INT_MAX,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Parameter is too large for Revolve, which is restricted to 32 bit integers"); 17 #endif 18 *b = (PetscRevolveInt)(a); 19 PetscFunctionReturn(0); 20 } 21 #endif 22 #if defined(PETSC_HAVE_CAMS) 23 #include <offline_schedule.h> 24 #endif 25 26 PetscLogEvent TSTrajectory_DiskWrite, TSTrajectory_DiskRead; 27 static PetscErrorCode TSTrajectorySet_Memory(TSTrajectory,TS,PetscInt,PetscReal,Vec); 28 29 typedef enum {NONE,TWO_LEVEL_NOREVOLVE,TWO_LEVEL_REVOLVE,TWO_LEVEL_TWO_REVOLVE,REVOLVE_OFFLINE,REVOLVE_ONLINE,REVOLVE_MULTISTAGE,CAMS_OFFLINE} SchedulerType; 30 31 typedef enum {UNSET=-1,SOLUTIONONLY=0,STAGESONLY=1,SOLUTION_STAGES=2} CheckpointType; 32 33 typedef enum {TJ_REVOLVE, TJ_CAMS, TJ_PETSC} TSTrajectoryMemoryType; 34 static const char *const TSTrajectoryMemoryTypes[] = {"REVOLVE","CAMS","PETSC","TSTrajectoryMemoryType","TJ_",NULL}; 35 36 #define HaveSolution(m) ((m) == SOLUTIONONLY || (m) == SOLUTION_STAGES) 37 #define HaveStages(m) ((m) == STAGESONLY || (m) == SOLUTION_STAGES) 38 39 typedef struct _StackElement { 40 PetscInt stepnum; 41 Vec X; 42 Vec *Y; 43 PetscReal time; 44 PetscReal timeprev; /* for no solution_only mode */ 45 PetscReal timenext; /* for solution_only mode */ 46 CheckpointType cptype; 47 } *StackElement; 48 49 #if defined(PETSC_HAVE_REVOLVE) 50 typedef struct _RevolveCTX { 51 PetscBool reverseonestep; 52 PetscRevolveInt where; 53 PetscRevolveInt snaps_in; 54 PetscRevolveInt stepsleft; 55 PetscRevolveInt check; 56 PetscRevolveInt oldcapo; 57 PetscRevolveInt capo; 58 PetscRevolveInt fine; 59 PetscRevolveInt info; 60 } RevolveCTX; 61 #endif 62 63 #if defined(PETSC_HAVE_CAMS) 64 typedef struct _CAMSCTX { 65 PetscInt lastcheckpointstep; 66 PetscInt lastcheckpointtype; 67 PetscInt num_units_avail; 68 PetscInt endstep; 69 PetscInt num_stages; 70 PetscInt nextcheckpointstep; 71 PetscInt nextcheckpointtype; /* (0) solution only (1) stages (2) solution+stages */ 72 PetscInt info; 73 } CAMSCTX; 74 #endif 75 76 typedef struct _Stack { 77 PetscInt stacksize; 78 PetscInt top; 79 StackElement *container; 80 PetscInt nallocated; 81 PetscInt numY; 82 PetscBool solution_only; 83 PetscBool use_dram; 84 } Stack; 85 86 typedef struct _DiskStack { 87 PetscInt stacksize; 88 PetscInt top; 89 PetscInt *container; 90 } DiskStack; 91 92 typedef struct _TJScheduler { 93 SchedulerType stype; 94 TSTrajectoryMemoryType tj_memory_type; 95 #if defined(PETSC_HAVE_REVOLVE) 96 RevolveCTX *rctx,*rctx2; 97 PetscBool use_online; 98 PetscInt store_stride; 99 #endif 100 #if defined(PETSC_HAVE_CAMS) 101 CAMSCTX *actx; 102 #endif 103 PetscBool recompute; 104 PetscBool skip_trajectory; 105 PetscBool save_stack; 106 PetscInt max_units_ram; /* maximum checkpointing units in RAM */ 107 PetscInt max_units_disk; /* maximum checkpointing units on disk */ 108 PetscInt max_cps_ram; /* maximum checkpoints in RAM */ 109 PetscInt max_cps_disk; /* maximum checkpoints on disk */ 110 PetscInt stride; 111 PetscInt total_steps; /* total number of steps */ 112 Stack stack; 113 DiskStack diskstack; 114 PetscViewer viewer; 115 } TJScheduler; 116 117 static PetscErrorCode TurnForwardWithStepsize(TS ts,PetscReal nextstepsize) 118 { 119 PetscFunctionBegin; 120 /* reverse the direction */ 121 CHKERRQ(TSSetTimeStep(ts,nextstepsize)); 122 PetscFunctionReturn(0); 123 } 124 125 static PetscErrorCode TurnForward(TS ts) 126 { 127 PetscReal stepsize; 128 129 PetscFunctionBegin; 130 /* reverse the direction */ 131 CHKERRQ(TSGetTimeStep(ts,&stepsize)); 132 CHKERRQ(TSSetTimeStep(ts,-stepsize)); 133 PetscFunctionReturn(0); 134 } 135 136 static PetscErrorCode TurnBackward(TS ts) 137 { 138 PetscReal stepsize; 139 140 PetscFunctionBegin; 141 if (!ts->trajectory->adjoint_solve_mode) PetscFunctionReturn(0); 142 /* reverse the direction */ 143 stepsize = ts->ptime_prev-ts->ptime; 144 CHKERRQ(TSSetTimeStep(ts,stepsize)); 145 PetscFunctionReturn(0); 146 } 147 148 static PetscErrorCode ElementCreate(TS ts,CheckpointType cptype,Stack *stack,StackElement *e) 149 { 150 Vec X; 151 Vec *Y; 152 153 PetscFunctionBegin; 154 if (stack->top < stack->stacksize-1 && stack->container[stack->top+1]) { 155 *e = stack->container[stack->top+1]; 156 if (HaveSolution(cptype) && !(*e)->X) { 157 CHKERRQ(TSGetSolution(ts,&X)); 158 CHKERRQ(VecDuplicate(X,&(*e)->X)); 159 } 160 if (cptype==1 && (*e)->X) { 161 CHKERRQ(VecDestroy(&(*e)->X)); 162 } 163 if (HaveStages(cptype) && !(*e)->Y) { 164 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 165 if (stack->numY) { 166 CHKERRQ(VecDuplicateVecs(Y[0],stack->numY,&(*e)->Y)); 167 } 168 } 169 if (cptype==0 && (*e)->Y) { 170 CHKERRQ(VecDestroyVecs(stack->numY,&(*e)->Y)); 171 } 172 (*e)->cptype = cptype; 173 PetscFunctionReturn(0); 174 } 175 if (stack->use_dram) { 176 CHKERRQ(PetscMallocSetDRAM()); 177 } 178 CHKERRQ(PetscNew(e)); 179 if (HaveSolution(cptype)) { 180 CHKERRQ(TSGetSolution(ts,&X)); 181 CHKERRQ(VecDuplicate(X,&(*e)->X)); 182 } 183 if (HaveStages(cptype)) { 184 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 185 if (stack->numY) { 186 CHKERRQ(VecDuplicateVecs(Y[0],stack->numY,&(*e)->Y)); 187 } 188 } 189 if (stack->use_dram) { 190 CHKERRQ(PetscMallocResetDRAM()); 191 } 192 stack->nallocated++; 193 (*e)->cptype = cptype; 194 PetscFunctionReturn(0); 195 } 196 197 static PetscErrorCode ElementSet(TS ts, Stack *stack, StackElement *e, PetscInt stepnum, PetscReal time, Vec X) 198 { 199 Vec *Y; 200 PetscInt i; 201 PetscReal timeprev; 202 203 PetscFunctionBegin; 204 if (HaveSolution((*e)->cptype)) { 205 CHKERRQ(VecCopy(X,(*e)->X)); 206 } 207 if (HaveStages((*e)->cptype)) { 208 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 209 for (i=0;i<stack->numY;i++) { 210 CHKERRQ(VecCopy(Y[i],(*e)->Y[i])); 211 } 212 } 213 (*e)->stepnum = stepnum; 214 (*e)->time = time; 215 /* for consistency */ 216 if (stepnum == 0) { 217 (*e)->timeprev = (*e)->time - ts->time_step; 218 } else { 219 CHKERRQ(TSGetPrevTime(ts,&timeprev)); 220 (*e)->timeprev = timeprev; 221 } 222 PetscFunctionReturn(0); 223 } 224 225 static PetscErrorCode ElementDestroy(Stack *stack,StackElement e) 226 { 227 PetscFunctionBegin; 228 if (stack->use_dram) { 229 CHKERRQ(PetscMallocSetDRAM()); 230 } 231 CHKERRQ(VecDestroy(&e->X)); 232 if (e->Y) { 233 CHKERRQ(VecDestroyVecs(stack->numY,&e->Y)); 234 } 235 CHKERRQ(PetscFree(e)); 236 if (stack->use_dram) { 237 CHKERRQ(PetscMallocResetDRAM()); 238 } 239 stack->nallocated--; 240 PetscFunctionReturn(0); 241 } 242 243 static PetscErrorCode StackResize(Stack *stack,PetscInt newsize) 244 { 245 StackElement *newcontainer; 246 PetscInt i; 247 248 PetscFunctionBegin; 249 CHKERRQ(PetscCalloc1(newsize*sizeof(StackElement),&newcontainer)); 250 for (i=0;i<stack->stacksize;i++) { 251 newcontainer[i] = stack->container[i]; 252 } 253 CHKERRQ(PetscFree(stack->container)); 254 stack->container = newcontainer; 255 stack->stacksize = newsize; 256 PetscFunctionReturn(0); 257 } 258 259 static PetscErrorCode StackPush(Stack *stack,StackElement e) 260 { 261 PetscFunctionBegin; 262 PetscCheck(stack->top+1 < stack->stacksize,PETSC_COMM_SELF,PETSC_ERR_MEMC,"Maximum stack size (%D) exceeded",stack->stacksize); 263 stack->container[++stack->top] = e; 264 PetscFunctionReturn(0); 265 } 266 267 static PetscErrorCode StackPop(Stack *stack,StackElement *e) 268 { 269 PetscFunctionBegin; 270 *e = NULL; 271 PetscCheck(stack->top != -1,PETSC_COMM_SELF,PETSC_ERR_MEMC,"Empty stack"); 272 *e = stack->container[stack->top--]; 273 PetscFunctionReturn(0); 274 } 275 276 static PetscErrorCode StackTop(Stack *stack,StackElement *e) 277 { 278 PetscFunctionBegin; 279 *e = stack->container[stack->top]; 280 PetscFunctionReturn(0); 281 } 282 283 static PetscErrorCode StackInit(Stack *stack,PetscInt size,PetscInt ny) 284 { 285 PetscFunctionBegin; 286 stack->top = -1; 287 stack->numY = ny; 288 289 if (!stack->container) { 290 CHKERRQ(PetscCalloc1(size,&stack->container)); 291 } 292 PetscFunctionReturn(0); 293 } 294 295 static PetscErrorCode StackDestroy(Stack *stack) 296 { 297 const PetscInt n = stack->nallocated; 298 299 PetscFunctionBegin; 300 if (!stack->container) PetscFunctionReturn(0); 301 PetscCheck(stack->top+1 <= n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Stack size does not match element counter %D",n); 302 for (PetscInt i=0; i<n; i++) CHKERRQ(ElementDestroy(stack,stack->container[i])); 303 CHKERRQ(PetscFree(stack->container)); 304 PetscFunctionReturn(0); 305 } 306 307 static PetscErrorCode StackFind(Stack *stack,StackElement *e,PetscInt index) 308 { 309 PetscFunctionBegin; 310 *e = NULL; 311 PetscCheck(index >= 0 && index <= stack->top,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %D",index); 312 *e = stack->container[index]; 313 PetscFunctionReturn(0); 314 } 315 316 static PetscErrorCode WriteToDisk(PetscBool stifflyaccurate,PetscInt stepnum,PetscReal time,PetscReal timeprev,Vec X,Vec *Y,PetscInt numY,CheckpointType cptype,PetscViewer viewer) 317 { 318 PetscFunctionBegin; 319 CHKERRQ(PetscViewerBinaryWrite(viewer,&stepnum,1,PETSC_INT)); 320 if (HaveSolution(cptype)) CHKERRQ(VecView(X,viewer)); 321 if (HaveStages(cptype)) { 322 for (PetscInt i=0; i<numY; i++) { 323 /* For stiffly accurate TS methods, the last stage Y[ns-1] is the same as the solution X, thus does not need to be saved again. */ 324 if (stifflyaccurate && i == numY-1 && HaveSolution(cptype)) continue; 325 CHKERRQ(VecView(Y[i],viewer)); 326 } 327 } 328 CHKERRQ(PetscViewerBinaryWrite(viewer,&time,1,PETSC_REAL)); 329 CHKERRQ(PetscViewerBinaryWrite(viewer,&timeprev,1,PETSC_REAL)); 330 PetscFunctionReturn(0); 331 } 332 333 static PetscErrorCode ReadFromDisk(PetscBool stifflyaccurate,PetscInt *stepnum,PetscReal *time,PetscReal *timeprev,Vec X,Vec *Y,PetscInt numY,CheckpointType cptype,PetscViewer viewer) 334 { 335 PetscFunctionBegin; 336 CHKERRQ(PetscViewerBinaryRead(viewer,stepnum,1,NULL,PETSC_INT)); 337 if (HaveSolution(cptype)) CHKERRQ(VecLoad(X,viewer)); 338 if (HaveStages(cptype)) { 339 for (PetscInt i=0; i<numY; i++) { 340 /* For stiffly accurate TS methods, the last stage Y[ns-1] is the same as the solution X, thus does not need to be loaded again. */ 341 if (stifflyaccurate && i == numY-1 && HaveSolution(cptype)) continue; 342 CHKERRQ(VecLoad(Y[i],viewer)); 343 } 344 } 345 CHKERRQ(PetscViewerBinaryRead(viewer,time,1,NULL,PETSC_REAL)); 346 CHKERRQ(PetscViewerBinaryRead(viewer,timeprev,1,NULL,PETSC_REAL)); 347 PetscFunctionReturn(0); 348 } 349 350 static PetscErrorCode StackDumpAll(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 351 { 352 Vec *Y; 353 PetscInt ndumped,cptype_int; 354 StackElement e = NULL; 355 TJScheduler *tjsch = (TJScheduler*)tj->data; 356 char filename[PETSC_MAX_PATH_LEN]; 357 MPI_Comm comm; 358 359 PetscFunctionBegin; 360 CHKERRQ(PetscObjectGetComm((PetscObject)ts,&comm)); 361 if (tj->monitor) { 362 CHKERRQ(PetscViewerASCIIPushTab(tj->monitor)); 363 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Dump stack id %D to file\n",id)); 364 CHKERRQ(PetscViewerASCIIPopTab(tj->monitor)); 365 } 366 CHKERRQ(PetscSNPrintf(filename,sizeof(filename),"%s/TS-STACK%06d.bin",tj->dirname,id)); 367 CHKERRQ(PetscViewerFileSetName(tjsch->viewer,filename)); 368 CHKERRQ(PetscViewerSetUp(tjsch->viewer)); 369 ndumped = stack->top+1; 370 CHKERRQ(PetscViewerBinaryWrite(tjsch->viewer,&ndumped,1,PETSC_INT)); 371 for (PetscInt i=0;i<ndumped;i++) { 372 e = stack->container[i]; 373 cptype_int = (PetscInt)e->cptype; 374 CHKERRQ(PetscViewerBinaryWrite(tjsch->viewer,&cptype_int,1,PETSC_INT)); 375 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0)); 376 CHKERRQ(WriteToDisk(ts->stifflyaccurate,e->stepnum,e->time,e->timeprev,e->X,e->Y,stack->numY,e->cptype,tjsch->viewer)); 377 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0)); 378 ts->trajectory->diskwrites++; 379 CHKERRQ(StackPop(stack,&e)); 380 } 381 /* save the last step for restart, the last step is in memory when using single level schemes, but not necessarily the case for multi level schemes */ 382 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 383 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0)); 384 CHKERRQ(WriteToDisk(ts->stifflyaccurate,ts->steps,ts->ptime,ts->ptime_prev,ts->vec_sol,Y,stack->numY,SOLUTION_STAGES,tjsch->viewer)); 385 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0)); 386 ts->trajectory->diskwrites++; 387 PetscFunctionReturn(0); 388 } 389 390 static PetscErrorCode StackLoadAll(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 391 { 392 Vec *Y; 393 PetscInt i,nloaded,cptype_int; 394 StackElement e; 395 PetscViewer viewer; 396 char filename[PETSC_MAX_PATH_LEN]; 397 398 PetscFunctionBegin; 399 if (tj->monitor) { 400 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 401 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Load stack from file\n")); 402 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 403 } 404 CHKERRQ(PetscSNPrintf(filename,sizeof filename,"%s/TS-STACK%06d.bin",tj->dirname,id)); 405 CHKERRQ(PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer)); 406 CHKERRQ(PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE)); 407 CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE)); 408 CHKERRQ(PetscViewerBinaryRead(viewer,&nloaded,1,NULL,PETSC_INT)); 409 for (i=0;i<nloaded;i++) { 410 CHKERRQ(PetscViewerBinaryRead(viewer,&cptype_int,1,NULL,PETSC_INT)); 411 CHKERRQ(ElementCreate(ts,(CheckpointType)cptype_int,stack,&e)); 412 CHKERRQ(StackPush(stack,e)); 413 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0)); 414 CHKERRQ(ReadFromDisk(ts->stifflyaccurate,&e->stepnum,&e->time,&e->timeprev,e->X,e->Y,stack->numY,e->cptype,viewer)); 415 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0)); 416 ts->trajectory->diskreads++; 417 } 418 /* load the last step into TS */ 419 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 420 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0)); 421 CHKERRQ(ReadFromDisk(ts->stifflyaccurate,&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,SOLUTION_STAGES,viewer)); 422 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0)); 423 ts->trajectory->diskreads++; 424 CHKERRQ(TurnBackward(ts)); 425 CHKERRQ(PetscViewerDestroy(&viewer)); 426 PetscFunctionReturn(0); 427 } 428 429 #if defined(PETSC_HAVE_REVOLVE) 430 static PetscErrorCode StackLoadLast(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 431 { 432 Vec *Y; 433 PetscInt size; 434 PetscViewer viewer; 435 char filename[PETSC_MAX_PATH_LEN]; 436 #if defined(PETSC_HAVE_MPIIO) 437 PetscBool usempiio; 438 #endif 439 int fd; 440 off_t off,offset; 441 442 PetscFunctionBegin; 443 if (tj->monitor) { 444 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 445 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Load last stack element from file\n")); 446 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 447 } 448 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 449 CHKERRQ(VecGetSize(Y[0],&size)); 450 /* VecView writes to file two extra int's for class id and number of rows */ 451 off = -((stack->solution_only?0:stack->numY)+1)*(size*PETSC_BINARY_SCALAR_SIZE+2*PETSC_BINARY_INT_SIZE)-PETSC_BINARY_INT_SIZE-2*PETSC_BINARY_SCALAR_SIZE; 452 453 CHKERRQ(PetscSNPrintf(filename,sizeof filename,"%s/TS-STACK%06d.bin",tj->dirname,id)); 454 CHKERRQ(PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer)); 455 CHKERRQ(PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE)); 456 CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE)); 457 #if defined(PETSC_HAVE_MPIIO) 458 CHKERRQ(PetscViewerBinaryGetUseMPIIO(viewer,&usempiio)); 459 if (usempiio) { 460 CHKERRQ(PetscViewerBinaryGetMPIIODescriptor(viewer,(MPI_File*)&fd)); 461 CHKERRQ(PetscBinarySynchronizedSeek(PetscObjectComm((PetscObject)tj),fd,off,PETSC_BINARY_SEEK_END,&offset)); 462 } else { 463 #endif 464 CHKERRQ(PetscViewerBinaryGetDescriptor(viewer,&fd)); 465 CHKERRQ(PetscBinarySeek(fd,off,PETSC_BINARY_SEEK_END,&offset)); 466 #if defined(PETSC_HAVE_MPIIO) 467 } 468 #endif 469 /* load the last step into TS */ 470 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0)); 471 CHKERRQ(ReadFromDisk(ts->stifflyaccurate,&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,SOLUTION_STAGES,viewer)); 472 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0)); 473 ts->trajectory->diskreads++; 474 CHKERRQ(PetscViewerDestroy(&viewer)); 475 CHKERRQ(TurnBackward(ts)); 476 PetscFunctionReturn(0); 477 } 478 #endif 479 480 static PetscErrorCode DumpSingle(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 481 { 482 Vec *Y; 483 PetscInt stepnum; 484 TJScheduler *tjsch = (TJScheduler*)tj->data; 485 char filename[PETSC_MAX_PATH_LEN]; 486 MPI_Comm comm; 487 488 PetscFunctionBegin; 489 CHKERRQ(PetscObjectGetComm((PetscObject)ts,&comm)); 490 if (tj->monitor) { 491 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 492 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Dump a single point from file\n")); 493 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 494 } 495 CHKERRQ(TSGetStepNumber(ts,&stepnum)); 496 CHKERRQ(PetscSNPrintf(filename,sizeof(filename),"%s/TS-CPS%06d.bin",tj->dirname,id)); 497 CHKERRQ(PetscViewerFileSetName(tjsch->viewer,filename)); 498 CHKERRQ(PetscViewerSetUp(tjsch->viewer)); 499 500 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 501 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0)); 502 CHKERRQ(WriteToDisk(ts->stifflyaccurate,stepnum,ts->ptime,ts->ptime_prev,ts->vec_sol,Y,stack->numY,SOLUTION_STAGES,tjsch->viewer)); 503 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0)); 504 ts->trajectory->diskwrites++; 505 PetscFunctionReturn(0); 506 } 507 508 static PetscErrorCode LoadSingle(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 509 { 510 Vec *Y; 511 PetscViewer viewer; 512 char filename[PETSC_MAX_PATH_LEN]; 513 514 PetscFunctionBegin; 515 if (tj->monitor) { 516 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 517 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Load a single point from file\n")); 518 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 519 } 520 CHKERRQ(PetscSNPrintf(filename,sizeof filename,"%s/TS-CPS%06d.bin",tj->dirname,id)); 521 CHKERRQ(PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer)); 522 CHKERRQ(PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE)); 523 CHKERRQ(PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE)); 524 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 525 CHKERRQ(PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0)); 526 CHKERRQ(ReadFromDisk(ts->stifflyaccurate,&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,SOLUTION_STAGES,viewer)); 527 CHKERRQ(PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0)); 528 ts->trajectory->diskreads++; 529 CHKERRQ(PetscViewerDestroy(&viewer)); 530 PetscFunctionReturn(0); 531 } 532 533 static PetscErrorCode UpdateTS(TS ts,Stack *stack,StackElement e,PetscInt stepnum,PetscBool adjoint_mode) 534 { 535 Vec *Y; 536 PetscInt i; 537 538 PetscFunctionBegin; 539 /* In adjoint mode we do not need to copy solution if the stepnum is the same */ 540 if (!adjoint_mode || (HaveSolution(e->cptype) && e->stepnum!=stepnum)) { 541 CHKERRQ(VecCopy(e->X,ts->vec_sol)); 542 } 543 if (HaveStages(e->cptype)) { 544 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 545 if (e->stepnum && e->stepnum==stepnum) { 546 for (i=0;i<stack->numY;i++) { 547 CHKERRQ(VecCopy(e->Y[i],Y[i])); 548 } 549 } else if (ts->stifflyaccurate) { 550 CHKERRQ(VecCopy(e->Y[stack->numY-1],ts->vec_sol)); 551 } 552 } 553 if (adjoint_mode) { 554 CHKERRQ(TSSetTimeStep(ts,e->timeprev-e->time)); /* stepsize will be negative */ 555 } else { 556 CHKERRQ(TSSetTimeStep(ts,e->time-e->timeprev)); /* stepsize will be positive */ 557 } 558 ts->ptime = e->time; 559 ts->ptime_prev = e->timeprev; 560 PetscFunctionReturn(0); 561 } 562 563 static PetscErrorCode ReCompute(TS ts,TJScheduler *tjsch,PetscInt stepnumbegin,PetscInt stepnumend) 564 { 565 Stack *stack = &tjsch->stack; 566 PetscInt i; 567 568 PetscFunctionBegin; 569 tjsch->recompute = PETSC_TRUE; /* hints TSTrajectorySet() that it is in recompute mode */ 570 CHKERRQ(TSSetStepNumber(ts,stepnumbegin));/* global step number */ 571 for (i=stepnumbegin;i<stepnumend;i++) { /* assume fixed step size */ 572 if (stack->solution_only && !tjsch->skip_trajectory) { /* revolve online need this */ 573 /* don't use the public interface as it will update the TSHistory: this need a better fix */ 574 CHKERRQ(TSTrajectorySet_Memory(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol)); 575 } 576 CHKERRQ(TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol)); 577 CHKERRQ(TSStep(ts)); 578 if (!stack->solution_only && !tjsch->skip_trajectory) { 579 /* don't use the public interface as it will update the TSHistory: this need a better fix */ 580 CHKERRQ(TSTrajectorySet_Memory(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol)); 581 } 582 CHKERRQ(TSEventHandler(ts)); 583 if (!ts->steprollback) { 584 CHKERRQ(TSPostStep(ts)); 585 } 586 } 587 CHKERRQ(TurnBackward(ts)); 588 ts->trajectory->recomps += stepnumend-stepnumbegin; /* recomputation counter */ 589 CHKERRQ(TSSetStepNumber(ts,stepnumend)); 590 tjsch->recompute = PETSC_FALSE; /* reset the flag for recompute mode */ 591 PetscFunctionReturn(0); 592 } 593 594 static PetscErrorCode TopLevelStore(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscInt localstepnum,PetscInt laststridesize,PetscBool *done) 595 { 596 Stack *stack = &tjsch->stack; 597 DiskStack *diskstack = &tjsch->diskstack; 598 PetscInt stridenum; 599 600 PetscFunctionBegin; 601 *done = PETSC_FALSE; 602 stridenum = stepnum/tjsch->stride; 603 /* make sure saved checkpoint id starts from 1 604 skip last stride when using stridenum+1 605 skip first stride when using stridenum */ 606 if (stack->solution_only) { 607 if (tjsch->save_stack) { 608 if (localstepnum == tjsch->stride-1 && stepnum < tjsch->total_steps-laststridesize) { /* current step will be saved without going through stack */ 609 CHKERRQ(StackDumpAll(tj,ts,stack,stridenum+1)); 610 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 611 *done = PETSC_TRUE; 612 } 613 } else { 614 if (localstepnum == 0 && stepnum < tjsch->total_steps-laststridesize) { 615 CHKERRQ(DumpSingle(tj,ts,stack,stridenum+1)); 616 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 617 *done = PETSC_TRUE; 618 } 619 } 620 } else { 621 if (tjsch->save_stack) { 622 if (localstepnum == 0 && stepnum < tjsch->total_steps && stepnum != 0) { /* skip the first stride */ 623 CHKERRQ(StackDumpAll(tj,ts,stack,stridenum)); 624 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum; 625 *done = PETSC_TRUE; 626 } 627 } else { 628 if (localstepnum == 1 && stepnum < tjsch->total_steps-laststridesize) { 629 CHKERRQ(DumpSingle(tj,ts,stack,stridenum+1)); 630 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 631 *done = PETSC_TRUE; 632 } 633 } 634 } 635 PetscFunctionReturn(0); 636 } 637 638 static PetscErrorCode TSTrajectoryMemorySet_N(TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 639 { 640 Stack *stack = &tjsch->stack; 641 StackElement e; 642 CheckpointType cptype; 643 644 PetscFunctionBegin; 645 /* skip the last step */ 646 if (ts->reason) { /* only affect the forward run */ 647 /* update total_steps in the end of forward run */ 648 if (stepnum != tjsch->total_steps) tjsch->total_steps = stepnum; 649 if (stack->solution_only) { 650 /* get rid of the solution at second last step */ 651 CHKERRQ(StackPop(stack,&e)); 652 } 653 PetscFunctionReturn(0); 654 } 655 /* do not save trajectory at the recompute stage for solution_only mode */ 656 if (stack->solution_only && tjsch->recompute) PetscFunctionReturn(0); 657 /* skip the first step for no_solution_only mode */ 658 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 659 660 /* resize the stack */ 661 if (stack->top+1 == stack->stacksize) { 662 CHKERRQ(StackResize(stack,2*stack->stacksize)); 663 } 664 /* update timenext for the previous step; necessary for step adaptivity */ 665 if (stack->top > -1) { 666 CHKERRQ(StackTop(stack,&e)); 667 e->timenext = ts->ptime; 668 } 669 if (stepnum < stack->top) { 670 SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 671 } 672 cptype = stack->solution_only ? SOLUTIONONLY : STAGESONLY; 673 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 674 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 675 CHKERRQ(StackPush(stack,e)); 676 PetscFunctionReturn(0); 677 } 678 679 static PetscErrorCode TSTrajectoryMemorySet_N_2(TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 680 { 681 Stack *stack = &tjsch->stack; 682 StackElement e; 683 CheckpointType cptype; 684 685 PetscFunctionBegin; 686 if (stack->top+1 == stack->stacksize) { 687 CHKERRQ(StackResize(stack,2*stack->stacksize)); 688 } 689 /* update timenext for the previous step; necessary for step adaptivity */ 690 if (stack->top > -1) { 691 CHKERRQ(StackTop(stack,&e)); 692 e->timenext = ts->ptime; 693 } 694 PetscCheck(stepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 695 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; /* Always include solution in a checkpoint in non-adjoint mode */ 696 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 697 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 698 CHKERRQ(StackPush(stack,e)); 699 PetscFunctionReturn(0); 700 } 701 702 static PetscErrorCode TSTrajectoryMemoryGet_N(TS ts,TJScheduler *tjsch,PetscInt stepnum) 703 { 704 Stack *stack = &tjsch->stack; 705 StackElement e; 706 PetscInt ns; 707 708 PetscFunctionBegin; 709 /* If TSTrajectoryGet() is called after TSAdjointSolve() converges (e.g. outside the while loop in TSAdjointSolve()), skip getting the checkpoint. */ 710 if (ts->reason) PetscFunctionReturn(0); 711 if (stepnum == tjsch->total_steps) { 712 CHKERRQ(TurnBackward(ts)); 713 PetscFunctionReturn(0); 714 } 715 /* restore a checkpoint */ 716 CHKERRQ(StackTop(stack,&e)); 717 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 718 CHKERRQ(TSGetStages(ts,&ns,PETSC_IGNORE)); 719 if (stack->solution_only && ns) { /* recompute one step */ 720 CHKERRQ(TurnForwardWithStepsize(ts,e->timenext-e->time)); 721 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 722 } 723 CHKERRQ(StackPop(stack,&e)); 724 PetscFunctionReturn(0); 725 } 726 727 static PetscErrorCode TSTrajectoryMemoryGet_N_2(TS ts,TJScheduler *tjsch,PetscInt stepnum) 728 { 729 Stack *stack = &tjsch->stack; 730 StackElement e = NULL; 731 732 PetscFunctionBegin; 733 CHKERRQ(StackFind(stack,&e,stepnum)); 734 PetscCheck(stepnum == e->stepnum,PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Inconsistent steps! %D != %D",stepnum,e->stepnum); 735 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_FALSE)); 736 PetscFunctionReturn(0); 737 } 738 739 static PetscErrorCode TSTrajectoryMemorySet_TLNR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 740 { 741 Stack *stack = &tjsch->stack; 742 PetscInt localstepnum,laststridesize; 743 StackElement e; 744 PetscBool done; 745 CheckpointType cptype; 746 747 PetscFunctionBegin; 748 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 749 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 750 if (tjsch->save_stack && tjsch->recompute) PetscFunctionReturn(0); 751 752 localstepnum = stepnum%tjsch->stride; 753 /* (stridesize-1) checkpoints are saved in each stride; an extra point is added by StackDumpAll() */ 754 laststridesize = tjsch->total_steps%tjsch->stride; 755 if (!laststridesize) laststridesize = tjsch->stride; 756 757 if (!tjsch->recompute) { 758 CHKERRQ(TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done)); 759 if (!tjsch->save_stack && stepnum < tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 760 } 761 if (!stack->solution_only && localstepnum == 0) PetscFunctionReturn(0); /* skip last point in each stride at recompute stage or last stride */ 762 if (stack->solution_only && localstepnum == tjsch->stride-1) PetscFunctionReturn(0); /* skip last step in each stride at recompute stage or last stride */ 763 764 cptype = stack->solution_only ? SOLUTIONONLY : STAGESONLY; 765 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 766 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 767 CHKERRQ(StackPush(stack,e)); 768 PetscFunctionReturn(0); 769 } 770 771 static PetscErrorCode TSTrajectoryMemoryGet_TLNR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 772 { 773 Stack *stack = &tjsch->stack; 774 PetscInt id,localstepnum,laststridesize; 775 StackElement e; 776 777 PetscFunctionBegin; 778 if (stepnum == tjsch->total_steps) { 779 CHKERRQ(TurnBackward(ts)); 780 PetscFunctionReturn(0); 781 } 782 783 localstepnum = stepnum%tjsch->stride; 784 laststridesize = tjsch->total_steps%tjsch->stride; 785 if (!laststridesize) laststridesize = tjsch->stride; 786 if (stack->solution_only) { 787 /* fill stack with info */ 788 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 789 id = stepnum/tjsch->stride; 790 if (tjsch->save_stack) { 791 CHKERRQ(StackLoadAll(tj,ts,stack,id)); 792 tjsch->skip_trajectory = PETSC_TRUE; 793 CHKERRQ(TurnForward(ts)); 794 CHKERRQ(ReCompute(ts,tjsch,id*tjsch->stride-1,id*tjsch->stride)); 795 tjsch->skip_trajectory = PETSC_FALSE; 796 } else { 797 CHKERRQ(LoadSingle(tj,ts,stack,id)); 798 CHKERRQ(TurnForward(ts)); 799 CHKERRQ(ReCompute(ts,tjsch,(id-1)*tjsch->stride,id*tjsch->stride)); 800 } 801 PetscFunctionReturn(0); 802 } 803 /* restore a checkpoint */ 804 CHKERRQ(StackPop(stack,&e)); 805 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 806 tjsch->skip_trajectory = PETSC_TRUE; 807 CHKERRQ(TurnForward(ts)); 808 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 809 tjsch->skip_trajectory = PETSC_FALSE; 810 } else { 811 CheckpointType cptype = STAGESONLY; 812 /* fill stack with info */ 813 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 814 id = stepnum/tjsch->stride; 815 if (tjsch->save_stack) { 816 CHKERRQ(StackLoadAll(tj,ts,stack,id)); 817 } else { 818 CHKERRQ(LoadSingle(tj,ts,stack,id)); 819 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 820 CHKERRQ(ElementSet(ts,stack,&e,(id-1)*tjsch->stride+1,ts->ptime,ts->vec_sol)); 821 CHKERRQ(StackPush(stack,e)); 822 CHKERRQ(TurnForward(ts)); 823 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,id*tjsch->stride)); 824 } 825 PetscFunctionReturn(0); 826 } 827 /* restore a checkpoint */ 828 CHKERRQ(StackPop(stack,&e)); 829 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 830 } 831 PetscFunctionReturn(0); 832 } 833 834 #if defined(PETSC_HAVE_REVOLVE) 835 static PetscErrorCode printwhattodo(PetscViewer viewer,PetscRevolveInt whattodo,RevolveCTX *rctx,PetscRevolveInt shift) 836 { 837 PetscFunctionBegin; 838 if (!viewer) PetscFunctionReturn(0); 839 840 switch(whattodo) { 841 case 1: 842 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Advance from %D to %D\n",rctx->oldcapo+shift,rctx->capo+shift)); 843 break; 844 case 2: 845 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Store in checkpoint number %D (located in RAM)\n",rctx->check)); 846 break; 847 case 3: 848 CHKERRQ(PetscViewerASCIIPrintf(viewer,"First turn: Initialize adjoints and reverse first step\n")); 849 break; 850 case 4: 851 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Forward and reverse one step\n")); 852 break; 853 case 5: 854 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Restore in checkpoint number %D (located in RAM)\n",rctx->check)); 855 break; 856 case 7: 857 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Store in checkpoint number %D (located on disk)\n",rctx->check)); 858 break; 859 case 8: 860 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Restore in checkpoint number %D (located on disk)\n",rctx->check)); 861 break; 862 case -1: 863 CHKERRQ(PetscViewerASCIIPrintf(viewer,"Error!")); 864 break; 865 } 866 PetscFunctionReturn(0); 867 } 868 869 static PetscErrorCode printwhattodo2(PetscViewer viewer,PetscRevolveInt whattodo,RevolveCTX *rctx,PetscRevolveInt shift) 870 { 871 PetscFunctionBegin; 872 if (!viewer) PetscFunctionReturn(0); 873 874 switch(whattodo) { 875 case 1: 876 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Advance from stride %D to stride %D\n",rctx->oldcapo+shift,rctx->capo+shift)); 877 break; 878 case 2: 879 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Store in checkpoint number %D\n",rctx->check)); 880 break; 881 case 3: 882 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] First turn: Initialize adjoints and reverse first stride\n")); 883 break; 884 case 4: 885 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Forward and reverse one stride\n")); 886 break; 887 case 5: 888 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Restore in checkpoint number %D\n",rctx->check)); 889 break; 890 case 7: 891 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Store in top-level checkpoint number %D\n",rctx->check)); 892 break; 893 case 8: 894 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Restore in top-level checkpoint number %D\n",rctx->check)); 895 break; 896 case -1: 897 CHKERRQ(PetscViewerASCIIPrintf(viewer,"[Top Level] Error!")); 898 break; 899 } 900 PetscFunctionReturn(0); 901 } 902 903 static PetscErrorCode InitRevolve(PetscInt fine,PetscInt snaps,RevolveCTX *rctx) 904 { 905 PetscRevolveInt rsnaps,rfine; 906 907 PetscFunctionBegin; 908 CHKERRQ(PetscRevolveIntCast(snaps,&rsnaps)); 909 CHKERRQ(PetscRevolveIntCast(fine,&rfine)); 910 revolve_reset(); 911 revolve_create_offline(rfine,rsnaps); 912 rctx->snaps_in = rsnaps; 913 rctx->fine = rfine; 914 rctx->check = 0; 915 rctx->capo = 0; 916 rctx->reverseonestep = PETSC_FALSE; 917 /* check stepsleft? */ 918 PetscFunctionReturn(0); 919 } 920 921 static PetscErrorCode FastForwardRevolve(RevolveCTX *rctx) 922 { 923 PetscRevolveInt whattodo; 924 925 PetscFunctionBegin; 926 whattodo = 0; 927 while (whattodo!=3) { /* we have to fast forward revolve to the beginning of the backward sweep due to unfriendly revolve interface */ 928 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 929 } 930 PetscFunctionReturn(0); 931 } 932 933 static PetscErrorCode ApplyRevolve(PetscViewer viewer,SchedulerType stype,RevolveCTX *rctx,PetscRevolveInt total_steps,PetscRevolveInt stepnum,PetscRevolveInt localstepnum,PetscBool toplevel,PetscInt *store) 934 { 935 PetscRevolveInt shift,whattodo; 936 937 PetscFunctionBegin; 938 *store = 0; 939 if (rctx->stepsleft > 0) { /* advance the solution without checkpointing anything as Revolve requires */ 940 rctx->stepsleft--; 941 PetscFunctionReturn(0); 942 } 943 /* let Revolve determine what to do next */ 944 shift = stepnum-localstepnum; 945 rctx->oldcapo = rctx->capo; 946 rctx->capo = localstepnum; 947 948 if (!toplevel) whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 949 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 950 if (stype == REVOLVE_ONLINE && whattodo == 8) whattodo = 5; 951 if (stype == REVOLVE_ONLINE && whattodo == 7) whattodo = 2; 952 if (!toplevel) CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 953 else CHKERRQ(printwhattodo2(viewer,whattodo,rctx,shift)); 954 PetscCheck(whattodo != -1,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in the Revolve library"); 955 if (whattodo == 1) { /* advance some time steps */ 956 if (stype == REVOLVE_ONLINE && rctx->capo >= total_steps-1) { 957 revolve_turn(total_steps,&rctx->capo,&rctx->fine); 958 if (!toplevel) CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 959 else CHKERRQ(printwhattodo2(viewer,whattodo,rctx,shift)); 960 } 961 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 962 } 963 if (whattodo == 3 || whattodo == 4) { /* ready for a reverse step */ 964 rctx->reverseonestep = PETSC_TRUE; 965 } 966 if (whattodo == 5) { /* restore a checkpoint and ask Revolve what to do next */ 967 rctx->oldcapo = rctx->capo; 968 if (!toplevel) whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1 or 3 or 4*/ 969 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 970 if (!toplevel) CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 971 else CHKERRQ(printwhattodo2(viewer,whattodo,rctx,shift)); 972 if (whattodo == 3 || whattodo == 4) rctx->reverseonestep = PETSC_TRUE; 973 if (whattodo == 1) rctx->stepsleft = rctx->capo-rctx->oldcapo; 974 } 975 if (whattodo == 7) { /* save the checkpoint to disk */ 976 *store = 2; 977 rctx->oldcapo = rctx->capo; 978 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1 */ 979 CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 980 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 981 } 982 if (whattodo == 2) { /* store a checkpoint to RAM and ask Revolve how many time steps to advance next */ 983 *store = 1; 984 rctx->oldcapo = rctx->capo; 985 if (!toplevel) whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1 */ 986 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 987 if (!toplevel) CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 988 else CHKERRQ(printwhattodo2(viewer,whattodo,rctx,shift)); 989 if (stype == REVOLVE_ONLINE && rctx->capo >= total_steps-1) { 990 revolve_turn(total_steps,&rctx->capo,&rctx->fine); 991 CHKERRQ(printwhattodo(viewer,whattodo,rctx,shift)); 992 } 993 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 994 } 995 PetscFunctionReturn(0); 996 } 997 998 static PetscErrorCode TSTrajectoryMemorySet_ROF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 999 { 1000 Stack *stack = &tjsch->stack; 1001 PetscInt store; 1002 StackElement e; 1003 PetscRevolveInt rtotal_steps,rstepnum; 1004 CheckpointType cptype; 1005 1006 PetscFunctionBegin; 1007 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1008 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1009 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1010 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1011 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store)); 1012 if (store == 1) { 1013 PetscCheck(stepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1014 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; 1015 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1016 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1017 CHKERRQ(StackPush(stack,e)); 1018 } 1019 PetscFunctionReturn(0); 1020 } 1021 1022 static PetscErrorCode TSTrajectoryMemoryGet_ROF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1023 { 1024 Stack *stack = &tjsch->stack; 1025 PetscInt store; 1026 PetscRevolveInt whattodo,shift,rtotal_steps,rstepnum; 1027 StackElement e; 1028 1029 PetscFunctionBegin; 1030 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1031 CHKERRQ(TurnBackward(ts)); 1032 tjsch->rctx->reverseonestep = PETSC_FALSE; 1033 PetscFunctionReturn(0); 1034 } 1035 /* restore a checkpoint */ 1036 CHKERRQ(StackTop(stack,&e)); 1037 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1038 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1039 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1040 if (stack->solution_only) { /* start with restoring a checkpoint */ 1041 tjsch->rctx->capo = rstepnum; 1042 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1043 shift = 0; 1044 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1045 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1046 } else { /* 2 revolve actions: restore a checkpoint and then advance */ 1047 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store)); 1048 if (tj->monitor) { 1049 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1050 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1)); 1051 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1052 } 1053 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1054 } 1055 if (stack->solution_only || (!stack->solution_only && e->stepnum < stepnum)) { 1056 CHKERRQ(TurnForward(ts)); 1057 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1058 } 1059 if ((stack->solution_only && e->stepnum+1 == stepnum) || (!stack->solution_only && e->stepnum == stepnum)) { 1060 CHKERRQ(StackPop(stack,&e)); 1061 } 1062 tjsch->rctx->reverseonestep = PETSC_FALSE; 1063 PetscFunctionReturn(0); 1064 } 1065 1066 static PetscErrorCode TSTrajectoryMemorySet_RON(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1067 { 1068 Stack *stack = &tjsch->stack; 1069 Vec *Y; 1070 PetscInt i,store; 1071 PetscReal timeprev; 1072 StackElement e; 1073 RevolveCTX *rctx = tjsch->rctx; 1074 PetscRevolveInt rtotal_steps,rstepnum; 1075 CheckpointType cptype; 1076 1077 PetscFunctionBegin; 1078 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1079 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1080 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1081 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1082 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store)); 1083 if (store == 1) { 1084 if (rctx->check != stack->top+1) { /* overwrite some non-top checkpoint in the stack */ 1085 CHKERRQ(StackFind(stack,&e,rctx->check)); 1086 if (HaveSolution(e->cptype)) { 1087 CHKERRQ(VecCopy(X,e->X)); 1088 } 1089 if (HaveStages(e->cptype)) { 1090 CHKERRQ(TSGetStages(ts,&stack->numY,&Y)); 1091 for (i=0;i<stack->numY;i++) { 1092 CHKERRQ(VecCopy(Y[i],e->Y[i])); 1093 } 1094 } 1095 e->stepnum = stepnum; 1096 e->time = time; 1097 CHKERRQ(TSGetPrevTime(ts,&timeprev)); 1098 e->timeprev = timeprev; 1099 } else { 1100 PetscCheck(stepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1101 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; 1102 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1103 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1104 CHKERRQ(StackPush(stack,e)); 1105 } 1106 } 1107 PetscFunctionReturn(0); 1108 } 1109 1110 static PetscErrorCode TSTrajectoryMemoryGet_RON(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1111 { 1112 Stack *stack = &tjsch->stack; 1113 PetscRevolveInt whattodo,shift,rstepnum; 1114 StackElement e; 1115 1116 PetscFunctionBegin; 1117 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1118 CHKERRQ(TurnBackward(ts)); 1119 tjsch->rctx->reverseonestep = PETSC_FALSE; 1120 PetscFunctionReturn(0); 1121 } 1122 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1123 tjsch->rctx->capo = rstepnum; 1124 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1125 shift = 0; 1126 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* whattodo=restore */ 1127 if (whattodo == 8) whattodo = 5; 1128 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1129 /* restore a checkpoint */ 1130 CHKERRQ(StackFind(stack,&e,tjsch->rctx->check)); 1131 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1132 if (!stack->solution_only) { /* whattodo must be 5 */ 1133 /* ask Revolve what to do next */ 1134 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1135 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* must return 1 or 3 or 4*/ 1136 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1137 if (whattodo == 3 || whattodo == 4) tjsch->rctx->reverseonestep = PETSC_TRUE; 1138 if (whattodo == 1) tjsch->rctx->stepsleft = tjsch->rctx->capo-tjsch->rctx->oldcapo; 1139 if (tj->monitor) { 1140 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1141 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1)); 1142 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1143 } 1144 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1145 } 1146 if (stack->solution_only || (!stack->solution_only && e->stepnum < stepnum)) { 1147 CHKERRQ(TurnForward(ts)); 1148 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1149 } 1150 tjsch->rctx->reverseonestep = PETSC_FALSE; 1151 PetscFunctionReturn(0); 1152 } 1153 1154 static PetscErrorCode TSTrajectoryMemorySet_TLR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1155 { 1156 Stack *stack = &tjsch->stack; 1157 PetscInt store,localstepnum,laststridesize; 1158 StackElement e; 1159 PetscBool done = PETSC_FALSE; 1160 PetscRevolveInt rtotal_steps,rstepnum,rlocalstepnum; 1161 CheckpointType cptype; 1162 1163 PetscFunctionBegin; 1164 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1165 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1166 1167 localstepnum = stepnum%tjsch->stride; 1168 laststridesize = tjsch->total_steps%tjsch->stride; 1169 if (!laststridesize) laststridesize = tjsch->stride; 1170 1171 if (!tjsch->recompute) { 1172 CHKERRQ(TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done)); 1173 /* revolve is needed for the last stride; different starting points for last stride between solutin_only and !solutin_only */ 1174 if (!stack->solution_only && !tjsch->save_stack && stepnum <= tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 1175 if (stack->solution_only && !tjsch->save_stack && stepnum < tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 1176 } 1177 if (tjsch->save_stack && done) { 1178 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1179 PetscFunctionReturn(0); 1180 } 1181 if (laststridesize < tjsch->stride) { 1182 if (stack->solution_only && stepnum == tjsch->total_steps-laststridesize && !tjsch->recompute) { /* step tjsch->total_steps-laststridesize-1 is skipped, but the next step is not */ 1183 CHKERRQ(InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx)); 1184 } 1185 if (!stack->solution_only && stepnum == tjsch->total_steps-laststridesize+1 && !tjsch->recompute) { /* step tjsch->total_steps-laststridesize is skipped, but the next step is not */ 1186 CHKERRQ(InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx)); 1187 } 1188 } 1189 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1190 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1191 CHKERRQ(PetscRevolveIntCast(localstepnum,&rlocalstepnum)); 1192 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store)); 1193 if (store == 1) { 1194 PetscCheck(localstepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1195 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; 1196 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1197 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1198 CHKERRQ(StackPush(stack,e)); 1199 } 1200 PetscFunctionReturn(0); 1201 } 1202 1203 static PetscErrorCode TSTrajectoryMemoryGet_TLR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1204 { 1205 Stack *stack = &tjsch->stack; 1206 PetscRevolveInt whattodo,shift,rstepnum,rlocalstepnum,rtotal_steps; 1207 PetscInt localstepnum,stridenum,laststridesize,store; 1208 StackElement e; 1209 CheckpointType cptype; 1210 1211 PetscFunctionBegin; 1212 localstepnum = stepnum%tjsch->stride; 1213 stridenum = stepnum/tjsch->stride; 1214 if (stepnum == tjsch->total_steps) { 1215 CHKERRQ(TurnBackward(ts)); 1216 tjsch->rctx->reverseonestep = PETSC_FALSE; 1217 PetscFunctionReturn(0); 1218 } 1219 laststridesize = tjsch->total_steps%tjsch->stride; 1220 if (!laststridesize) laststridesize = tjsch->stride; 1221 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1222 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1223 CHKERRQ(PetscRevolveIntCast(localstepnum,&rlocalstepnum)); 1224 if (stack->solution_only) { 1225 /* fill stack */ 1226 if (localstepnum == 0 && stepnum <= tjsch->total_steps-laststridesize) { 1227 if (tjsch->save_stack) { 1228 CHKERRQ(StackLoadAll(tj,ts,stack,stridenum)); 1229 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1230 CHKERRQ(FastForwardRevolve(tjsch->rctx)); 1231 tjsch->skip_trajectory = PETSC_TRUE; 1232 CHKERRQ(TurnForward(ts)); 1233 CHKERRQ(ReCompute(ts,tjsch,stridenum*tjsch->stride-1,stridenum*tjsch->stride)); 1234 tjsch->skip_trajectory = PETSC_FALSE; 1235 } else { 1236 CHKERRQ(LoadSingle(tj,ts,stack,stridenum)); 1237 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1238 CHKERRQ(TurnForward(ts)); 1239 CHKERRQ(ReCompute(ts,tjsch,(stridenum-1)*tjsch->stride,stridenum*tjsch->stride)); 1240 } 1241 PetscFunctionReturn(0); 1242 } 1243 /* restore a checkpoint */ 1244 CHKERRQ(StackTop(stack,&e)); 1245 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1246 /* start with restoring a checkpoint */ 1247 tjsch->rctx->capo = rstepnum; 1248 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1249 shift = rstepnum-rlocalstepnum; 1250 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1251 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1252 CHKERRQ(TurnForward(ts)); 1253 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1254 if (e->stepnum+1 == stepnum) { 1255 CHKERRQ(StackPop(stack,&e)); 1256 } 1257 } else { 1258 /* fill stack with info */ 1259 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 1260 if (tjsch->save_stack) { 1261 CHKERRQ(StackLoadAll(tj,ts,stack,stridenum)); 1262 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1263 CHKERRQ(FastForwardRevolve(tjsch->rctx)); 1264 } else { 1265 PetscRevolveInt rnum; 1266 CHKERRQ(LoadSingle(tj,ts,stack,stridenum)); 1267 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1268 CHKERRQ(PetscRevolveIntCast((stridenum-1)*tjsch->stride+1,&rnum)); 1269 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rnum,1,PETSC_FALSE,&store)); 1270 if (tj->monitor) { 1271 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1272 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",(stridenum-1)*tjsch->stride+tjsch->rctx->oldcapo,(stridenum-1)*tjsch->stride+tjsch->rctx->oldcapo+1)); 1273 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1274 } 1275 cptype = SOLUTION_STAGES; 1276 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1277 CHKERRQ(ElementSet(ts,stack,&e,(stridenum-1)*tjsch->stride+1,ts->ptime,ts->vec_sol)); 1278 CHKERRQ(StackPush(stack,e)); 1279 CHKERRQ(TurnForward(ts)); 1280 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stridenum*tjsch->stride)); 1281 } 1282 PetscFunctionReturn(0); 1283 } 1284 /* restore a checkpoint */ 1285 CHKERRQ(StackTop(stack,&e)); 1286 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1287 /* 2 revolve actions: restore a checkpoint and then advance */ 1288 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store)); 1289 if (tj->monitor) { 1290 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1291 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",stepnum-localstepnum+tjsch->rctx->oldcapo,stepnum-localstepnum+tjsch->rctx->oldcapo+1)); 1292 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1293 } 1294 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1295 if (e->stepnum < stepnum) { 1296 CHKERRQ(TurnForward(ts)); 1297 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1298 } 1299 if (e->stepnum == stepnum) { 1300 CHKERRQ(StackPop(stack,&e)); 1301 } 1302 } 1303 tjsch->rctx->reverseonestep = PETSC_FALSE; 1304 PetscFunctionReturn(0); 1305 } 1306 1307 static PetscErrorCode TSTrajectoryMemorySet_TLTR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1308 { 1309 Stack *stack = &tjsch->stack; 1310 PetscInt store,localstepnum,stridenum,laststridesize; 1311 StackElement e; 1312 PetscBool done = PETSC_FALSE; 1313 PetscRevolveInt rlocalstepnum,rstepnum,rtotal_steps; 1314 1315 PetscFunctionBegin; 1316 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1317 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1318 1319 localstepnum = stepnum%tjsch->stride; /* index at the bottom level (inside a stride) */ 1320 stridenum = stepnum/tjsch->stride; /* index at the top level */ 1321 laststridesize = tjsch->total_steps%tjsch->stride; 1322 if (!laststridesize) laststridesize = tjsch->stride; 1323 if (stack->solution_only && localstepnum == 0 && !tjsch->rctx2->reverseonestep) { 1324 CHKERRQ(PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps)); 1325 CHKERRQ(PetscRevolveIntCast(stridenum,&rstepnum)); 1326 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride)); 1327 if (laststridesize < tjsch->stride && stepnum == tjsch->total_steps-laststridesize) { 1328 CHKERRQ(InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx)); 1329 } 1330 } 1331 if (!stack->solution_only && localstepnum == 1 && !tjsch->rctx2->reverseonestep) { 1332 CHKERRQ(PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps)); 1333 CHKERRQ(PetscRevolveIntCast(stridenum,&rstepnum)); 1334 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride)); 1335 if (laststridesize < tjsch->stride && stepnum == tjsch->total_steps-laststridesize+1) { 1336 CHKERRQ(InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx)); 1337 } 1338 } 1339 if (tjsch->store_stride) { 1340 CHKERRQ(TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done)); 1341 if (done) { 1342 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1343 PetscFunctionReturn(0); 1344 } 1345 } 1346 if (stepnum < tjsch->total_steps-laststridesize) { 1347 if (tjsch->save_stack && !tjsch->store_stride && !tjsch->rctx2->reverseonestep) PetscFunctionReturn(0); /* store or forward-and-reverse at top level trigger revolve at bottom level */ 1348 if (!tjsch->save_stack && !tjsch->rctx2->reverseonestep) PetscFunctionReturn(0); /* store operation does not require revolve be called at bottom level */ 1349 } 1350 /* Skipping stepnum=0 for !stack->only is enough for TLR, but not for TLTR. Here we skip the first step for each stride so that the top-level revolve is applied (always at localstepnum=1) ahead of the bottom-level revolve */ 1351 if (!stack->solution_only && localstepnum == 0 && stepnum != tjsch->total_steps && !tjsch->recompute) PetscFunctionReturn(0); 1352 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1353 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1354 CHKERRQ(PetscRevolveIntCast(localstepnum,&rlocalstepnum)); 1355 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store)); 1356 if (store == 1) { 1357 CheckpointType cptype; 1358 PetscCheck(localstepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1359 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; 1360 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1361 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1362 CHKERRQ(StackPush(stack,e)); 1363 } 1364 PetscFunctionReturn(0); 1365 } 1366 1367 static PetscErrorCode TSTrajectoryMemoryGet_TLTR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1368 { 1369 Stack *stack = &tjsch->stack; 1370 DiskStack *diskstack = &tjsch->diskstack; 1371 PetscInt localstepnum,stridenum,restoredstridenum,laststridesize,store; 1372 StackElement e; 1373 PetscRevolveInt whattodo,shift; 1374 PetscRevolveInt rtotal_steps,rstepnum,rlocalstepnum; 1375 1376 PetscFunctionBegin; 1377 localstepnum = stepnum%tjsch->stride; 1378 stridenum = stepnum/tjsch->stride; 1379 if (stepnum == tjsch->total_steps) { 1380 CHKERRQ(TurnBackward(ts)); 1381 tjsch->rctx->reverseonestep = PETSC_FALSE; 1382 PetscFunctionReturn(0); 1383 } 1384 laststridesize = tjsch->total_steps%tjsch->stride; 1385 if (!laststridesize) laststridesize = tjsch->stride; 1386 /* 1387 Last stride can be adjoined directly. All the other strides require that the stack in memory be ready before an adjoint step is taken (at the end of each stride). The following two cases need to be addressed differently: 1388 Case 1 (save_stack) 1389 Restore a disk checkpoint; update TS with the last element in the restored data; recompute to the current point. 1390 Case 2 (!save_stack) 1391 Restore a disk checkpoint; update TS with the restored point; recompute to the current point. 1392 */ 1393 if (localstepnum == 0 && stepnum <= tjsch->total_steps-laststridesize) { 1394 /* restore the top element in the stack for disk checkpoints */ 1395 restoredstridenum = diskstack->container[diskstack->top]; 1396 tjsch->rctx2->reverseonestep = PETSC_FALSE; 1397 /* top-level revolve must be applied before current step, just like the solution_only mode for single-level revolve */ 1398 if (!tjsch->save_stack && stack->solution_only) { /* start with restoring a checkpoint */ 1399 CHKERRQ(PetscRevolveIntCast(stridenum,&rstepnum)); 1400 tjsch->rctx2->capo = rstepnum; 1401 tjsch->rctx2->oldcapo = tjsch->rctx2->capo; 1402 shift = 0; 1403 whattodo = revolve2_action(&tjsch->rctx2->check,&tjsch->rctx2->capo,&tjsch->rctx2->fine,tjsch->rctx2->snaps_in,&tjsch->rctx2->info,&tjsch->rctx2->where); 1404 CHKERRQ(printwhattodo2(tj->monitor,whattodo,tjsch->rctx2,shift)); 1405 } else { /* 2 revolve actions: restore a checkpoint and then advance */ 1406 CHKERRQ(PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps)); 1407 CHKERRQ(PetscRevolveIntCast(stridenum,&rstepnum)); 1408 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride)); 1409 if (tj->monitor) { 1410 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1411 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"[Top Level] Skip the stride from %D to %D (stage values already checkpointed)\n",tjsch->rctx2->oldcapo,tjsch->rctx2->oldcapo+1)); 1412 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1413 } 1414 if (!tjsch->rctx2->reverseonestep && tjsch->rctx2->stepsleft > 0) tjsch->rctx2->stepsleft--; 1415 } 1416 /* fill stack */ 1417 if (stack->solution_only) { 1418 if (tjsch->save_stack) { 1419 if (restoredstridenum < stridenum) { 1420 CHKERRQ(StackLoadLast(tj,ts,stack,restoredstridenum)); 1421 } else { 1422 CHKERRQ(StackLoadAll(tj,ts,stack,restoredstridenum)); 1423 } 1424 /* recompute one step ahead */ 1425 tjsch->skip_trajectory = PETSC_TRUE; 1426 CHKERRQ(TurnForward(ts)); 1427 CHKERRQ(ReCompute(ts,tjsch,stridenum*tjsch->stride-1,stridenum*tjsch->stride)); 1428 tjsch->skip_trajectory = PETSC_FALSE; 1429 if (restoredstridenum < stridenum) { 1430 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1431 CHKERRQ(TurnForward(ts)); 1432 CHKERRQ(ReCompute(ts,tjsch,restoredstridenum*tjsch->stride,stepnum)); 1433 } else { /* stack ready, fast forward revolve status */ 1434 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1435 CHKERRQ(FastForwardRevolve(tjsch->rctx)); 1436 } 1437 } else { 1438 CHKERRQ(LoadSingle(tj,ts,stack,restoredstridenum)); 1439 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1440 CHKERRQ(TurnForward(ts)); 1441 CHKERRQ(ReCompute(ts,tjsch,(restoredstridenum-1)*tjsch->stride,stepnum)); 1442 } 1443 } else { 1444 if (tjsch->save_stack) { 1445 if (restoredstridenum < stridenum) { 1446 CHKERRQ(StackLoadLast(tj,ts,stack,restoredstridenum)); 1447 /* reset revolve */ 1448 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1449 CHKERRQ(TurnForward(ts)); 1450 CHKERRQ(ReCompute(ts,tjsch,restoredstridenum*tjsch->stride,stepnum)); 1451 } else { /* stack ready, fast forward revolve status */ 1452 CHKERRQ(StackLoadAll(tj,ts,stack,restoredstridenum)); 1453 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1454 CHKERRQ(FastForwardRevolve(tjsch->rctx)); 1455 } 1456 } else { 1457 CHKERRQ(LoadSingle(tj,ts,stack,restoredstridenum)); 1458 CHKERRQ(InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx)); 1459 /* push first element to stack */ 1460 if (tjsch->store_stride || tjsch->rctx2->reverseonestep) { 1461 CheckpointType cptype = SOLUTION_STAGES; 1462 shift = (restoredstridenum-1)*tjsch->stride-localstepnum; 1463 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1464 CHKERRQ(PetscRevolveIntCast((restoredstridenum-1)*tjsch->stride+1,&rstepnum)); 1465 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,1,PETSC_FALSE,&store)); 1466 if (tj->monitor) { 1467 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1468 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",(restoredstridenum-1)*tjsch->stride,(restoredstridenum-1)*tjsch->stride+1)); 1469 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1470 } 1471 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1472 CHKERRQ(ElementSet(ts,stack,&e,(restoredstridenum-1)*tjsch->stride+1,ts->ptime,ts->vec_sol)); 1473 CHKERRQ(StackPush(stack,e)); 1474 } 1475 CHKERRQ(TurnForward(ts)); 1476 CHKERRQ(ReCompute(ts,tjsch,(restoredstridenum-1)*tjsch->stride+1,stepnum)); 1477 } 1478 } 1479 if (restoredstridenum == stridenum) diskstack->top--; 1480 tjsch->rctx->reverseonestep = PETSC_FALSE; 1481 PetscFunctionReturn(0); 1482 } 1483 1484 if (stack->solution_only) { 1485 /* restore a checkpoint */ 1486 CHKERRQ(StackTop(stack,&e)); 1487 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1488 /* start with restoring a checkpoint */ 1489 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1490 CHKERRQ(PetscRevolveIntCast(localstepnum,&rlocalstepnum)); 1491 tjsch->rctx->capo = rstepnum; 1492 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1493 shift = rstepnum-rlocalstepnum; 1494 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1495 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1496 CHKERRQ(TurnForward(ts)); 1497 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1498 if (e->stepnum+1 == stepnum) { 1499 CHKERRQ(StackPop(stack,&e)); 1500 } 1501 } else { 1502 PetscRevolveInt rlocalstepnum; 1503 /* restore a checkpoint */ 1504 CHKERRQ(StackTop(stack,&e)); 1505 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1506 /* 2 revolve actions: restore a checkpoint and then advance */ 1507 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1508 CHKERRQ(PetscRevolveIntCast(stridenum,&rstepnum)); 1509 CHKERRQ(PetscRevolveIntCast(localstepnum,&rlocalstepnum)); 1510 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store)); 1511 if (tj->monitor) { 1512 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1513 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",stepnum-localstepnum+tjsch->rctx->oldcapo,stepnum-localstepnum+tjsch->rctx->oldcapo+1)); 1514 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1515 } 1516 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1517 if (e->stepnum < stepnum) { 1518 CHKERRQ(TurnForward(ts)); 1519 CHKERRQ(ReCompute(ts,tjsch,e->stepnum,stepnum)); 1520 } 1521 if (e->stepnum == stepnum) { 1522 CHKERRQ(StackPop(stack,&e)); 1523 } 1524 } 1525 tjsch->rctx->reverseonestep = PETSC_FALSE; 1526 PetscFunctionReturn(0); 1527 } 1528 1529 static PetscErrorCode TSTrajectoryMemorySet_RMS(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1530 { 1531 Stack *stack = &tjsch->stack; 1532 PetscInt store; 1533 StackElement e; 1534 PetscRevolveInt rtotal_steps,rstepnum; 1535 1536 PetscFunctionBegin; 1537 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1538 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1539 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps)); 1540 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1541 CHKERRQ(ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store)); 1542 if (store == 1) { 1543 CheckpointType cptype; 1544 PetscCheck(stepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1545 cptype = stack->solution_only ? SOLUTIONONLY : SOLUTION_STAGES; 1546 CHKERRQ(ElementCreate(ts,cptype,stack,&e)); 1547 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1548 CHKERRQ(StackPush(stack,e)); 1549 } else if (store == 2) { 1550 CHKERRQ(DumpSingle(tj,ts,stack,tjsch->rctx->check+1)); 1551 } 1552 PetscFunctionReturn(0); 1553 } 1554 1555 static PetscErrorCode TSTrajectoryMemoryGet_RMS(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1556 { 1557 Stack *stack = &tjsch->stack; 1558 PetscRevolveInt whattodo,shift,rstepnum; 1559 PetscInt restart; 1560 PetscBool ondisk; 1561 StackElement e; 1562 1563 PetscFunctionBegin; 1564 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1565 CHKERRQ(TurnBackward(ts)); 1566 tjsch->rctx->reverseonestep = PETSC_FALSE; 1567 PetscFunctionReturn(0); 1568 } 1569 CHKERRQ(PetscRevolveIntCast(stepnum,&rstepnum)); 1570 tjsch->rctx->capo = rstepnum; 1571 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1572 shift = 0; 1573 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* whattodo=restore */ 1574 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1575 /* restore a checkpoint */ 1576 restart = tjsch->rctx->capo; 1577 if (!tjsch->rctx->where) { 1578 ondisk = PETSC_TRUE; 1579 CHKERRQ(LoadSingle(tj,ts,stack,tjsch->rctx->check+1)); 1580 CHKERRQ(TurnBackward(ts)); 1581 } else { 1582 ondisk = PETSC_FALSE; 1583 CHKERRQ(StackTop(stack,&e)); 1584 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1585 } 1586 if (!stack->solution_only) { /* whattodo must be 5 or 8 */ 1587 /* ask Revolve what to do next */ 1588 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1589 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* must return 1 or 3 or 4*/ 1590 CHKERRQ(printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift)); 1591 if (whattodo == 3 || whattodo == 4) tjsch->rctx->reverseonestep = PETSC_TRUE; 1592 if (whattodo == 1) tjsch->rctx->stepsleft = tjsch->rctx->capo-tjsch->rctx->oldcapo; 1593 if (tj->monitor) { 1594 CHKERRQ(PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel)); 1595 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1)); 1596 CHKERRQ(PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel)); 1597 } 1598 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1599 restart++; /* skip one step */ 1600 } 1601 if (stack->solution_only || (!stack->solution_only && restart < stepnum)) { 1602 CHKERRQ(TurnForward(ts)); 1603 CHKERRQ(ReCompute(ts,tjsch,restart,stepnum)); 1604 } 1605 if (!ondisk && ( (stack->solution_only && e->stepnum+1 == stepnum) || (!stack->solution_only && e->stepnum == stepnum))) { 1606 CHKERRQ(StackPop(stack,&e)); 1607 } 1608 tjsch->rctx->reverseonestep = PETSC_FALSE; 1609 PetscFunctionReturn(0); 1610 } 1611 #endif 1612 1613 #if defined(PETSC_HAVE_CAMS) 1614 /* Optimal offline adjoint checkpointing for multistage time integration methods */ 1615 static PetscErrorCode TSTrajectoryMemorySet_AOF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1616 { 1617 Stack *stack = &tjsch->stack; 1618 StackElement e; 1619 1620 PetscFunctionBegin; 1621 /* skip if no checkpoint to use. This also avoids an error when num_units_avail=0 */ 1622 if (tjsch->actx->nextcheckpointstep == -1) PetscFunctionReturn(0); 1623 if (stepnum == 0) { /* When placing the first checkpoint, no need to change the units available */ 1624 if (stack->solution_only) { 1625 CHKERRQ(offline_ca(tjsch->actx->lastcheckpointstep,tjsch->actx->num_units_avail,tjsch->actx->endstep,&tjsch->actx->nextcheckpointstep)); 1626 } else { 1627 /* First two arguments must be -1 when first time calling cams */ 1628 CHKERRQ(offline_cams(tjsch->actx->lastcheckpointstep,tjsch->actx->lastcheckpointtype,tjsch->actx->num_units_avail,tjsch->actx->endstep,tjsch->actx->num_stages,&tjsch->actx->nextcheckpointstep,&tjsch->actx->nextcheckpointtype)); 1629 } 1630 } 1631 1632 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1633 1634 if (tjsch->actx->nextcheckpointstep == stepnum) { 1635 PetscCheck(stepnum >= stack->top,PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1636 1637 if (tjsch->actx->nextcheckpointtype == 2) { /* solution + stage values */ 1638 if (tj->monitor) { 1639 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Store in checkpoint number %D with stage values and solution (located in RAM)\n",stepnum)); 1640 } 1641 CHKERRQ(ElementCreate(ts,SOLUTION_STAGES,stack,&e)); 1642 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1643 } 1644 if (tjsch->actx->nextcheckpointtype == 1) { 1645 if (tj->monitor) { 1646 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Store in checkpoint number %D with stage values (located in RAM)\n",stepnum)); 1647 } 1648 CHKERRQ(ElementCreate(ts,STAGESONLY,stack,&e)); 1649 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1650 } 1651 if (tjsch->actx->nextcheckpointtype == 0) { /* solution only */ 1652 if (tj->monitor) { 1653 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Store in checkpoint number %D (located in RAM)\n",stepnum)); 1654 } 1655 CHKERRQ(ElementCreate(ts,SOLUTIONONLY,stack,&e)); 1656 CHKERRQ(ElementSet(ts,stack,&e,stepnum,time,X)); 1657 } 1658 CHKERRQ(StackPush(stack,e)); 1659 1660 tjsch->actx->lastcheckpointstep = stepnum; 1661 if (stack->solution_only) { 1662 CHKERRQ(offline_ca(tjsch->actx->lastcheckpointstep,tjsch->actx->num_units_avail,tjsch->actx->endstep,&tjsch->actx->nextcheckpointstep)); 1663 tjsch->actx->num_units_avail--; 1664 } else { 1665 tjsch->actx->lastcheckpointtype = tjsch->actx->nextcheckpointtype; 1666 CHKERRQ(offline_cams(tjsch->actx->lastcheckpointstep,tjsch->actx->lastcheckpointtype,tjsch->actx->num_units_avail,tjsch->actx->endstep,tjsch->actx->num_stages,&tjsch->actx->nextcheckpointstep,&tjsch->actx->nextcheckpointtype)); 1667 if (tjsch->actx->lastcheckpointtype == 2) tjsch->actx->num_units_avail -= tjsch->actx->num_stages+1; 1668 if (tjsch->actx->lastcheckpointtype == 1) tjsch->actx->num_units_avail -= tjsch->actx->num_stages; 1669 if (tjsch->actx->lastcheckpointtype == 0) tjsch->actx->num_units_avail--; 1670 } 1671 } 1672 PetscFunctionReturn(0); 1673 } 1674 1675 static PetscErrorCode TSTrajectoryMemoryGet_AOF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1676 { 1677 Stack *stack = &tjsch->stack; 1678 StackElement e; 1679 PetscInt estepnum; 1680 1681 PetscFunctionBegin; 1682 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1683 CHKERRQ(TurnBackward(ts)); 1684 PetscFunctionReturn(0); 1685 } 1686 /* Restore a checkpoint */ 1687 CHKERRQ(StackTop(stack,&e)); 1688 estepnum = e->stepnum; 1689 if (estepnum == stepnum && e->cptype == SOLUTIONONLY) { /* discard the checkpoint if not useful (corner case) */ 1690 CHKERRQ(StackPop(stack,&e)); 1691 tjsch->actx->num_units_avail++; 1692 CHKERRQ(StackTop(stack,&e)); 1693 estepnum = e->stepnum; 1694 } 1695 /* Update TS with stage values if an adjoint step can be taken immediately */ 1696 if (HaveStages(e->cptype)) { 1697 if (tj->monitor) { 1698 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Restore in checkpoint number %D with stage values (located in RAM)\n",e->stepnum)); 1699 } 1700 if (e->cptype == STAGESONLY) tjsch->actx->num_units_avail += tjsch->actx->num_stages; 1701 if (e->cptype == SOLUTION_STAGES) tjsch->actx->num_units_avail += tjsch->actx->num_stages+1; 1702 } else { 1703 if (tj->monitor) { 1704 CHKERRQ(PetscViewerASCIIPrintf(tj->monitor,"Restore in checkpoint number %D (located in RAM)\n",e->stepnum)); 1705 } 1706 tjsch->actx->num_units_avail++; 1707 } 1708 CHKERRQ(UpdateTS(ts,stack,e,stepnum,PETSC_TRUE)); 1709 /* Query the scheduler */ 1710 tjsch->actx->lastcheckpointstep = estepnum; 1711 tjsch->actx->endstep = stepnum; 1712 if (stack->solution_only) { /* start with restoring a checkpoint */ 1713 CHKERRQ(offline_ca(tjsch->actx->lastcheckpointstep,tjsch->actx->num_units_avail,tjsch->actx->endstep,&tjsch->actx->nextcheckpointstep)); 1714 } else { /* 2 revolve actions: restore a checkpoint and then advance */ 1715 tjsch->actx->lastcheckpointtype = e->cptype; 1716 CHKERRQ(offline_cams(tjsch->actx->lastcheckpointstep,tjsch->actx->lastcheckpointtype,tjsch->actx->num_units_avail,tjsch->actx->endstep,tjsch->actx->num_stages,&tjsch->actx->nextcheckpointstep, &tjsch->actx->nextcheckpointtype)); 1717 } 1718 /* Discard the checkpoint if not needed, decrease the number of available checkpoints if it still stays in stack */ 1719 if (HaveStages(e->cptype)) { 1720 if (estepnum == stepnum) { 1721 CHKERRQ(StackPop(stack,&e)); 1722 } else { 1723 if (e->cptype == STAGESONLY) tjsch->actx->num_units_avail -= tjsch->actx->num_stages; 1724 if (e->cptype == SOLUTION_STAGES) tjsch->actx->num_units_avail -= tjsch->actx->num_stages+1; 1725 } 1726 } else { 1727 if (estepnum+1 == stepnum) { 1728 CHKERRQ(StackPop(stack,&e)); 1729 } else { 1730 tjsch->actx->num_units_avail--; 1731 } 1732 } 1733 /* Recompute from the restored checkpoint */ 1734 if (stack->solution_only || (!stack->solution_only && estepnum < stepnum)) { 1735 CHKERRQ(TurnForward(ts)); 1736 CHKERRQ(ReCompute(ts,tjsch,estepnum,stepnum)); 1737 } 1738 PetscFunctionReturn(0); 1739 } 1740 #endif 1741 1742 static PetscErrorCode TSTrajectorySet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal time,Vec X) 1743 { 1744 TJScheduler *tjsch = (TJScheduler*)tj->data; 1745 1746 PetscFunctionBegin; 1747 if (!tjsch->recompute) { /* use global stepnum in the forward sweep */ 1748 CHKERRQ(TSGetStepNumber(ts,&stepnum)); 1749 } 1750 /* for consistency */ 1751 if (!tjsch->recompute && stepnum == 0) ts->ptime_prev = ts->ptime-ts->time_step; 1752 switch (tjsch->stype) { 1753 case NONE: 1754 if (tj->adjoint_solve_mode) { 1755 CHKERRQ(TSTrajectoryMemorySet_N(ts,tjsch,stepnum,time,X)); 1756 } else { 1757 CHKERRQ(TSTrajectoryMemorySet_N_2(ts,tjsch,stepnum,time,X)); 1758 } 1759 break; 1760 case TWO_LEVEL_NOREVOLVE: 1761 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1762 CHKERRQ(TSTrajectoryMemorySet_TLNR(tj,ts,tjsch,stepnum,time,X)); 1763 break; 1764 #if defined(PETSC_HAVE_REVOLVE) 1765 case TWO_LEVEL_REVOLVE: 1766 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1767 CHKERRQ(TSTrajectoryMemorySet_TLR(tj,ts,tjsch,stepnum,time,X)); 1768 break; 1769 case TWO_LEVEL_TWO_REVOLVE: 1770 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1771 CHKERRQ(TSTrajectoryMemorySet_TLTR(tj,ts,tjsch,stepnum,time,X)); 1772 break; 1773 case REVOLVE_OFFLINE: 1774 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1775 CHKERRQ(TSTrajectoryMemorySet_ROF(tj,ts,tjsch,stepnum,time,X)); 1776 break; 1777 case REVOLVE_ONLINE: 1778 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1779 CHKERRQ(TSTrajectoryMemorySet_RON(tj,ts,tjsch,stepnum,time,X)); 1780 break; 1781 case REVOLVE_MULTISTAGE: 1782 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1783 CHKERRQ(TSTrajectoryMemorySet_RMS(tj,ts,tjsch,stepnum,time,X)); 1784 break; 1785 #endif 1786 #if defined(PETSC_HAVE_CAMS) 1787 case CAMS_OFFLINE: 1788 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1789 CHKERRQ(TSTrajectoryMemorySet_AOF(tj,ts,tjsch,stepnum,time,X)); 1790 break; 1791 #endif 1792 default: 1793 break; 1794 } 1795 PetscFunctionReturn(0); 1796 } 1797 1798 static PetscErrorCode TSTrajectoryGet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal *t) 1799 { 1800 TJScheduler *tjsch = (TJScheduler*)tj->data; 1801 1802 PetscFunctionBegin; 1803 if (tj->adjoint_solve_mode && stepnum == 0) { 1804 CHKERRQ(TSTrajectoryReset(tj)); /* reset TSTrajectory so users do not need to reset TSTrajectory */ 1805 PetscFunctionReturn(0); 1806 } 1807 switch (tjsch->stype) { 1808 case NONE: 1809 if (tj->adjoint_solve_mode) { 1810 CHKERRQ(TSTrajectoryMemoryGet_N(ts,tjsch,stepnum)); 1811 } else { 1812 CHKERRQ(TSTrajectoryMemoryGet_N_2(ts,tjsch,stepnum)); 1813 } 1814 break; 1815 case TWO_LEVEL_NOREVOLVE: 1816 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1817 CHKERRQ(TSTrajectoryMemoryGet_TLNR(tj,ts,tjsch,stepnum)); 1818 break; 1819 #if defined(PETSC_HAVE_REVOLVE) 1820 case TWO_LEVEL_REVOLVE: 1821 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1822 CHKERRQ(TSTrajectoryMemoryGet_TLR(tj,ts,tjsch,stepnum)); 1823 break; 1824 case TWO_LEVEL_TWO_REVOLVE: 1825 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1826 CHKERRQ(TSTrajectoryMemoryGet_TLTR(tj,ts,tjsch,stepnum)); 1827 break; 1828 case REVOLVE_OFFLINE: 1829 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1830 CHKERRQ(TSTrajectoryMemoryGet_ROF(tj,ts,tjsch,stepnum)); 1831 break; 1832 case REVOLVE_ONLINE: 1833 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1834 CHKERRQ(TSTrajectoryMemoryGet_RON(tj,ts,tjsch,stepnum)); 1835 break; 1836 case REVOLVE_MULTISTAGE: 1837 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1838 CHKERRQ(TSTrajectoryMemoryGet_RMS(tj,ts,tjsch,stepnum)); 1839 break; 1840 #endif 1841 #if defined(PETSC_HAVE_CAMS) 1842 case CAMS_OFFLINE: 1843 PetscCheck(tj->adjoint_solve_mode,PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1844 CHKERRQ(TSTrajectoryMemoryGet_AOF(tj,ts,tjsch,stepnum)); 1845 break; 1846 #endif 1847 default: 1848 break; 1849 } 1850 PetscFunctionReturn(0); 1851 } 1852 1853 PETSC_UNUSED static PetscErrorCode TSTrajectorySetStride_Memory(TSTrajectory tj,PetscInt stride) 1854 { 1855 TJScheduler *tjsch = (TJScheduler*)tj->data; 1856 1857 PetscFunctionBegin; 1858 tjsch->stride = stride; 1859 PetscFunctionReturn(0); 1860 } 1861 1862 static PetscErrorCode TSTrajectorySetMaxCpsRAM_Memory(TSTrajectory tj,PetscInt max_cps_ram) 1863 { 1864 TJScheduler *tjsch = (TJScheduler*)tj->data; 1865 1866 PetscFunctionBegin; 1867 tjsch->max_cps_ram = max_cps_ram; 1868 PetscFunctionReturn(0); 1869 } 1870 1871 static PetscErrorCode TSTrajectorySetMaxCpsDisk_Memory(TSTrajectory tj,PetscInt max_cps_disk) 1872 { 1873 TJScheduler *tjsch = (TJScheduler*)tj->data; 1874 1875 PetscFunctionBegin; 1876 tjsch->max_cps_disk = max_cps_disk; 1877 PetscFunctionReturn(0); 1878 } 1879 1880 static PetscErrorCode TSTrajectorySetMaxUnitsRAM_Memory(TSTrajectory tj,PetscInt max_units_ram) 1881 { 1882 TJScheduler *tjsch = (TJScheduler*)tj->data; 1883 1884 PetscFunctionBegin; 1885 PetscCheck(tjsch->max_cps_ram,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_INCOMP,"Conflict with -ts_trjaectory_max_cps_ram or TSTrajectorySetMaxCpsRAM. You can set max_cps_ram or max_units_ram, but not both at the same time."); 1886 tjsch->max_units_ram = max_units_ram; 1887 PetscFunctionReturn(0); 1888 } 1889 1890 static PetscErrorCode TSTrajectorySetMaxUnitsDisk_Memory(TSTrajectory tj,PetscInt max_units_disk) 1891 { 1892 TJScheduler *tjsch = (TJScheduler*)tj->data; 1893 1894 PetscFunctionBegin; 1895 PetscCheck(tjsch->max_cps_disk,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_INCOMP,"Conflict with -ts_trjaectory_max_cps_disk or TSTrajectorySetMaxCpsDisk. You can set max_cps_disk or max_units_disk, but not both at the same time."); 1896 tjsch->max_units_ram = max_units_disk; 1897 PetscFunctionReturn(0); 1898 } 1899 1900 static PetscErrorCode TSTrajectoryMemorySetType_Memory(TSTrajectory tj,TSTrajectoryMemoryType tj_memory_type) 1901 { 1902 TJScheduler *tjsch = (TJScheduler*)tj->data; 1903 1904 PetscFunctionBegin; 1905 PetscCheck(!tj->setupcalled,PetscObjectComm((PetscObject)tj),PETSC_ERR_ARG_WRONGSTATE,"Cannot change schedule software after TSTrajectory has been setup or used"); 1906 tjsch->tj_memory_type = tj_memory_type; 1907 PetscFunctionReturn(0); 1908 } 1909 1910 #if defined(PETSC_HAVE_REVOLVE) 1911 PETSC_UNUSED static PetscErrorCode TSTrajectorySetRevolveOnline(TSTrajectory tj,PetscBool use_online) 1912 { 1913 TJScheduler *tjsch = (TJScheduler*)tj->data; 1914 1915 PetscFunctionBegin; 1916 tjsch->use_online = use_online; 1917 PetscFunctionReturn(0); 1918 } 1919 #endif 1920 1921 PETSC_UNUSED static PetscErrorCode TSTrajectorySetSaveStack(TSTrajectory tj,PetscBool save_stack) 1922 { 1923 TJScheduler *tjsch = (TJScheduler*)tj->data; 1924 1925 PetscFunctionBegin; 1926 tjsch->save_stack = save_stack; 1927 PetscFunctionReturn(0); 1928 } 1929 1930 PETSC_UNUSED static PetscErrorCode TSTrajectorySetUseDRAM(TSTrajectory tj,PetscBool use_dram) 1931 { 1932 TJScheduler *tjsch = (TJScheduler*)tj->data; 1933 1934 PetscFunctionBegin; 1935 tjsch->stack.use_dram = use_dram; 1936 PetscFunctionReturn(0); 1937 } 1938 1939 /*@C 1940 TSTrajectoryMemorySetType - sets the software that is used to generate the checkpointing schedule. 1941 1942 Logically Collective on TSTrajectory 1943 1944 Input Parameters: 1945 + tj - the TSTrajectory context 1946 - tj_memory_type - Revolve or CAMS 1947 1948 Options Database Key: 1949 . -ts_trajectory_memory_type <tj_memory_type> - petsc, revolve, cams 1950 1951 Level: intermediate 1952 1953 Note: 1954 By default this will use Revolve if it exists 1955 @*/ 1956 PetscErrorCode TSTrajectoryMemorySetType(TSTrajectory tj,TSTrajectoryMemoryType tj_memory_type) 1957 { 1958 PetscFunctionBegin; 1959 CHKERRQ(PetscTryMethod(tj,"TSTrajectoryMemorySetType_C",(TSTrajectory,TSTrajectoryMemoryType),(tj,tj_memory_type))); 1960 PetscFunctionReturn(0); 1961 } 1962 1963 /*@C 1964 TSTrajectorySetMaxCpsRAM - Set maximum number of checkpoints in RAM 1965 1966 Logically collective 1967 1968 Input Parameter: 1969 . tj - tstrajectory context 1970 1971 Output Parameter: 1972 . max_cps_ram - maximum number of checkpoints in RAM 1973 1974 Level: intermediate 1975 1976 .seealso: TSTrajectorySetMaxUnitsRAM() 1977 @*/ 1978 PetscErrorCode TSTrajectorySetMaxCpsRAM(TSTrajectory tj,PetscInt max_cps_ram) 1979 { 1980 PetscFunctionBegin; 1981 CHKERRQ(PetscUseMethod(tj,"TSTrajectorySetMaxCpsRAM_C",(TSTrajectory,PetscInt),(tj,max_cps_ram))); 1982 PetscFunctionReturn(0); 1983 } 1984 1985 /*@C 1986 TSTrajectorySetMaxCpsDisk - Set maximum number of checkpoints on disk 1987 1988 Logically collective 1989 1990 Input Parameter: 1991 . tj - tstrajectory context 1992 1993 Output Parameter: 1994 . max_cps_disk - maximum number of checkpoints on disk 1995 1996 Level: intermediate 1997 1998 .seealso: TSTrajectorySetMaxUnitsDisk(), TSTrajectorySetMaxUnitsRAM() 1999 @*/ 2000 PetscErrorCode TSTrajectorySetMaxCpsDisk(TSTrajectory tj,PetscInt max_cps_disk) 2001 { 2002 PetscFunctionBegin; 2003 CHKERRQ(PetscUseMethod(tj,"TSTrajectorySetMaxCpsDisk_C",(TSTrajectory,PetscInt),(tj,max_cps_disk))); 2004 PetscFunctionReturn(0); 2005 } 2006 2007 /*@C 2008 TSTrajectorySetMaxUnitsRAM - Set maximum number of checkpointing units in RAM 2009 2010 Logically collective 2011 2012 Input Parameter: 2013 . tj - tstrajectory context 2014 2015 Output Parameter: 2016 . max_units_ram - maximum number of checkpointing units in RAM 2017 2018 Level: intermediate 2019 2020 .seealso: TSTrajectorySetMaxCpsRAM() 2021 @*/ 2022 PetscErrorCode TSTrajectorySetMaxUnitsRAM(TSTrajectory tj,PetscInt max_units_ram) 2023 { 2024 PetscFunctionBegin; 2025 CHKERRQ(PetscUseMethod(tj,"TSTrajectorySetMaxUnitsRAM_C",(TSTrajectory,PetscInt),(tj,max_units_ram))); 2026 PetscFunctionReturn(0); 2027 } 2028 2029 /*@C 2030 TSTrajectorySetMaxUnitsDisk - Set maximum number of checkpointing units on disk 2031 2032 Logically collective 2033 2034 Input Parameter: 2035 . tj - tstrajectory context 2036 2037 Output Parameter: 2038 . max_units_disk - maximum number of checkpointing units on disk 2039 2040 Level: intermediate 2041 2042 .seealso: TSTrajectorySetMaxCpsDisk() 2043 @*/ 2044 PetscErrorCode TSTrajectorySetMaxUnitsDisk(TSTrajectory tj,PetscInt max_units_disk) 2045 { 2046 PetscFunctionBegin; 2047 CHKERRQ(PetscUseMethod(tj,"TSTrajectorySetMaxUnitsDisk_C",(TSTrajectory,PetscInt),(tj,max_units_disk))); 2048 PetscFunctionReturn(0); 2049 } 2050 2051 static PetscErrorCode TSTrajectorySetFromOptions_Memory(PetscOptionItems *PetscOptionsObject,TSTrajectory tj) 2052 { 2053 TJScheduler *tjsch = (TJScheduler*)tj->data; 2054 PetscEnum etmp; 2055 PetscInt max_cps_ram,max_cps_disk,max_units_ram,max_units_disk; 2056 PetscBool flg; 2057 2058 PetscFunctionBegin; 2059 CHKERRQ(PetscOptionsHead(PetscOptionsObject,"Memory based TS trajectory options")); 2060 { 2061 CHKERRQ(PetscOptionsInt("-ts_trajectory_max_cps_ram","Maximum number of checkpoints in RAM","TSTrajectorySetMaxCpsRAM",tjsch->max_cps_ram,&max_cps_ram,&flg)); 2062 if (flg) { 2063 CHKERRQ(TSTrajectorySetMaxCpsRAM(tj,max_cps_ram)); 2064 } 2065 CHKERRQ(PetscOptionsInt("-ts_trajectory_max_cps_disk","Maximum number of checkpoints on disk","TSTrajectorySetMaxCpsDisk",tjsch->max_cps_disk,&max_cps_disk,&flg)); 2066 if (flg) { 2067 CHKERRQ(TSTrajectorySetMaxCpsDisk(tj,max_cps_disk)); 2068 } 2069 CHKERRQ(PetscOptionsInt("-ts_trajectory_max_units_ram","Maximum number of checkpointing units in RAM","TSTrajectorySetMaxUnitsRAM",tjsch->max_units_ram,&max_units_ram,&flg)); 2070 if (flg) { 2071 CHKERRQ(TSTrajectorySetMaxUnitsRAM(tj,max_units_ram)); 2072 } 2073 CHKERRQ(PetscOptionsInt("-ts_trajectory_max_units_disk","Maximum number of checkpointing units on disk","TSTrajectorySetMaxUnitsDisk",tjsch->max_units_disk,&max_units_disk,&flg)); 2074 if (flg) { 2075 CHKERRQ(TSTrajectorySetMaxUnitsDisk(tj,max_units_disk)); 2076 } 2077 CHKERRQ(PetscOptionsInt("-ts_trajectory_stride","Stride to save checkpoints to file","TSTrajectorySetStride",tjsch->stride,&tjsch->stride,NULL)); 2078 #if defined(PETSC_HAVE_REVOLVE) 2079 CHKERRQ(PetscOptionsBool("-ts_trajectory_revolve_online","Trick TS trajectory into using online mode of revolve","TSTrajectorySetRevolveOnline",tjsch->use_online,&tjsch->use_online,NULL)); 2080 #endif 2081 CHKERRQ(PetscOptionsBool("-ts_trajectory_save_stack","Save all stack to disk","TSTrajectorySetSaveStack",tjsch->save_stack,&tjsch->save_stack,NULL)); 2082 CHKERRQ(PetscOptionsBool("-ts_trajectory_use_dram","Use DRAM for checkpointing","TSTrajectorySetUseDRAM",tjsch->stack.use_dram,&tjsch->stack.use_dram,NULL)); 2083 CHKERRQ(PetscOptionsEnum("-ts_trajectory_memory_type","Checkpointing scchedule software to use","TSTrajectoryMemorySetType",TSTrajectoryMemoryTypes,(PetscEnum)(int)(tjsch->tj_memory_type),&etmp,&flg)); 2084 if (flg) { 2085 CHKERRQ(TSTrajectoryMemorySetType(tj,(TSTrajectoryMemoryType)etmp)); 2086 } 2087 } 2088 CHKERRQ(PetscOptionsTail()); 2089 PetscFunctionReturn(0); 2090 } 2091 2092 static PetscErrorCode TSTrajectorySetUp_Memory(TSTrajectory tj,TS ts) 2093 { 2094 TJScheduler *tjsch = (TJScheduler*)tj->data; 2095 Stack *stack = &tjsch->stack; 2096 #if defined(PETSC_HAVE_REVOLVE) 2097 RevolveCTX *rctx,*rctx2; 2098 DiskStack *diskstack = &tjsch->diskstack; 2099 PetscInt diskblocks; 2100 #endif 2101 PetscInt numY,total_steps; 2102 PetscBool fixedtimestep; 2103 2104 PetscFunctionBegin; 2105 if (ts->adapt) { 2106 CHKERRQ(PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&fixedtimestep)); 2107 } else { 2108 fixedtimestep = PETSC_TRUE; 2109 } 2110 total_steps = (PetscInt)(PetscCeilReal((ts->max_time-ts->ptime)/ts->time_step)); 2111 total_steps = total_steps < 0 ? PETSC_MAX_INT : total_steps; 2112 if (fixedtimestep) tjsch->total_steps = PetscMin(ts->max_steps,total_steps); 2113 2114 tjsch->stack.solution_only = tj->solution_only; 2115 CHKERRQ(TSGetStages(ts,&numY,PETSC_IGNORE)); 2116 if (stack->solution_only) { 2117 if (tjsch->max_units_ram) tjsch->max_cps_ram = tjsch->max_units_ram; 2118 else tjsch->max_units_ram = tjsch->max_cps_ram; 2119 if (tjsch->max_units_disk) tjsch->max_cps_disk = tjsch->max_units_disk; 2120 } else { 2121 if (tjsch->max_units_ram) tjsch->max_cps_ram = (ts->stifflyaccurate) ? tjsch->max_units_ram/numY : tjsch->max_units_ram/(numY+1); 2122 else tjsch->max_units_ram = (ts->stifflyaccurate) ? numY*tjsch->max_cps_ram : (numY+1)*tjsch->max_cps_ram; 2123 if (tjsch->max_units_disk) tjsch->max_cps_disk = (ts->stifflyaccurate) ? tjsch->max_units_disk/numY : tjsch->max_units_disk/(numY+1); 2124 else tjsch->max_units_disk = (ts->stifflyaccurate) ? numY*tjsch->max_cps_disk : (numY+1)*tjsch->max_cps_disk; 2125 } 2126 if (tjsch->max_cps_ram > 0) stack->stacksize = tjsch->max_units_ram; /* maximum stack size. Could be overallocated. */ 2127 2128 /* Determine the scheduler type */ 2129 if (tjsch->stride > 1) { /* two level mode */ 2130 PetscCheckFalse(tjsch->save_stack && tjsch->max_cps_disk > 1 && tjsch->max_cps_disk <= tjsch->max_cps_ram,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"The specified disk capacity is not enough to store a full stack of RAM checkpoints. You might want to change the disk capacity or use single level checkpointing instead."); 2131 if (tjsch->max_cps_disk <= 1 && tjsch->max_cps_ram > 1 && tjsch->max_cps_ram <= tjsch->stride-1) tjsch->stype = TWO_LEVEL_REVOLVE; /* use revolve_offline for each stride */ 2132 if (tjsch->max_cps_disk > 1 && tjsch->max_cps_ram > 1 && tjsch->max_cps_ram <= tjsch->stride-1) tjsch->stype = TWO_LEVEL_TWO_REVOLVE; /* use revolve_offline for each stride */ 2133 if (tjsch->max_cps_disk <= 1 && (tjsch->max_cps_ram >= tjsch->stride || tjsch->max_cps_ram == -1)) tjsch->stype = TWO_LEVEL_NOREVOLVE; /* can also be handled by TWO_LEVEL_REVOLVE */ 2134 } else { /* single level mode */ 2135 if (fixedtimestep) { 2136 if (tjsch->max_cps_ram >= tjsch->total_steps-1 || tjsch->max_cps_ram == -1) 2137 tjsch->stype = NONE; /* checkpoint all */ 2138 else { /* choose the schedule software for offline checkpointing */ 2139 switch (tjsch->tj_memory_type) { 2140 case TJ_PETSC: 2141 tjsch->stype = NONE; 2142 break; 2143 case TJ_CAMS: 2144 tjsch->stype = CAMS_OFFLINE; 2145 break; 2146 case TJ_REVOLVE: 2147 tjsch->stype = (tjsch->max_cps_disk>1) ? REVOLVE_MULTISTAGE : REVOLVE_OFFLINE; 2148 break; 2149 default: 2150 break; 2151 } 2152 } 2153 } else tjsch->stype = NONE; /* checkpoint all for adaptive time step */ 2154 #if defined(PETSC_HAVE_REVOLVE) 2155 if (tjsch->use_online) tjsch->stype = REVOLVE_ONLINE; /* trick into online (for testing purpose only) */ 2156 #endif 2157 PetscCheckFalse(tjsch->stype != NONE && tjsch->max_cps_ram < 1 && tjsch->max_cps_disk < 1,PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_INCOMP,"The specified storage capacity is insufficient for one checkpoint, which is the minimum"); 2158 } 2159 if (tjsch->stype >= CAMS_OFFLINE) { 2160 #ifndef PETSC_HAVE_CAMS 2161 SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"CAMS is needed when there is not enough memory to checkpoint all time steps according to the user's settings, please reconfigure with the additional option --download-cams."); 2162 #else 2163 CAMSCTX *actx; 2164 PetscInt ns = 0; 2165 if (stack->solution_only) { 2166 offline_ca_create(tjsch->total_steps,tjsch->max_cps_ram); 2167 } else { 2168 CHKERRQ(TSGetStages(ts,&ns,PETSC_IGNORE)); 2169 offline_cams_create(tjsch->total_steps,tjsch->max_units_ram,ns,ts->stifflyaccurate); 2170 } 2171 CHKERRQ(PetscNew(&actx)); 2172 actx->lastcheckpointstep = -1; /* -1 can trigger the initialization of CAMS */ 2173 actx->lastcheckpointtype = -1; /* -1 can trigger the initialization of CAMS */ 2174 actx->endstep = tjsch->total_steps; 2175 actx->num_units_avail = tjsch->max_units_ram; 2176 actx->num_stages = ns; 2177 tjsch->actx = actx; 2178 #endif 2179 } else if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 2180 #ifndef PETSC_HAVE_REVOLVE 2181 SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"revolve is needed when there is not enough memory to checkpoint all time steps according to the user's settings, please reconfigure with the additional option --download-revolve."); 2182 #else 2183 PetscRevolveInt rfine,rsnaps,rsnaps2; 2184 2185 switch (tjsch->stype) { 2186 case TWO_LEVEL_REVOLVE: 2187 CHKERRQ(PetscRevolveIntCast(tjsch->stride,&rfine)); 2188 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2189 revolve_create_offline(rfine,rsnaps); 2190 break; 2191 case TWO_LEVEL_TWO_REVOLVE: 2192 diskblocks = tjsch->save_stack ? tjsch->max_cps_disk/(tjsch->max_cps_ram+1) : tjsch->max_cps_disk; /* The block size depends on whether the stack is saved. */ 2193 diskstack->stacksize = diskblocks; 2194 CHKERRQ(PetscRevolveIntCast(tjsch->stride,&rfine)); 2195 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2196 revolve_create_offline(rfine,rsnaps); 2197 CHKERRQ(PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rfine)); 2198 CHKERRQ(PetscRevolveIntCast(diskblocks,&rsnaps)); 2199 revolve2_create_offline(rfine,rsnaps); 2200 CHKERRQ(PetscNew(&rctx2)); 2201 rctx2->snaps_in = rsnaps; 2202 rctx2->reverseonestep = PETSC_FALSE; 2203 rctx2->check = 0; 2204 rctx2->oldcapo = 0; 2205 rctx2->capo = 0; 2206 rctx2->info = 2; 2207 rctx2->fine = rfine; 2208 tjsch->rctx2 = rctx2; 2209 diskstack->top = -1; 2210 CHKERRQ(PetscMalloc1(diskstack->stacksize,&diskstack->container)); 2211 break; 2212 case REVOLVE_OFFLINE: 2213 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rfine)); 2214 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2215 revolve_create_offline(rfine,rsnaps); 2216 break; 2217 case REVOLVE_ONLINE: 2218 stack->stacksize = tjsch->max_cps_ram; 2219 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2220 revolve_create_online(rsnaps); 2221 break; 2222 case REVOLVE_MULTISTAGE: 2223 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rfine)); 2224 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2225 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram+tjsch->max_cps_disk,&rsnaps2)); 2226 revolve_create_multistage(rfine,rsnaps2,rsnaps); 2227 break; 2228 default: 2229 break; 2230 } 2231 CHKERRQ(PetscNew(&rctx)); 2232 CHKERRQ(PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps)); 2233 rctx->snaps_in = rsnaps; /* for theta methods snaps_in=2*max_cps_ram */ 2234 rctx->reverseonestep = PETSC_FALSE; 2235 rctx->check = 0; 2236 rctx->oldcapo = 0; 2237 rctx->capo = 0; 2238 rctx->info = 2; 2239 if (tjsch->stride > 1) { 2240 CHKERRQ(PetscRevolveIntCast(tjsch->stride,&rfine)); 2241 } else { 2242 CHKERRQ(PetscRevolveIntCast(tjsch->total_steps,&rfine)); 2243 } 2244 rctx->fine = rfine; 2245 tjsch->rctx = rctx; 2246 if (tjsch->stype == REVOLVE_ONLINE) rctx->fine = -1; 2247 #endif 2248 } else { 2249 if (tjsch->stype == TWO_LEVEL_NOREVOLVE) stack->stacksize = tjsch->stride-1; /* need tjsch->stride-1 at most */ 2250 if (tjsch->stype == NONE) { 2251 if (fixedtimestep) stack->stacksize = stack->solution_only ? tjsch->total_steps : tjsch->total_steps-1; 2252 else { /* adaptive time step */ 2253 /* if max_cps_ram is not specified, use maximal allowed number of steps for stack size */ 2254 if (tjsch->max_cps_ram == -1) stack->stacksize = ts->max_steps < PETSC_MAX_INT ? ts->max_steps : 10000; 2255 tjsch->total_steps = stack->solution_only ? stack->stacksize : stack->stacksize+1; /* will be updated as time integration advances */ 2256 } 2257 } 2258 } 2259 2260 if ((tjsch->stype >= TWO_LEVEL_NOREVOLVE && tjsch->stype < REVOLVE_OFFLINE) || tjsch->stype == REVOLVE_MULTISTAGE) { /* these types need to use disk */ 2261 CHKERRQ(TSTrajectorySetUp_Basic(tj,ts)); 2262 } 2263 2264 stack->stacksize = PetscMax(stack->stacksize,1); 2265 tjsch->recompute = PETSC_FALSE; 2266 CHKERRQ(StackInit(stack,stack->stacksize,numY)); 2267 PetscFunctionReturn(0); 2268 } 2269 2270 static PetscErrorCode TSTrajectoryReset_Memory(TSTrajectory tj) 2271 { 2272 #if defined (PETSC_HAVE_REVOLVE) || defined (PETSC_HAVE_CAMS) 2273 TJScheduler *tjsch = (TJScheduler*)tj->data; 2274 #endif 2275 2276 PetscFunctionBegin; 2277 #if defined(PETSC_HAVE_REVOLVE) 2278 if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 2279 revolve_reset(); 2280 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) { 2281 revolve2_reset(); 2282 CHKERRQ(PetscFree(tjsch->diskstack.container)); 2283 } 2284 } 2285 if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 2286 CHKERRQ(PetscFree(tjsch->rctx)); 2287 CHKERRQ(PetscFree(tjsch->rctx2)); 2288 } 2289 #endif 2290 #if defined(PETSC_HAVE_CAMS) 2291 if (tjsch->stype == CAMS_OFFLINE) { 2292 if (tjsch->stack.solution_only) offline_ca_destroy(); 2293 else offline_ca_destroy(); 2294 CHKERRQ(PetscFree(tjsch->actx)); 2295 } 2296 #endif 2297 PetscFunctionReturn(0); 2298 } 2299 2300 static PetscErrorCode TSTrajectoryDestroy_Memory(TSTrajectory tj) 2301 { 2302 TJScheduler *tjsch = (TJScheduler*)tj->data; 2303 2304 PetscFunctionBegin; 2305 CHKERRQ(StackDestroy(&tjsch->stack)); 2306 CHKERRQ(PetscViewerDestroy(&tjsch->viewer)); 2307 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxCpsRAM_C",NULL)); 2308 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxCpsDisk_C",NULL)); 2309 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxUnitsRAM_C",NULL)); 2310 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxUnitsDisk_C",NULL)); 2311 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectoryMemorySetType_C",NULL)); 2312 CHKERRQ(PetscFree(tjsch)); 2313 PetscFunctionReturn(0); 2314 } 2315 2316 /*MC 2317 TSTRAJECTORYMEMORY - Stores each solution of the ODE/ADE in memory 2318 2319 Level: intermediate 2320 2321 .seealso: TSTrajectoryCreate(), TS, TSTrajectorySetType() 2322 2323 M*/ 2324 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory tj,TS ts) 2325 { 2326 TJScheduler *tjsch; 2327 2328 PetscFunctionBegin; 2329 tj->ops->set = TSTrajectorySet_Memory; 2330 tj->ops->get = TSTrajectoryGet_Memory; 2331 tj->ops->setup = TSTrajectorySetUp_Memory; 2332 tj->ops->setfromoptions = TSTrajectorySetFromOptions_Memory; 2333 tj->ops->reset = TSTrajectoryReset_Memory; 2334 tj->ops->destroy = TSTrajectoryDestroy_Memory; 2335 2336 CHKERRQ(PetscNew(&tjsch)); 2337 tjsch->stype = NONE; 2338 tjsch->max_cps_ram = -1; /* -1 indicates that it is not set */ 2339 tjsch->max_cps_disk = -1; /* -1 indicates that it is not set */ 2340 tjsch->stride = 0; /* if not zero, two-level checkpointing will be used */ 2341 #if defined(PETSC_HAVE_REVOLVE) 2342 tjsch->use_online = PETSC_FALSE; 2343 #endif 2344 tjsch->save_stack = PETSC_TRUE; 2345 2346 tjsch->stack.solution_only = tj->solution_only; 2347 CHKERRQ(PetscViewerCreate(PetscObjectComm((PetscObject)tj),&tjsch->viewer)); 2348 CHKERRQ(PetscViewerSetType(tjsch->viewer,PETSCVIEWERBINARY)); 2349 CHKERRQ(PetscViewerPushFormat(tjsch->viewer,PETSC_VIEWER_NATIVE)); 2350 CHKERRQ(PetscViewerFileSetMode(tjsch->viewer,FILE_MODE_WRITE)); 2351 2352 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxCpsRAM_C",TSTrajectorySetMaxCpsRAM_Memory)); 2353 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxCpsDisk_C",TSTrajectorySetMaxCpsDisk_Memory)); 2354 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxUnitsRAM_C",TSTrajectorySetMaxUnitsRAM_Memory)); 2355 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectorySetMaxUnitsDisk_C",TSTrajectorySetMaxUnitsDisk_Memory)); 2356 CHKERRQ(PetscObjectComposeFunction((PetscObject)tj,"TSTrajectoryMemorySetType_C",TSTrajectoryMemorySetType_Memory)); 2357 tj->data = tjsch; 2358 PetscFunctionReturn(0); 2359 } 2360