1 /* 2 Code for timestepping with implicit Theta method 3 */ 4 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 5 #include <petscsnes.h> 6 #include <petscdm.h> 7 #include <petscmat.h> 8 9 typedef struct { 10 /* context for time stepping */ 11 PetscReal stage_time; 12 Vec Stages[2]; /* Storage for stage solutions */ 13 Vec X0,X,Xdot; /* Storage for u^n, u^n + dt a_{11} k_1, and time derivative u^{n+1}_t */ 14 Vec affine; /* Affine vector needed for residual at beginning of step in endpoint formulation */ 15 PetscReal Theta; 16 PetscReal shift; /* Shift parameter for SNES Jacobian, used by forward, TLM and adjoint */ 17 PetscInt order; 18 PetscBool endpoint; 19 PetscBool extrapolate; 20 TSStepStatus status; 21 Vec VecCostIntegral0; /* Backup for roll-backs due to events, used by cost integral */ 22 PetscReal ptime0; /* Backup for ts->ptime, the start time of current time step, used by TLM and cost integral */ 23 PetscReal time_step0; /* Backup for ts->timestep, the step size of current time step, used by TLM and cost integral*/ 24 25 /* context for sensitivity analysis */ 26 PetscInt num_tlm; /* Total number of tangent linear equations */ 27 Vec *VecsDeltaLam; /* Increment of the adjoint sensitivity w.r.t IC at stage */ 28 Vec *VecsDeltaMu; /* Increment of the adjoint sensitivity w.r.t P at stage */ 29 Vec *VecsSensiTemp; /* Vector to be multiplied with Jacobian transpose */ 30 Mat MatFwdStages[2]; /* TLM Stages */ 31 Mat MatDeltaFwdSensip; /* Increment of the forward sensitivity at stage */ 32 Vec VecDeltaFwdSensipCol; /* Working vector for holding one column of the sensitivity matrix */ 33 Mat MatFwdSensip0; /* backup for roll-backs due to events */ 34 Mat MatIntegralSensipTemp; /* Working vector for forward integral sensitivity */ 35 Mat MatIntegralSensip0; /* backup for roll-backs due to events */ 36 Vec *VecsDeltaLam2; /* Increment of the 2nd-order adjoint sensitivity w.r.t IC at stage */ 37 Vec *VecsDeltaMu2; /* Increment of the 2nd-order adjoint sensitivity w.r.t P at stage */ 38 Vec *VecsSensi2Temp; /* Working vectors that holds the residual for the second-order adjoint */ 39 Vec *VecsAffine; /* Working vectors to store residuals */ 40 /* context for error estimation */ 41 Vec vec_sol_prev; 42 Vec vec_lte_work; 43 } TS_Theta; 44 45 static PetscErrorCode TSThetaGetX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 46 { 47 TS_Theta *th = (TS_Theta*)ts->data; 48 PetscErrorCode ierr; 49 50 PetscFunctionBegin; 51 if (X0) { 52 if (dm && dm != ts->dm) { 53 ierr = DMGetNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 54 } else *X0 = ts->vec_sol; 55 } 56 if (Xdot) { 57 if (dm && dm != ts->dm) { 58 ierr = DMGetNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 59 } else *Xdot = th->Xdot; 60 } 61 PetscFunctionReturn(0); 62 } 63 64 static PetscErrorCode TSThetaRestoreX0AndXdot(TS ts,DM dm,Vec *X0,Vec *Xdot) 65 { 66 PetscErrorCode ierr; 67 68 PetscFunctionBegin; 69 if (X0) { 70 if (dm && dm != ts->dm) { 71 ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_X0",X0);CHKERRQ(ierr); 72 } 73 } 74 if (Xdot) { 75 if (dm && dm != ts->dm) { 76 ierr = DMRestoreNamedGlobalVector(dm,"TSTheta_Xdot",Xdot);CHKERRQ(ierr); 77 } 78 } 79 PetscFunctionReturn(0); 80 } 81 82 static PetscErrorCode DMCoarsenHook_TSTheta(DM fine,DM coarse,void *ctx) 83 { 84 PetscFunctionBegin; 85 PetscFunctionReturn(0); 86 } 87 88 static PetscErrorCode DMRestrictHook_TSTheta(DM fine,Mat restrct,Vec rscale,Mat inject,DM coarse,void *ctx) 89 { 90 TS ts = (TS)ctx; 91 PetscErrorCode ierr; 92 Vec X0,Xdot,X0_c,Xdot_c; 93 94 PetscFunctionBegin; 95 ierr = TSThetaGetX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 96 ierr = TSThetaGetX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 97 ierr = MatRestrict(restrct,X0,X0_c);CHKERRQ(ierr); 98 ierr = MatRestrict(restrct,Xdot,Xdot_c);CHKERRQ(ierr); 99 ierr = VecPointwiseMult(X0_c,rscale,X0_c);CHKERRQ(ierr); 100 ierr = VecPointwiseMult(Xdot_c,rscale,Xdot_c);CHKERRQ(ierr); 101 ierr = TSThetaRestoreX0AndXdot(ts,fine,&X0,&Xdot);CHKERRQ(ierr); 102 ierr = TSThetaRestoreX0AndXdot(ts,coarse,&X0_c,&Xdot_c);CHKERRQ(ierr); 103 PetscFunctionReturn(0); 104 } 105 106 static PetscErrorCode DMSubDomainHook_TSTheta(DM dm,DM subdm,void *ctx) 107 { 108 PetscFunctionBegin; 109 PetscFunctionReturn(0); 110 } 111 112 static PetscErrorCode DMSubDomainRestrictHook_TSTheta(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx) 113 { 114 TS ts = (TS)ctx; 115 PetscErrorCode ierr; 116 Vec X0,Xdot,X0_sub,Xdot_sub; 117 118 PetscFunctionBegin; 119 ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 120 ierr = TSThetaGetX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 121 122 ierr = VecScatterBegin(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 123 ierr = VecScatterEnd(gscat,X0,X0_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 124 125 ierr = VecScatterBegin(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 126 ierr = VecScatterEnd(gscat,Xdot,Xdot_sub,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 127 128 ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 129 ierr = TSThetaRestoreX0AndXdot(ts,subdm,&X0_sub,&Xdot_sub);CHKERRQ(ierr); 130 PetscFunctionReturn(0); 131 } 132 133 static PetscErrorCode TSThetaEvaluateCostIntegral(TS ts) 134 { 135 TS_Theta *th = (TS_Theta*)ts->data; 136 TS quadts = ts->quadraturets; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 if (th->endpoint) { 141 /* Evolve ts->vec_costintegral to compute integrals */ 142 if (th->Theta!=1.0) { 143 ierr = TSComputeRHSFunction(quadts,th->ptime0,th->X0,ts->vec_costintegrand);CHKERRQ(ierr); 144 ierr = VecAXPY(quadts->vec_sol,th->time_step0*(1.0-th->Theta),ts->vec_costintegrand);CHKERRQ(ierr); 145 } 146 ierr = TSComputeRHSFunction(quadts,ts->ptime,ts->vec_sol,ts->vec_costintegrand);CHKERRQ(ierr); 147 ierr = VecAXPY(quadts->vec_sol,th->time_step0*th->Theta,ts->vec_costintegrand);CHKERRQ(ierr); 148 } else { 149 ierr = TSComputeRHSFunction(quadts,th->stage_time,th->X,ts->vec_costintegrand);CHKERRQ(ierr); 150 ierr = VecAXPY(quadts->vec_sol,th->time_step0,ts->vec_costintegrand);CHKERRQ(ierr); 151 } 152 PetscFunctionReturn(0); 153 } 154 155 static PetscErrorCode TSForwardCostIntegral_Theta(TS ts) 156 { 157 TS_Theta *th = (TS_Theta*)ts->data; 158 TS quadts = ts->quadraturets; 159 PetscErrorCode ierr; 160 161 PetscFunctionBegin; 162 /* backup cost integral */ 163 ierr = VecCopy(quadts->vec_sol,th->VecCostIntegral0);CHKERRQ(ierr); 164 ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 165 PetscFunctionReturn(0); 166 } 167 168 static PetscErrorCode TSAdjointCostIntegral_Theta(TS ts) 169 { 170 TS_Theta *th = (TS_Theta*)ts->data; 171 PetscErrorCode ierr; 172 173 PetscFunctionBegin; 174 /* Like TSForwardCostIntegral(), the adjoint cost integral evaluation relies on ptime0 and time_step0. */ 175 th->ptime0 = ts->ptime + ts->time_step; 176 th->time_step0 = -ts->time_step; 177 ierr = TSThetaEvaluateCostIntegral(ts);CHKERRQ(ierr); 178 PetscFunctionReturn(0); 179 } 180 181 static PetscErrorCode TSTheta_SNESSolve(TS ts,Vec b,Vec x) 182 { 183 PetscInt nits,lits; 184 PetscErrorCode ierr; 185 186 PetscFunctionBegin; 187 ierr = SNESSolve(ts->snes,b,x);CHKERRQ(ierr); 188 ierr = SNESGetIterationNumber(ts->snes,&nits);CHKERRQ(ierr); 189 ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 190 ts->snes_its += nits; ts->ksp_its += lits; 191 PetscFunctionReturn(0); 192 } 193 194 static PetscErrorCode TSStep_Theta(TS ts) 195 { 196 TS_Theta *th = (TS_Theta*)ts->data; 197 PetscInt rejections = 0; 198 PetscBool stageok,accept = PETSC_TRUE; 199 PetscReal next_time_step = ts->time_step; 200 PetscErrorCode ierr; 201 202 PetscFunctionBegin; 203 if (!ts->steprollback) { 204 if (th->vec_sol_prev) { ierr = VecCopy(th->X0,th->vec_sol_prev);CHKERRQ(ierr); } 205 ierr = VecCopy(ts->vec_sol,th->X0);CHKERRQ(ierr); 206 } 207 208 th->status = TS_STEP_INCOMPLETE; 209 while (!ts->reason && th->status != TS_STEP_COMPLETE) { 210 th->shift = 1/(th->Theta*ts->time_step); 211 th->stage_time = ts->ptime + (th->endpoint ? (PetscReal)1 : th->Theta)*ts->time_step; 212 ierr = VecCopy(th->X0,th->X);CHKERRQ(ierr); 213 if (th->extrapolate && !ts->steprestart) { 214 ierr = VecAXPY(th->X,1/th->shift,th->Xdot);CHKERRQ(ierr); 215 } 216 if (th->endpoint) { /* This formulation assumes linear time-independent mass matrix */ 217 if (!th->affine) {ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr);} 218 ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 219 ierr = TSComputeIFunction(ts,ts->ptime,th->X0,th->Xdot,th->affine,PETSC_FALSE);CHKERRQ(ierr); 220 ierr = VecScale(th->affine,(th->Theta-1)/th->Theta);CHKERRQ(ierr); 221 } else if (th->affine) { /* Just in case th->endpoint is changed between calls to TSStep_Theta() */ 222 ierr = VecZeroEntries(th->affine);CHKERRQ(ierr); 223 } 224 ierr = TSPreStage(ts,th->stage_time);CHKERRQ(ierr); 225 ierr = TSTheta_SNESSolve(ts,th->affine,th->X);CHKERRQ(ierr); 226 ierr = TSPostStage(ts,th->stage_time,0,&th->X);CHKERRQ(ierr); 227 ierr = TSAdaptCheckStage(ts->adapt,ts,th->stage_time,th->X,&stageok);CHKERRQ(ierr); 228 if (!stageok) goto reject_step; 229 230 th->status = TS_STEP_PENDING; 231 if (th->endpoint) { 232 ierr = VecCopy(th->X,ts->vec_sol);CHKERRQ(ierr); 233 } else { 234 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 235 ierr = VecAXPY(ts->vec_sol,ts->time_step,th->Xdot);CHKERRQ(ierr); 236 } 237 ierr = TSAdaptChoose(ts->adapt,ts,ts->time_step,NULL,&next_time_step,&accept);CHKERRQ(ierr); 238 th->status = accept ? TS_STEP_COMPLETE : TS_STEP_INCOMPLETE; 239 if (!accept) { 240 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 241 ts->time_step = next_time_step; 242 goto reject_step; 243 } 244 245 if (ts->forward_solve || ts->costintegralfwd) { /* Save the info for the later use in cost integral evaluation */ 246 th->ptime0 = ts->ptime; 247 th->time_step0 = ts->time_step; 248 } 249 ts->ptime += ts->time_step; 250 ts->time_step = next_time_step; 251 break; 252 253 reject_step: 254 ts->reject++; accept = PETSC_FALSE; 255 if (!ts->reason && ++rejections > ts->max_reject && ts->max_reject >= 0) { 256 ts->reason = TS_DIVERGED_STEP_REJECTED; 257 ierr = PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,rejections);CHKERRQ(ierr); 258 } 259 } 260 PetscFunctionReturn(0); 261 } 262 263 static PetscErrorCode TSAdjointStepBEuler_Private(TS ts) 264 { 265 TS_Theta *th = (TS_Theta*)ts->data; 266 TS quadts = ts->quadraturets; 267 Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 268 Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 269 PetscInt nadj; 270 Mat J,Jpre,quadJ = NULL,quadJp = NULL; 271 KSP ksp; 272 PetscScalar *xarr; 273 TSEquationType eqtype; 274 PetscBool isexplicitode = PETSC_FALSE; 275 PetscReal adjoint_time_step; 276 PetscErrorCode ierr; 277 278 PetscFunctionBegin; 279 ierr = TSGetEquationType(ts,&eqtype);CHKERRQ(ierr); 280 if (eqtype == TS_EQ_ODE_EXPLICIT) { 281 isexplicitode = PETSC_TRUE; 282 VecsDeltaLam = ts->vecs_sensi; 283 VecsDeltaLam2 = ts->vecs_sensi2; 284 } 285 th->status = TS_STEP_INCOMPLETE; 286 ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 287 ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 288 if (quadts) { 289 ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 290 ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 291 } 292 293 th->stage_time = ts->ptime; 294 adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 295 296 /* Build RHS for first-order adjoint lambda_{n+1}/h + r_u^T(n+1) */ 297 if (quadts) { 298 ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 299 } 300 301 for (nadj=0; nadj<ts->numcost; nadj++) { 302 ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 303 ierr = VecScale(VecsSensiTemp[nadj],1./adjoint_time_step);CHKERRQ(ierr); /* lambda_{n+1}/h */ 304 if (quadJ) { 305 ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 306 ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 307 ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr); 308 ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 309 ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 310 } 311 } 312 313 /* Build LHS for first-order adjoint */ 314 th->shift = 1./adjoint_time_step; 315 ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 316 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 317 318 /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 319 for (nadj=0; nadj<ts->numcost; nadj++) { 320 KSPConvergedReason kspreason; 321 ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 322 ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 323 if (kspreason < 0) { 324 ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 325 ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 326 } 327 } 328 329 if (ts->vecs_sensi2) { /* U_{n+1} */ 330 /* Get w1 at t_{n+1} from TLM matrix */ 331 ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 332 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 333 /* lambda_s^T F_UU w_1 */ 334 ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 335 /* lambda_s^T F_UP w_2 */ 336 ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 337 for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 338 ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 339 ierr = VecScale(VecsSensi2Temp[nadj],1./adjoint_time_step);CHKERRQ(ierr); 340 ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 341 if (ts->vecs_fup) { 342 ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 343 } 344 } 345 /* Solve stage equation LHS X = RHS for second-order adjoint */ 346 for (nadj=0; nadj<ts->numcost; nadj++) { 347 KSPConvergedReason kspreason; 348 ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr); 349 ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 350 if (kspreason < 0) { 351 ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 352 ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 353 } 354 } 355 } 356 357 /* Update sensitivities, and evaluate integrals if there is any */ 358 if (!isexplicitode) { 359 th->shift = 0.0; 360 ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 361 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 362 ierr = MatScale(J,-1.);CHKERRQ(ierr); 363 for (nadj=0; nadj<ts->numcost; nadj++) { 364 /* Add f_U \lambda_s to the original RHS */ 365 ierr = MatMultTransposeAdd(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 366 ierr = VecScale(VecsSensiTemp[nadj],adjoint_time_step);CHKERRQ(ierr); 367 ierr = VecCopy(VecsSensiTemp[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 368 if (ts->vecs_sensi2) { 369 ierr = MatMultTransposeAdd(J,VecsDeltaLam2[nadj],VecsSensi2Temp[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 370 ierr = VecScale(VecsSensi2Temp[nadj],adjoint_time_step);CHKERRQ(ierr); 371 ierr = VecCopy(VecsSensi2Temp[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr); 372 } 373 } 374 } 375 if (ts->vecs_sensip) { 376 ierr = VecAXPBYPCZ(th->Xdot,-1./adjoint_time_step,1.0/adjoint_time_step,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 377 ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,1./adjoint_time_step,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); /* get -f_p */ 378 if (quadts) { 379 ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 380 } 381 if (ts->vecs_sensi2p) { 382 /* lambda_s^T F_PU w_1 */ 383 ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 384 /* lambda_s^T F_PP w_2 */ 385 ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 386 } 387 388 for (nadj=0; nadj<ts->numcost; nadj++) { 389 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 390 ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 391 if (quadJp) { 392 ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 393 ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 394 ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr); 395 ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 396 ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 397 } 398 if (ts->vecs_sensi2p) { 399 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 400 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,VecsDeltaMu2[nadj]);CHKERRQ(ierr); 401 if (ts->vecs_fpu) { 402 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpu[nadj]);CHKERRQ(ierr); 403 } 404 if (ts->vecs_fpp) { 405 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step,ts->vecs_fpp[nadj]);CHKERRQ(ierr); 406 } 407 } 408 } 409 } 410 411 if (ts->vecs_sensi2) { 412 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 413 ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 414 } 415 th->status = TS_STEP_COMPLETE; 416 PetscFunctionReturn(0); 417 } 418 419 static PetscErrorCode TSAdjointStep_Theta(TS ts) 420 { 421 TS_Theta *th = (TS_Theta*)ts->data; 422 TS quadts = ts->quadraturets; 423 Vec *VecsDeltaLam = th->VecsDeltaLam,*VecsDeltaMu = th->VecsDeltaMu,*VecsSensiTemp = th->VecsSensiTemp; 424 Vec *VecsDeltaLam2 = th->VecsDeltaLam2,*VecsDeltaMu2 = th->VecsDeltaMu2,*VecsSensi2Temp = th->VecsSensi2Temp; 425 PetscInt nadj; 426 Mat J,Jpre,quadJ = NULL,quadJp = NULL; 427 KSP ksp; 428 PetscScalar *xarr; 429 PetscReal adjoint_time_step; 430 PetscReal adjoint_ptime; /* end time of the adjoint time step (ts->ptime is the start time, ususally ts->ptime is larger than adjoint_ptime) */ 431 PetscErrorCode ierr; 432 433 PetscFunctionBegin; 434 if (th->Theta == 1.) { 435 ierr = TSAdjointStepBEuler_Private(ts);CHKERRQ(ierr); 436 PetscFunctionReturn(0); 437 } 438 th->status = TS_STEP_INCOMPLETE; 439 ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 440 ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 441 if (quadts) { 442 ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 443 ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 444 } 445 /* If endpoint=1, th->ptime and th->X0 will be used; if endpoint=0, th->stage_time and th->X will be used. */ 446 th->stage_time = th->endpoint ? ts->ptime : (ts->ptime+(1.-th->Theta)*ts->time_step); 447 adjoint_ptime = ts->ptime + ts->time_step; 448 adjoint_time_step = -ts->time_step; /* always positive since time_step is negative */ 449 450 if (!th->endpoint) { 451 /* recover th->X0 using vec_sol and the stage value th->X */ 452 ierr = VecAXPBYPCZ(th->X0,1.0/(1.0-th->Theta),th->Theta/(th->Theta-1.0),0,th->X,ts->vec_sol);CHKERRQ(ierr); 453 } 454 455 /* Build RHS for first-order adjoint */ 456 /* Cost function has an integral term */ 457 if (quadts) { 458 if (th->endpoint) { 459 ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 460 } else { 461 ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 462 } 463 } 464 465 for (nadj=0; nadj<ts->numcost; nadj++) { 466 ierr = VecCopy(ts->vecs_sensi[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 467 ierr = VecScale(VecsSensiTemp[nadj],1./(th->Theta*adjoint_time_step));CHKERRQ(ierr); 468 if (quadJ) { 469 ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 470 ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 471 ierr = VecAXPY(VecsSensiTemp[nadj],1.,ts->vec_drdu_col);CHKERRQ(ierr); 472 ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 473 ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 474 } 475 } 476 477 /* Build LHS for first-order adjoint */ 478 th->shift = 1./(th->Theta*adjoint_time_step); 479 if (th->endpoint) { 480 ierr = TSComputeSNESJacobian(ts,ts->vec_sol,J,Jpre);CHKERRQ(ierr); 481 } else { 482 ierr = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr); 483 } 484 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 485 486 /* Solve stage equation LHS*lambda_s = RHS for first-order adjoint */ 487 for (nadj=0; nadj<ts->numcost; nadj++) { 488 KSPConvergedReason kspreason; 489 ierr = KSPSolveTranspose(ksp,VecsSensiTemp[nadj],VecsDeltaLam[nadj]);CHKERRQ(ierr); 490 ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 491 if (kspreason < 0) { 492 ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 493 ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 1st-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 494 } 495 } 496 497 /* Second-order adjoint */ 498 if (ts->vecs_sensi2) { /* U_{n+1} */ 499 if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Operation not implemented in TS_Theta"); 500 /* Get w1 at t_{n+1} from TLM matrix */ 501 ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 502 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 503 /* lambda_s^T F_UU w_1 */ 504 ierr = TSComputeIHessianProductFunctionUU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 505 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 506 ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 507 /* lambda_s^T F_UP w_2 */ 508 ierr = TSComputeIHessianProductFunctionUP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 509 for (nadj=0; nadj<ts->numcost; nadj++) { /* compute the residual */ 510 ierr = VecCopy(ts->vecs_sensi2[nadj],VecsSensi2Temp[nadj]);CHKERRQ(ierr); 511 ierr = VecScale(VecsSensi2Temp[nadj],th->shift);CHKERRQ(ierr); 512 ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 513 if (ts->vecs_fup) { 514 ierr = VecAXPY(VecsSensi2Temp[nadj],-1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 515 } 516 } 517 /* Solve stage equation LHS X = RHS for second-order adjoint */ 518 for (nadj=0; nadj<ts->numcost; nadj++) { 519 KSPConvergedReason kspreason; 520 ierr = KSPSolveTranspose(ksp,VecsSensi2Temp[nadj],VecsDeltaLam2[nadj]);CHKERRQ(ierr); 521 ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 522 if (kspreason < 0) { 523 ts->reason = TSADJOINT_DIVERGED_LINEAR_SOLVE; 524 ierr = PetscInfo2(ts,"Step=%D, %Dth cost function, transposed linear solve fails, stopping 2nd-order adjoint solve\n",ts->steps,nadj);CHKERRQ(ierr); 525 } 526 } 527 } 528 529 /* Update sensitivities, and evaluate integrals if there is any */ 530 if (th->endpoint) { /* two-stage Theta methods with th->Theta!=1, th->Theta==1 leads to BEuler */ 531 th->shift = 1./((th->Theta-1.)*adjoint_time_step); 532 th->stage_time = adjoint_ptime; 533 ierr = TSComputeSNESJacobian(ts,th->X0,J,Jpre);CHKERRQ(ierr); 534 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 535 /* R_U at t_n */ 536 if (quadts) { 537 ierr = TSComputeRHSJacobian(quadts,adjoint_ptime,th->X0,quadJ,NULL);CHKERRQ(ierr); 538 } 539 for (nadj=0; nadj<ts->numcost; nadj++) { 540 ierr = MatMultTranspose(J,VecsDeltaLam[nadj],ts->vecs_sensi[nadj]);CHKERRQ(ierr); 541 if (quadJ) { 542 ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 543 ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 544 ierr = VecAXPY(ts->vecs_sensi[nadj],-1.,ts->vec_drdu_col);CHKERRQ(ierr); 545 ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 546 ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 547 } 548 ierr = VecScale(ts->vecs_sensi[nadj],1./th->shift);CHKERRQ(ierr); 549 } 550 551 /* Second-order adjoint */ 552 if (ts->vecs_sensi2) { /* U_n */ 553 /* Get w1 at t_n from TLM matrix */ 554 ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr); 555 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 556 /* lambda_s^T F_UU w_1 */ 557 ierr = TSComputeIHessianProductFunctionUU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fuu);CHKERRQ(ierr); 558 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 559 ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr); 560 /* lambda_s^T F_UU w_2 */ 561 ierr = TSComputeIHessianProductFunctionUP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fup);CHKERRQ(ierr); 562 for (nadj=0; nadj<ts->numcost; nadj++) { 563 /* M^T Lambda_s + h(1-theta) F_U^T Lambda_s + h(1-theta) lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2 */ 564 ierr = MatMultTranspose(J,VecsDeltaLam2[nadj],ts->vecs_sensi2[nadj]);CHKERRQ(ierr); 565 ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fuu[nadj]);CHKERRQ(ierr); 566 if (ts->vecs_fup) { 567 ierr = VecAXPY(ts->vecs_sensi2[nadj],1.,ts->vecs_fup[nadj]);CHKERRQ(ierr); 568 } 569 ierr = VecScale(ts->vecs_sensi2[nadj],1./th->shift);CHKERRQ(ierr); 570 } 571 } 572 573 th->stage_time = ts->ptime; /* recover the old value */ 574 575 if (ts->vecs_sensip) { /* sensitivities wrt parameters */ 576 /* U_{n+1} */ 577 th->shift = 1.0/(adjoint_time_step*th->Theta); 578 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 579 ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,-1./(th->Theta*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 580 if (quadts) { 581 ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 582 } 583 for (nadj=0; nadj<ts->numcost; nadj++) { 584 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 585 ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu[nadj]);CHKERRQ(ierr); 586 if (quadJp) { 587 ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 588 ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 589 ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*th->Theta,ts->vec_drdp_col);CHKERRQ(ierr); 590 ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 591 ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 592 } 593 } 594 if (ts->vecs_sensi2p) { /* second-order */ 595 /* Get w1 at t_{n+1} from TLM matrix */ 596 ierr = MatDenseGetColumn(ts->mat_sensip,0,&xarr);CHKERRQ(ierr); 597 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 598 /* lambda_s^T F_PU w_1 */ 599 ierr = TSComputeIHessianProductFunctionPU(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 600 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 601 ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 602 603 /* lambda_s^T F_PP w_2 */ 604 ierr = TSComputeIHessianProductFunctionPP(ts,th->stage_time,ts->vec_sol,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 605 for (nadj=0; nadj<ts->numcost; nadj++) { 606 /* Mu2 <- Mu2 + h theta F_P^T Lambda_s + h theta (lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2) */ 607 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 608 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,VecsDeltaMu2[nadj]);CHKERRQ(ierr); 609 if (ts->vecs_fpu) { 610 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpu[nadj]);CHKERRQ(ierr); 611 } 612 if (ts->vecs_fpp) { 613 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*th->Theta,ts->vecs_fpp[nadj]);CHKERRQ(ierr); 614 } 615 } 616 } 617 618 /* U_s */ 619 ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 620 ierr = TSComputeIJacobianP(ts,adjoint_ptime,th->X0,th->Xdot,1./((th->Theta-1.0)*adjoint_time_step),ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 621 if (quadts) { 622 ierr = TSComputeRHSJacobianP(quadts,adjoint_ptime,th->X0,quadJp);CHKERRQ(ierr); 623 } 624 for (nadj=0; nadj<ts->numcost; nadj++) { 625 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 626 ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu[nadj]);CHKERRQ(ierr); 627 if (quadJp) { 628 ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 629 ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 630 ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step*(1.0-th->Theta),ts->vec_drdp_col);CHKERRQ(ierr); 631 ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 632 ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 633 } 634 if (ts->vecs_sensi2p) { /* second-order */ 635 /* Get w1 at t_n from TLM matrix */ 636 ierr = MatDenseGetColumn(th->MatFwdSensip0,0,&xarr);CHKERRQ(ierr); 637 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 638 /* lambda_s^T F_PU w_1 */ 639 ierr = TSComputeIHessianProductFunctionPU(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_sensip_col,ts->vecs_fpu);CHKERRQ(ierr); 640 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 641 ierr = MatDenseRestoreColumn(th->MatFwdSensip0,&xarr);CHKERRQ(ierr); 642 /* lambda_s^T F_PP w_2 */ 643 ierr = TSComputeIHessianProductFunctionPP(ts,adjoint_ptime,th->X0,VecsDeltaLam,ts->vec_dir,ts->vecs_fpp);CHKERRQ(ierr); 644 for (nadj=0; nadj<ts->numcost; nadj++) { 645 /* Mu2 <- Mu2 + h(1-theta) F_P^T Lambda_s + h(1-theta) (lambda_s^T F_UU w_1 + lambda_s^T F_UP w_2) */ 646 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam2[nadj],VecsDeltaMu2[nadj]);CHKERRQ(ierr); 647 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),VecsDeltaMu2[nadj]);CHKERRQ(ierr); 648 if (ts->vecs_fpu) { 649 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpu[nadj]);CHKERRQ(ierr); 650 } 651 if (ts->vecs_fpp) { 652 ierr = VecAXPY(ts->vecs_sensi2p[nadj],-adjoint_time_step*(1.0-th->Theta),ts->vecs_fpp[nadj]);CHKERRQ(ierr); 653 } 654 } 655 } 656 } 657 } 658 } else { /* one-stage case */ 659 th->shift = 0.0; 660 ierr = TSComputeSNESJacobian(ts,th->X,J,Jpre);CHKERRQ(ierr); /* get -f_y */ 661 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 662 if (quadts) { 663 ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 664 } 665 for (nadj=0; nadj<ts->numcost; nadj++) { 666 ierr = MatMultTranspose(J,VecsDeltaLam[nadj],VecsSensiTemp[nadj]);CHKERRQ(ierr); 667 ierr = VecAXPY(ts->vecs_sensi[nadj],-adjoint_time_step,VecsSensiTemp[nadj]);CHKERRQ(ierr); 668 if (quadJ) { 669 ierr = MatDenseGetColumn(quadJ,nadj,&xarr);CHKERRQ(ierr); 670 ierr = VecPlaceArray(ts->vec_drdu_col,xarr);CHKERRQ(ierr); 671 ierr = VecAXPY(ts->vecs_sensi[nadj],adjoint_time_step,ts->vec_drdu_col);CHKERRQ(ierr); 672 ierr = VecResetArray(ts->vec_drdu_col);CHKERRQ(ierr); 673 ierr = MatDenseRestoreColumn(quadJ,&xarr);CHKERRQ(ierr); 674 } 675 } 676 if (ts->vecs_sensip) { 677 th->shift = 1.0/(adjoint_time_step*th->Theta); 678 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 679 ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 680 if (quadts) { 681 ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr); 682 } 683 for (nadj=0; nadj<ts->numcost; nadj++) { 684 ierr = MatMultTranspose(ts->Jacp,VecsDeltaLam[nadj],VecsDeltaMu[nadj]);CHKERRQ(ierr); 685 ierr = VecAXPY(ts->vecs_sensip[nadj],-adjoint_time_step,VecsDeltaMu[nadj]);CHKERRQ(ierr); 686 if (quadJp) { 687 ierr = MatDenseGetColumn(quadJp,nadj,&xarr);CHKERRQ(ierr); 688 ierr = VecPlaceArray(ts->vec_drdp_col,xarr);CHKERRQ(ierr); 689 ierr = VecAXPY(ts->vecs_sensip[nadj],adjoint_time_step,ts->vec_drdp_col);CHKERRQ(ierr); 690 ierr = VecResetArray(ts->vec_drdp_col);CHKERRQ(ierr); 691 ierr = MatDenseRestoreColumn(quadJp,&xarr);CHKERRQ(ierr); 692 } 693 } 694 } 695 } 696 697 th->status = TS_STEP_COMPLETE; 698 PetscFunctionReturn(0); 699 } 700 701 static PetscErrorCode TSInterpolate_Theta(TS ts,PetscReal t,Vec X) 702 { 703 TS_Theta *th = (TS_Theta*)ts->data; 704 PetscReal dt = t - ts->ptime; 705 PetscErrorCode ierr; 706 707 PetscFunctionBegin; 708 ierr = VecCopy(ts->vec_sol,th->X);CHKERRQ(ierr); 709 if (th->endpoint) dt *= th->Theta; 710 ierr = VecWAXPY(X,dt,th->Xdot,th->X);CHKERRQ(ierr); 711 PetscFunctionReturn(0); 712 } 713 714 static PetscErrorCode TSEvaluateWLTE_Theta(TS ts,NormType wnormtype,PetscInt *order,PetscReal *wlte) 715 { 716 TS_Theta *th = (TS_Theta*)ts->data; 717 Vec X = ts->vec_sol; /* X = solution */ 718 Vec Y = th->vec_lte_work; /* Y = X + LTE */ 719 PetscReal wltea,wlter; 720 PetscErrorCode ierr; 721 722 PetscFunctionBegin; 723 if (!th->vec_sol_prev) {*wlte = -1; PetscFunctionReturn(0);} 724 /* Cannot compute LTE in first step or in restart after event */ 725 if (ts->steprestart) {*wlte = -1; PetscFunctionReturn(0);} 726 /* Compute LTE using backward differences with non-constant time step */ 727 { 728 PetscReal h = ts->time_step, h_prev = ts->ptime - ts->ptime_prev; 729 PetscReal a = 1 + h_prev/h; 730 PetscScalar scal[3]; Vec vecs[3]; 731 scal[0] = +1/a; scal[1] = -1/(a-1); scal[2] = +1/(a*(a-1)); 732 vecs[0] = X; vecs[1] = th->X0; vecs[2] = th->vec_sol_prev; 733 ierr = VecCopy(X,Y);CHKERRQ(ierr); 734 ierr = VecMAXPY(Y,3,scal,vecs);CHKERRQ(ierr); 735 ierr = TSErrorWeightedNorm(ts,X,Y,wnormtype,wlte,&wltea,&wlter);CHKERRQ(ierr); 736 } 737 if (order) *order = 2; 738 PetscFunctionReturn(0); 739 } 740 741 static PetscErrorCode TSRollBack_Theta(TS ts) 742 { 743 TS_Theta *th = (TS_Theta*)ts->data; 744 TS quadts = ts->quadraturets; 745 PetscErrorCode ierr; 746 747 PetscFunctionBegin; 748 ierr = VecCopy(th->X0,ts->vec_sol);CHKERRQ(ierr); 749 if (quadts && ts->costintegralfwd) { 750 ierr = VecCopy(th->VecCostIntegral0,quadts->vec_sol);CHKERRQ(ierr); 751 } 752 th->status = TS_STEP_INCOMPLETE; 753 if (ts->mat_sensip) { 754 ierr = MatCopy(th->MatFwdSensip0,ts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 755 } 756 if (quadts && quadts->mat_sensip) { 757 ierr = MatCopy(th->MatIntegralSensip0,quadts->mat_sensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 758 } 759 PetscFunctionReturn(0); 760 } 761 762 static PetscErrorCode TSForwardStep_Theta(TS ts) 763 { 764 TS_Theta *th = (TS_Theta*)ts->data; 765 TS quadts = ts->quadraturets; 766 Mat MatDeltaFwdSensip = th->MatDeltaFwdSensip; 767 Vec VecDeltaFwdSensipCol = th->VecDeltaFwdSensipCol; 768 PetscInt ntlm; 769 KSP ksp; 770 Mat J,Jpre,quadJ = NULL,quadJp = NULL; 771 PetscScalar *barr,*xarr; 772 PetscReal previous_shift; 773 PetscErrorCode ierr; 774 775 PetscFunctionBegin; 776 previous_shift = th->shift; 777 ierr = MatCopy(ts->mat_sensip,th->MatFwdSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 778 779 if (quadts && quadts->mat_sensip) { 780 ierr = MatCopy(quadts->mat_sensip,th->MatIntegralSensip0,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 781 } 782 ierr = SNESGetKSP(ts->snes,&ksp);CHKERRQ(ierr); 783 ierr = TSGetIJacobian(ts,&J,&Jpre,NULL,NULL);CHKERRQ(ierr); 784 if (quadts) { 785 ierr = TSGetRHSJacobian(quadts,&quadJ,NULL,NULL,NULL);CHKERRQ(ierr); 786 ierr = TSGetRHSJacobianP(quadts,&quadJp,NULL,NULL);CHKERRQ(ierr); 787 } 788 789 /* Build RHS */ 790 if (th->endpoint) { /* 2-stage method*/ 791 th->shift = 1./((th->Theta-1.)*th->time_step0); 792 ierr = TSComputeIJacobian(ts,th->ptime0,th->X0,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 793 ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr); 794 ierr = MatScale(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta);CHKERRQ(ierr); 795 796 /* Add the f_p forcing terms */ 797 if (ts->Jacp) { 798 ierr = VecZeroEntries(th->Xdot);CHKERRQ(ierr); 799 ierr = TSComputeIJacobianP(ts,th->ptime0,th->X0,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 800 ierr = MatAXPY(MatDeltaFwdSensip,(th->Theta-1.)/th->Theta,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 801 th->shift = previous_shift; 802 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,ts->vec_sol);CHKERRQ(ierr); 803 ierr = TSComputeIJacobianP(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 804 ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 805 } 806 } else { /* 1-stage method */ 807 th->shift = 0.0; 808 ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 809 ierr = MatMatMult(J,ts->mat_sensip,MAT_REUSE_MATRIX,PETSC_DEFAULT,&MatDeltaFwdSensip);CHKERRQ(ierr); 810 ierr = MatScale(MatDeltaFwdSensip,-1.);CHKERRQ(ierr); 811 812 /* Add the f_p forcing terms */ 813 if (ts->Jacp) { 814 th->shift = previous_shift; 815 ierr = VecAXPBYPCZ(th->Xdot,-th->shift,th->shift,0,th->X0,th->X);CHKERRQ(ierr); 816 ierr = TSComputeIJacobianP(ts,th->stage_time,th->X,th->Xdot,th->shift,ts->Jacp,PETSC_FALSE);CHKERRQ(ierr); 817 ierr = MatAXPY(MatDeltaFwdSensip,-1.,ts->Jacp,SUBSET_NONZERO_PATTERN);CHKERRQ(ierr); 818 } 819 } 820 821 /* Build LHS */ 822 th->shift = previous_shift; /* recover the previous shift used in TSStep_Theta() */ 823 if (th->endpoint) { 824 ierr = TSComputeIJacobian(ts,th->stage_time,ts->vec_sol,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 825 } else { 826 ierr = TSComputeIJacobian(ts,th->stage_time,th->X,th->Xdot,th->shift,J,Jpre,PETSC_FALSE);CHKERRQ(ierr); 827 } 828 ierr = KSPSetOperators(ksp,J,Jpre);CHKERRQ(ierr); 829 830 /* 831 Evaluate the first stage of integral gradients with the 2-stage method: 832 drdu|t_n*S(t_n) + drdp|t_n 833 This is done before the linear solve because the sensitivity variable S(t_n) will be propagated to S(t_{n+1}) 834 */ 835 if (th->endpoint) { /* 2-stage method only */ 836 if (quadts && quadts->mat_sensip) { 837 ierr = TSComputeRHSJacobian(quadts,th->ptime0,th->X0,quadJ,NULL);CHKERRQ(ierr); 838 ierr = TSComputeRHSJacobianP(quadts,th->ptime0,th->X0,quadJp);CHKERRQ(ierr); 839 ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 840 ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 841 ierr = MatAXPY(quadts->mat_sensip,th->time_step0*(1.-th->Theta),th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 842 } 843 } 844 845 /* Solve the tangent linear equation for forward sensitivities to parameters */ 846 for (ntlm=0; ntlm<th->num_tlm; ntlm++) { 847 KSPConvergedReason kspreason; 848 ierr = MatDenseGetColumn(MatDeltaFwdSensip,ntlm,&barr);CHKERRQ(ierr); 849 ierr = VecPlaceArray(VecDeltaFwdSensipCol,barr);CHKERRQ(ierr); 850 if (th->endpoint) { 851 ierr = MatDenseGetColumn(ts->mat_sensip,ntlm,&xarr);CHKERRQ(ierr); 852 ierr = VecPlaceArray(ts->vec_sensip_col,xarr);CHKERRQ(ierr); 853 ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,ts->vec_sensip_col);CHKERRQ(ierr); 854 ierr = VecResetArray(ts->vec_sensip_col);CHKERRQ(ierr); 855 ierr = MatDenseRestoreColumn(ts->mat_sensip,&xarr);CHKERRQ(ierr); 856 } else { 857 ierr = KSPSolve(ksp,VecDeltaFwdSensipCol,VecDeltaFwdSensipCol);CHKERRQ(ierr); 858 } 859 ierr = KSPGetConvergedReason(ksp,&kspreason);CHKERRQ(ierr); 860 if (kspreason < 0) { 861 ts->reason = TSFORWARD_DIVERGED_LINEAR_SOLVE; 862 ierr = PetscInfo2(ts,"Step=%D, %Dth tangent linear solve, linear solve fails, stopping tangent linear solve\n",ts->steps,ntlm);CHKERRQ(ierr); 863 } 864 ierr = VecResetArray(VecDeltaFwdSensipCol);CHKERRQ(ierr); 865 ierr = MatDenseRestoreColumn(MatDeltaFwdSensip,&barr);CHKERRQ(ierr); 866 } 867 868 /* 869 Evaluate the second stage of integral gradients with the 2-stage method: 870 drdu|t_{n+1}*S(t_{n+1}) + drdp|t_{n+1} 871 */ 872 if (quadts && quadts->mat_sensip) { 873 if (!th->endpoint) { 874 ierr = MatAXPY(ts->mat_sensip,1,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* stage sensitivity */ 875 ierr = TSComputeRHSJacobian(quadts,th->stage_time,th->X,quadJ,NULL);CHKERRQ(ierr); 876 ierr = TSComputeRHSJacobianP(quadts,th->stage_time,th->X,quadJp);CHKERRQ(ierr); 877 ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 878 ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 879 ierr = MatAXPY(quadts->mat_sensip,th->time_step0,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 880 ierr = MatAXPY(ts->mat_sensip,(1.-th->Theta)/th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 881 } else { 882 ierr = TSComputeRHSJacobian(quadts,th->stage_time,ts->vec_sol,quadJ,NULL);CHKERRQ(ierr); 883 ierr = TSComputeRHSJacobianP(quadts,th->stage_time,ts->vec_sol,quadJp);CHKERRQ(ierr); 884 ierr = MatTransposeMatMult(ts->mat_sensip,quadJ,MAT_REUSE_MATRIX,PETSC_DEFAULT,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 885 ierr = MatAXPY(th->MatIntegralSensipTemp,1,quadJp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 886 ierr = MatAXPY(quadts->mat_sensip,th->time_step0*th->Theta,th->MatIntegralSensipTemp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 887 } 888 } else { 889 if (!th->endpoint) { 890 ierr = MatAXPY(ts->mat_sensip,1./th->Theta,MatDeltaFwdSensip,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 891 } 892 } 893 PetscFunctionReturn(0); 894 } 895 896 static PetscErrorCode TSForwardGetStages_Theta(TS ts,PetscInt *ns,Mat *stagesensip[]) 897 { 898 TS_Theta *th = (TS_Theta*)ts->data; 899 900 PetscFunctionBegin; 901 if (ns) { 902 if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 903 else *ns = 2; /* endpoint form */ 904 } 905 if (stagesensip) { 906 if (!th->endpoint && th->Theta != 1.0) { 907 th->MatFwdStages[0] = th->MatDeltaFwdSensip; 908 } else { 909 th->MatFwdStages[0] = th->MatFwdSensip0; 910 th->MatFwdStages[1] = ts->mat_sensip; /* stiffly accurate */ 911 } 912 *stagesensip = th->MatFwdStages; 913 } 914 PetscFunctionReturn(0); 915 } 916 917 /*------------------------------------------------------------*/ 918 static PetscErrorCode TSReset_Theta(TS ts) 919 { 920 TS_Theta *th = (TS_Theta*)ts->data; 921 PetscErrorCode ierr; 922 923 PetscFunctionBegin; 924 ierr = VecDestroy(&th->X);CHKERRQ(ierr); 925 ierr = VecDestroy(&th->Xdot);CHKERRQ(ierr); 926 ierr = VecDestroy(&th->X0);CHKERRQ(ierr); 927 ierr = VecDestroy(&th->affine);CHKERRQ(ierr); 928 929 ierr = VecDestroy(&th->vec_sol_prev);CHKERRQ(ierr); 930 ierr = VecDestroy(&th->vec_lte_work);CHKERRQ(ierr); 931 932 ierr = VecDestroy(&th->VecCostIntegral0);CHKERRQ(ierr); 933 PetscFunctionReturn(0); 934 } 935 936 static PetscErrorCode TSAdjointReset_Theta(TS ts) 937 { 938 TS_Theta *th = (TS_Theta*)ts->data; 939 PetscErrorCode ierr; 940 941 PetscFunctionBegin; 942 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 943 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 944 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr); 945 ierr = VecDestroyVecs(ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr); 946 ierr = VecDestroyVecs(ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 947 ierr = VecDestroyVecs(ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr); 948 PetscFunctionReturn(0); 949 } 950 951 static PetscErrorCode TSDestroy_Theta(TS ts) 952 { 953 PetscErrorCode ierr; 954 955 PetscFunctionBegin; 956 ierr = TSReset_Theta(ts);CHKERRQ(ierr); 957 if (ts->dm) { 958 ierr = DMCoarsenHookRemove(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 959 ierr = DMSubDomainHookRemove(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 960 } 961 ierr = PetscFree(ts->data);CHKERRQ(ierr); 962 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",NULL);CHKERRQ(ierr); 963 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",NULL);CHKERRQ(ierr); 964 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",NULL);CHKERRQ(ierr); 965 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",NULL);CHKERRQ(ierr); 966 PetscFunctionReturn(0); 967 } 968 969 /* 970 This defines the nonlinear equation that is to be solved with SNES 971 G(U) = F[t0+Theta*dt, U, (U-U0)*shift] = 0 972 973 Note that U here is the stage argument. This means that U = U_{n+1} only if endpoint = true, 974 otherwise U = theta U_{n+1} + (1 - theta) U0, which for the case of implicit midpoint is 975 U = (U_{n+1} + U0)/2 976 */ 977 static PetscErrorCode SNESTSFormFunction_Theta(SNES snes,Vec x,Vec y,TS ts) 978 { 979 TS_Theta *th = (TS_Theta*)ts->data; 980 PetscErrorCode ierr; 981 Vec X0,Xdot; 982 DM dm,dmsave; 983 PetscReal shift = th->shift; 984 985 PetscFunctionBegin; 986 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 987 /* When using the endpoint variant, this is actually 1/Theta * Xdot */ 988 ierr = TSThetaGetX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 989 if (x != X0) { 990 ierr = VecAXPBYPCZ(Xdot,-shift,shift,0,X0,x);CHKERRQ(ierr); 991 } else { 992 ierr = VecZeroEntries(Xdot);CHKERRQ(ierr); 993 } 994 /* DM monkey-business allows user code to call TSGetDM() inside of functions evaluated on levels of FAS */ 995 dmsave = ts->dm; 996 ts->dm = dm; 997 ierr = TSComputeIFunction(ts,th->stage_time,x,Xdot,y,PETSC_FALSE);CHKERRQ(ierr); 998 ts->dm = dmsave; 999 ierr = TSThetaRestoreX0AndXdot(ts,dm,&X0,&Xdot);CHKERRQ(ierr); 1000 PetscFunctionReturn(0); 1001 } 1002 1003 static PetscErrorCode SNESTSFormJacobian_Theta(SNES snes,Vec x,Mat A,Mat B,TS ts) 1004 { 1005 TS_Theta *th = (TS_Theta*)ts->data; 1006 PetscErrorCode ierr; 1007 Vec Xdot; 1008 DM dm,dmsave; 1009 PetscReal shift = th->shift; 1010 1011 PetscFunctionBegin; 1012 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1013 /* Xdot has already been computed in SNESTSFormFunction_Theta (SNES guarantees this) */ 1014 ierr = TSThetaGetX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 1015 1016 dmsave = ts->dm; 1017 ts->dm = dm; 1018 ierr = TSComputeIJacobian(ts,th->stage_time,x,Xdot,shift,A,B,PETSC_FALSE);CHKERRQ(ierr); 1019 ts->dm = dmsave; 1020 ierr = TSThetaRestoreX0AndXdot(ts,dm,NULL,&Xdot);CHKERRQ(ierr); 1021 PetscFunctionReturn(0); 1022 } 1023 1024 static PetscErrorCode TSForwardSetUp_Theta(TS ts) 1025 { 1026 TS_Theta *th = (TS_Theta*)ts->data; 1027 TS quadts = ts->quadraturets; 1028 PetscErrorCode ierr; 1029 1030 PetscFunctionBegin; 1031 /* combine sensitivities to parameters and sensitivities to initial values into one array */ 1032 th->num_tlm = ts->num_parameters; 1033 ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatDeltaFwdSensip);CHKERRQ(ierr); 1034 if (quadts && quadts->mat_sensip) { 1035 ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensipTemp);CHKERRQ(ierr); 1036 ierr = MatDuplicate(quadts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatIntegralSensip0);CHKERRQ(ierr); 1037 } 1038 /* backup sensitivity results for roll-backs */ 1039 ierr = MatDuplicate(ts->mat_sensip,MAT_DO_NOT_COPY_VALUES,&th->MatFwdSensip0);CHKERRQ(ierr); 1040 1041 ierr = VecDuplicate(ts->vec_sol,&th->VecDeltaFwdSensipCol);CHKERRQ(ierr); 1042 PetscFunctionReturn(0); 1043 } 1044 1045 static PetscErrorCode TSForwardReset_Theta(TS ts) 1046 { 1047 TS_Theta *th = (TS_Theta*)ts->data; 1048 TS quadts = ts->quadraturets; 1049 PetscErrorCode ierr; 1050 1051 PetscFunctionBegin; 1052 if (quadts && quadts->mat_sensip) { 1053 ierr = MatDestroy(&th->MatIntegralSensipTemp);CHKERRQ(ierr); 1054 ierr = MatDestroy(&th->MatIntegralSensip0);CHKERRQ(ierr); 1055 } 1056 ierr = VecDestroy(&th->VecDeltaFwdSensipCol);CHKERRQ(ierr); 1057 ierr = MatDestroy(&th->MatDeltaFwdSensip);CHKERRQ(ierr); 1058 ierr = MatDestroy(&th->MatFwdSensip0);CHKERRQ(ierr); 1059 PetscFunctionReturn(0); 1060 } 1061 1062 static PetscErrorCode TSSetUp_Theta(TS ts) 1063 { 1064 TS_Theta *th = (TS_Theta*)ts->data; 1065 TS quadts = ts->quadraturets; 1066 PetscBool match; 1067 PetscErrorCode ierr; 1068 1069 PetscFunctionBegin; 1070 if (!th->VecCostIntegral0 && quadts && ts->costintegralfwd) { /* back up cost integral */ 1071 ierr = VecDuplicate(quadts->vec_sol,&th->VecCostIntegral0);CHKERRQ(ierr); 1072 } 1073 if (!th->X) { 1074 ierr = VecDuplicate(ts->vec_sol,&th->X);CHKERRQ(ierr); 1075 } 1076 if (!th->Xdot) { 1077 ierr = VecDuplicate(ts->vec_sol,&th->Xdot);CHKERRQ(ierr); 1078 } 1079 if (!th->X0) { 1080 ierr = VecDuplicate(ts->vec_sol,&th->X0);CHKERRQ(ierr); 1081 } 1082 if (th->endpoint) { 1083 ierr = VecDuplicate(ts->vec_sol,&th->affine);CHKERRQ(ierr); 1084 } 1085 1086 th->order = (th->Theta == 0.5) ? 2 : 1; 1087 th->shift = 1/(th->Theta*ts->time_step); 1088 1089 ierr = TSGetDM(ts,&ts->dm);CHKERRQ(ierr); 1090 ierr = DMCoarsenHookAdd(ts->dm,DMCoarsenHook_TSTheta,DMRestrictHook_TSTheta,ts);CHKERRQ(ierr); 1091 ierr = DMSubDomainHookAdd(ts->dm,DMSubDomainHook_TSTheta,DMSubDomainRestrictHook_TSTheta,ts);CHKERRQ(ierr); 1092 1093 ierr = TSGetAdapt(ts,&ts->adapt);CHKERRQ(ierr); 1094 ierr = TSAdaptCandidatesClear(ts->adapt);CHKERRQ(ierr); 1095 ierr = PetscObjectTypeCompare((PetscObject)ts->adapt,TSADAPTNONE,&match);CHKERRQ(ierr); 1096 if (!match) { 1097 ierr = VecDuplicate(ts->vec_sol,&th->vec_sol_prev);CHKERRQ(ierr); 1098 ierr = VecDuplicate(ts->vec_sol,&th->vec_lte_work);CHKERRQ(ierr); 1099 } 1100 ierr = TSGetSNES(ts,&ts->snes);CHKERRQ(ierr); 1101 1102 ts->stifflyaccurate = (!th->endpoint && th->Theta != 1.0) ? PETSC_FALSE : PETSC_TRUE; 1103 PetscFunctionReturn(0); 1104 } 1105 1106 /*------------------------------------------------------------*/ 1107 1108 static PetscErrorCode TSAdjointSetUp_Theta(TS ts) 1109 { 1110 TS_Theta *th = (TS_Theta*)ts->data; 1111 PetscErrorCode ierr; 1112 1113 PetscFunctionBegin; 1114 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam);CHKERRQ(ierr); 1115 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsSensiTemp);CHKERRQ(ierr); 1116 if (ts->vecs_sensip) { 1117 ierr = VecDuplicateVecs(ts->vecs_sensip[0],ts->numcost,&th->VecsDeltaMu);CHKERRQ(ierr); 1118 } 1119 if (ts->vecs_sensi2) { 1120 ierr = VecDuplicateVecs(ts->vecs_sensi[0],ts->numcost,&th->VecsDeltaLam2);CHKERRQ(ierr); 1121 ierr = VecDuplicateVecs(ts->vecs_sensi2[0],ts->numcost,&th->VecsSensi2Temp);CHKERRQ(ierr); 1122 /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 1123 if (!ts->ihessianproduct_fuu) ts->vecs_fuu = ts->vecs_guu; 1124 if (!ts->ihessianproduct_fup) ts->vecs_fup = ts->vecs_gup; 1125 } 1126 if (ts->vecs_sensi2p) { 1127 ierr = VecDuplicateVecs(ts->vecs_sensi2p[0],ts->numcost,&th->VecsDeltaMu2);CHKERRQ(ierr); 1128 /* hack ts to make implicit TS solver work when users provide only explicit versions of callbacks (RHSFunction,RHSJacobian,RHSHessian etc.) */ 1129 if (!ts->ihessianproduct_fpu) ts->vecs_fpu = ts->vecs_gpu; 1130 if (!ts->ihessianproduct_fpp) ts->vecs_fpp = ts->vecs_gpp; 1131 } 1132 PetscFunctionReturn(0); 1133 } 1134 1135 static PetscErrorCode TSSetFromOptions_Theta(PetscOptionItems *PetscOptionsObject,TS ts) 1136 { 1137 TS_Theta *th = (TS_Theta*)ts->data; 1138 PetscErrorCode ierr; 1139 1140 PetscFunctionBegin; 1141 ierr = PetscOptionsHead(PetscOptionsObject,"Theta ODE solver options");CHKERRQ(ierr); 1142 { 1143 ierr = PetscOptionsReal("-ts_theta_theta","Location of stage (0<Theta<=1)","TSThetaSetTheta",th->Theta,&th->Theta,NULL);CHKERRQ(ierr); 1144 ierr = PetscOptionsBool("-ts_theta_endpoint","Use the endpoint instead of midpoint form of the Theta method","TSThetaSetEndpoint",th->endpoint,&th->endpoint,NULL);CHKERRQ(ierr); 1145 ierr = PetscOptionsBool("-ts_theta_initial_guess_extrapolate","Extrapolate stage initial guess from previous solution (sometimes unstable)","TSThetaSetExtrapolate",th->extrapolate,&th->extrapolate,NULL);CHKERRQ(ierr); 1146 } 1147 ierr = PetscOptionsTail();CHKERRQ(ierr); 1148 PetscFunctionReturn(0); 1149 } 1150 1151 static PetscErrorCode TSView_Theta(TS ts,PetscViewer viewer) 1152 { 1153 TS_Theta *th = (TS_Theta*)ts->data; 1154 PetscBool iascii; 1155 PetscErrorCode ierr; 1156 1157 PetscFunctionBegin; 1158 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1159 if (iascii) { 1160 ierr = PetscViewerASCIIPrintf(viewer," Theta=%g\n",(double)th->Theta);CHKERRQ(ierr); 1161 ierr = PetscViewerASCIIPrintf(viewer," Extrapolation=%s\n",th->extrapolate ? "yes" : "no");CHKERRQ(ierr); 1162 } 1163 PetscFunctionReturn(0); 1164 } 1165 1166 static PetscErrorCode TSThetaGetTheta_Theta(TS ts,PetscReal *theta) 1167 { 1168 TS_Theta *th = (TS_Theta*)ts->data; 1169 1170 PetscFunctionBegin; 1171 *theta = th->Theta; 1172 PetscFunctionReturn(0); 1173 } 1174 1175 static PetscErrorCode TSThetaSetTheta_Theta(TS ts,PetscReal theta) 1176 { 1177 TS_Theta *th = (TS_Theta*)ts->data; 1178 1179 PetscFunctionBegin; 1180 if (theta <= 0 || 1 < theta) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Theta %g not in range (0,1]",(double)theta); 1181 th->Theta = theta; 1182 th->order = (th->Theta == 0.5) ? 2 : 1; 1183 PetscFunctionReturn(0); 1184 } 1185 1186 static PetscErrorCode TSThetaGetEndpoint_Theta(TS ts,PetscBool *endpoint) 1187 { 1188 TS_Theta *th = (TS_Theta*)ts->data; 1189 1190 PetscFunctionBegin; 1191 *endpoint = th->endpoint; 1192 PetscFunctionReturn(0); 1193 } 1194 1195 static PetscErrorCode TSThetaSetEndpoint_Theta(TS ts,PetscBool flg) 1196 { 1197 TS_Theta *th = (TS_Theta*)ts->data; 1198 1199 PetscFunctionBegin; 1200 th->endpoint = flg; 1201 PetscFunctionReturn(0); 1202 } 1203 1204 #if defined(PETSC_HAVE_COMPLEX) 1205 static PetscErrorCode TSComputeLinearStability_Theta(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi) 1206 { 1207 PetscComplex z = xr + xi*PETSC_i,f; 1208 TS_Theta *th = (TS_Theta*)ts->data; 1209 const PetscReal one = 1.0; 1210 1211 PetscFunctionBegin; 1212 f = (one + (one - th->Theta)*z)/(one - th->Theta*z); 1213 *yr = PetscRealPartComplex(f); 1214 *yi = PetscImaginaryPartComplex(f); 1215 PetscFunctionReturn(0); 1216 } 1217 #endif 1218 1219 static PetscErrorCode TSGetStages_Theta(TS ts,PetscInt *ns,Vec *Y[]) 1220 { 1221 TS_Theta *th = (TS_Theta*)ts->data; 1222 1223 PetscFunctionBegin; 1224 if (ns) { 1225 if (!th->endpoint && th->Theta != 1.0) *ns = 1; /* midpoint form */ 1226 else *ns = 2; /* endpoint form */ 1227 } 1228 if (Y) { 1229 if (!th->endpoint && th->Theta != 1.0) { 1230 th->Stages[0] = th->X; 1231 } else { 1232 th->Stages[0] = th->X0; 1233 th->Stages[1] = ts->vec_sol; /* stiffly accurate */ 1234 } 1235 *Y = th->Stages; 1236 } 1237 PetscFunctionReturn(0); 1238 } 1239 1240 /* ------------------------------------------------------------ */ 1241 /*MC 1242 TSTHETA - DAE solver using the implicit Theta method 1243 1244 Level: beginner 1245 1246 Options Database: 1247 + -ts_theta_theta <Theta> - Location of stage (0<Theta<=1) 1248 . -ts_theta_endpoint <flag> - Use the endpoint (like Crank-Nicholson) instead of midpoint form of the Theta method 1249 - -ts_theta_initial_guess_extrapolate <flg> - Extrapolate stage initial guess from previous solution (sometimes unstable) 1250 1251 Notes: 1252 $ -ts_type theta -ts_theta_theta 1.0 corresponds to backward Euler (TSBEULER) 1253 $ -ts_type theta -ts_theta_theta 0.5 corresponds to the implicit midpoint rule 1254 $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint corresponds to Crank-Nicholson (TSCN) 1255 1256 The endpoint variant of the Theta method and backward Euler can be applied to DAE. The midpoint variant is not suitable for DAEs because it is not stiffly accurate. 1257 1258 The midpoint variant is cast as a 1-stage implicit Runge-Kutta method. 1259 1260 .vb 1261 Theta | Theta 1262 ------------- 1263 | 1 1264 .ve 1265 1266 For the default Theta=0.5, this is also known as the implicit midpoint rule. 1267 1268 When the endpoint variant is chosen, the method becomes a 2-stage method with first stage explicit: 1269 1270 .vb 1271 0 | 0 0 1272 1 | 1-Theta Theta 1273 ------------------- 1274 | 1-Theta Theta 1275 .ve 1276 1277 For the default Theta=0.5, this is the trapezoid rule (also known as Crank-Nicolson, see TSCN). 1278 1279 To apply a diagonally implicit RK method to DAE, the stage formula 1280 1281 $ Y_i = X + h sum_j a_ij Y'_j 1282 1283 is interpreted as a formula for Y'_i in terms of Y_i and known values (Y'_j, j<i) 1284 1285 .seealso: TSCreate(), TS, TSSetType(), TSCN, TSBEULER, TSThetaSetTheta(), TSThetaSetEndpoint() 1286 1287 M*/ 1288 PETSC_EXTERN PetscErrorCode TSCreate_Theta(TS ts) 1289 { 1290 TS_Theta *th; 1291 PetscErrorCode ierr; 1292 1293 PetscFunctionBegin; 1294 ts->ops->reset = TSReset_Theta; 1295 ts->ops->adjointreset = TSAdjointReset_Theta; 1296 ts->ops->destroy = TSDestroy_Theta; 1297 ts->ops->view = TSView_Theta; 1298 ts->ops->setup = TSSetUp_Theta; 1299 ts->ops->adjointsetup = TSAdjointSetUp_Theta; 1300 ts->ops->adjointreset = TSAdjointReset_Theta; 1301 ts->ops->step = TSStep_Theta; 1302 ts->ops->interpolate = TSInterpolate_Theta; 1303 ts->ops->evaluatewlte = TSEvaluateWLTE_Theta; 1304 ts->ops->rollback = TSRollBack_Theta; 1305 ts->ops->setfromoptions = TSSetFromOptions_Theta; 1306 ts->ops->snesfunction = SNESTSFormFunction_Theta; 1307 ts->ops->snesjacobian = SNESTSFormJacobian_Theta; 1308 #if defined(PETSC_HAVE_COMPLEX) 1309 ts->ops->linearstability = TSComputeLinearStability_Theta; 1310 #endif 1311 ts->ops->getstages = TSGetStages_Theta; 1312 ts->ops->adjointstep = TSAdjointStep_Theta; 1313 ts->ops->adjointintegral = TSAdjointCostIntegral_Theta; 1314 ts->ops->forwardintegral = TSForwardCostIntegral_Theta; 1315 ts->default_adapt_type = TSADAPTNONE; 1316 1317 ts->ops->forwardsetup = TSForwardSetUp_Theta; 1318 ts->ops->forwardreset = TSForwardReset_Theta; 1319 ts->ops->forwardstep = TSForwardStep_Theta; 1320 ts->ops->forwardgetstages = TSForwardGetStages_Theta; 1321 1322 ts->usessnes = PETSC_TRUE; 1323 1324 ierr = PetscNewLog(ts,&th);CHKERRQ(ierr); 1325 ts->data = (void*)th; 1326 1327 th->VecsDeltaLam = NULL; 1328 th->VecsDeltaMu = NULL; 1329 th->VecsSensiTemp = NULL; 1330 th->VecsSensi2Temp = NULL; 1331 1332 th->extrapolate = PETSC_FALSE; 1333 th->Theta = 0.5; 1334 th->order = 2; 1335 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetTheta_C",TSThetaGetTheta_Theta);CHKERRQ(ierr); 1336 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetTheta_C",TSThetaSetTheta_Theta);CHKERRQ(ierr); 1337 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaGetEndpoint_C",TSThetaGetEndpoint_Theta);CHKERRQ(ierr); 1338 ierr = PetscObjectComposeFunction((PetscObject)ts,"TSThetaSetEndpoint_C",TSThetaSetEndpoint_Theta);CHKERRQ(ierr); 1339 PetscFunctionReturn(0); 1340 } 1341 1342 /*@ 1343 TSThetaGetTheta - Get the abscissa of the stage in (0,1]. 1344 1345 Not Collective 1346 1347 Input Parameter: 1348 . ts - timestepping context 1349 1350 Output Parameter: 1351 . theta - stage abscissa 1352 1353 Note: 1354 Use of this function is normally only required to hack TSTHETA to use a modified integration scheme. 1355 1356 Level: Advanced 1357 1358 .seealso: TSThetaSetTheta() 1359 @*/ 1360 PetscErrorCode TSThetaGetTheta(TS ts,PetscReal *theta) 1361 { 1362 PetscErrorCode ierr; 1363 1364 PetscFunctionBegin; 1365 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1366 PetscValidPointer(theta,2); 1367 ierr = PetscUseMethod(ts,"TSThetaGetTheta_C",(TS,PetscReal*),(ts,theta));CHKERRQ(ierr); 1368 PetscFunctionReturn(0); 1369 } 1370 1371 /*@ 1372 TSThetaSetTheta - Set the abscissa of the stage in (0,1]. 1373 1374 Not Collective 1375 1376 Input Parameter: 1377 + ts - timestepping context 1378 - theta - stage abscissa 1379 1380 Options Database: 1381 . -ts_theta_theta <theta> 1382 1383 Level: Intermediate 1384 1385 .seealso: TSThetaGetTheta() 1386 @*/ 1387 PetscErrorCode TSThetaSetTheta(TS ts,PetscReal theta) 1388 { 1389 PetscErrorCode ierr; 1390 1391 PetscFunctionBegin; 1392 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1393 ierr = PetscTryMethod(ts,"TSThetaSetTheta_C",(TS,PetscReal),(ts,theta));CHKERRQ(ierr); 1394 PetscFunctionReturn(0); 1395 } 1396 1397 /*@ 1398 TSThetaGetEndpoint - Gets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 1399 1400 Not Collective 1401 1402 Input Parameter: 1403 . ts - timestepping context 1404 1405 Output Parameter: 1406 . endpoint - PETSC_TRUE when using the endpoint variant 1407 1408 Level: Advanced 1409 1410 .seealso: TSThetaSetEndpoint(), TSTHETA, TSCN 1411 @*/ 1412 PetscErrorCode TSThetaGetEndpoint(TS ts,PetscBool *endpoint) 1413 { 1414 PetscErrorCode ierr; 1415 1416 PetscFunctionBegin; 1417 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1418 PetscValidPointer(endpoint,2); 1419 ierr = PetscUseMethod(ts,"TSThetaGetEndpoint_C",(TS,PetscBool*),(ts,endpoint));CHKERRQ(ierr); 1420 PetscFunctionReturn(0); 1421 } 1422 1423 /*@ 1424 TSThetaSetEndpoint - Sets whether to use the endpoint variant of the method (e.g. trapezoid/Crank-Nicolson instead of midpoint rule). 1425 1426 Not Collective 1427 1428 Input Parameter: 1429 + ts - timestepping context 1430 - flg - PETSC_TRUE to use the endpoint variant 1431 1432 Options Database: 1433 . -ts_theta_endpoint <flg> 1434 1435 Level: Intermediate 1436 1437 .seealso: TSTHETA, TSCN 1438 @*/ 1439 PetscErrorCode TSThetaSetEndpoint(TS ts,PetscBool flg) 1440 { 1441 PetscErrorCode ierr; 1442 1443 PetscFunctionBegin; 1444 PetscValidHeaderSpecific(ts,TS_CLASSID,1); 1445 ierr = PetscTryMethod(ts,"TSThetaSetEndpoint_C",(TS,PetscBool),(ts,flg));CHKERRQ(ierr); 1446 PetscFunctionReturn(0); 1447 } 1448 1449 /* 1450 * TSBEULER and TSCN are straightforward specializations of TSTHETA. 1451 * The creation functions for these specializations are below. 1452 */ 1453 1454 static PetscErrorCode TSSetUp_BEuler(TS ts) 1455 { 1456 TS_Theta *th = (TS_Theta*)ts->data; 1457 PetscErrorCode ierr; 1458 1459 PetscFunctionBegin; 1460 if (th->Theta != 1.0) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (1) of theta when using backward Euler\n"); 1461 if (th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the endpoint form of the Theta methods when using backward Euler\n"); 1462 ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 1463 PetscFunctionReturn(0); 1464 } 1465 1466 static PetscErrorCode TSView_BEuler(TS ts,PetscViewer viewer) 1467 { 1468 PetscFunctionBegin; 1469 PetscFunctionReturn(0); 1470 } 1471 1472 /*MC 1473 TSBEULER - ODE solver using the implicit backward Euler method 1474 1475 Level: beginner 1476 1477 Notes: 1478 TSBEULER is equivalent to TSTHETA with Theta=1.0 1479 1480 $ -ts_type theta -ts_theta_theta 1.0 1481 1482 .seealso: TSCreate(), TS, TSSetType(), TSEULER, TSCN, TSTHETA 1483 1484 M*/ 1485 PETSC_EXTERN PetscErrorCode TSCreate_BEuler(TS ts) 1486 { 1487 PetscErrorCode ierr; 1488 1489 PetscFunctionBegin; 1490 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1491 ierr = TSThetaSetTheta(ts,1.0);CHKERRQ(ierr); 1492 ierr = TSThetaSetEndpoint(ts,PETSC_FALSE);CHKERRQ(ierr); 1493 ts->ops->setup = TSSetUp_BEuler; 1494 ts->ops->view = TSView_BEuler; 1495 PetscFunctionReturn(0); 1496 } 1497 1498 static PetscErrorCode TSSetUp_CN(TS ts) 1499 { 1500 TS_Theta *th = (TS_Theta*)ts->data; 1501 PetscErrorCode ierr; 1502 1503 PetscFunctionBegin; 1504 if (th->Theta != 0.5) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change the default value (0.5) of theta when using Crank-Nicolson\n"); 1505 if (!th->endpoint) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_OPT_OVERWRITE,"Can not change to the midpoint form of the Theta methods when using Crank-Nicolson\n"); 1506 ierr = TSSetUp_Theta(ts);CHKERRQ(ierr); 1507 PetscFunctionReturn(0); 1508 } 1509 1510 static PetscErrorCode TSView_CN(TS ts,PetscViewer viewer) 1511 { 1512 PetscFunctionBegin; 1513 PetscFunctionReturn(0); 1514 } 1515 1516 /*MC 1517 TSCN - ODE solver using the implicit Crank-Nicolson method. 1518 1519 Level: beginner 1520 1521 Notes: 1522 TSCN is equivalent to TSTHETA with Theta=0.5 and the "endpoint" option set. I.e. 1523 1524 $ -ts_type theta -ts_theta_theta 0.5 -ts_theta_endpoint 1525 1526 .seealso: TSCreate(), TS, TSSetType(), TSBEULER, TSTHETA 1527 1528 M*/ 1529 PETSC_EXTERN PetscErrorCode TSCreate_CN(TS ts) 1530 { 1531 PetscErrorCode ierr; 1532 1533 PetscFunctionBegin; 1534 ierr = TSCreate_Theta(ts);CHKERRQ(ierr); 1535 ierr = TSThetaSetTheta(ts,0.5);CHKERRQ(ierr); 1536 ierr = TSThetaSetEndpoint(ts,PETSC_TRUE);CHKERRQ(ierr); 1537 ts->ops->setup = TSSetUp_CN; 1538 ts->ops->view = TSView_CN; 1539 PetscFunctionReturn(0); 1540 } 1541