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 PETSC_STATIC_INLINE PetscErrorCode PetscRevolveIntCast(PetscInt a,PetscRevolveInt *b) 12 { 13 PetscFunctionBegin; 14 #if defined(PETSC_USE_64BIT_INDICES) 15 *b = 0; 16 if (a > PETSC_REVOLVE_INT_MAX) SETERRQ(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 23 PetscLogEvent TSTrajectory_DiskWrite, TSTrajectory_DiskRead; 24 static PetscErrorCode TSTrajectorySet_Memory(TSTrajectory,TS,PetscInt,PetscReal,Vec); 25 26 typedef enum {NONE,TWO_LEVEL_NOREVOLVE,TWO_LEVEL_REVOLVE,TWO_LEVEL_TWO_REVOLVE,REVOLVE_OFFLINE,REVOLVE_ONLINE,REVOLVE_MULTISTAGE} SchedulerType; 27 28 typedef struct _StackElement { 29 PetscInt stepnum; 30 Vec X; 31 Vec *Y; 32 PetscReal time; 33 PetscReal timeprev; /* for no solution_only mode */ 34 PetscReal timenext; /* for solution_only mode */ 35 } *StackElement; 36 37 #if defined(PETSC_HAVE_REVOLVE) 38 typedef struct _RevolveCTX { 39 PetscBool reverseonestep; 40 PetscRevolveInt where; 41 PetscRevolveInt snaps_in; 42 PetscRevolveInt stepsleft; 43 PetscRevolveInt check; 44 PetscRevolveInt oldcapo; 45 PetscRevolveInt capo; 46 PetscRevolveInt fine; 47 PetscRevolveInt info; 48 } RevolveCTX; 49 #endif 50 51 typedef struct _Stack { 52 PetscInt stacksize; 53 PetscInt top; 54 StackElement *container; 55 PetscInt nallocated; 56 PetscInt numY; 57 PetscBool solution_only; 58 PetscBool use_dram; 59 } Stack; 60 61 typedef struct _DiskStack { 62 PetscInt stacksize; 63 PetscInt top; 64 PetscInt *container; 65 } DiskStack; 66 67 typedef struct _TJScheduler { 68 SchedulerType stype; 69 #if defined(PETSC_HAVE_REVOLVE) 70 RevolveCTX *rctx,*rctx2; 71 PetscBool use_online; 72 PetscInt store_stride; 73 #endif 74 PetscBool recompute; 75 PetscBool skip_trajectory; 76 PetscBool save_stack; 77 PetscInt max_cps_ram; /* maximum checkpoints in RAM */ 78 PetscInt max_cps_disk; /* maximum checkpoints on disk */ 79 PetscInt stride; 80 PetscInt total_steps; /* total number of steps */ 81 Stack stack; 82 DiskStack diskstack; 83 PetscViewer viewer; 84 } TJScheduler; 85 86 static PetscErrorCode TurnForwardWithStepsize(TS ts,PetscReal nextstepsize) 87 { 88 PetscErrorCode ierr; 89 90 PetscFunctionBegin; 91 /* reverse the direction */ 92 ierr = TSSetTimeStep(ts,nextstepsize);CHKERRQ(ierr); 93 PetscFunctionReturn(0); 94 } 95 96 static PetscErrorCode TurnForward(TS ts) 97 { 98 PetscReal stepsize; 99 PetscErrorCode ierr; 100 101 PetscFunctionBegin; 102 /* reverse the direction */ 103 ierr = TSGetTimeStep(ts,&stepsize);CHKERRQ(ierr); 104 ierr = TSSetTimeStep(ts,-stepsize);CHKERRQ(ierr); 105 PetscFunctionReturn(0); 106 } 107 108 static PetscErrorCode TurnBackward(TS ts) 109 { 110 PetscReal stepsize; 111 PetscErrorCode ierr; 112 113 PetscFunctionBegin; 114 if (!ts->trajectory->adjoint_solve_mode) PetscFunctionReturn(0); 115 /* reverse the direction */ 116 stepsize = ts->ptime_prev-ts->ptime; 117 ierr = TSSetTimeStep(ts,stepsize);CHKERRQ(ierr); 118 PetscFunctionReturn(0); 119 } 120 121 static PetscErrorCode ElementCreate(TS ts,Stack *stack,StackElement *e) 122 { 123 Vec X; 124 Vec *Y; 125 PetscErrorCode ierr; 126 127 PetscFunctionBegin; 128 if (stack->top < stack->stacksize-1 && stack->container[stack->top+1]) { 129 *e = stack->container[stack->top+1]; 130 PetscFunctionReturn(0); 131 } 132 if (stack->use_dram) { 133 ierr = PetscMallocSetDRAM();CHKERRQ(ierr); 134 } 135 ierr = PetscNew(e);CHKERRQ(ierr); 136 ierr = TSGetSolution(ts,&X);CHKERRQ(ierr); 137 ierr = VecDuplicate(X,&(*e)->X);CHKERRQ(ierr); 138 if (stack->numY > 0 && !stack->solution_only) { 139 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 140 ierr = VecDuplicateVecs(Y[0],stack->numY,&(*e)->Y);CHKERRQ(ierr); 141 } 142 if (stack->use_dram) { 143 ierr = PetscMallocResetDRAM();CHKERRQ(ierr); 144 } 145 stack->nallocated++; 146 PetscFunctionReturn(0); 147 } 148 149 static PetscErrorCode ElementSet(TS ts,Stack *stack,StackElement *e,PetscInt stepnum,PetscReal time,Vec X) 150 { 151 Vec *Y; 152 PetscInt i; 153 PetscReal timeprev; 154 PetscErrorCode ierr; 155 156 PetscFunctionBegin; 157 ierr = VecCopy(X,(*e)->X);CHKERRQ(ierr); 158 if (stack->numY > 0 && !stack->solution_only) { 159 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 160 for (i=0;i<stack->numY;i++) { 161 ierr = VecCopy(Y[i],(*e)->Y[i]);CHKERRQ(ierr); 162 } 163 } 164 (*e)->stepnum = stepnum; 165 (*e)->time = time; 166 /* for consistency */ 167 if (stepnum == 0) { 168 (*e)->timeprev = (*e)->time - ts->time_step; 169 } else { 170 ierr = TSGetPrevTime(ts,&timeprev);CHKERRQ(ierr); 171 (*e)->timeprev = timeprev; 172 } 173 PetscFunctionReturn(0); 174 } 175 176 static PetscErrorCode ElementDestroy(Stack *stack,StackElement e) 177 { 178 PetscErrorCode ierr; 179 180 PetscFunctionBegin; 181 if (stack->use_dram) { 182 ierr = PetscMallocSetDRAM();CHKERRQ(ierr); 183 } 184 ierr = VecDestroy(&e->X);CHKERRQ(ierr); 185 if (stack->numY > 0 && !stack->solution_only) { 186 ierr = VecDestroyVecs(stack->numY,&e->Y);CHKERRQ(ierr); 187 } 188 ierr = PetscFree(e);CHKERRQ(ierr); 189 if (stack->use_dram) { 190 ierr = PetscMallocResetDRAM();CHKERRQ(ierr); 191 } 192 stack->nallocated--; 193 PetscFunctionReturn(0); 194 } 195 196 static PetscErrorCode StackResize(Stack *stack,PetscInt newsize) 197 { 198 StackElement *newcontainer; 199 PetscInt i; 200 PetscErrorCode ierr; 201 202 PetscFunctionBegin; 203 ierr = PetscCalloc1(newsize*sizeof(StackElement),&newcontainer);CHKERRQ(ierr); 204 for (i=0;i<stack->stacksize;i++) { 205 newcontainer[i] = stack->container[i]; 206 } 207 ierr = PetscFree(stack->container);CHKERRQ(ierr); 208 stack->container = newcontainer; 209 stack->stacksize = newsize; 210 PetscFunctionReturn(0); 211 } 212 213 static PetscErrorCode StackPush(Stack *stack,StackElement e) 214 { 215 PetscFunctionBegin; 216 if (stack->top+1 >= stack->stacksize) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Maximum stack size (%D) exceeded",stack->stacksize); 217 stack->container[++stack->top] = e; 218 PetscFunctionReturn(0); 219 } 220 221 static PetscErrorCode StackPop(Stack *stack,StackElement *e) 222 { 223 PetscFunctionBegin; 224 *e = NULL; 225 if (stack->top == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MEMC,"Empty stack"); 226 *e = stack->container[stack->top--]; 227 PetscFunctionReturn(0); 228 } 229 230 static PetscErrorCode StackTop(Stack *stack,StackElement *e) 231 { 232 PetscFunctionBegin; 233 *e = stack->container[stack->top]; 234 PetscFunctionReturn(0); 235 } 236 237 static PetscErrorCode StackInit(Stack *stack,PetscInt size,PetscInt ny) 238 { 239 PetscErrorCode ierr; 240 241 PetscFunctionBegin; 242 stack->top = -1; 243 stack->numY = ny; 244 245 if (!stack->container) { 246 ierr = PetscCalloc1(size,&stack->container);CHKERRQ(ierr); 247 } 248 PetscFunctionReturn(0); 249 } 250 251 static PetscErrorCode StackDestroy(Stack *stack) 252 { 253 PetscInt i,n = stack->nallocated; 254 PetscErrorCode ierr; 255 256 PetscFunctionBegin; 257 if (!stack->container) PetscFunctionReturn(0); 258 if (stack->top+1 > stack->nallocated) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Stack size does not match element counter %D",stack->nallocated); 259 for (i=0; i<n; i++) { 260 ierr = ElementDestroy(stack,stack->container[i]);CHKERRQ(ierr); 261 } 262 ierr = PetscFree(stack->container);CHKERRQ(ierr); 263 PetscFunctionReturn(0); 264 } 265 266 static PetscErrorCode StackFind(Stack *stack,StackElement *e,PetscInt index) 267 { 268 PetscFunctionBegin; 269 *e = NULL; 270 if (index < 0 || index > stack->top) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid index %D",index); 271 *e = stack->container[index]; 272 PetscFunctionReturn(0); 273 } 274 275 static PetscErrorCode WriteToDisk(PetscInt stepnum,PetscReal time,PetscReal timeprev,Vec X,Vec *Y,PetscInt numY,PetscBool solution_only,PetscViewer viewer) 276 { 277 PetscInt i; 278 PetscErrorCode ierr; 279 280 PetscFunctionBegin; 281 ierr = PetscViewerBinaryWrite(viewer,&stepnum,1,PETSC_INT);CHKERRQ(ierr); 282 ierr = VecView(X,viewer);CHKERRQ(ierr); 283 for (i=0;!solution_only && i<numY;i++) { 284 ierr = VecView(Y[i],viewer);CHKERRQ(ierr); 285 } 286 ierr = PetscViewerBinaryWrite(viewer,&time,1,PETSC_REAL);CHKERRQ(ierr); 287 ierr = PetscViewerBinaryWrite(viewer,&timeprev,1,PETSC_REAL);CHKERRQ(ierr); 288 PetscFunctionReturn(0); 289 } 290 291 static PetscErrorCode ReadFromDisk(PetscInt *stepnum,PetscReal *time,PetscReal *timeprev,Vec X,Vec *Y,PetscInt numY,PetscBool solution_only,PetscViewer viewer) 292 { 293 PetscInt i; 294 PetscErrorCode ierr; 295 296 PetscFunctionBegin; 297 ierr = PetscViewerBinaryRead(viewer,stepnum,1,NULL,PETSC_INT);CHKERRQ(ierr); 298 ierr = VecLoad(X,viewer);CHKERRQ(ierr); 299 for (i=0;!solution_only && i<numY;i++) { 300 ierr = VecLoad(Y[i],viewer);CHKERRQ(ierr); 301 } 302 ierr = PetscViewerBinaryRead(viewer,time,1,NULL,PETSC_REAL);CHKERRQ(ierr); 303 ierr = PetscViewerBinaryRead(viewer,timeprev,1,NULL,PETSC_REAL);CHKERRQ(ierr); 304 PetscFunctionReturn(0); 305 } 306 307 static PetscErrorCode StackDumpAll(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 308 { 309 Vec *Y; 310 PetscInt i; 311 StackElement e = NULL; 312 TJScheduler *tjsch = (TJScheduler*)tj->data; 313 char filename[PETSC_MAX_PATH_LEN]; 314 PetscErrorCode ierr; 315 MPI_Comm comm; 316 317 PetscFunctionBegin; 318 ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr); 319 if (tj->monitor) { 320 ierr = PetscViewerASCIIPushTab(tj->monitor);CHKERRQ(ierr); 321 ierr = PetscViewerASCIIPrintf(tj->monitor,"Dump stack id %D to file\n",id);CHKERRQ(ierr); 322 ierr = PetscViewerASCIIPopTab(tj->monitor);CHKERRQ(ierr); 323 } 324 ierr = PetscSNPrintf(filename,sizeof(filename),"%s/TS-STACK%06d.bin",tj->dirname,id);CHKERRQ(ierr); 325 ierr = PetscViewerFileSetName(tjsch->viewer,filename);CHKERRQ(ierr); 326 ierr = PetscViewerSetUp(tjsch->viewer);CHKERRQ(ierr); 327 for (i=0;i<stack->stacksize;i++) { 328 e = stack->container[i]; 329 ierr = PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 330 ierr = WriteToDisk(e->stepnum,e->time,e->timeprev,e->X,e->Y,stack->numY,stack->solution_only,tjsch->viewer);CHKERRQ(ierr); 331 ierr = PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 332 ts->trajectory->diskwrites++; 333 } 334 /* 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 */ 335 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 336 ierr = PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 337 ierr = WriteToDisk(ts->steps,ts->ptime,ts->ptime_prev,ts->vec_sol,Y,stack->numY,stack->solution_only,tjsch->viewer);CHKERRQ(ierr); 338 ierr = PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 339 ts->trajectory->diskwrites++; 340 for (i=0;i<stack->stacksize;i++) { 341 ierr = StackPop(stack,&e);CHKERRQ(ierr); 342 } 343 PetscFunctionReturn(0); 344 } 345 346 static PetscErrorCode StackLoadAll(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 347 { 348 Vec *Y; 349 PetscInt i; 350 StackElement e; 351 PetscViewer viewer; 352 char filename[PETSC_MAX_PATH_LEN]; 353 PetscErrorCode ierr; 354 355 PetscFunctionBegin; 356 if (tj->monitor) { 357 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 358 ierr = PetscViewerASCIIPrintf(tj->monitor,"Load stack from file\n");CHKERRQ(ierr); 359 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 360 } 361 ierr = PetscSNPrintf(filename,sizeof filename,"%s/TS-STACK%06d.bin",tj->dirname,id);CHKERRQ(ierr); 362 ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr); 363 ierr = PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);CHKERRQ(ierr); 364 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE);CHKERRQ(ierr); 365 for (i=0;i<stack->stacksize;i++) { 366 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 367 ierr = StackPush(stack,e);CHKERRQ(ierr); 368 ierr = PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 369 ierr = ReadFromDisk(&e->stepnum,&e->time,&e->timeprev,e->X,e->Y,stack->numY,stack->solution_only,viewer);CHKERRQ(ierr); 370 ierr = PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 371 ts->trajectory->diskreads++; 372 } 373 /* load the last step into TS */ 374 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 375 ierr = PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 376 ierr = ReadFromDisk(&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,stack->solution_only,viewer);CHKERRQ(ierr); 377 ierr = PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 378 ts->trajectory->diskreads++; 379 ierr = TurnBackward(ts);CHKERRQ(ierr); 380 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 381 PetscFunctionReturn(0); 382 } 383 384 #if defined(PETSC_HAVE_REVOLVE) 385 static PetscErrorCode StackLoadLast(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 386 { 387 Vec *Y; 388 PetscInt size; 389 PetscViewer viewer; 390 char filename[PETSC_MAX_PATH_LEN]; 391 #if defined(PETSC_HAVE_MPIIO) 392 PetscBool usempiio; 393 #endif 394 int fd; 395 off_t off,offset; 396 PetscErrorCode ierr; 397 398 PetscFunctionBegin; 399 if (tj->monitor) { 400 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 401 ierr = PetscViewerASCIIPrintf(tj->monitor,"Load last stack element from file\n");CHKERRQ(ierr); 402 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 403 } 404 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 405 ierr = VecGetSize(Y[0],&size);CHKERRQ(ierr); 406 /* VecView writes to file two extra int's for class id and number of rows */ 407 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; 408 409 ierr = PetscSNPrintf(filename,sizeof filename,"%s/TS-STACK%06d.bin",tj->dirname,id);CHKERRQ(ierr); 410 ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr); 411 ierr = PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);CHKERRQ(ierr); 412 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE);CHKERRQ(ierr); 413 #if defined(PETSC_HAVE_MPIIO) 414 ierr = PetscViewerBinaryGetUseMPIIO(viewer,&usempiio);CHKERRQ(ierr); 415 if (usempiio) { 416 ierr = PetscViewerBinaryGetMPIIODescriptor(viewer,(MPI_File*)&fd);CHKERRQ(ierr); 417 ierr = PetscBinarySynchronizedSeek(PetscObjectComm((PetscObject)tj),fd,off,PETSC_BINARY_SEEK_END,&offset);CHKERRQ(ierr); 418 } else { 419 #endif 420 ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 421 ierr = PetscBinarySeek(fd,off,PETSC_BINARY_SEEK_END,&offset);CHKERRQ(ierr); 422 #if defined(PETSC_HAVE_MPIIO) 423 } 424 #endif 425 /* load the last step into TS */ 426 ierr = PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 427 ierr = ReadFromDisk(&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,stack->solution_only,viewer);CHKERRQ(ierr); 428 ierr = PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 429 ts->trajectory->diskreads++; 430 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 431 ierr = TurnBackward(ts);CHKERRQ(ierr); 432 PetscFunctionReturn(0); 433 } 434 #endif 435 436 static PetscErrorCode DumpSingle(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 437 { 438 Vec *Y; 439 PetscInt stepnum; 440 TJScheduler *tjsch = (TJScheduler*)tj->data; 441 char filename[PETSC_MAX_PATH_LEN]; 442 PetscErrorCode ierr; 443 MPI_Comm comm; 444 445 PetscFunctionBegin; 446 ierr = PetscObjectGetComm((PetscObject)ts,&comm);CHKERRQ(ierr); 447 if (tj->monitor) { 448 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 449 ierr = PetscViewerASCIIPrintf(tj->monitor,"Dump a single point from file\n");CHKERRQ(ierr); 450 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 451 } 452 ierr = TSGetStepNumber(ts,&stepnum);CHKERRQ(ierr); 453 ierr = PetscSNPrintf(filename,sizeof(filename),"%s/TS-CPS%06d.bin",tj->dirname,id);CHKERRQ(ierr); 454 ierr = PetscViewerFileSetName(tjsch->viewer,filename);CHKERRQ(ierr); 455 ierr = PetscViewerSetUp(tjsch->viewer);CHKERRQ(ierr); 456 457 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 458 ierr = PetscLogEventBegin(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 459 ierr = WriteToDisk(stepnum,ts->ptime,ts->ptime_prev,ts->vec_sol,Y,stack->numY,stack->solution_only,tjsch->viewer);CHKERRQ(ierr); 460 ierr = PetscLogEventEnd(TSTrajectory_DiskWrite,tj,ts,0,0);CHKERRQ(ierr); 461 ts->trajectory->diskwrites++; 462 PetscFunctionReturn(0); 463 } 464 465 static PetscErrorCode LoadSingle(TSTrajectory tj,TS ts,Stack *stack,PetscInt id) 466 { 467 Vec *Y; 468 PetscViewer viewer; 469 char filename[PETSC_MAX_PATH_LEN]; 470 PetscErrorCode ierr; 471 472 PetscFunctionBegin; 473 if (tj->monitor) { 474 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 475 ierr = PetscViewerASCIIPrintf(tj->monitor,"Load a single point from file\n");CHKERRQ(ierr); 476 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 477 } 478 ierr = PetscSNPrintf(filename,sizeof filename,"%s/TS-CPS%06d.bin",tj->dirname,id);CHKERRQ(ierr); 479 ierr = PetscViewerBinaryOpen(PetscObjectComm((PetscObject)tj),filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr); 480 ierr = PetscViewerBinarySetSkipInfo(viewer,PETSC_TRUE);CHKERRQ(ierr); 481 ierr = PetscViewerPushFormat(viewer,PETSC_VIEWER_NATIVE);CHKERRQ(ierr); 482 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 483 ierr = PetscLogEventBegin(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 484 ierr = ReadFromDisk(&ts->steps,&ts->ptime,&ts->ptime_prev,ts->vec_sol,Y,stack->numY,stack->solution_only,viewer);CHKERRQ(ierr); 485 ierr = PetscLogEventEnd(TSTrajectory_DiskRead,tj,ts,0,0);CHKERRQ(ierr); 486 ts->trajectory->diskreads++; 487 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 488 PetscFunctionReturn(0); 489 } 490 491 static PetscErrorCode UpdateTS(TS ts,Stack *stack,StackElement e, PetscBool adjoint_mode) 492 { 493 Vec *Y; 494 PetscInt i; 495 PetscErrorCode ierr; 496 497 PetscFunctionBegin; 498 ierr = VecCopy(e->X,ts->vec_sol);CHKERRQ(ierr); 499 if (!stack->solution_only && e->stepnum) { 500 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 501 for (i=0;i<stack->numY;i++) { 502 ierr = VecCopy(e->Y[i],Y[i]);CHKERRQ(ierr); 503 } 504 } 505 if (adjoint_mode) { 506 ierr = TSSetTimeStep(ts,e->timeprev-e->time);CHKERRQ(ierr); /* stepsize will be negative */ 507 } else { 508 ierr = TSSetTimeStep(ts,e->time-e->timeprev);CHKERRQ(ierr); /* stepsize will be positive */ 509 } 510 ts->ptime = e->time; 511 ts->ptime_prev = e->timeprev; 512 PetscFunctionReturn(0); 513 } 514 515 static PetscErrorCode ReCompute(TS ts,TJScheduler *tjsch,PetscInt stepnumbegin,PetscInt stepnumend) 516 { 517 Stack *stack = &tjsch->stack; 518 PetscInt i; 519 PetscErrorCode ierr; 520 521 PetscFunctionBegin; 522 tjsch->recompute = PETSC_TRUE; /* hints TSTrajectorySet() that it is in recompute mode */ 523 ierr = TSSetStepNumber(ts,stepnumbegin);CHKERRQ(ierr);/* global step number */ 524 for (i=stepnumbegin;i<stepnumend;i++) { /* assume fixed step size */ 525 if (stack->solution_only && !tjsch->skip_trajectory) { /* revolve online need this */ 526 /* don't use the public interface as it will update the TSHistory: this need a better fix */ 527 ierr = TSTrajectorySet_Memory(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 528 } 529 ierr = TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 530 ierr = TSStep(ts);CHKERRQ(ierr); 531 if (!stack->solution_only && !tjsch->skip_trajectory) { 532 /* don't use the public interface as it will update the TSHistory: this need a better fix */ 533 ierr = TSTrajectorySet_Memory(ts->trajectory,ts,ts->steps,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 534 } 535 ierr = TSEventHandler(ts);CHKERRQ(ierr); 536 if (!ts->steprollback) { 537 ierr = TSPostStep(ts);CHKERRQ(ierr); 538 } 539 } 540 ierr = TurnBackward(ts);CHKERRQ(ierr); 541 ts->trajectory->recomps += stepnumend-stepnumbegin; /* recomputation counter */ 542 ierr = TSSetStepNumber(ts,stepnumend);CHKERRQ(ierr); 543 tjsch->recompute = PETSC_FALSE; /* reset the flag for recompute mode */ 544 PetscFunctionReturn(0); 545 } 546 547 static PetscErrorCode TopLevelStore(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscInt localstepnum,PetscInt laststridesize,PetscBool *done) 548 { 549 Stack *stack = &tjsch->stack; 550 DiskStack *diskstack = &tjsch->diskstack; 551 PetscInt stridenum; 552 PetscErrorCode ierr; 553 554 PetscFunctionBegin; 555 *done = PETSC_FALSE; 556 stridenum = stepnum/tjsch->stride; 557 /* make sure saved checkpoint id starts from 1 558 skip last stride when using stridenum+1 559 skip first stride when using stridenum */ 560 if (stack->solution_only) { 561 if (tjsch->save_stack) { 562 if (localstepnum == tjsch->stride-1 && stepnum < tjsch->total_steps-laststridesize) { /* current step will be saved without going through stack */ 563 ierr = StackDumpAll(tj,ts,stack,stridenum+1);CHKERRQ(ierr); 564 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 565 *done = PETSC_TRUE; 566 } 567 } else { 568 if (localstepnum == 0 && stepnum < tjsch->total_steps-laststridesize) { 569 ierr = DumpSingle(tj,ts,stack,stridenum+1);CHKERRQ(ierr); 570 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 571 *done = PETSC_TRUE; 572 } 573 } 574 } else { 575 if (tjsch->save_stack) { 576 if (localstepnum == 0 && stepnum < tjsch->total_steps && stepnum != 0) { /* skip the first stride */ 577 ierr = StackDumpAll(tj,ts,stack,stridenum);CHKERRQ(ierr); 578 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum; 579 *done = PETSC_TRUE; 580 } 581 } else { 582 if (localstepnum == 1 && stepnum < tjsch->total_steps-laststridesize) { 583 ierr = DumpSingle(tj,ts,stack,stridenum+1);CHKERRQ(ierr); 584 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) diskstack->container[++diskstack->top] = stridenum+1; 585 *done = PETSC_TRUE; 586 } 587 } 588 } 589 PetscFunctionReturn(0); 590 } 591 592 static PetscErrorCode SetTrajN(TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 593 { 594 Stack *stack = &tjsch->stack; 595 StackElement e; 596 PetscErrorCode ierr; 597 598 PetscFunctionBegin; 599 /* skip the last step */ 600 if (ts->reason) { /* only affect the forward run */ 601 /* update total_steps in the end of forward run */ 602 if (stepnum != tjsch->total_steps) tjsch->total_steps = stepnum; 603 if (stack->solution_only) { 604 /* get rid of the solution at second last step */ 605 ierr = StackPop(stack,&e);CHKERRQ(ierr); 606 } 607 PetscFunctionReturn(0); 608 } 609 /* do not save trajectory at the recompute stage for solution_only mode */ 610 if (stack->solution_only && tjsch->recompute) PetscFunctionReturn(0); 611 /* skip the first step for no_solution_only mode */ 612 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 613 614 /* resize the stack */ 615 if (stack->top+1 == stack->stacksize) { 616 ierr = StackResize(stack,2*stack->stacksize);CHKERRQ(ierr); 617 } 618 /* update timenext for the previous step; necessary for step adaptivity */ 619 if (stack->top > -1) { 620 ierr = StackTop(stack,&e);CHKERRQ(ierr); 621 e->timenext = ts->ptime; 622 } 623 if (stepnum < stack->top) { 624 SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 625 } 626 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 627 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 628 ierr = StackPush(stack,e);CHKERRQ(ierr); 629 PetscFunctionReturn(0); 630 } 631 632 static PetscErrorCode SetTrajN_2(TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 633 { 634 Stack *stack = &tjsch->stack; 635 StackElement e; 636 PetscErrorCode ierr; 637 638 PetscFunctionBegin; 639 if (stack->top+1 == stack->stacksize) { 640 ierr = StackResize(stack,2*stack->stacksize);CHKERRQ(ierr); 641 } 642 /* update timenext for the previous step; necessary for step adaptivity */ 643 if (stack->top > -1) { 644 ierr = StackTop(stack,&e);CHKERRQ(ierr); 645 e->timenext = ts->ptime; 646 } 647 if (stepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 648 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 649 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 650 ierr = StackPush(stack,e);CHKERRQ(ierr); 651 PetscFunctionReturn(0); 652 } 653 654 static PetscErrorCode GetTrajN(TS ts,TJScheduler *tjsch,PetscInt stepnum) 655 { 656 Stack *stack = &tjsch->stack; 657 StackElement e; 658 PetscInt ns; 659 PetscErrorCode ierr; 660 661 PetscFunctionBegin; 662 /* If TSTrajectoryGet() is called after TSAdjointSolve() converges (e.g. outside the while loop in TSAdjointSolve()), skip getting the checkpoint. */ 663 if (ts->reason) PetscFunctionReturn(0); 664 if (stepnum == tjsch->total_steps) { 665 ierr = TurnBackward(ts);CHKERRQ(ierr); 666 PetscFunctionReturn(0); 667 } 668 /* restore a checkpoint */ 669 ierr = StackTop(stack,&e);CHKERRQ(ierr); 670 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 671 ierr = TSGetStages(ts,&ns,NULL);CHKERRQ(ierr); 672 if (stack->solution_only && ns) { /* recompute one step */ 673 ierr = TurnForwardWithStepsize(ts,e->timenext-e->time);CHKERRQ(ierr); 674 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 675 } 676 ierr = StackPop(stack,&e);CHKERRQ(ierr); 677 PetscFunctionReturn(0); 678 } 679 680 static PetscErrorCode GetTrajN_2(TS ts,TJScheduler *tjsch,PetscInt stepnum) 681 { 682 Stack *stack = &tjsch->stack; 683 StackElement e = NULL; 684 PetscErrorCode ierr; 685 686 PetscFunctionBegin; 687 ierr = StackFind(stack,&e,stepnum);CHKERRQ(ierr); 688 if (stepnum != e->stepnum) SETERRQ2(PetscObjectComm((PetscObject)ts),PETSC_ERR_PLIB,"Inconsistent steps! %D != %D",stepnum,e->stepnum); 689 ierr = UpdateTS(ts,stack,e,PETSC_FALSE);CHKERRQ(ierr); 690 PetscFunctionReturn(0); 691 } 692 693 static PetscErrorCode SetTrajTLNR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 694 { 695 Stack *stack = &tjsch->stack; 696 PetscInt localstepnum,laststridesize; 697 StackElement e; 698 PetscBool done; 699 PetscErrorCode ierr; 700 701 PetscFunctionBegin; 702 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 703 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 704 if (tjsch->save_stack && tjsch->recompute) PetscFunctionReturn(0); 705 706 localstepnum = stepnum%tjsch->stride; 707 /* (stridesize-1) checkpoints are saved in each stride; an extra point is added by StackDumpAll() */ 708 laststridesize = tjsch->total_steps%tjsch->stride; 709 if (!laststridesize) laststridesize = tjsch->stride; 710 711 if (!tjsch->recompute) { 712 ierr = TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done);CHKERRQ(ierr); 713 if (!tjsch->save_stack && stepnum < tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 714 } 715 if (!stack->solution_only && localstepnum == 0) PetscFunctionReturn(0); /* skip last point in each stride at recompute stage or last stride */ 716 if (stack->solution_only && localstepnum == tjsch->stride-1) PetscFunctionReturn(0); /* skip last step in each stride at recompute stage or last stride */ 717 718 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 719 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 720 ierr = StackPush(stack,e);CHKERRQ(ierr); 721 PetscFunctionReturn(0); 722 } 723 724 static PetscErrorCode GetTrajTLNR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 725 { 726 Stack *stack = &tjsch->stack; 727 PetscInt id,localstepnum,laststridesize; 728 StackElement e; 729 PetscErrorCode ierr; 730 731 PetscFunctionBegin; 732 if (stepnum == tjsch->total_steps) { 733 ierr = TurnBackward(ts);CHKERRQ(ierr); 734 PetscFunctionReturn(0); 735 } 736 737 localstepnum = stepnum%tjsch->stride; 738 laststridesize = tjsch->total_steps%tjsch->stride; 739 if (!laststridesize) laststridesize = tjsch->stride; 740 if (stack->solution_only) { 741 /* fill stack with info */ 742 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 743 id = stepnum/tjsch->stride; 744 if (tjsch->save_stack) { 745 ierr = StackLoadAll(tj,ts,stack,id);CHKERRQ(ierr); 746 tjsch->skip_trajectory = PETSC_TRUE; 747 ierr = TurnForward(ts);CHKERRQ(ierr); 748 ierr = ReCompute(ts,tjsch,id*tjsch->stride-1,id*tjsch->stride);CHKERRQ(ierr); 749 tjsch->skip_trajectory = PETSC_FALSE; 750 } else { 751 ierr = LoadSingle(tj,ts,stack,id);CHKERRQ(ierr); 752 ierr = TurnForward(ts);CHKERRQ(ierr); 753 ierr = ReCompute(ts,tjsch,(id-1)*tjsch->stride,id*tjsch->stride);CHKERRQ(ierr); 754 } 755 PetscFunctionReturn(0); 756 } 757 /* restore a checkpoint */ 758 ierr = StackPop(stack,&e);CHKERRQ(ierr); 759 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 760 tjsch->skip_trajectory = PETSC_TRUE; 761 ierr = TurnForward(ts);CHKERRQ(ierr); 762 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 763 tjsch->skip_trajectory = PETSC_FALSE; 764 } else { 765 /* fill stack with info */ 766 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 767 id = stepnum/tjsch->stride; 768 if (tjsch->save_stack) { 769 ierr = StackLoadAll(tj,ts,stack,id);CHKERRQ(ierr); 770 } else { 771 ierr = LoadSingle(tj,ts,stack,id);CHKERRQ(ierr); 772 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 773 ierr = ElementSet(ts,stack,&e,(id-1)*tjsch->stride+1,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 774 ierr = StackPush(stack,e);CHKERRQ(ierr); 775 ierr = TurnForward(ts);CHKERRQ(ierr); 776 ierr = ReCompute(ts,tjsch,e->stepnum,id*tjsch->stride);CHKERRQ(ierr); 777 } 778 PetscFunctionReturn(0); 779 } 780 /* restore a checkpoint */ 781 ierr = StackPop(stack,&e);CHKERRQ(ierr); 782 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 783 } 784 PetscFunctionReturn(0); 785 } 786 787 #if defined(PETSC_HAVE_REVOLVE) 788 static PetscErrorCode printwhattodo(PetscViewer viewer,PetscRevolveInt whattodo,RevolveCTX *rctx,PetscRevolveInt shift) 789 { 790 PetscErrorCode ierr; 791 792 PetscFunctionBegin; 793 if (!viewer) PetscFunctionReturn(0); 794 795 switch(whattodo) { 796 case 1: 797 ierr = PetscViewerASCIIPrintf(viewer,"Advance from %D to %D\n",rctx->oldcapo+shift,rctx->capo+shift);CHKERRQ(ierr); 798 break; 799 case 2: 800 ierr = PetscViewerASCIIPrintf(viewer,"Store in checkpoint number %D (located in RAM)\n",rctx->check);CHKERRQ(ierr); 801 break; 802 case 3: 803 ierr = PetscViewerASCIIPrintf(viewer,"First turn: Initialize adjoints and reverse first step\n");CHKERRQ(ierr); 804 break; 805 case 4: 806 ierr = PetscViewerASCIIPrintf(viewer,"Forward and reverse one step\n");CHKERRQ(ierr); 807 break; 808 case 5: 809 ierr = PetscViewerASCIIPrintf(viewer,"Restore in checkpoint number %D (located in RAM)\n",rctx->check);CHKERRQ(ierr); 810 break; 811 case 7: 812 ierr = PetscViewerASCIIPrintf(viewer,"Store in checkpoint number %D (located on disk)\n",rctx->check);CHKERRQ(ierr); 813 break; 814 case 8: 815 ierr = PetscViewerASCIIPrintf(viewer,"Restore in checkpoint number %D (located on disk)\n",rctx->check);CHKERRQ(ierr); 816 break; 817 case -1: 818 ierr = PetscViewerASCIIPrintf(viewer,"Error!");CHKERRQ(ierr); 819 break; 820 } 821 PetscFunctionReturn(0); 822 } 823 824 static PetscErrorCode printwhattodo2(PetscViewer viewer,PetscRevolveInt whattodo,RevolveCTX *rctx,PetscRevolveInt shift) 825 { 826 PetscErrorCode ierr; 827 828 PetscFunctionBegin; 829 if (!viewer) PetscFunctionReturn(0); 830 831 switch(whattodo) { 832 case 1: 833 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Advance from stride %D to stride %D\n",rctx->oldcapo+shift,rctx->capo+shift);CHKERRQ(ierr); 834 break; 835 case 2: 836 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Store in checkpoint number %D\n",rctx->check);CHKERRQ(ierr); 837 break; 838 case 3: 839 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] First turn: Initialize adjoints and reverse first stride\n");CHKERRQ(ierr); 840 break; 841 case 4: 842 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Forward and reverse one stride\n");CHKERRQ(ierr); 843 break; 844 case 5: 845 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Restore in checkpoint number %D\n",rctx->check);CHKERRQ(ierr); 846 break; 847 case 7: 848 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Store in top-level checkpoint number %D\n",rctx->check);CHKERRQ(ierr); 849 break; 850 case 8: 851 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Restore in top-level checkpoint number %D\n",rctx->check);CHKERRQ(ierr); 852 break; 853 case -1: 854 ierr = PetscViewerASCIIPrintf(viewer,"[Top Level] Error!");CHKERRQ(ierr); 855 break; 856 } 857 PetscFunctionReturn(0); 858 } 859 860 static PetscErrorCode InitRevolve(PetscInt fine,PetscInt snaps,RevolveCTX *rctx) 861 { 862 PetscRevolveInt rsnaps,rfine; 863 PetscErrorCode ierr; 864 865 PetscFunctionBegin; 866 ierr = PetscRevolveIntCast(snaps,&rsnaps);CHKERRQ(ierr); 867 ierr = PetscRevolveIntCast(fine,&rfine);CHKERRQ(ierr); 868 revolve_reset(); 869 revolve_create_offline(rfine,rsnaps); 870 rctx->snaps_in = rsnaps; 871 rctx->fine = rfine; 872 rctx->check = 0; 873 rctx->capo = 0; 874 rctx->reverseonestep = PETSC_FALSE; 875 /* check stepsleft? */ 876 PetscFunctionReturn(0); 877 } 878 879 static PetscErrorCode FastForwardRevolve(RevolveCTX *rctx) 880 { 881 PetscRevolveInt whattodo; 882 883 PetscFunctionBegin; 884 whattodo = 0; 885 while (whattodo!=3) { /* we have to fast forward revolve to the beginning of the backward sweep due to unfriendly revolve interface */ 886 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 887 } 888 PetscFunctionReturn(0); 889 } 890 891 static PetscErrorCode ApplyRevolve(PetscViewer viewer,SchedulerType stype,RevolveCTX *rctx,PetscRevolveInt total_steps,PetscRevolveInt stepnum,PetscRevolveInt localstepnum,PetscBool toplevel,PetscInt *store) 892 { 893 PetscErrorCode ierr; 894 PetscRevolveInt shift,whattodo; 895 896 PetscFunctionBegin; 897 *store = 0; 898 if (rctx->stepsleft > 0) { /* advance the solution without checkpointing anything as Revolve requires */ 899 rctx->stepsleft--; 900 PetscFunctionReturn(0); 901 } 902 /* let Revolve determine what to do next */ 903 shift = stepnum-localstepnum; 904 rctx->oldcapo = rctx->capo; 905 rctx->capo = localstepnum; 906 907 if (!toplevel) whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 908 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 909 if (stype == REVOLVE_ONLINE && whattodo == 8) whattodo = 5; 910 if (stype == REVOLVE_ONLINE && whattodo == 7) whattodo = 2; 911 if (!toplevel) {ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 912 else {ierr = printwhattodo2(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 913 if (whattodo == -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in the Revolve library"); 914 if (whattodo == 1) { /* advance some time steps */ 915 if (stype == REVOLVE_ONLINE && rctx->capo >= total_steps-1) { 916 revolve_turn(total_steps,&rctx->capo,&rctx->fine); 917 if (!toplevel) {ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 918 else {ierr = printwhattodo2(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 919 } 920 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 921 } 922 if (whattodo == 3 || whattodo == 4) { /* ready for a reverse step */ 923 rctx->reverseonestep = PETSC_TRUE; 924 } 925 if (whattodo == 5) { /* restore a checkpoint and ask Revolve what to do next */ 926 rctx->oldcapo = rctx->capo; 927 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*/ 928 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 929 if (!toplevel) {ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 930 else {ierr = printwhattodo2(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 931 if (whattodo == 3 || whattodo == 4) rctx->reverseonestep = PETSC_TRUE; 932 if (whattodo == 1) rctx->stepsleft = rctx->capo-rctx->oldcapo; 933 } 934 if (whattodo == 7) { /* save the checkpoint to disk */ 935 *store = 2; 936 rctx->oldcapo = rctx->capo; 937 whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1 */ 938 ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr); 939 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 940 } 941 if (whattodo == 2) { /* store a checkpoint to RAM and ask Revolve how many time steps to advance next */ 942 *store = 1; 943 rctx->oldcapo = rctx->capo; 944 if (!toplevel) whattodo = revolve_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); /* must return 1 */ 945 else whattodo = revolve2_action(&rctx->check,&rctx->capo,&rctx->fine,rctx->snaps_in,&rctx->info,&rctx->where); 946 if (!toplevel) {ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 947 else {ierr = printwhattodo2(viewer,whattodo,rctx,shift);CHKERRQ(ierr);} 948 if (stype == REVOLVE_ONLINE && rctx->capo >= total_steps-1) { 949 revolve_turn(total_steps,&rctx->capo,&rctx->fine); 950 ierr = printwhattodo(viewer,whattodo,rctx,shift);CHKERRQ(ierr); 951 } 952 rctx->stepsleft = rctx->capo-rctx->oldcapo-1; 953 } 954 PetscFunctionReturn(0); 955 } 956 957 static PetscErrorCode SetTrajROF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 958 { 959 Stack *stack = &tjsch->stack; 960 PetscInt store; 961 StackElement e; 962 PetscRevolveInt rtotal_steps,rstepnum; 963 PetscErrorCode ierr; 964 965 PetscFunctionBegin; 966 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 967 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 968 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 969 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 970 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 971 if (store == 1) { 972 if (stepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 973 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 974 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 975 ierr = StackPush(stack,e);CHKERRQ(ierr); 976 } 977 PetscFunctionReturn(0); 978 } 979 980 static PetscErrorCode GetTrajROF(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 981 { 982 Stack *stack = &tjsch->stack; 983 PetscInt store; 984 PetscRevolveInt whattodo,shift,rtotal_steps,rstepnum; 985 StackElement e; 986 PetscErrorCode ierr; 987 988 PetscFunctionBegin; 989 if (stepnum == 0 || stepnum == tjsch->total_steps) { 990 ierr = TurnBackward(ts);CHKERRQ(ierr); 991 tjsch->rctx->reverseonestep = PETSC_FALSE; 992 PetscFunctionReturn(0); 993 } 994 /* restore a checkpoint */ 995 ierr = StackTop(stack,&e);CHKERRQ(ierr); 996 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 997 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 998 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 999 if (stack->solution_only) { /* start with restoring a checkpoint */ 1000 tjsch->rctx->capo = rstepnum; 1001 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1002 shift = 0; 1003 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1004 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1005 } else { /* 2 revolve actions: restore a checkpoint and then advance */ 1006 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1007 if (tj->monitor) { 1008 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1009 ierr = PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1);CHKERRQ(ierr); 1010 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1011 } 1012 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1013 } 1014 if (stack->solution_only || (!stack->solution_only && e->stepnum < stepnum)) { 1015 ierr = TurnForward(ts);CHKERRQ(ierr); 1016 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1017 } 1018 if ((stack->solution_only && e->stepnum+1 == stepnum) || (!stack->solution_only && e->stepnum == stepnum)) { 1019 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1020 } 1021 tjsch->rctx->reverseonestep = PETSC_FALSE; 1022 PetscFunctionReturn(0); 1023 } 1024 1025 static PetscErrorCode SetTrajRON(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1026 { 1027 Stack *stack = &tjsch->stack; 1028 Vec *Y; 1029 PetscInt i,store; 1030 PetscReal timeprev; 1031 StackElement e; 1032 RevolveCTX *rctx = tjsch->rctx; 1033 PetscRevolveInt rtotal_steps,rstepnum; 1034 PetscErrorCode ierr; 1035 1036 PetscFunctionBegin; 1037 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1038 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1039 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1040 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1041 ierr = ApplyRevolve(tj->monitor,tjsch->stype,rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1042 if (store == 1) { 1043 if (rctx->check != stack->top+1) { /* overwrite some non-top checkpoint in the stack */ 1044 ierr = StackFind(stack,&e,rctx->check);CHKERRQ(ierr); 1045 ierr = VecCopy(X,e->X);CHKERRQ(ierr); 1046 if (stack->numY > 0 && !stack->solution_only) { 1047 ierr = TSGetStages(ts,&stack->numY,&Y);CHKERRQ(ierr); 1048 for (i=0;i<stack->numY;i++) { 1049 ierr = VecCopy(Y[i],e->Y[i]);CHKERRQ(ierr); 1050 } 1051 } 1052 e->stepnum = stepnum; 1053 e->time = time; 1054 ierr = TSGetPrevTime(ts,&timeprev);CHKERRQ(ierr); 1055 e->timeprev = timeprev; 1056 } else { 1057 if (stepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1058 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1059 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 1060 ierr = StackPush(stack,e);CHKERRQ(ierr); 1061 } 1062 } 1063 PetscFunctionReturn(0); 1064 } 1065 1066 static PetscErrorCode GetTrajRON(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1067 { 1068 Stack *stack = &tjsch->stack; 1069 PetscRevolveInt whattodo,shift,rstepnum; 1070 StackElement e; 1071 PetscErrorCode ierr; 1072 1073 PetscFunctionBegin; 1074 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1075 ierr = TurnBackward(ts);CHKERRQ(ierr); 1076 tjsch->rctx->reverseonestep = PETSC_FALSE; 1077 PetscFunctionReturn(0); 1078 } 1079 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1080 tjsch->rctx->capo = rstepnum; 1081 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1082 shift = 0; 1083 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* whattodo=restore */ 1084 if (whattodo == 8) whattodo = 5; 1085 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1086 /* restore a checkpoint */ 1087 ierr = StackFind(stack,&e,tjsch->rctx->check);CHKERRQ(ierr); 1088 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1089 if (!stack->solution_only) { /* whattodo must be 5 */ 1090 /* ask Revolve what to do next */ 1091 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1092 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*/ 1093 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1094 if (whattodo == 3 || whattodo == 4) tjsch->rctx->reverseonestep = PETSC_TRUE; 1095 if (whattodo == 1) tjsch->rctx->stepsleft = tjsch->rctx->capo-tjsch->rctx->oldcapo; 1096 if (tj->monitor) { 1097 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1098 ierr = PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1);CHKERRQ(ierr); 1099 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1100 } 1101 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1102 } 1103 if (stack->solution_only || (!stack->solution_only && e->stepnum < stepnum)) { 1104 ierr = TurnForward(ts);CHKERRQ(ierr); 1105 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1106 } 1107 tjsch->rctx->reverseonestep = PETSC_FALSE; 1108 PetscFunctionReturn(0); 1109 } 1110 1111 static PetscErrorCode SetTrajTLR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1112 { 1113 Stack *stack = &tjsch->stack; 1114 PetscInt store,localstepnum,laststridesize; 1115 StackElement e; 1116 PetscBool done = PETSC_FALSE; 1117 PetscRevolveInt rtotal_steps,rstepnum,rlocalstepnum; 1118 PetscErrorCode ierr; 1119 1120 PetscFunctionBegin; 1121 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1122 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1123 1124 localstepnum = stepnum%tjsch->stride; 1125 laststridesize = tjsch->total_steps%tjsch->stride; 1126 if (!laststridesize) laststridesize = tjsch->stride; 1127 1128 if (!tjsch->recompute) { 1129 ierr = TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done);CHKERRQ(ierr); 1130 /* revolve is needed for the last stride; different starting points for last stride between solutin_only and !solutin_only */ 1131 if (!stack->solution_only && !tjsch->save_stack && stepnum <= tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 1132 if (stack->solution_only && !tjsch->save_stack && stepnum < tjsch->total_steps-laststridesize) PetscFunctionReturn(0); 1133 } 1134 if (tjsch->save_stack && done) { 1135 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1136 PetscFunctionReturn(0); 1137 } 1138 if (laststridesize < tjsch->stride) { 1139 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 */ 1140 ierr = InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1141 } 1142 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 */ 1143 ierr = InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1144 } 1145 } 1146 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1147 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1148 ierr = PetscRevolveIntCast(localstepnum,&rlocalstepnum);CHKERRQ(ierr); 1149 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1150 if (store == 1) { 1151 if (localstepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1152 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1153 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 1154 ierr = StackPush(stack,e);CHKERRQ(ierr); 1155 } 1156 PetscFunctionReturn(0); 1157 } 1158 1159 static PetscErrorCode GetTrajTLR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1160 { 1161 Stack *stack = &tjsch->stack; 1162 PetscRevolveInt whattodo,shift,rstepnum,rlocalstepnum,rtotal_steps; 1163 PetscInt localstepnum,stridenum,laststridesize,store; 1164 StackElement e; 1165 PetscErrorCode ierr; 1166 1167 PetscFunctionBegin; 1168 localstepnum = stepnum%tjsch->stride; 1169 stridenum = stepnum/tjsch->stride; 1170 if (stepnum == tjsch->total_steps) { 1171 ierr = TurnBackward(ts);CHKERRQ(ierr); 1172 tjsch->rctx->reverseonestep = PETSC_FALSE; 1173 PetscFunctionReturn(0); 1174 } 1175 laststridesize = tjsch->total_steps%tjsch->stride; 1176 if (!laststridesize) laststridesize = tjsch->stride; 1177 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1178 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1179 ierr = PetscRevolveIntCast(localstepnum,&rlocalstepnum);CHKERRQ(ierr); 1180 if (stack->solution_only) { 1181 /* fill stack */ 1182 if (localstepnum == 0 && stepnum <= tjsch->total_steps-laststridesize) { 1183 if (tjsch->save_stack) { 1184 ierr = StackLoadAll(tj,ts,stack,stridenum);CHKERRQ(ierr); 1185 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1186 ierr = FastForwardRevolve(tjsch->rctx);CHKERRQ(ierr); 1187 tjsch->skip_trajectory = PETSC_TRUE; 1188 ierr = TurnForward(ts);CHKERRQ(ierr); 1189 ierr = ReCompute(ts,tjsch,stridenum*tjsch->stride-1,stridenum*tjsch->stride);CHKERRQ(ierr); 1190 tjsch->skip_trajectory = PETSC_FALSE; 1191 } else { 1192 ierr = LoadSingle(tj,ts,stack,stridenum);CHKERRQ(ierr); 1193 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1194 ierr = TurnForward(ts);CHKERRQ(ierr); 1195 ierr = ReCompute(ts,tjsch,(stridenum-1)*tjsch->stride,stridenum*tjsch->stride);CHKERRQ(ierr); 1196 } 1197 PetscFunctionReturn(0); 1198 } 1199 /* restore a checkpoint */ 1200 ierr = StackTop(stack,&e);CHKERRQ(ierr); 1201 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1202 /* start with restoring a checkpoint */ 1203 tjsch->rctx->capo = rstepnum; 1204 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1205 shift = rstepnum-rlocalstepnum; 1206 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1207 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1208 ierr = TurnForward(ts);CHKERRQ(ierr); 1209 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1210 if (e->stepnum+1 == stepnum) { 1211 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1212 } 1213 } else { 1214 /* fill stack with info */ 1215 if (localstepnum == 0 && tjsch->total_steps-stepnum >= laststridesize) { 1216 if (tjsch->save_stack) { 1217 ierr = StackLoadAll(tj,ts,stack,stridenum);CHKERRQ(ierr); 1218 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1219 ierr = FastForwardRevolve(tjsch->rctx);CHKERRQ(ierr); 1220 } else { 1221 PetscRevolveInt rnum; 1222 ierr = LoadSingle(tj,ts,stack,stridenum);CHKERRQ(ierr); 1223 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1224 ierr = PetscRevolveIntCast((stridenum-1)*tjsch->stride+1,&rnum);CHKERRQ(ierr); 1225 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rnum,1,PETSC_FALSE,&store);CHKERRQ(ierr); 1226 if (tj->monitor) { 1227 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1228 ierr = 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);CHKERRQ(ierr); 1229 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1230 } 1231 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1232 ierr = ElementSet(ts,stack,&e,(stridenum-1)*tjsch->stride+1,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 1233 ierr = StackPush(stack,e);CHKERRQ(ierr); 1234 ierr = TurnForward(ts);CHKERRQ(ierr); 1235 ierr = ReCompute(ts,tjsch,e->stepnum,stridenum*tjsch->stride);CHKERRQ(ierr); 1236 } 1237 PetscFunctionReturn(0); 1238 } 1239 /* restore a checkpoint */ 1240 ierr = StackTop(stack,&e);CHKERRQ(ierr); 1241 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1242 /* 2 revolve actions: restore a checkpoint and then advance */ 1243 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1244 if (tj->monitor) { 1245 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1246 ierr = 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);CHKERRQ(ierr); 1247 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1248 } 1249 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1250 if (e->stepnum < stepnum) { 1251 ierr = TurnForward(ts);CHKERRQ(ierr); 1252 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1253 } 1254 if (e->stepnum == stepnum) { 1255 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1256 } 1257 } 1258 tjsch->rctx->reverseonestep = PETSC_FALSE; 1259 PetscFunctionReturn(0); 1260 } 1261 1262 static PetscErrorCode SetTrajTLTR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1263 { 1264 Stack *stack = &tjsch->stack; 1265 PetscInt store,localstepnum,stridenum,laststridesize; 1266 StackElement e; 1267 PetscBool done = PETSC_FALSE; 1268 PetscRevolveInt rlocalstepnum,rstepnum,rtotal_steps; 1269 PetscErrorCode ierr; 1270 1271 PetscFunctionBegin; 1272 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1273 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1274 1275 localstepnum = stepnum%tjsch->stride; /* index at the bottom level (inside a stride) */ 1276 stridenum = stepnum/tjsch->stride; /* index at the top level */ 1277 laststridesize = tjsch->total_steps%tjsch->stride; 1278 if (!laststridesize) laststridesize = tjsch->stride; 1279 if (stack->solution_only && localstepnum == 0 && !tjsch->rctx2->reverseonestep) { 1280 ierr = PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps);CHKERRQ(ierr); 1281 ierr = PetscRevolveIntCast(stridenum,&rstepnum);CHKERRQ(ierr); 1282 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride);CHKERRQ(ierr); 1283 if (laststridesize < tjsch->stride && stepnum == tjsch->total_steps-laststridesize) { 1284 ierr = InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1285 } 1286 } 1287 if (!stack->solution_only && localstepnum == 1 && !tjsch->rctx2->reverseonestep) { 1288 ierr = PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps);CHKERRQ(ierr); 1289 ierr = PetscRevolveIntCast(stridenum,&rstepnum);CHKERRQ(ierr); 1290 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride);CHKERRQ(ierr); 1291 if (laststridesize < tjsch->stride && stepnum == tjsch->total_steps-laststridesize+1) { 1292 ierr = InitRevolve(laststridesize,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1293 } 1294 } 1295 if (tjsch->store_stride) { 1296 ierr = TopLevelStore(tj,ts,tjsch,stepnum,localstepnum,laststridesize,&done);CHKERRQ(ierr); 1297 if (done) { 1298 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1299 PetscFunctionReturn(0); 1300 } 1301 } 1302 if (stepnum < tjsch->total_steps-laststridesize) { 1303 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 */ 1304 if (!tjsch->save_stack && !tjsch->rctx2->reverseonestep) PetscFunctionReturn(0); /* store operation does not require revolve be called at bottom level */ 1305 } 1306 /* 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 */ 1307 if (!stack->solution_only && localstepnum == 0 && stepnum != tjsch->total_steps && !tjsch->recompute) PetscFunctionReturn(0); 1308 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1309 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1310 ierr = PetscRevolveIntCast(localstepnum,&rlocalstepnum);CHKERRQ(ierr); 1311 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1312 if (store == 1) { 1313 if (localstepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1314 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1315 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 1316 ierr = StackPush(stack,e);CHKERRQ(ierr); 1317 } 1318 PetscFunctionReturn(0); 1319 } 1320 1321 static PetscErrorCode GetTrajTLTR(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1322 { 1323 Stack *stack = &tjsch->stack; 1324 DiskStack *diskstack = &tjsch->diskstack; 1325 PetscInt localstepnum,stridenum,restoredstridenum,laststridesize,store; 1326 StackElement e; 1327 PetscRevolveInt whattodo,shift; 1328 PetscRevolveInt rtotal_steps,rstepnum,rlocalstepnum; 1329 PetscErrorCode ierr; 1330 1331 PetscFunctionBegin; 1332 localstepnum = stepnum%tjsch->stride; 1333 stridenum = stepnum/tjsch->stride; 1334 if (stepnum == tjsch->total_steps) { 1335 ierr = TurnBackward(ts);CHKERRQ(ierr); 1336 tjsch->rctx->reverseonestep = PETSC_FALSE; 1337 PetscFunctionReturn(0); 1338 } 1339 laststridesize = tjsch->total_steps%tjsch->stride; 1340 if (!laststridesize) laststridesize = tjsch->stride; 1341 /* 1342 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: 1343 Case 1 (save_stack) 1344 Restore a disk checkpoint; update TS with the last element in the restored data; recompute to the current point. 1345 Case 2 (!save_stack) 1346 Restore a disk checkpoint; update TS with the restored point; recompute to the current point. 1347 */ 1348 if (localstepnum == 0 && stepnum <= tjsch->total_steps-laststridesize) { 1349 /* restore the top element in the stack for disk checkpoints */ 1350 restoredstridenum = diskstack->container[diskstack->top]; 1351 tjsch->rctx2->reverseonestep = PETSC_FALSE; 1352 /* top-level revolve must be applied before current step, just like the solution_only mode for single-level revolve */ 1353 if (!tjsch->save_stack && stack->solution_only) { /* start with restoring a checkpoint */ 1354 ierr = PetscRevolveIntCast(stridenum,&rstepnum);CHKERRQ(ierr); 1355 tjsch->rctx2->capo = rstepnum; 1356 tjsch->rctx2->oldcapo = tjsch->rctx2->capo; 1357 shift = 0; 1358 whattodo = revolve2_action(&tjsch->rctx2->check,&tjsch->rctx2->capo,&tjsch->rctx2->fine,tjsch->rctx2->snaps_in,&tjsch->rctx2->info,&tjsch->rctx2->where); 1359 ierr = printwhattodo2(tj->monitor,whattodo,tjsch->rctx2,shift);CHKERRQ(ierr); 1360 } else { /* 2 revolve actions: restore a checkpoint and then advance */ 1361 ierr = PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rtotal_steps);CHKERRQ(ierr); 1362 ierr = PetscRevolveIntCast(stridenum,&rstepnum);CHKERRQ(ierr); 1363 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx2,rtotal_steps,rstepnum,rstepnum,PETSC_TRUE,&tjsch->store_stride);CHKERRQ(ierr); 1364 if (tj->monitor) { 1365 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1366 ierr = PetscViewerASCIIPrintf(tj->monitor,"[Top Level] Skip the stride from %D to %D (stage values already checkpointed)\n",tjsch->rctx2->oldcapo,tjsch->rctx2->oldcapo+1);CHKERRQ(ierr); 1367 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1368 } 1369 if (!tjsch->rctx2->reverseonestep && tjsch->rctx2->stepsleft > 0) tjsch->rctx2->stepsleft--; 1370 } 1371 /* fill stack */ 1372 if (stack->solution_only) { 1373 if (tjsch->save_stack) { 1374 if (restoredstridenum < stridenum) { 1375 ierr = StackLoadLast(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1376 } else { 1377 ierr = StackLoadAll(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1378 } 1379 /* recompute one step ahead */ 1380 tjsch->skip_trajectory = PETSC_TRUE; 1381 ierr = TurnForward(ts);CHKERRQ(ierr); 1382 ierr = ReCompute(ts,tjsch,stridenum*tjsch->stride-1,stridenum*tjsch->stride);CHKERRQ(ierr); 1383 tjsch->skip_trajectory = PETSC_FALSE; 1384 if (restoredstridenum < stridenum) { 1385 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1386 ierr = TurnForward(ts);CHKERRQ(ierr); 1387 ierr = ReCompute(ts,tjsch,restoredstridenum*tjsch->stride,stepnum);CHKERRQ(ierr); 1388 } else { /* stack ready, fast forward revolve status */ 1389 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1390 ierr = FastForwardRevolve(tjsch->rctx);CHKERRQ(ierr); 1391 } 1392 } else { 1393 ierr = LoadSingle(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1394 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1395 ierr = TurnForward(ts);CHKERRQ(ierr); 1396 ierr = ReCompute(ts,tjsch,(restoredstridenum-1)*tjsch->stride,stepnum);CHKERRQ(ierr); 1397 } 1398 } else { 1399 if (tjsch->save_stack) { 1400 if (restoredstridenum < stridenum) { 1401 ierr = StackLoadLast(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1402 /* reset revolve */ 1403 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1404 ierr = TurnForward(ts);CHKERRQ(ierr); 1405 ierr = ReCompute(ts,tjsch,restoredstridenum*tjsch->stride,stepnum);CHKERRQ(ierr); 1406 } else { /* stack ready, fast forward revolve status */ 1407 ierr = StackLoadAll(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1408 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1409 ierr = FastForwardRevolve(tjsch->rctx);CHKERRQ(ierr); 1410 } 1411 } else { 1412 ierr = LoadSingle(tj,ts,stack,restoredstridenum);CHKERRQ(ierr); 1413 ierr = InitRevolve(tjsch->stride,tjsch->max_cps_ram,tjsch->rctx);CHKERRQ(ierr); 1414 /* push first element to stack */ 1415 if (tjsch->store_stride || tjsch->rctx2->reverseonestep) { 1416 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1417 ierr = PetscRevolveIntCast((restoredstridenum-1)*tjsch->stride+1,&rstepnum);CHKERRQ(ierr); 1418 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,1,PETSC_FALSE,&store);CHKERRQ(ierr); 1419 if (tj->monitor) { 1420 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1421 ierr = PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",(restoredstridenum-1)*tjsch->stride,(restoredstridenum-1)*tjsch->stride+1);CHKERRQ(ierr); 1422 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1423 } 1424 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1425 ierr = ElementSet(ts,stack,&e,(restoredstridenum-1)*tjsch->stride+1,ts->ptime,ts->vec_sol);CHKERRQ(ierr); 1426 ierr = StackPush(stack,e);CHKERRQ(ierr); 1427 } 1428 ierr = TurnForward(ts);CHKERRQ(ierr); 1429 ierr = ReCompute(ts,tjsch,(restoredstridenum-1)*tjsch->stride+1,stepnum);CHKERRQ(ierr); 1430 } 1431 } 1432 if (restoredstridenum == stridenum) diskstack->top--; 1433 tjsch->rctx->reverseonestep = PETSC_FALSE; 1434 PetscFunctionReturn(0); 1435 } 1436 1437 if (stack->solution_only) { 1438 /* restore a checkpoint */ 1439 ierr = StackTop(stack,&e);CHKERRQ(ierr); 1440 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1441 /* start with restoring a checkpoint */ 1442 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1443 ierr = PetscRevolveIntCast(localstepnum,&rlocalstepnum);CHKERRQ(ierr); 1444 tjsch->rctx->capo = rstepnum; 1445 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1446 shift = rstepnum-rlocalstepnum; 1447 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); 1448 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1449 ierr = TurnForward(ts);CHKERRQ(ierr); 1450 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1451 if (e->stepnum+1 == stepnum) { 1452 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1453 } 1454 } else { 1455 PetscRevolveInt rlocalstepnum; 1456 /* restore a checkpoint */ 1457 ierr = StackTop(stack,&e);CHKERRQ(ierr); 1458 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1459 /* 2 revolve actions: restore a checkpoint and then advance */ 1460 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1461 ierr = PetscRevolveIntCast(stridenum,&rstepnum);CHKERRQ(ierr); 1462 ierr = PetscRevolveIntCast(localstepnum,&rlocalstepnum);CHKERRQ(ierr); 1463 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rlocalstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1464 if (tj->monitor) { 1465 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1466 ierr = 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);CHKERRQ(ierr); 1467 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1468 } 1469 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1470 if (e->stepnum < stepnum) { 1471 ierr = TurnForward(ts);CHKERRQ(ierr); 1472 ierr = ReCompute(ts,tjsch,e->stepnum,stepnum);CHKERRQ(ierr); 1473 } 1474 if (e->stepnum == stepnum) { 1475 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1476 } 1477 } 1478 tjsch->rctx->reverseonestep = PETSC_FALSE; 1479 PetscFunctionReturn(0); 1480 } 1481 1482 static PetscErrorCode SetTrajRMS(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum,PetscReal time,Vec X) 1483 { 1484 Stack *stack = &tjsch->stack; 1485 PetscInt store; 1486 StackElement e; 1487 PetscRevolveInt rtotal_steps,rstepnum; 1488 PetscErrorCode ierr; 1489 1490 PetscFunctionBegin; 1491 if (!stack->solution_only && stepnum == 0) PetscFunctionReturn(0); 1492 if (stack->solution_only && stepnum == tjsch->total_steps) PetscFunctionReturn(0); 1493 ierr = PetscRevolveIntCast(tjsch->total_steps,&rtotal_steps);CHKERRQ(ierr); 1494 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1495 ierr = ApplyRevolve(tj->monitor,tjsch->stype,tjsch->rctx,rtotal_steps,rstepnum,rstepnum,PETSC_FALSE,&store);CHKERRQ(ierr); 1496 if (store == 1) { 1497 if (stepnum < stack->top) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_MEMC,"Illegal modification of a non-top stack element"); 1498 ierr = ElementCreate(ts,stack,&e);CHKERRQ(ierr); 1499 ierr = ElementSet(ts,stack,&e,stepnum,time,X);CHKERRQ(ierr); 1500 ierr = StackPush(stack,e);CHKERRQ(ierr); 1501 } else if (store == 2) { 1502 ierr = DumpSingle(tj,ts,stack,tjsch->rctx->check+1);CHKERRQ(ierr); 1503 } 1504 PetscFunctionReturn(0); 1505 } 1506 1507 static PetscErrorCode GetTrajRMS(TSTrajectory tj,TS ts,TJScheduler *tjsch,PetscInt stepnum) 1508 { 1509 Stack *stack = &tjsch->stack; 1510 PetscRevolveInt whattodo,shift,rstepnum; 1511 PetscInt restart; 1512 PetscBool ondisk; 1513 StackElement e; 1514 PetscErrorCode ierr; 1515 1516 PetscFunctionBegin; 1517 if (stepnum == 0 || stepnum == tjsch->total_steps) { 1518 ierr = TurnBackward(ts);CHKERRQ(ierr); 1519 tjsch->rctx->reverseonestep = PETSC_FALSE; 1520 PetscFunctionReturn(0); 1521 } 1522 ierr = PetscRevolveIntCast(stepnum,&rstepnum);CHKERRQ(ierr); 1523 tjsch->rctx->capo = rstepnum; 1524 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1525 shift = 0; 1526 whattodo = revolve_action(&tjsch->rctx->check,&tjsch->rctx->capo,&tjsch->rctx->fine,tjsch->rctx->snaps_in,&tjsch->rctx->info,&tjsch->rctx->where); /* whattodo=restore */ 1527 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1528 /* restore a checkpoint */ 1529 restart = tjsch->rctx->capo; 1530 if (!tjsch->rctx->where) { 1531 ondisk = PETSC_TRUE; 1532 ierr = LoadSingle(tj,ts,stack,tjsch->rctx->check+1);CHKERRQ(ierr); 1533 ierr = TurnBackward(ts);CHKERRQ(ierr); 1534 } else { 1535 ondisk = PETSC_FALSE; 1536 ierr = StackTop(stack,&e);CHKERRQ(ierr); 1537 ierr = UpdateTS(ts,stack,e,PETSC_TRUE);CHKERRQ(ierr); 1538 } 1539 if (!stack->solution_only) { /* whattodo must be 5 or 8 */ 1540 /* ask Revolve what to do next */ 1541 tjsch->rctx->oldcapo = tjsch->rctx->capo; 1542 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*/ 1543 ierr = printwhattodo(tj->monitor,whattodo,tjsch->rctx,shift);CHKERRQ(ierr); 1544 if (whattodo == 3 || whattodo == 4) tjsch->rctx->reverseonestep = PETSC_TRUE; 1545 if (whattodo == 1) tjsch->rctx->stepsleft = tjsch->rctx->capo-tjsch->rctx->oldcapo; 1546 if (tj->monitor) { 1547 ierr = PetscViewerASCIIAddTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1548 ierr = PetscViewerASCIIPrintf(tj->monitor,"Skip the step from %D to %D (stage values already checkpointed)\n",tjsch->rctx->oldcapo,tjsch->rctx->oldcapo+1);CHKERRQ(ierr); 1549 ierr = PetscViewerASCIISubtractTab(tj->monitor,((PetscObject)tj)->tablevel);CHKERRQ(ierr); 1550 } 1551 if (!tjsch->rctx->reverseonestep && tjsch->rctx->stepsleft > 0) tjsch->rctx->stepsleft--; 1552 restart++; /* skip one step */ 1553 } 1554 if (stack->solution_only || (!stack->solution_only && restart < stepnum)) { 1555 ierr = TurnForward(ts);CHKERRQ(ierr); 1556 ierr = ReCompute(ts,tjsch,restart,stepnum);CHKERRQ(ierr); 1557 } 1558 if (!ondisk && ( (stack->solution_only && e->stepnum+1 == stepnum) || (!stack->solution_only && e->stepnum == stepnum))) { 1559 ierr = StackPop(stack,&e);CHKERRQ(ierr); 1560 } 1561 tjsch->rctx->reverseonestep = PETSC_FALSE; 1562 PetscFunctionReturn(0); 1563 } 1564 #endif 1565 1566 static PetscErrorCode TSTrajectorySet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal time,Vec X) 1567 { 1568 TJScheduler *tjsch = (TJScheduler*)tj->data; 1569 PetscErrorCode ierr; 1570 1571 PetscFunctionBegin; 1572 if (!tjsch->recompute) { /* use global stepnum in the forward sweep */ 1573 ierr = TSGetStepNumber(ts,&stepnum);CHKERRQ(ierr); 1574 } 1575 /* for consistency */ 1576 if (!tjsch->recompute && stepnum == 0) ts->ptime_prev = ts->ptime-ts->time_step; 1577 switch (tjsch->stype) { 1578 case NONE: 1579 if (tj->adjoint_solve_mode) { 1580 ierr = SetTrajN(ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1581 } else { 1582 ierr = SetTrajN_2(ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1583 } 1584 break; 1585 case TWO_LEVEL_NOREVOLVE: 1586 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1587 ierr = SetTrajTLNR(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1588 break; 1589 #if defined(PETSC_HAVE_REVOLVE) 1590 case TWO_LEVEL_REVOLVE: 1591 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1592 ierr = SetTrajTLR(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1593 break; 1594 case TWO_LEVEL_TWO_REVOLVE: 1595 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1596 ierr = SetTrajTLTR(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1597 break; 1598 case REVOLVE_OFFLINE: 1599 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1600 ierr = SetTrajROF(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1601 break; 1602 case REVOLVE_ONLINE: 1603 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1604 ierr = SetTrajRON(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1605 break; 1606 case REVOLVE_MULTISTAGE: 1607 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1608 ierr = SetTrajRMS(tj,ts,tjsch,stepnum,time,X);CHKERRQ(ierr); 1609 break; 1610 #endif 1611 default: 1612 break; 1613 } 1614 PetscFunctionReturn(0); 1615 } 1616 1617 static PetscErrorCode TSTrajectoryGet_Memory(TSTrajectory tj,TS ts,PetscInt stepnum,PetscReal *t) 1618 { 1619 TJScheduler *tjsch = (TJScheduler*)tj->data; 1620 PetscErrorCode ierr; 1621 1622 PetscFunctionBegin; 1623 if (tj->adjoint_solve_mode && stepnum == 0) { 1624 ierr = TSTrajectoryReset(tj);CHKERRQ(ierr); /* reset TSTrajectory so users do not need to reset TSTrajectory */ 1625 PetscFunctionReturn(0); 1626 } 1627 switch (tjsch->stype) { 1628 case NONE: 1629 if (tj->adjoint_solve_mode) { 1630 ierr = GetTrajN(ts,tjsch,stepnum);CHKERRQ(ierr); 1631 } else { 1632 ierr = GetTrajN_2(ts,tjsch,stepnum);CHKERRQ(ierr); 1633 } 1634 break; 1635 case TWO_LEVEL_NOREVOLVE: 1636 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1637 ierr = GetTrajTLNR(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1638 break; 1639 #if defined(PETSC_HAVE_REVOLVE) 1640 case TWO_LEVEL_REVOLVE: 1641 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1642 ierr = GetTrajTLR(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1643 break; 1644 case TWO_LEVEL_TWO_REVOLVE: 1645 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1646 ierr = GetTrajTLTR(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1647 break; 1648 case REVOLVE_OFFLINE: 1649 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1650 ierr = GetTrajROF(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1651 break; 1652 case REVOLVE_ONLINE: 1653 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1654 ierr = GetTrajRON(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1655 break; 1656 case REVOLVE_MULTISTAGE: 1657 if (!tj->adjoint_solve_mode) SETERRQ(PetscObjectComm((PetscObject)tj),PETSC_ERR_SUP,"Not implemented"); 1658 ierr = GetTrajRMS(tj,ts,tjsch,stepnum);CHKERRQ(ierr); 1659 break; 1660 #endif 1661 default: 1662 break; 1663 } 1664 PetscFunctionReturn(0); 1665 } 1666 1667 PETSC_UNUSED static PetscErrorCode TSTrajectorySetStride_Memory(TSTrajectory tj,PetscInt stride) 1668 { 1669 TJScheduler *tjsch = (TJScheduler*)tj->data; 1670 1671 PetscFunctionBegin; 1672 tjsch->stride = stride; 1673 PetscFunctionReturn(0); 1674 } 1675 1676 PETSC_UNUSED static PetscErrorCode TSTrajectorySetMaxCpsRAM_Memory(TSTrajectory tj,PetscInt max_cps_ram) 1677 { 1678 TJScheduler *tjsch = (TJScheduler*)tj->data; 1679 1680 PetscFunctionBegin; 1681 tjsch->max_cps_ram = max_cps_ram; 1682 PetscFunctionReturn(0); 1683 } 1684 1685 PETSC_UNUSED static PetscErrorCode TSTrajectorySetMaxCpsDisk_Memory(TSTrajectory tj,PetscInt max_cps_disk) 1686 { 1687 TJScheduler *tjsch = (TJScheduler*)tj->data; 1688 1689 PetscFunctionBegin; 1690 tjsch->max_cps_disk = max_cps_disk; 1691 PetscFunctionReturn(0); 1692 } 1693 1694 #if defined(PETSC_HAVE_REVOLVE) 1695 PETSC_UNUSED static PetscErrorCode TSTrajectorySetRevolveOnline(TSTrajectory tj,PetscBool use_online) 1696 { 1697 TJScheduler *tjsch = (TJScheduler*)tj->data; 1698 1699 PetscFunctionBegin; 1700 tjsch->use_online = use_online; 1701 PetscFunctionReturn(0); 1702 } 1703 #endif 1704 1705 PETSC_UNUSED static PetscErrorCode TSTrajectorySetSaveStack(TSTrajectory tj,PetscBool save_stack) 1706 { 1707 TJScheduler *tjsch = (TJScheduler*)tj->data; 1708 1709 PetscFunctionBegin; 1710 tjsch->save_stack = save_stack; 1711 PetscFunctionReturn(0); 1712 } 1713 1714 PETSC_UNUSED static PetscErrorCode TSTrajectorySetUseDRAM(TSTrajectory tj,PetscBool use_dram) 1715 { 1716 TJScheduler *tjsch = (TJScheduler*)tj->data; 1717 1718 PetscFunctionBegin; 1719 tjsch->stack.use_dram = use_dram; 1720 PetscFunctionReturn(0); 1721 } 1722 1723 static PetscErrorCode TSTrajectorySetFromOptions_Memory(PetscOptionItems *PetscOptionsObject,TSTrajectory tj) 1724 { 1725 TJScheduler *tjsch = (TJScheduler*)tj->data; 1726 PetscErrorCode ierr; 1727 1728 PetscFunctionBegin; 1729 ierr = PetscOptionsHead(PetscOptionsObject,"Memory based TS trajectory options");CHKERRQ(ierr); 1730 { 1731 ierr = PetscOptionsInt("-ts_trajectory_max_cps_ram","Maximum number of checkpoints in RAM","TSTrajectorySetMaxCpsRAM_Memory",tjsch->max_cps_ram,&tjsch->max_cps_ram,NULL);CHKERRQ(ierr); 1732 ierr = PetscOptionsInt("-ts_trajectory_max_cps_disk","Maximum number of checkpoints on disk","TSTrajectorySetMaxCpsDisk_Memory",tjsch->max_cps_disk,&tjsch->max_cps_disk,NULL);CHKERRQ(ierr); 1733 ierr = PetscOptionsInt("-ts_trajectory_stride","Stride to save checkpoints to file","TSTrajectorySetStride_Memory",tjsch->stride,&tjsch->stride,NULL);CHKERRQ(ierr); 1734 #if defined(PETSC_HAVE_REVOLVE) 1735 ierr = PetscOptionsBool("-ts_trajectory_revolve_online","Trick TS trajectory into using online mode of revolve","TSTrajectorySetRevolveOnline",tjsch->use_online,&tjsch->use_online,NULL);CHKERRQ(ierr); 1736 #endif 1737 ierr = PetscOptionsBool("-ts_trajectory_save_stack","Save all stack to disk","TSTrajectorySetSaveStack",tjsch->save_stack,&tjsch->save_stack,NULL);CHKERRQ(ierr); 1738 ierr = PetscOptionsBool("-ts_trajectory_use_dram","Use DRAM for checkpointing","TSTrajectorySetUseDRAM",tjsch->stack.use_dram,&tjsch->stack.use_dram,NULL);CHKERRQ(ierr); 1739 } 1740 ierr = PetscOptionsTail();CHKERRQ(ierr); 1741 tjsch->stack.solution_only = tj->solution_only; 1742 PetscFunctionReturn(0); 1743 } 1744 1745 static PetscErrorCode TSTrajectorySetUp_Memory(TSTrajectory tj,TS ts) 1746 { 1747 TJScheduler *tjsch = (TJScheduler*)tj->data; 1748 Stack *stack = &tjsch->stack; 1749 #if defined(PETSC_HAVE_REVOLVE) 1750 RevolveCTX *rctx,*rctx2; 1751 DiskStack *diskstack = &tjsch->diskstack; 1752 PetscInt diskblocks; 1753 #endif 1754 PetscInt numY,total_steps; 1755 PetscBool fixedtimestep; 1756 PetscErrorCode ierr; 1757 1758 PetscFunctionBegin; 1759 if (ts->adapt) { 1760 ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&fixedtimestep);CHKERRQ(ierr); 1761 } else fixedtimestep = PETSC_TRUE; 1762 total_steps = (PetscInt)(PetscCeilReal((ts->max_time-ts->ptime)/ts->time_step)); 1763 total_steps = total_steps < 0 ? PETSC_MAX_INT : total_steps; 1764 if (fixedtimestep) tjsch->total_steps = PetscMin(ts->max_steps,total_steps); 1765 if (tjsch->max_cps_ram > 0) stack->stacksize = tjsch->max_cps_ram; 1766 1767 if (tjsch->stride > 1) { /* two level mode */ 1768 if (tjsch->save_stack && tjsch->max_cps_disk > 1 && tjsch->max_cps_disk <= tjsch->max_cps_ram) SETERRQ(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."); 1769 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 */ 1770 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 */ 1771 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 */ 1772 } else { /* single level mode */ 1773 if (fixedtimestep) { 1774 if (tjsch->max_cps_ram >= tjsch->total_steps-1 || tjsch->max_cps_ram < 1) tjsch->stype = NONE; /* checkpoint all */ 1775 else tjsch->stype = (tjsch->max_cps_disk>1) ? REVOLVE_MULTISTAGE : REVOLVE_OFFLINE; 1776 } else tjsch->stype = NONE; /* checkpoint all for adaptive time step */ 1777 #if defined(PETSC_HAVE_REVOLVE) 1778 if (tjsch->use_online) tjsch->stype = REVOLVE_ONLINE; /* trick into online (for testing purpose only) */ 1779 #endif 1780 } 1781 1782 if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 1783 #ifndef PETSC_HAVE_REVOLVE 1784 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."); 1785 #else 1786 PetscRevolveInt rfine,rsnaps,rsnaps2; 1787 switch (tjsch->stype) { 1788 case TWO_LEVEL_REVOLVE: 1789 ierr = PetscRevolveIntCast(tjsch->stride,&rfine);CHKERRQ(ierr); 1790 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1791 revolve_create_offline(rfine,rsnaps); 1792 break; 1793 case TWO_LEVEL_TWO_REVOLVE: 1794 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. */ 1795 diskstack->stacksize = diskblocks; 1796 ierr = PetscRevolveIntCast(tjsch->stride,&rfine);CHKERRQ(ierr); 1797 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1798 revolve_create_offline(rfine,rsnaps); 1799 ierr = PetscRevolveIntCast((tjsch->total_steps+tjsch->stride-1)/tjsch->stride,&rfine);CHKERRQ(ierr); 1800 ierr = PetscRevolveIntCast(diskblocks,&rsnaps);CHKERRQ(ierr); 1801 revolve2_create_offline(rfine,rsnaps); 1802 ierr = PetscNew(&rctx2);CHKERRQ(ierr); 1803 rctx2->snaps_in = rsnaps; 1804 rctx2->reverseonestep = PETSC_FALSE; 1805 rctx2->check = 0; 1806 rctx2->oldcapo = 0; 1807 rctx2->capo = 0; 1808 rctx2->info = 2; 1809 rctx2->fine = rfine; 1810 tjsch->rctx2 = rctx2; 1811 diskstack->top = -1; 1812 ierr = PetscMalloc1(diskstack->stacksize*sizeof(PetscInt),&diskstack->container);CHKERRQ(ierr); 1813 break; 1814 case REVOLVE_OFFLINE: 1815 ierr = PetscRevolveIntCast(tjsch->total_steps,&rfine);CHKERRQ(ierr); 1816 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1817 revolve_create_offline(rfine,rsnaps); 1818 break; 1819 case REVOLVE_ONLINE: 1820 stack->stacksize = tjsch->max_cps_ram; 1821 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1822 revolve_create_online(rsnaps); 1823 break; 1824 case REVOLVE_MULTISTAGE: 1825 ierr = PetscRevolveIntCast(tjsch->total_steps,&rfine);CHKERRQ(ierr); 1826 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1827 ierr = PetscRevolveIntCast(tjsch->max_cps_ram+tjsch->max_cps_disk,&rsnaps2);CHKERRQ(ierr); 1828 revolve_create_multistage(rfine,rsnaps2,rsnaps); 1829 break; 1830 default: 1831 break; 1832 } 1833 ierr = PetscNew(&rctx);CHKERRQ(ierr); 1834 ierr = PetscRevolveIntCast(tjsch->max_cps_ram,&rsnaps);CHKERRQ(ierr); 1835 rctx->snaps_in = rsnaps; /* for theta methods snaps_in=2*max_cps_ram */ 1836 rctx->reverseonestep = PETSC_FALSE; 1837 rctx->check = 0; 1838 rctx->oldcapo = 0; 1839 rctx->capo = 0; 1840 rctx->info = 2; 1841 if (tjsch->stride > 1) { 1842 ierr = PetscRevolveIntCast(tjsch->stride,&rfine);CHKERRQ(ierr); 1843 } else { 1844 ierr = PetscRevolveIntCast(tjsch->total_steps,&rfine);CHKERRQ(ierr); 1845 } 1846 rctx->fine = rfine; 1847 tjsch->rctx = rctx; 1848 if (tjsch->stype == REVOLVE_ONLINE) rctx->fine = -1; 1849 #endif 1850 } else { 1851 if (tjsch->stype == TWO_LEVEL_NOREVOLVE) stack->stacksize = tjsch->stride-1; /* need tjsch->stride-1 at most */ 1852 if (tjsch->stype == NONE) { 1853 if (fixedtimestep) stack->stacksize = stack->solution_only ? tjsch->total_steps : tjsch->total_steps-1; 1854 else { /* adaptive time step */ 1855 /* if max_cps_ram is not specified, use maximal allowed number of steps for stack size */ 1856 if (tjsch->max_cps_ram == -1) stack->stacksize = ts->max_steps < PETSC_MAX_INT ? ts->max_steps : 10000; 1857 tjsch->total_steps = stack->solution_only ? stack->stacksize : stack->stacksize+1; /* will be updated as time integration advances */ 1858 } 1859 } 1860 } 1861 1862 if ((tjsch->stype >= TWO_LEVEL_NOREVOLVE && tjsch->stype < REVOLVE_OFFLINE) || tjsch->stype == REVOLVE_MULTISTAGE) { /* these types need to use disk */ 1863 ierr = TSTrajectorySetUp_Basic(tj,ts);CHKERRQ(ierr); 1864 } 1865 1866 stack->stacksize = PetscMax(stack->stacksize,1); 1867 tjsch->recompute = PETSC_FALSE; 1868 ierr = TSGetStages(ts,&numY,PETSC_IGNORE);CHKERRQ(ierr); 1869 ierr = StackInit(stack,stack->stacksize,numY);CHKERRQ(ierr); 1870 PetscFunctionReturn(0); 1871 } 1872 1873 static PetscErrorCode TSTrajectoryReset_Memory(TSTrajectory tj) 1874 { 1875 #if defined(PETSC_HAVE_REVOLVE) 1876 TJScheduler *tjsch = (TJScheduler*)tj->data; 1877 PetscErrorCode ierr; 1878 1879 PetscFunctionBegin; 1880 if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 1881 revolve_reset(); 1882 if (tjsch->stype == TWO_LEVEL_TWO_REVOLVE) { 1883 revolve2_reset(); 1884 ierr = PetscFree(tjsch->diskstack.container);CHKERRQ(ierr); 1885 } 1886 } 1887 if (tjsch->stype > TWO_LEVEL_NOREVOLVE) { 1888 ierr = PetscFree(tjsch->rctx);CHKERRQ(ierr); 1889 ierr = PetscFree(tjsch->rctx2);CHKERRQ(ierr); 1890 } 1891 #else 1892 PetscFunctionBegin; 1893 #endif 1894 PetscFunctionReturn(0); 1895 } 1896 1897 static PetscErrorCode TSTrajectoryDestroy_Memory(TSTrajectory tj) 1898 { 1899 TJScheduler *tjsch = (TJScheduler*)tj->data; 1900 PetscErrorCode ierr; 1901 1902 PetscFunctionBegin; 1903 ierr = StackDestroy(&tjsch->stack);CHKERRQ(ierr); 1904 ierr = PetscViewerDestroy(&tjsch->viewer);CHKERRQ(ierr); 1905 ierr = PetscFree(tjsch);CHKERRQ(ierr); 1906 PetscFunctionReturn(0); 1907 } 1908 1909 /*MC 1910 TSTRAJECTORYMEMORY - Stores each solution of the ODE/ADE in memory 1911 1912 Level: intermediate 1913 1914 .seealso: TSTrajectoryCreate(), TS, TSTrajectorySetType() 1915 1916 M*/ 1917 PETSC_EXTERN PetscErrorCode TSTrajectoryCreate_Memory(TSTrajectory tj,TS ts) 1918 { 1919 TJScheduler *tjsch; 1920 PetscErrorCode ierr; 1921 1922 PetscFunctionBegin; 1923 tj->ops->set = TSTrajectorySet_Memory; 1924 tj->ops->get = TSTrajectoryGet_Memory; 1925 tj->ops->setup = TSTrajectorySetUp_Memory; 1926 tj->ops->setfromoptions = TSTrajectorySetFromOptions_Memory; 1927 tj->ops->reset = TSTrajectoryReset_Memory; 1928 tj->ops->destroy = TSTrajectoryDestroy_Memory; 1929 1930 ierr = PetscNew(&tjsch);CHKERRQ(ierr); 1931 tjsch->stype = NONE; 1932 tjsch->max_cps_ram = -1; /* -1 indicates that it is not set */ 1933 tjsch->max_cps_disk = -1; /* -1 indicates that it is not set */ 1934 tjsch->stride = 0; /* if not zero, two-level checkpointing will be used */ 1935 #if defined(PETSC_HAVE_REVOLVE) 1936 tjsch->use_online = PETSC_FALSE; 1937 #endif 1938 tjsch->save_stack = PETSC_TRUE; 1939 1940 tjsch->stack.solution_only = tj->solution_only; 1941 ierr = PetscViewerCreate(PetscObjectComm((PetscObject)tj),&tjsch->viewer);CHKERRQ(ierr); 1942 ierr = PetscViewerSetType(tjsch->viewer,PETSCVIEWERBINARY);CHKERRQ(ierr); 1943 ierr = PetscViewerPushFormat(tjsch->viewer,PETSC_VIEWER_NATIVE);CHKERRQ(ierr); 1944 ierr = PetscViewerFileSetMode(tjsch->viewer,FILE_MODE_WRITE);CHKERRQ(ierr); 1945 1946 tj->data = tjsch; 1947 PetscFunctionReturn(0); 1948 } 1949