1c4762a1bSJed Brown #include <petsc/private/taoimpl.h> 2c4762a1bSJed Brown 3c4762a1bSJed Brown typedef struct { 4c4762a1bSJed Brown PetscInt n; /* Number of variables */ 5c4762a1bSJed Brown PetscInt m; /* Number of constraints per time step */ 6c4762a1bSJed Brown PetscInt mx; /* grid points in each direction */ 7c4762a1bSJed Brown PetscInt nt; /* Number of time steps; as of now, must be divisible by 8 */ 8c4762a1bSJed Brown PetscInt ndata; /* Number of data points per sample */ 9c4762a1bSJed Brown PetscInt ns; /* Number of samples */ 10c4762a1bSJed Brown PetscInt *sample_times; /* Times of samples */ 11c4762a1bSJed Brown IS s_is; 12c4762a1bSJed Brown IS d_is; 13c4762a1bSJed Brown 14c4762a1bSJed Brown VecScatter state_scatter; 15c4762a1bSJed Brown VecScatter design_scatter; 16c4762a1bSJed Brown VecScatter *yi_scatter; 17c4762a1bSJed Brown VecScatter *di_scatter; 18c4762a1bSJed Brown 19c4762a1bSJed Brown Mat Js, Jd, JsBlockPrec, JsInv, JsBlock; 20c4762a1bSJed Brown PetscBool jformed, dsg_formed; 21c4762a1bSJed Brown 22c4762a1bSJed Brown PetscReal alpha; /* Regularization parameter */ 23c4762a1bSJed Brown PetscReal beta; /* Weight attributed to ||u||^2 in regularization functional */ 24c4762a1bSJed Brown PetscReal noise; /* Amount of noise to add to data */ 25c4762a1bSJed Brown PetscReal ht; /* Time step */ 26c4762a1bSJed Brown 27c4762a1bSJed Brown Mat Qblock, QblockT; 28c4762a1bSJed Brown Mat L, LT; 29c4762a1bSJed Brown Mat Div, Divwork; 30c4762a1bSJed Brown Mat Grad; 31c4762a1bSJed Brown Mat Av, Avwork, AvT; 32c4762a1bSJed Brown Mat DSG; 33c4762a1bSJed Brown Vec q; 34c4762a1bSJed Brown Vec ur; /* reference */ 35c4762a1bSJed Brown 36c4762a1bSJed Brown Vec d; 37c4762a1bSJed Brown Vec dwork; 38c4762a1bSJed Brown Vec *di; 39c4762a1bSJed Brown 40c4762a1bSJed Brown Vec y; /* state variables */ 41c4762a1bSJed Brown Vec ywork; 42c4762a1bSJed Brown 43c4762a1bSJed Brown Vec ytrue; 44c4762a1bSJed Brown Vec *yi, *yiwork; 45c4762a1bSJed Brown 46c4762a1bSJed Brown Vec u; /* design variables */ 47c4762a1bSJed Brown Vec uwork; 48c4762a1bSJed Brown 49c4762a1bSJed Brown Vec utrue; 50c4762a1bSJed Brown Vec js_diag; 51c4762a1bSJed Brown Vec c; /* constraint vector */ 52c4762a1bSJed Brown Vec cwork; 53c4762a1bSJed Brown 54c4762a1bSJed Brown Vec lwork; 55c4762a1bSJed Brown Vec S; 56c4762a1bSJed Brown Vec Rwork, Swork, Twork; 57c4762a1bSJed Brown Vec Av_u; 58c4762a1bSJed Brown 59c4762a1bSJed Brown KSP solver; 60c4762a1bSJed Brown PC prec; 61c4762a1bSJed Brown 62c4762a1bSJed Brown PetscInt ksp_its; 63c4762a1bSJed Brown PetscInt ksp_its_initial; 64c4762a1bSJed Brown } AppCtx; 65c4762a1bSJed Brown 66c4762a1bSJed Brown PetscErrorCode FormFunction(Tao, Vec, PetscReal *, void *); 67c4762a1bSJed Brown PetscErrorCode FormGradient(Tao, Vec, Vec, void *); 68c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao, Vec, PetscReal *, Vec, void *); 69c4762a1bSJed Brown PetscErrorCode FormJacobianState(Tao, Vec, Mat, Mat, Mat, void *); 70c4762a1bSJed Brown PetscErrorCode FormJacobianDesign(Tao, Vec, Mat, void *); 71c4762a1bSJed Brown PetscErrorCode FormConstraints(Tao, Vec, Vec, void *); 72c4762a1bSJed Brown PetscErrorCode FormHessian(Tao, Vec, Mat, Mat, void *); 73c4762a1bSJed Brown PetscErrorCode Gather(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat); 74c4762a1bSJed Brown PetscErrorCode Scatter(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat); 75c4762a1bSJed Brown PetscErrorCode ParabolicInitialize(AppCtx *user); 76c4762a1bSJed Brown PetscErrorCode ParabolicDestroy(AppCtx *user); 77c4762a1bSJed Brown PetscErrorCode ParabolicMonitor(Tao, void *); 78c4762a1bSJed Brown 79c4762a1bSJed Brown PetscErrorCode StateMatMult(Mat, Vec, Vec); 80c4762a1bSJed Brown PetscErrorCode StateMatBlockMult(Mat, Vec, Vec); 81c4762a1bSJed Brown PetscErrorCode StateMatMultTranspose(Mat, Vec, Vec); 82c4762a1bSJed Brown PetscErrorCode StateMatGetDiagonal(Mat, Vec); 83c4762a1bSJed Brown PetscErrorCode StateMatDuplicate(Mat, MatDuplicateOption, Mat *); 84c4762a1bSJed Brown PetscErrorCode StateMatInvMult(Mat, Vec, Vec); 85c4762a1bSJed Brown PetscErrorCode StateMatInvTransposeMult(Mat, Vec, Vec); 86c4762a1bSJed Brown PetscErrorCode StateMatBlockPrecMult(PC, Vec, Vec); 87c4762a1bSJed Brown 88c4762a1bSJed Brown PetscErrorCode DesignMatMult(Mat, Vec, Vec); 89c4762a1bSJed Brown PetscErrorCode DesignMatMultTranspose(Mat, Vec, Vec); 90c4762a1bSJed Brown 91c4762a1bSJed Brown PetscErrorCode Gather_i(Vec, Vec *, VecScatter *, PetscInt); 92c4762a1bSJed Brown PetscErrorCode Scatter_i(Vec, Vec *, VecScatter *, PetscInt); 93c4762a1bSJed Brown 94c4762a1bSJed Brown static char help[] = ""; 95c4762a1bSJed Brown 96*9371c9d4SSatish Balay int main(int argc, char **argv) { 97c4762a1bSJed Brown Vec x, x0; 98c4762a1bSJed Brown Tao tao; 99c4762a1bSJed Brown AppCtx user; 100c4762a1bSJed Brown IS is_allstate, is_alldesign; 101c4762a1bSJed Brown PetscInt lo, hi, hi2, lo2, ksp_old; 102c4762a1bSJed Brown PetscInt ntests = 1; 103c4762a1bSJed Brown PetscInt i; 104c4762a1bSJed Brown #if defined(PETSC_USE_LOG) 105c4762a1bSJed Brown PetscLogStage stages[1]; 106c4762a1bSJed Brown #endif 107c4762a1bSJed Brown 108327415f7SBarry Smith PetscFunctionBeginUser; 1099566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); 110c4762a1bSJed Brown user.mx = 8; 111d0609cedSBarry Smith PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "parabolic example", NULL); 1129566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-mx", "Number of grid points in each direction", "", user.mx, &user.mx, NULL)); 113c4762a1bSJed Brown user.nt = 8; 1149566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-nt", "Number of time steps", "", user.nt, &user.nt, NULL)); 115c4762a1bSJed Brown user.ndata = 64; 1169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ndata", "Numbers of data points per sample", "", user.ndata, &user.ndata, NULL)); 117c4762a1bSJed Brown user.ns = 8; 1189566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ns", "Number of samples", "", user.ns, &user.ns, NULL)); 119c4762a1bSJed Brown user.alpha = 1.0; 1209566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-alpha", "Regularization parameter", "", user.alpha, &user.alpha, NULL)); 121c4762a1bSJed Brown user.beta = 0.01; 1229566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-beta", "Weight attributed to ||u||^2 in regularization functional", "", user.beta, &user.beta, NULL)); 123c4762a1bSJed Brown user.noise = 0.01; 1249566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-noise", "Amount of noise to add to data", "", user.noise, &user.noise, NULL)); 1259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-ntests", "Number of times to repeat TaoSolve", "", ntests, &ntests, NULL)); 126d0609cedSBarry Smith PetscOptionsEnd(); 127c4762a1bSJed Brown 128c4762a1bSJed Brown user.m = user.mx * user.mx * user.mx; /* number of constraints per time step */ 129c4762a1bSJed Brown user.n = user.m * (user.nt + 1); /* number of variables */ 130c4762a1bSJed Brown user.ht = (PetscReal)1 / user.nt; 131c4762a1bSJed Brown 1329566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user.u)); 1339566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user.y)); 1349566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user.c)); 1359566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user.u, PETSC_DECIDE, user.n - user.m * user.nt)); 1369566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user.y, PETSC_DECIDE, user.m * user.nt)); 1379566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user.c, PETSC_DECIDE, user.m * user.nt)); 1389566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user.u)); 1399566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user.y)); 1409566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user.c)); 141c4762a1bSJed Brown 142c4762a1bSJed Brown /* Create scatters for reduced spaces. 143c4762a1bSJed Brown If the state vector y and design vector u are partitioned as 144c4762a1bSJed Brown [y_1; y_2; ...; y_np] and [u_1; u_2; ...; u_np] (with np = # of processors), 145c4762a1bSJed Brown then the solution vector x is organized as 146c4762a1bSJed Brown [y_1; u_1; y_2; u_2; ...; y_np; u_np]. 147c4762a1bSJed Brown The index sets user.s_is and user.d_is correspond to the indices of the 148c4762a1bSJed Brown state and design variables owned by the current processor. 149c4762a1bSJed Brown */ 1509566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &x)); 151c4762a1bSJed Brown 1529566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user.y, &lo, &hi)); 1539566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user.u, &lo2, &hi2)); 154c4762a1bSJed Brown 1559566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo, 1, &is_allstate)); 1569566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo + lo2, 1, &user.s_is)); 157c4762a1bSJed Brown 1589566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi2 - lo2, lo2, 1, &is_alldesign)); 1599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi2 - lo2, hi + lo2, 1, &user.d_is)); 160c4762a1bSJed Brown 1619566063dSJacob Faibussowitsch PetscCall(VecSetSizes(x, hi - lo + hi2 - lo2, user.n)); 1629566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(x)); 163c4762a1bSJed Brown 1649566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(x, user.s_is, user.y, is_allstate, &user.state_scatter)); 1659566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(x, user.d_is, user.u, is_alldesign, &user.design_scatter)); 1669566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_alldesign)); 1679566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_allstate)); 168c4762a1bSJed Brown 169c4762a1bSJed Brown /* Create TAO solver and set desired solution method */ 1709566063dSJacob Faibussowitsch PetscCall(TaoCreate(PETSC_COMM_WORLD, &tao)); 1719566063dSJacob Faibussowitsch PetscCall(TaoSetType(tao, TAOLCL)); 172c4762a1bSJed Brown 173c4762a1bSJed Brown /* Set up initial vectors and matrices */ 1749566063dSJacob Faibussowitsch PetscCall(ParabolicInitialize(&user)); 175c4762a1bSJed Brown 1769566063dSJacob Faibussowitsch PetscCall(Gather(x, user.y, user.state_scatter, user.u, user.design_scatter)); 1779566063dSJacob Faibussowitsch PetscCall(VecDuplicate(x, &x0)); 1789566063dSJacob Faibussowitsch PetscCall(VecCopy(x, x0)); 179c4762a1bSJed Brown 180c4762a1bSJed Brown /* Set solution vector with an initial guess */ 1819566063dSJacob Faibussowitsch PetscCall(TaoSetSolution(tao, x)); 1829566063dSJacob Faibussowitsch PetscCall(TaoSetObjective(tao, FormFunction, &user)); 1839566063dSJacob Faibussowitsch PetscCall(TaoSetGradient(tao, NULL, FormGradient, &user)); 1849566063dSJacob Faibussowitsch PetscCall(TaoSetConstraintsRoutine(tao, user.c, FormConstraints, &user)); 185c4762a1bSJed Brown 1869566063dSJacob Faibussowitsch PetscCall(TaoSetJacobianStateRoutine(tao, user.Js, user.JsBlockPrec, user.JsInv, FormJacobianState, &user)); 1879566063dSJacob Faibussowitsch PetscCall(TaoSetJacobianDesignRoutine(tao, user.Jd, FormJacobianDesign, &user)); 188c4762a1bSJed Brown 1899566063dSJacob Faibussowitsch PetscCall(TaoSetFromOptions(tao)); 1909566063dSJacob Faibussowitsch PetscCall(TaoSetStateDesignIS(tao, user.s_is, user.d_is)); 191c4762a1bSJed Brown 192c4762a1bSJed Brown /* SOLVE THE APPLICATION */ 1939566063dSJacob Faibussowitsch PetscCall(PetscLogStageRegister("Trials", &stages[0])); 1949566063dSJacob Faibussowitsch PetscCall(PetscLogStagePush(stages[0])); 195c4762a1bSJed Brown user.ksp_its_initial = user.ksp_its; 196c4762a1bSJed Brown ksp_old = user.ksp_its; 197c4762a1bSJed Brown for (i = 0; i < ntests; i++) { 1989566063dSJacob Faibussowitsch PetscCall(TaoSolve(tao)); 19963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "KSP Iterations = %" PetscInt_FMT "\n", user.ksp_its - ksp_old)); 2009566063dSJacob Faibussowitsch PetscCall(VecCopy(x0, x)); 2019566063dSJacob Faibussowitsch PetscCall(TaoSetSolution(tao, x)); 202c4762a1bSJed Brown } 2039566063dSJacob Faibussowitsch PetscCall(PetscLogStagePop()); 2049566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)x)); 2059566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "KSP iterations within initialization: ")); 20663a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT "\n", user.ksp_its_initial)); 20763a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Total KSP iterations over %" PetscInt_FMT " trial(s): ", ntests)); 20863a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT "\n", user.ksp_its)); 2099566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "KSP iterations per trial: ")); 21063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT "\n", (user.ksp_its - user.ksp_its_initial) / ntests)); 211c4762a1bSJed Brown 2129566063dSJacob Faibussowitsch PetscCall(TaoDestroy(&tao)); 2139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x)); 2149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&x0)); 2159566063dSJacob Faibussowitsch PetscCall(ParabolicDestroy(&user)); 216c4762a1bSJed Brown 2179566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 218b122ec5aSJacob Faibussowitsch return 0; 219c4762a1bSJed Brown } 220c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 221c4762a1bSJed Brown /* 222c4762a1bSJed Brown dwork = Qy - d 223c4762a1bSJed Brown lwork = L*(u-ur) 224c4762a1bSJed Brown f = 1/2 * (dwork.dork + alpha*lwork.lwork) 225c4762a1bSJed Brown */ 226*9371c9d4SSatish Balay PetscErrorCode FormFunction(Tao tao, Vec X, PetscReal *f, void *ptr) { 227c4762a1bSJed Brown PetscReal d1 = 0, d2 = 0; 228c4762a1bSJed Brown PetscInt i, j; 229c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 230c4762a1bSJed Brown 231c4762a1bSJed Brown PetscFunctionBegin; 2329566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 2339566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 234c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 235c4762a1bSJed Brown i = user->sample_times[j]; 2369566063dSJacob Faibussowitsch PetscCall(MatMult(user->Qblock, user->yi[i], user->di[j])); 237c4762a1bSJed Brown } 2389566063dSJacob Faibussowitsch PetscCall(Gather_i(user->dwork, user->di, user->di_scatter, user->ns)); 2399566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->dwork, -1.0, user->d)); 2409566063dSJacob Faibussowitsch PetscCall(VecDot(user->dwork, user->dwork, &d1)); 241c4762a1bSJed Brown 2429566063dSJacob Faibussowitsch PetscCall(VecWAXPY(user->uwork, -1.0, user->ur, user->u)); 2439566063dSJacob Faibussowitsch PetscCall(MatMult(user->L, user->uwork, user->lwork)); 2449566063dSJacob Faibussowitsch PetscCall(VecDot(user->lwork, user->lwork, &d2)); 245c4762a1bSJed Brown 246c4762a1bSJed Brown *f = 0.5 * (d1 + user->alpha * d2); 247c4762a1bSJed Brown PetscFunctionReturn(0); 248c4762a1bSJed Brown } 249c4762a1bSJed Brown 250c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 251c4762a1bSJed Brown /* 252c4762a1bSJed Brown state: g_s = Q' *(Qy - d) 253c4762a1bSJed Brown design: g_d = alpha*L'*L*(u-ur) 254c4762a1bSJed Brown */ 255*9371c9d4SSatish Balay PetscErrorCode FormGradient(Tao tao, Vec X, Vec G, void *ptr) { 256c4762a1bSJed Brown PetscInt i, j; 257c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 258c4762a1bSJed Brown 259c4762a1bSJed Brown PetscFunctionBegin; 2609566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 2619566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 262c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 263c4762a1bSJed Brown i = user->sample_times[j]; 2649566063dSJacob Faibussowitsch PetscCall(MatMult(user->Qblock, user->yi[i], user->di[j])); 265c4762a1bSJed Brown } 2669566063dSJacob Faibussowitsch PetscCall(Gather_i(user->dwork, user->di, user->di_scatter, user->ns)); 2679566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->dwork, -1.0, user->d)); 2689566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->dwork, user->di, user->di_scatter, user->ns)); 2699566063dSJacob Faibussowitsch PetscCall(VecSet(user->ywork, 0.0)); 2709566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->ywork, user->yiwork, user->yi_scatter, user->nt)); 271c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 272c4762a1bSJed Brown i = user->sample_times[j]; 2739566063dSJacob Faibussowitsch PetscCall(MatMult(user->QblockT, user->di[j], user->yiwork[i])); 274c4762a1bSJed Brown } 2759566063dSJacob Faibussowitsch PetscCall(Gather_i(user->ywork, user->yiwork, user->yi_scatter, user->nt)); 276c4762a1bSJed Brown 2779566063dSJacob Faibussowitsch PetscCall(VecWAXPY(user->uwork, -1.0, user->ur, user->u)); 2789566063dSJacob Faibussowitsch PetscCall(MatMult(user->L, user->uwork, user->lwork)); 2799566063dSJacob Faibussowitsch PetscCall(MatMult(user->LT, user->lwork, user->uwork)); 2809566063dSJacob Faibussowitsch PetscCall(VecScale(user->uwork, user->alpha)); 2819566063dSJacob Faibussowitsch PetscCall(Gather(G, user->ywork, user->state_scatter, user->uwork, user->design_scatter)); 282c4762a1bSJed Brown PetscFunctionReturn(0); 283c4762a1bSJed Brown } 284c4762a1bSJed Brown 285*9371c9d4SSatish Balay PetscErrorCode FormFunctionGradient(Tao tao, Vec X, PetscReal *f, Vec G, void *ptr) { 286c4762a1bSJed Brown PetscReal d1, d2; 287c4762a1bSJed Brown PetscInt i, j; 288c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 289c4762a1bSJed Brown 290c4762a1bSJed Brown PetscFunctionBegin; 2919566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 2929566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 293c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 294c4762a1bSJed Brown i = user->sample_times[j]; 2959566063dSJacob Faibussowitsch PetscCall(MatMult(user->Qblock, user->yi[i], user->di[j])); 296c4762a1bSJed Brown } 2979566063dSJacob Faibussowitsch PetscCall(Gather_i(user->dwork, user->di, user->di_scatter, user->ns)); 2989566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->dwork, -1.0, user->d)); 2999566063dSJacob Faibussowitsch PetscCall(VecDot(user->dwork, user->dwork, &d1)); 3009566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->dwork, user->di, user->di_scatter, user->ns)); 3019566063dSJacob Faibussowitsch PetscCall(VecSet(user->ywork, 0.0)); 3029566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->ywork, user->yiwork, user->yi_scatter, user->nt)); 303c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 304c4762a1bSJed Brown i = user->sample_times[j]; 3059566063dSJacob Faibussowitsch PetscCall(MatMult(user->QblockT, user->di[j], user->yiwork[i])); 306c4762a1bSJed Brown } 3079566063dSJacob Faibussowitsch PetscCall(Gather_i(user->ywork, user->yiwork, user->yi_scatter, user->nt)); 308c4762a1bSJed Brown 3099566063dSJacob Faibussowitsch PetscCall(VecWAXPY(user->uwork, -1.0, user->ur, user->u)); 3109566063dSJacob Faibussowitsch PetscCall(MatMult(user->L, user->uwork, user->lwork)); 3119566063dSJacob Faibussowitsch PetscCall(VecDot(user->lwork, user->lwork, &d2)); 3129566063dSJacob Faibussowitsch PetscCall(MatMult(user->LT, user->lwork, user->uwork)); 3139566063dSJacob Faibussowitsch PetscCall(VecScale(user->uwork, user->alpha)); 314c4762a1bSJed Brown *f = 0.5 * (d1 + user->alpha * d2); 315c4762a1bSJed Brown 3169566063dSJacob Faibussowitsch PetscCall(Gather(G, user->ywork, user->state_scatter, user->uwork, user->design_scatter)); 317c4762a1bSJed Brown PetscFunctionReturn(0); 318c4762a1bSJed Brown } 319c4762a1bSJed Brown 320c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 321c4762a1bSJed Brown /* A 322c4762a1bSJed Brown MatShell object 323c4762a1bSJed Brown */ 324*9371c9d4SSatish Balay PetscErrorCode FormJacobianState(Tao tao, Vec X, Mat J, Mat JPre, Mat JInv, void *ptr) { 325c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 326c4762a1bSJed Brown 327c4762a1bSJed Brown PetscFunctionBegin; 3289566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 3299566063dSJacob Faibussowitsch PetscCall(VecSet(user->uwork, 0)); 3309566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->u)); 3319566063dSJacob Faibussowitsch PetscCall(VecExp(user->uwork)); 3329566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Av_u)); 3339566063dSJacob Faibussowitsch PetscCall(VecCopy(user->Av_u, user->Swork)); 3349566063dSJacob Faibussowitsch PetscCall(VecReciprocal(user->Swork)); 3359566063dSJacob Faibussowitsch PetscCall(MatCopy(user->Div, user->Divwork, SAME_NONZERO_PATTERN)); 3369566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(user->Divwork, NULL, user->Swork)); 337c4762a1bSJed Brown if (user->dsg_formed) { 3389566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(user->DSG)); 339c4762a1bSJed Brown } else { 3409566063dSJacob Faibussowitsch PetscCall(MatMatMult(user->Divwork, user->Grad, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &user->DSG)); 341c4762a1bSJed Brown user->dsg_formed = PETSC_TRUE; 342c4762a1bSJed Brown } 343c4762a1bSJed Brown 344c4762a1bSJed Brown /* B = speye(nx^3) + ht*DSG; */ 3459566063dSJacob Faibussowitsch PetscCall(MatScale(user->DSG, user->ht)); 3469566063dSJacob Faibussowitsch PetscCall(MatShift(user->DSG, 1.0)); 347c4762a1bSJed Brown PetscFunctionReturn(0); 348c4762a1bSJed Brown } 349c4762a1bSJed Brown 350c4762a1bSJed Brown /* ------------------------------------------------------------------- */ 351c4762a1bSJed Brown /* B */ 352*9371c9d4SSatish Balay PetscErrorCode FormJacobianDesign(Tao tao, Vec X, Mat J, void *ptr) { 353c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 354c4762a1bSJed Brown 355c4762a1bSJed Brown PetscFunctionBegin; 3569566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 357c4762a1bSJed Brown PetscFunctionReturn(0); 358c4762a1bSJed Brown } 359c4762a1bSJed Brown 360*9371c9d4SSatish Balay PetscErrorCode StateMatMult(Mat J_shell, Vec X, Vec Y) { 361c4762a1bSJed Brown PetscInt i; 362c4762a1bSJed Brown AppCtx *user; 363c4762a1bSJed Brown 364c4762a1bSJed Brown PetscFunctionBegin; 3659566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 3669566063dSJacob Faibussowitsch PetscCall(Scatter_i(X, user->yi, user->yi_scatter, user->nt)); 3679566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[0], user->yiwork[0])); 368c4762a1bSJed Brown for (i = 1; i < user->nt; i++) { 3699566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[i], user->yiwork[i])); 3709566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->yiwork[i], -1.0, user->yi[i - 1])); 371c4762a1bSJed Brown } 3729566063dSJacob Faibussowitsch PetscCall(Gather_i(Y, user->yiwork, user->yi_scatter, user->nt)); 373c4762a1bSJed Brown PetscFunctionReturn(0); 374c4762a1bSJed Brown } 375c4762a1bSJed Brown 376*9371c9d4SSatish Balay PetscErrorCode StateMatMultTranspose(Mat J_shell, Vec X, Vec Y) { 377c4762a1bSJed Brown PetscInt i; 378c4762a1bSJed Brown AppCtx *user; 379c4762a1bSJed Brown 380c4762a1bSJed Brown PetscFunctionBegin; 3819566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 3829566063dSJacob Faibussowitsch PetscCall(Scatter_i(X, user->yi, user->yi_scatter, user->nt)); 383c4762a1bSJed Brown for (i = 0; i < user->nt - 1; i++) { 3849566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[i], user->yiwork[i])); 3859566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->yiwork[i], -1.0, user->yi[i + 1])); 386c4762a1bSJed Brown } 387c4762a1bSJed Brown i = user->nt - 1; 3889566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[i], user->yiwork[i])); 3899566063dSJacob Faibussowitsch PetscCall(Gather_i(Y, user->yiwork, user->yi_scatter, user->nt)); 390c4762a1bSJed Brown PetscFunctionReturn(0); 391c4762a1bSJed Brown } 392c4762a1bSJed Brown 393*9371c9d4SSatish Balay PetscErrorCode StateMatBlockMult(Mat J_shell, Vec X, Vec Y) { 394c4762a1bSJed Brown AppCtx *user; 395c4762a1bSJed Brown 396c4762a1bSJed Brown PetscFunctionBegin; 3979566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 3989566063dSJacob Faibussowitsch PetscCall(MatMult(user->Grad, X, user->Swork)); 3999566063dSJacob Faibussowitsch PetscCall(VecPointwiseDivide(user->Swork, user->Swork, user->Av_u)); 4009566063dSJacob Faibussowitsch PetscCall(MatMult(user->Div, user->Swork, Y)); 4019566063dSJacob Faibussowitsch PetscCall(VecAYPX(Y, user->ht, X)); 402c4762a1bSJed Brown PetscFunctionReturn(0); 403c4762a1bSJed Brown } 404c4762a1bSJed Brown 405*9371c9d4SSatish Balay PetscErrorCode DesignMatMult(Mat J_shell, Vec X, Vec Y) { 406c4762a1bSJed Brown PetscInt i; 407c4762a1bSJed Brown AppCtx *user; 408c4762a1bSJed Brown 409c4762a1bSJed Brown PetscFunctionBegin; 4109566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 411c4762a1bSJed Brown 412c4762a1bSJed Brown /* sdiag(1./v) */ 4139566063dSJacob Faibussowitsch PetscCall(VecSet(user->uwork, 0)); 4149566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->u)); 4159566063dSJacob Faibussowitsch PetscCall(VecExp(user->uwork)); 416c4762a1bSJed Brown 417c4762a1bSJed Brown /* sdiag(1./((Av*(1./v)).^2)) */ 4189566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Swork)); 4199566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Swork, user->Swork, user->Swork)); 4209566063dSJacob Faibussowitsch PetscCall(VecReciprocal(user->Swork)); 421c4762a1bSJed Brown 422c4762a1bSJed Brown /* (Av * (sdiag(1./v) * b)) */ 4239566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->uwork, user->uwork, X)); 4249566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Twork)); 425c4762a1bSJed Brown 426c4762a1bSJed Brown /* (sdiag(1./((Av*(1./v)).^2)) * (Av * (sdiag(1./v) * b))) */ 4279566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Swork, user->Twork, user->Swork)); 428c4762a1bSJed Brown 4299566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 430c4762a1bSJed Brown for (i = 0; i < user->nt; i++) { 431c4762a1bSJed Brown /* (sdiag(Grad*y(:,i)) */ 4329566063dSJacob Faibussowitsch PetscCall(MatMult(user->Grad, user->yi[i], user->Twork)); 433c4762a1bSJed Brown 434c4762a1bSJed Brown /* ht * Div * (sdiag(Grad*y(:,i)) * (sdiag(1./((Av*(1./v)).^2)) * (Av * (sdiag(1./v) * b)))) */ 4359566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Twork, user->Twork, user->Swork)); 4369566063dSJacob Faibussowitsch PetscCall(MatMult(user->Div, user->Twork, user->yiwork[i])); 4379566063dSJacob Faibussowitsch PetscCall(VecScale(user->yiwork[i], user->ht)); 438c4762a1bSJed Brown } 4399566063dSJacob Faibussowitsch PetscCall(Gather_i(Y, user->yiwork, user->yi_scatter, user->nt)); 440c4762a1bSJed Brown 441c4762a1bSJed Brown PetscFunctionReturn(0); 442c4762a1bSJed Brown } 443c4762a1bSJed Brown 444*9371c9d4SSatish Balay PetscErrorCode DesignMatMultTranspose(Mat J_shell, Vec X, Vec Y) { 445c4762a1bSJed Brown PetscInt i; 446c4762a1bSJed Brown AppCtx *user; 447c4762a1bSJed Brown 448c4762a1bSJed Brown PetscFunctionBegin; 4499566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 450c4762a1bSJed Brown 451c4762a1bSJed Brown /* sdiag(1./((Av*(1./v)).^2)) */ 4529566063dSJacob Faibussowitsch PetscCall(VecSet(user->uwork, 0)); 4539566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->u)); 4549566063dSJacob Faibussowitsch PetscCall(VecExp(user->uwork)); 4559566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Rwork)); 4569566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Rwork, user->Rwork, user->Rwork)); 4579566063dSJacob Faibussowitsch PetscCall(VecReciprocal(user->Rwork)); 458c4762a1bSJed Brown 4599566063dSJacob Faibussowitsch PetscCall(VecSet(Y, 0.0)); 4609566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 4619566063dSJacob Faibussowitsch PetscCall(Scatter_i(X, user->yiwork, user->yi_scatter, user->nt)); 462c4762a1bSJed Brown for (i = 0; i < user->nt; i++) { 463c4762a1bSJed Brown /* (Div' * b(:,i)) */ 4649566063dSJacob Faibussowitsch PetscCall(MatMult(user->Grad, user->yiwork[i], user->Swork)); 465c4762a1bSJed Brown 466c4762a1bSJed Brown /* sdiag(Grad*y(:,i)) */ 4679566063dSJacob Faibussowitsch PetscCall(MatMult(user->Grad, user->yi[i], user->Twork)); 468c4762a1bSJed Brown 469c4762a1bSJed Brown /* (sdiag(Grad*y(:,i)) * (Div' * b(:,i))) */ 4709566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Twork, user->Swork, user->Twork)); 471c4762a1bSJed Brown 472c4762a1bSJed Brown /* (sdiag(1./((Av*(1./v)).^2)) * (sdiag(Grad*y(:,i)) * (Div' * b(:,i)))) */ 4739566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->Twork, user->Rwork, user->Twork)); 474c4762a1bSJed Brown 475c4762a1bSJed Brown /* (Av' * (sdiag(1./((Av*(1./v)).^2)) * (sdiag(Grad*y(:,i)) * (Div' * b(:,i))))) */ 4769566063dSJacob Faibussowitsch PetscCall(MatMult(user->AvT, user->Twork, user->yiwork[i])); 477c4762a1bSJed Brown 478c4762a1bSJed Brown /* sdiag(1./v) * (Av' * (sdiag(1./((Av*(1./v)).^2)) * (sdiag(Grad*y(:,i)) * (Div' * b(:,i))))) */ 4799566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(user->yiwork[i], user->uwork, user->yiwork[i])); 4809566063dSJacob Faibussowitsch PetscCall(VecAXPY(Y, user->ht, user->yiwork[i])); 481c4762a1bSJed Brown } 482c4762a1bSJed Brown PetscFunctionReturn(0); 483c4762a1bSJed Brown } 484c4762a1bSJed Brown 485*9371c9d4SSatish Balay PetscErrorCode StateMatBlockPrecMult(PC PC_shell, Vec X, Vec Y) { 486c4762a1bSJed Brown AppCtx *user; 487c4762a1bSJed Brown 488c4762a1bSJed Brown PetscFunctionBegin; 4899566063dSJacob Faibussowitsch PetscCall(PCShellGetContext(PC_shell, &user)); 490c4762a1bSJed Brown 491c4762a1bSJed Brown if (user->dsg_formed) { 4929566063dSJacob Faibussowitsch PetscCall(MatSOR(user->DSG, X, 1.0, (MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_SYMMETRIC_SWEEP), 0.0, 1, 1, Y)); 493c4762a1bSJed Brown } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "DSG not formed"); 494c4762a1bSJed Brown PetscFunctionReturn(0); 495c4762a1bSJed Brown } 496c4762a1bSJed Brown 497*9371c9d4SSatish Balay PetscErrorCode StateMatInvMult(Mat J_shell, Vec X, Vec Y) { 498c4762a1bSJed Brown AppCtx *user; 499c4762a1bSJed Brown PetscInt its, i; 500c4762a1bSJed Brown 501c4762a1bSJed Brown PetscFunctionBegin; 5029566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 503c4762a1bSJed Brown 504c4762a1bSJed Brown if (Y == user->ytrue) { 505c4762a1bSJed Brown /* First solve is done with true solution to set up problem */ 5069566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(user->solver, 1e-8, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 507c4762a1bSJed Brown } else { 5089566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(user->solver, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT)); 509c4762a1bSJed Brown } 510c4762a1bSJed Brown 5119566063dSJacob Faibussowitsch PetscCall(Scatter_i(X, user->yi, user->yi_scatter, user->nt)); 5129566063dSJacob Faibussowitsch PetscCall(KSPSolve(user->solver, user->yi[0], user->yiwork[0])); 5139566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(user->solver, &its)); 514c4762a1bSJed Brown user->ksp_its = user->ksp_its + its; 515c4762a1bSJed Brown 516c4762a1bSJed Brown for (i = 1; i < user->nt; i++) { 5179566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->yi[i], 1.0, user->yiwork[i - 1])); 5189566063dSJacob Faibussowitsch PetscCall(KSPSolve(user->solver, user->yi[i], user->yiwork[i])); 5199566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(user->solver, &its)); 520c4762a1bSJed Brown user->ksp_its = user->ksp_its + its; 521c4762a1bSJed Brown } 5229566063dSJacob Faibussowitsch PetscCall(Gather_i(Y, user->yiwork, user->yi_scatter, user->nt)); 523c4762a1bSJed Brown PetscFunctionReturn(0); 524c4762a1bSJed Brown } 525c4762a1bSJed Brown 526*9371c9d4SSatish Balay PetscErrorCode StateMatInvTransposeMult(Mat J_shell, Vec X, Vec Y) { 527c4762a1bSJed Brown AppCtx *user; 528c4762a1bSJed Brown PetscInt its, i; 529c4762a1bSJed Brown 530c4762a1bSJed Brown PetscFunctionBegin; 5319566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 532c4762a1bSJed Brown 5339566063dSJacob Faibussowitsch PetscCall(Scatter_i(X, user->yi, user->yi_scatter, user->nt)); 534c4762a1bSJed Brown 535c4762a1bSJed Brown i = user->nt - 1; 5369566063dSJacob Faibussowitsch PetscCall(KSPSolve(user->solver, user->yi[i], user->yiwork[i])); 537c4762a1bSJed Brown 5389566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(user->solver, &its)); 539c4762a1bSJed Brown user->ksp_its = user->ksp_its + its; 540c4762a1bSJed Brown 541c4762a1bSJed Brown for (i = user->nt - 2; i >= 0; i--) { 5429566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->yi[i], 1.0, user->yiwork[i + 1])); 5439566063dSJacob Faibussowitsch PetscCall(KSPSolve(user->solver, user->yi[i], user->yiwork[i])); 544c4762a1bSJed Brown 5459566063dSJacob Faibussowitsch PetscCall(KSPGetIterationNumber(user->solver, &its)); 546c4762a1bSJed Brown user->ksp_its = user->ksp_its + its; 547c4762a1bSJed Brown } 548c4762a1bSJed Brown 5499566063dSJacob Faibussowitsch PetscCall(Gather_i(Y, user->yiwork, user->yi_scatter, user->nt)); 550c4762a1bSJed Brown PetscFunctionReturn(0); 551c4762a1bSJed Brown } 552c4762a1bSJed Brown 553*9371c9d4SSatish Balay PetscErrorCode StateMatDuplicate(Mat J_shell, MatDuplicateOption opt, Mat *new_shell) { 554c4762a1bSJed Brown AppCtx *user; 555c4762a1bSJed Brown 556c4762a1bSJed Brown PetscFunctionBegin; 5579566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 558c4762a1bSJed Brown 5599566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m, user->m, user, new_shell)); 5609566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(*new_shell, MATOP_MULT, (void (*)(void))StateMatMult)); 5619566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(*new_shell, MATOP_DUPLICATE, (void (*)(void))StateMatDuplicate)); 5629566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(*new_shell, MATOP_MULT_TRANSPOSE, (void (*)(void))StateMatMultTranspose)); 5639566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(*new_shell, MATOP_GET_DIAGONAL, (void (*)(void))StateMatGetDiagonal)); 564c4762a1bSJed Brown PetscFunctionReturn(0); 565c4762a1bSJed Brown } 566c4762a1bSJed Brown 567*9371c9d4SSatish Balay PetscErrorCode StateMatGetDiagonal(Mat J_shell, Vec X) { 568c4762a1bSJed Brown AppCtx *user; 569c4762a1bSJed Brown 570c4762a1bSJed Brown PetscFunctionBegin; 5719566063dSJacob Faibussowitsch PetscCall(MatShellGetContext(J_shell, &user)); 5729566063dSJacob Faibussowitsch PetscCall(VecCopy(user->js_diag, X)); 573c4762a1bSJed Brown PetscFunctionReturn(0); 574c4762a1bSJed Brown } 575c4762a1bSJed Brown 576*9371c9d4SSatish Balay PetscErrorCode FormConstraints(Tao tao, Vec X, Vec C, void *ptr) { 577c4762a1bSJed Brown /* con = Ay - q, A = [B 0 0 ... 0; 578c4762a1bSJed Brown -I B 0 ... 0; 579c4762a1bSJed Brown 0 -I B ... 0; 580c4762a1bSJed Brown ... ; 581c4762a1bSJed Brown 0 ... -I B] 582c4762a1bSJed Brown B = ht * Div * Sigma * Grad + eye */ 583c4762a1bSJed Brown PetscInt i; 584c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 585c4762a1bSJed Brown 586c4762a1bSJed Brown PetscFunctionBegin; 5879566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->y, user->state_scatter, user->u, user->design_scatter)); 5889566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->y, user->yi, user->yi_scatter, user->nt)); 5899566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[0], user->yiwork[0])); 590c4762a1bSJed Brown for (i = 1; i < user->nt; i++) { 5919566063dSJacob Faibussowitsch PetscCall(MatMult(user->JsBlock, user->yi[i], user->yiwork[i])); 5929566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->yiwork[i], -1.0, user->yi[i - 1])); 593c4762a1bSJed Brown } 5949566063dSJacob Faibussowitsch PetscCall(Gather_i(C, user->yiwork, user->yi_scatter, user->nt)); 5959566063dSJacob Faibussowitsch PetscCall(VecAXPY(C, -1.0, user->q)); 596c4762a1bSJed Brown PetscFunctionReturn(0); 597c4762a1bSJed Brown } 598c4762a1bSJed Brown 599*9371c9d4SSatish Balay PetscErrorCode Scatter(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat) { 600c4762a1bSJed Brown PetscFunctionBegin; 6019566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(s_scat, x, state, INSERT_VALUES, SCATTER_FORWARD)); 6029566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(s_scat, x, state, INSERT_VALUES, SCATTER_FORWARD)); 6039566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(d_scat, x, design, INSERT_VALUES, SCATTER_FORWARD)); 6049566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(d_scat, x, design, INSERT_VALUES, SCATTER_FORWARD)); 605c4762a1bSJed Brown PetscFunctionReturn(0); 606c4762a1bSJed Brown } 607c4762a1bSJed Brown 608*9371c9d4SSatish Balay PetscErrorCode Scatter_i(Vec y, Vec *yi, VecScatter *scat, PetscInt nt) { 609c4762a1bSJed Brown PetscInt i; 610c4762a1bSJed Brown 611c4762a1bSJed Brown PetscFunctionBegin; 612c4762a1bSJed Brown for (i = 0; i < nt; i++) { 6139566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat[i], y, yi[i], INSERT_VALUES, SCATTER_FORWARD)); 6149566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat[i], y, yi[i], INSERT_VALUES, SCATTER_FORWARD)); 615c4762a1bSJed Brown } 616c4762a1bSJed Brown PetscFunctionReturn(0); 617c4762a1bSJed Brown } 618c4762a1bSJed Brown 619*9371c9d4SSatish Balay PetscErrorCode Gather(Vec x, Vec state, VecScatter s_scat, Vec design, VecScatter d_scat) { 620c4762a1bSJed Brown PetscFunctionBegin; 6219566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(s_scat, state, x, INSERT_VALUES, SCATTER_REVERSE)); 6229566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(s_scat, state, x, INSERT_VALUES, SCATTER_REVERSE)); 6239566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(d_scat, design, x, INSERT_VALUES, SCATTER_REVERSE)); 6249566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(d_scat, design, x, INSERT_VALUES, SCATTER_REVERSE)); 625c4762a1bSJed Brown PetscFunctionReturn(0); 626c4762a1bSJed Brown } 627c4762a1bSJed Brown 628*9371c9d4SSatish Balay PetscErrorCode Gather_i(Vec y, Vec *yi, VecScatter *scat, PetscInt nt) { 629c4762a1bSJed Brown PetscInt i; 630c4762a1bSJed Brown 631c4762a1bSJed Brown PetscFunctionBegin; 632c4762a1bSJed Brown for (i = 0; i < nt; i++) { 6339566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(scat[i], yi[i], y, INSERT_VALUES, SCATTER_REVERSE)); 6349566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(scat[i], yi[i], y, INSERT_VALUES, SCATTER_REVERSE)); 635c4762a1bSJed Brown } 636c4762a1bSJed Brown PetscFunctionReturn(0); 637c4762a1bSJed Brown } 638c4762a1bSJed Brown 639*9371c9d4SSatish Balay PetscErrorCode ParabolicInitialize(AppCtx *user) { 640c4762a1bSJed Brown PetscInt m, n, i, j, k, linear_index, istart, iend, iblock, lo, hi, lo2, hi2; 641c4762a1bSJed Brown Vec XX, YY, ZZ, XXwork, YYwork, ZZwork, UTwork, yi, di, bc; 642c4762a1bSJed Brown PetscReal *x, *y, *z; 643c4762a1bSJed Brown PetscReal h, stime; 644c4762a1bSJed Brown PetscScalar hinv, neg_hinv, half = 0.5, sqrt_beta; 645c4762a1bSJed Brown PetscInt im, indx1, indx2, indy1, indy2, indz1, indz2, nx, ny, nz; 646c4762a1bSJed Brown PetscReal xri, yri, zri, xim, yim, zim, dx1, dx2, dy1, dy2, dz1, dz2, Dx, Dy, Dz; 647c4762a1bSJed Brown PetscScalar v, vx, vy, vz; 648c4762a1bSJed Brown IS is_from_y, is_to_yi, is_from_d, is_to_di; 649c4762a1bSJed Brown /* Data locations */ 650*9371c9d4SSatish Balay PetscScalar xr[64] = {0.4970, 0.8498, 0.7814, 0.6268, 0.7782, 0.6402, 0.3617, 0.3160, 0.3610, 0.5298, 0.6987, 0.3331, 0.7962, 0.5596, 0.3866, 0.6774, 0.5407, 0.4518, 0.6702, 0.6061, 0.7580, 0.8997, 651*9371c9d4SSatish Balay 0.5198, 0.8326, 0.2138, 0.9198, 0.3000, 0.2833, 0.8288, 0.7076, 0.1820, 0.0728, 0.8447, 0.2367, 0.3239, 0.6413, 0.3114, 0.4731, 0.1192, 0.9273, 0.5724, 0.4331, 0.5136, 0.3547, 652*9371c9d4SSatish Balay 0.4413, 0.2602, 0.5698, 0.7278, 0.5261, 0.6230, 0.2454, 0.3948, 0.7479, 0.6582, 0.4660, 0.5594, 0.7574, 0.1143, 0.5900, 0.1065, 0.4260, 0.3294, 0.8276, 0.0756}; 653c4762a1bSJed Brown 654*9371c9d4SSatish Balay PetscScalar yr[64] = {0.7345, 0.9120, 0.9288, 0.7528, 0.4463, 0.4985, 0.2497, 0.6256, 0.3425, 0.9026, 0.6983, 0.4230, 0.7140, 0.2970, 0.4474, 0.8792, 0.6604, 0.2485, 0.7968, 0.6127, 0.1796, 0.2437, 655*9371c9d4SSatish Balay 0.5938, 0.6137, 0.3867, 0.5658, 0.4575, 0.1009, 0.0863, 0.3361, 0.0738, 0.3985, 0.6602, 0.1437, 0.0934, 0.5983, 0.5950, 0.0763, 0.0768, 0.2288, 0.5761, 0.1129, 0.3841, 0.6150, 656*9371c9d4SSatish Balay 0.6904, 0.6686, 0.1361, 0.4601, 0.4491, 0.3716, 0.1969, 0.6537, 0.6743, 0.6991, 0.4811, 0.5480, 0.1684, 0.4569, 0.6889, 0.8437, 0.3015, 0.2854, 0.8199, 0.2658}; 657c4762a1bSJed Brown 658*9371c9d4SSatish Balay PetscScalar zr[64] = {0.7668, 0.8573, 0.2654, 0.2719, 0.1060, 0.1311, 0.6232, 0.2295, 0.8009, 0.2147, 0.2119, 0.9325, 0.4473, 0.3600, 0.3374, 0.3819, 0.4066, 0.5801, 0.1673, 0.0959, 0.4638, 0.8236, 659*9371c9d4SSatish Balay 0.8800, 0.2939, 0.2028, 0.8262, 0.2706, 0.6276, 0.9085, 0.6443, 0.8241, 0.0712, 0.1824, 0.7789, 0.4389, 0.8415, 0.7055, 0.6639, 0.3653, 0.2078, 0.1987, 0.2297, 0.4321, 0.8115, 660*9371c9d4SSatish Balay 0.4915, 0.7764, 0.4657, 0.4627, 0.4569, 0.4232, 0.8514, 0.0674, 0.3227, 0.1055, 0.6690, 0.6313, 0.9226, 0.5461, 0.4126, 0.2364, 0.6096, 0.7042, 0.3914, 0.0711}; 661c4762a1bSJed Brown 662c4762a1bSJed Brown PetscFunctionBegin; 6639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->mx, &x)); 6649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->mx, &y)); 6659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->mx, &z)); 666c4762a1bSJed Brown user->jformed = PETSC_FALSE; 667c4762a1bSJed Brown user->dsg_formed = PETSC_FALSE; 668c4762a1bSJed Brown 669c4762a1bSJed Brown n = user->mx * user->mx * user->mx; 670c4762a1bSJed Brown m = 3 * user->mx * user->mx * (user->mx - 1); 671c4762a1bSJed Brown sqrt_beta = PetscSqrtScalar(user->beta); 672c4762a1bSJed Brown 673c4762a1bSJed Brown user->ksp_its = 0; 674c4762a1bSJed Brown user->ksp_its_initial = 0; 675c4762a1bSJed Brown 676c4762a1bSJed Brown stime = (PetscReal)user->nt / user->ns; 6779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->ns, &user->sample_times)); 678*9371c9d4SSatish Balay for (i = 0; i < user->ns; i++) { user->sample_times[i] = (PetscInt)(stime * ((PetscReal)i + 1.0) - 0.5); } 679c4762a1bSJed Brown 6809566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &XX)); 6819566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->q)); 6829566063dSJacob Faibussowitsch PetscCall(VecSetSizes(XX, PETSC_DECIDE, n)); 6839566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->q, PETSC_DECIDE, n * user->nt)); 6849566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(XX)); 6859566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->q)); 686c4762a1bSJed Brown 6879566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &YY)); 6889566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &ZZ)); 6899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &XXwork)); 6909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &YYwork)); 6919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &ZZwork)); 6929566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &UTwork)); 6939566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &user->utrue)); 6949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(XX, &bc)); 695c4762a1bSJed Brown 696c4762a1bSJed Brown /* Generate 3D grid, and collect ns (1<=ns<=8) right-hand-side vectors into user->q */ 697c4762a1bSJed Brown h = 1.0 / user->mx; 698c4762a1bSJed Brown hinv = user->mx; 699c4762a1bSJed Brown neg_hinv = -hinv; 700c4762a1bSJed Brown 7019566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(XX, &istart, &iend)); 702c4762a1bSJed Brown for (linear_index = istart; linear_index < iend; linear_index++) { 703c4762a1bSJed Brown i = linear_index % user->mx; 704c4762a1bSJed Brown j = ((linear_index - i) / user->mx) % user->mx; 705c4762a1bSJed Brown k = ((linear_index - i) / user->mx - j) / user->mx; 706c4762a1bSJed Brown vx = h * (i + 0.5); 707c4762a1bSJed Brown vy = h * (j + 0.5); 708c4762a1bSJed Brown vz = h * (k + 0.5); 7099566063dSJacob Faibussowitsch PetscCall(VecSetValues(XX, 1, &linear_index, &vx, INSERT_VALUES)); 7109566063dSJacob Faibussowitsch PetscCall(VecSetValues(YY, 1, &linear_index, &vy, INSERT_VALUES)); 7119566063dSJacob Faibussowitsch PetscCall(VecSetValues(ZZ, 1, &linear_index, &vz, INSERT_VALUES)); 712c4762a1bSJed Brown if ((vx < 0.6) && (vx > 0.4) && (vy < 0.6) && (vy > 0.4) && (vy < 0.6) && (vz < 0.6) && (vz > 0.4)) { 713c4762a1bSJed Brown v = 1000.0; 7149566063dSJacob Faibussowitsch PetscCall(VecSetValues(bc, 1, &linear_index, &v, INSERT_VALUES)); 715c4762a1bSJed Brown } 716c4762a1bSJed Brown } 717c4762a1bSJed Brown 7189566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(XX)); 7199566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(XX)); 7209566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(YY)); 7219566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(YY)); 7229566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(ZZ)); 7239566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(ZZ)); 7249566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(bc)); 7259566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(bc)); 726c4762a1bSJed Brown 727c4762a1bSJed Brown /* Compute true parameter function 728c4762a1bSJed Brown ut = 0.5 + exp(-10*((x-0.5)^2+(y-0.5)^2+(z-0.5)^2)) */ 7299566063dSJacob Faibussowitsch PetscCall(VecCopy(XX, XXwork)); 7309566063dSJacob Faibussowitsch PetscCall(VecCopy(YY, YYwork)); 7319566063dSJacob Faibussowitsch PetscCall(VecCopy(ZZ, ZZwork)); 732c4762a1bSJed Brown 7339566063dSJacob Faibussowitsch PetscCall(VecShift(XXwork, -0.5)); 7349566063dSJacob Faibussowitsch PetscCall(VecShift(YYwork, -0.5)); 7359566063dSJacob Faibussowitsch PetscCall(VecShift(ZZwork, -0.5)); 736c4762a1bSJed Brown 7379566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(XXwork, XXwork, XXwork)); 7389566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(YYwork, YYwork, YYwork)); 7399566063dSJacob Faibussowitsch PetscCall(VecPointwiseMult(ZZwork, ZZwork, ZZwork)); 740c4762a1bSJed Brown 7419566063dSJacob Faibussowitsch PetscCall(VecCopy(XXwork, user->utrue)); 7429566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->utrue, 1.0, YYwork)); 7439566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->utrue, 1.0, ZZwork)); 7449566063dSJacob Faibussowitsch PetscCall(VecScale(user->utrue, -10.0)); 7459566063dSJacob Faibussowitsch PetscCall(VecExp(user->utrue)); 7469566063dSJacob Faibussowitsch PetscCall(VecShift(user->utrue, 0.5)); 747c4762a1bSJed Brown 7489566063dSJacob Faibussowitsch PetscCall(VecDestroy(&XX)); 7499566063dSJacob Faibussowitsch PetscCall(VecDestroy(&YY)); 7509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ZZ)); 7519566063dSJacob Faibussowitsch PetscCall(VecDestroy(&XXwork)); 7529566063dSJacob Faibussowitsch PetscCall(VecDestroy(&YYwork)); 7539566063dSJacob Faibussowitsch PetscCall(VecDestroy(&ZZwork)); 7549566063dSJacob Faibussowitsch PetscCall(VecDestroy(&UTwork)); 755c4762a1bSJed Brown 756c4762a1bSJed Brown /* Initial guess and reference model */ 7579566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->utrue, &user->ur)); 7589566063dSJacob Faibussowitsch PetscCall(VecSet(user->ur, 0.0)); 759c4762a1bSJed Brown 760c4762a1bSJed Brown /* Generate Grad matrix */ 7619566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->Grad)); 7629566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->Grad, PETSC_DECIDE, PETSC_DECIDE, m, n)); 7639566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->Grad)); 7649566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(user->Grad, 2, NULL, 2, NULL)); 7659566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(user->Grad, 2, NULL)); 7669566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(user->Grad, &istart, &iend)); 767c4762a1bSJed Brown 768c4762a1bSJed Brown for (i = istart; i < iend; i++) { 769c4762a1bSJed Brown if (i < m / 3) { 770c4762a1bSJed Brown iblock = i / (user->mx - 1); 771c4762a1bSJed Brown j = iblock * user->mx + (i % (user->mx - 1)); 7729566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 773c4762a1bSJed Brown j = j + 1; 7749566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 775c4762a1bSJed Brown } 776c4762a1bSJed Brown if (i >= m / 3 && i < 2 * m / 3) { 777c4762a1bSJed Brown iblock = (i - m / 3) / (user->mx * (user->mx - 1)); 778c4762a1bSJed Brown j = iblock * user->mx * user->mx + ((i - m / 3) % (user->mx * (user->mx - 1))); 7799566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 780c4762a1bSJed Brown j = j + user->mx; 7819566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 782c4762a1bSJed Brown } 783c4762a1bSJed Brown if (i >= 2 * m / 3) { 784c4762a1bSJed Brown j = i - 2 * m / 3; 7859566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 786c4762a1bSJed Brown j = j + user->mx * user->mx; 7879566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Grad, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 788c4762a1bSJed Brown } 789c4762a1bSJed Brown } 790c4762a1bSJed Brown 7919566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(user->Grad, MAT_FINAL_ASSEMBLY)); 7929566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(user->Grad, MAT_FINAL_ASSEMBLY)); 793c4762a1bSJed Brown 794c4762a1bSJed Brown /* Generate arithmetic averaging matrix Av */ 7959566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->Av)); 7969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->Av, PETSC_DECIDE, PETSC_DECIDE, m, n)); 7979566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->Av)); 7989566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(user->Av, 2, NULL, 2, NULL)); 7999566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(user->Av, 2, NULL)); 8009566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(user->Av, &istart, &iend)); 801c4762a1bSJed Brown 802c4762a1bSJed Brown for (i = istart; i < iend; i++) { 803c4762a1bSJed Brown if (i < m / 3) { 804c4762a1bSJed Brown iblock = i / (user->mx - 1); 805c4762a1bSJed Brown j = iblock * user->mx + (i % (user->mx - 1)); 8069566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 807c4762a1bSJed Brown j = j + 1; 8089566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 809c4762a1bSJed Brown } 810c4762a1bSJed Brown if (i >= m / 3 && i < 2 * m / 3) { 811c4762a1bSJed Brown iblock = (i - m / 3) / (user->mx * (user->mx - 1)); 812c4762a1bSJed Brown j = iblock * user->mx * user->mx + ((i - m / 3) % (user->mx * (user->mx - 1))); 8139566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 814c4762a1bSJed Brown j = j + user->mx; 8159566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 816c4762a1bSJed Brown } 817c4762a1bSJed Brown if (i >= 2 * m / 3) { 818c4762a1bSJed Brown j = i - 2 * m / 3; 8199566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 820c4762a1bSJed Brown j = j + user->mx * user->mx; 8219566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Av, 1, &i, 1, &j, &half, INSERT_VALUES)); 822c4762a1bSJed Brown } 823c4762a1bSJed Brown } 824c4762a1bSJed Brown 8259566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(user->Av, MAT_FINAL_ASSEMBLY)); 8269566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(user->Av, MAT_FINAL_ASSEMBLY)); 827c4762a1bSJed Brown 828c4762a1bSJed Brown /* Generate transpose of averaging matrix Av */ 8299566063dSJacob Faibussowitsch PetscCall(MatTranspose(user->Av, MAT_INITIAL_MATRIX, &user->AvT)); 830c4762a1bSJed Brown 8319566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->L)); 8329566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->L, PETSC_DECIDE, PETSC_DECIDE, m + n, n)); 8339566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->L)); 8349566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(user->L, 2, NULL, 2, NULL)); 8359566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(user->L, 2, NULL)); 8369566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(user->L, &istart, &iend)); 837c4762a1bSJed Brown 838c4762a1bSJed Brown for (i = istart; i < iend; i++) { 839c4762a1bSJed Brown if (i < m / 3) { 840c4762a1bSJed Brown iblock = i / (user->mx - 1); 841c4762a1bSJed Brown j = iblock * user->mx + (i % (user->mx - 1)); 8429566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 843c4762a1bSJed Brown j = j + 1; 8449566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 845c4762a1bSJed Brown } 846c4762a1bSJed Brown if (i >= m / 3 && i < 2 * m / 3) { 847c4762a1bSJed Brown iblock = (i - m / 3) / (user->mx * (user->mx - 1)); 848c4762a1bSJed Brown j = iblock * user->mx * user->mx + ((i - m / 3) % (user->mx * (user->mx - 1))); 8499566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 850c4762a1bSJed Brown j = j + user->mx; 8519566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 852c4762a1bSJed Brown } 853c4762a1bSJed Brown if (i >= 2 * m / 3 && i < m) { 854c4762a1bSJed Brown j = i - 2 * m / 3; 8559566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &neg_hinv, INSERT_VALUES)); 856c4762a1bSJed Brown j = j + user->mx * user->mx; 8579566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &hinv, INSERT_VALUES)); 858c4762a1bSJed Brown } 859c4762a1bSJed Brown if (i >= m) { 860c4762a1bSJed Brown j = i - m; 8619566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->L, 1, &i, 1, &j, &sqrt_beta, INSERT_VALUES)); 862c4762a1bSJed Brown } 863c4762a1bSJed Brown } 864c4762a1bSJed Brown 8659566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(user->L, MAT_FINAL_ASSEMBLY)); 8669566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(user->L, MAT_FINAL_ASSEMBLY)); 867c4762a1bSJed Brown 8689566063dSJacob Faibussowitsch PetscCall(MatScale(user->L, PetscPowScalar(h, 1.5))); 869c4762a1bSJed Brown 870c4762a1bSJed Brown /* Generate Div matrix */ 8719566063dSJacob Faibussowitsch PetscCall(MatTranspose(user->Grad, MAT_INITIAL_MATRIX, &user->Div)); 872c4762a1bSJed Brown 873c4762a1bSJed Brown /* Build work vectors and matrices */ 8749566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->S)); 8759566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->S, PETSC_DECIDE, user->mx * user->mx * (user->mx - 1) * 3)); 8769566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->S)); 877c4762a1bSJed Brown 8789566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->lwork)); 8799566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->lwork, PETSC_DECIDE, m + user->mx * user->mx * user->mx)); 8809566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->lwork)); 881c4762a1bSJed Brown 8829566063dSJacob Faibussowitsch PetscCall(MatDuplicate(user->Div, MAT_SHARE_NONZERO_PATTERN, &user->Divwork)); 8839566063dSJacob Faibussowitsch PetscCall(MatDuplicate(user->Av, MAT_SHARE_NONZERO_PATTERN, &user->Avwork)); 884c4762a1bSJed Brown 8859566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->d)); 8869566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->d, PETSC_DECIDE, user->ndata * user->nt)); 8879566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->d)); 888c4762a1bSJed Brown 8899566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->S, &user->Swork)); 8909566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->S, &user->Av_u)); 8919566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->S, &user->Twork)); 8929566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->S, &user->Rwork)); 8939566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->y, &user->ywork)); 8949566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->u, &user->uwork)); 8959566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->u, &user->js_diag)); 8969566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->c, &user->cwork)); 8979566063dSJacob Faibussowitsch PetscCall(VecDuplicate(user->d, &user->dwork)); 898c4762a1bSJed Brown 899c4762a1bSJed Brown /* Create matrix-free shell user->Js for computing A*x */ 9009566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m * user->nt, user->m * user->nt, user, &user->Js)); 9019566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Js, MATOP_MULT, (void (*)(void))StateMatMult)); 9029566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Js, MATOP_DUPLICATE, (void (*)(void))StateMatDuplicate)); 9039566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Js, MATOP_MULT_TRANSPOSE, (void (*)(void))StateMatMultTranspose)); 9049566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Js, MATOP_GET_DIAGONAL, (void (*)(void))StateMatGetDiagonal)); 905c4762a1bSJed Brown 906c4762a1bSJed Brown /* Diagonal blocks of user->Js */ 9079566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m, user->m, user, &user->JsBlock)); 9089566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsBlock, MATOP_MULT, (void (*)(void))StateMatBlockMult)); 909c4762a1bSJed Brown /* Blocks are symmetric */ 9109566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsBlock, MATOP_MULT_TRANSPOSE, (void (*)(void))StateMatBlockMult)); 911c4762a1bSJed Brown 912c4762a1bSJed Brown /* Create a matrix-free shell user->JsBlockPrec for computing (U+D)\D*(L+D)\x, where JsBlock = L+D+U, 913c4762a1bSJed Brown D is diagonal, L is strictly lower triangular, and U is strictly upper triangular. 914c4762a1bSJed Brown This is an SSOR preconditioner for user->JsBlock. */ 9159566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m, user->m, user, &user->JsBlockPrec)); 9169566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsBlockPrec, MATOP_MULT, (void (*)(void))StateMatBlockPrecMult)); 917c4762a1bSJed Brown /* JsBlockPrec is symmetric */ 9189566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsBlockPrec, MATOP_MULT_TRANSPOSE, (void (*)(void))StateMatBlockPrecMult)); 919e9b2f0d4SBarry Smith PetscCall(MatSetOption(user->JsBlockPrec, MAT_SYMMETRIC, PETSC_TRUE)); 9209566063dSJacob Faibussowitsch PetscCall(MatSetOption(user->JsBlockPrec, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 921c4762a1bSJed Brown 922c4762a1bSJed Brown /* Create a matrix-free shell user->Jd for computing B*x */ 9239566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m * user->nt, user->m, user, &user->Jd)); 9249566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Jd, MATOP_MULT, (void (*)(void))DesignMatMult)); 9259566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->Jd, MATOP_MULT_TRANSPOSE, (void (*)(void))DesignMatMultTranspose)); 926c4762a1bSJed Brown 927c4762a1bSJed Brown /* User-defined routines for computing user->Js\x and user->Js^T\x*/ 9289566063dSJacob Faibussowitsch PetscCall(MatCreateShell(PETSC_COMM_WORLD, PETSC_DETERMINE, PETSC_DETERMINE, user->m * user->nt, user->m * user->nt, user, &user->JsInv)); 9299566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsInv, MATOP_MULT, (void (*)(void))StateMatInvMult)); 9309566063dSJacob Faibussowitsch PetscCall(MatShellSetOperation(user->JsInv, MATOP_MULT_TRANSPOSE, (void (*)(void))StateMatInvTransposeMult)); 931c4762a1bSJed Brown 932c4762a1bSJed Brown /* Solver options and tolerances */ 9339566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_WORLD, &user->solver)); 9349566063dSJacob Faibussowitsch PetscCall(KSPSetType(user->solver, KSPCG)); 9359566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(user->solver, user->JsBlock, user->JsBlockPrec)); 9369566063dSJacob Faibussowitsch PetscCall(KSPSetInitialGuessNonzero(user->solver, PETSC_FALSE)); 9379566063dSJacob Faibussowitsch PetscCall(KSPSetTolerances(user->solver, 1e-4, 1e-20, 1e3, 500)); 9389566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(user->solver)); 9399566063dSJacob Faibussowitsch PetscCall(KSPGetPC(user->solver, &user->prec)); 9409566063dSJacob Faibussowitsch PetscCall(PCSetType(user->prec, PCSHELL)); 941c4762a1bSJed Brown 9429566063dSJacob Faibussowitsch PetscCall(PCShellSetApply(user->prec, StateMatBlockPrecMult)); 9439566063dSJacob Faibussowitsch PetscCall(PCShellSetApplyTranspose(user->prec, StateMatBlockPrecMult)); 9449566063dSJacob Faibussowitsch PetscCall(PCShellSetContext(user->prec, user)); 945c4762a1bSJed Brown 946c4762a1bSJed Brown /* Create scatter from y to y_1,y_2,...,y_nt */ 9479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->nt * user->m, &user->yi_scatter)); 9489566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &yi)); 9499566063dSJacob Faibussowitsch PetscCall(VecSetSizes(yi, PETSC_DECIDE, user->mx * user->mx * user->mx)); 9509566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(yi)); 9519566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(yi, user->nt, &user->yi)); 9529566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(yi, user->nt, &user->yiwork)); 953c4762a1bSJed Brown 9549566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user->y, &lo2, &hi2)); 955c4762a1bSJed Brown istart = 0; 956c4762a1bSJed Brown for (i = 0; i < user->nt; i++) { 9579566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user->yi[i], &lo, &hi)); 9589566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo, 1, &is_to_yi)); 9599566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo2 + istart, 1, &is_from_y)); 9609566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(user->y, is_from_y, user->yi[i], is_to_yi, &user->yi_scatter[i])); 961c4762a1bSJed Brown istart = istart + hi - lo; 9629566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_to_yi)); 9639566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_from_y)); 964c4762a1bSJed Brown } 9659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&yi)); 966c4762a1bSJed Brown 967c4762a1bSJed Brown /* Create scatter from d to d_1,d_2,...,d_ns */ 9689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(user->ns * user->ndata, &user->di_scatter)); 9699566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &di)); 9709566063dSJacob Faibussowitsch PetscCall(VecSetSizes(di, PETSC_DECIDE, user->ndata)); 9719566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(di)); 9729566063dSJacob Faibussowitsch PetscCall(VecDuplicateVecs(di, user->ns, &user->di)); 9739566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user->d, &lo2, &hi2)); 974c4762a1bSJed Brown istart = 0; 975c4762a1bSJed Brown for (i = 0; i < user->ns; i++) { 9769566063dSJacob Faibussowitsch PetscCall(VecGetOwnershipRange(user->di[i], &lo, &hi)); 9779566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo, 1, &is_to_di)); 9789566063dSJacob Faibussowitsch PetscCall(ISCreateStride(PETSC_COMM_SELF, hi - lo, lo2 + istart, 1, &is_from_d)); 9799566063dSJacob Faibussowitsch PetscCall(VecScatterCreate(user->d, is_from_d, user->di[i], is_to_di, &user->di_scatter[i])); 980c4762a1bSJed Brown istart = istart + hi - lo; 9819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_to_di)); 9829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&is_from_d)); 983c4762a1bSJed Brown } 9849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&di)); 985c4762a1bSJed Brown 986c4762a1bSJed Brown /* Assemble RHS of forward problem */ 9879566063dSJacob Faibussowitsch PetscCall(VecCopy(bc, user->yiwork[0])); 988*9371c9d4SSatish Balay for (i = 1; i < user->nt; i++) { PetscCall(VecSet(user->yiwork[i], 0.0)); } 9899566063dSJacob Faibussowitsch PetscCall(Gather_i(user->q, user->yiwork, user->yi_scatter, user->nt)); 9909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&bc)); 991c4762a1bSJed Brown 992c4762a1bSJed Brown /* Compute true state function yt given ut */ 9939566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_WORLD, &user->ytrue)); 9949566063dSJacob Faibussowitsch PetscCall(VecSetSizes(user->ytrue, PETSC_DECIDE, n * user->nt)); 9959566063dSJacob Faibussowitsch PetscCall(VecSetFromOptions(user->ytrue)); 996c4762a1bSJed Brown 997c4762a1bSJed Brown /* First compute Av_u = Av*exp(-u) */ 9989566063dSJacob Faibussowitsch PetscCall(VecSet(user->uwork, 0)); 9999566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->utrue)); /* Note: user->utrue */ 10009566063dSJacob Faibussowitsch PetscCall(VecExp(user->uwork)); 10019566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Av_u)); 1002c4762a1bSJed Brown 1003c20d7725SJed Brown /* Symbolic DSG = Div * Grad */ 10049566063dSJacob Faibussowitsch PetscCall(MatProductCreate(user->Div, user->Grad, NULL, &user->DSG)); 10059566063dSJacob Faibussowitsch PetscCall(MatProductSetType(user->DSG, MATPRODUCT_AB)); 10069566063dSJacob Faibussowitsch PetscCall(MatProductSetAlgorithm(user->DSG, "default")); 10079566063dSJacob Faibussowitsch PetscCall(MatProductSetFill(user->DSG, PETSC_DEFAULT)); 10089566063dSJacob Faibussowitsch PetscCall(MatProductSetFromOptions(user->DSG)); 10099566063dSJacob Faibussowitsch PetscCall(MatProductSymbolic(user->DSG)); 1010c20d7725SJed Brown 1011c4762a1bSJed Brown user->dsg_formed = PETSC_TRUE; 1012c4762a1bSJed Brown 1013c20d7725SJed Brown /* Next form DSG = Div*Grad */ 10149566063dSJacob Faibussowitsch PetscCall(MatCopy(user->Div, user->Divwork, SAME_NONZERO_PATTERN)); 10159566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(user->Divwork, NULL, user->Av_u)); 1016c4762a1bSJed Brown if (user->dsg_formed) { 10179566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(user->DSG)); 1018c4762a1bSJed Brown } else { 10199566063dSJacob Faibussowitsch PetscCall(MatMatMult(user->Div, user->Grad, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &user->DSG)); 1020c4762a1bSJed Brown user->dsg_formed = PETSC_TRUE; 1021c4762a1bSJed Brown } 1022c4762a1bSJed Brown /* B = speye(nx^3) + ht*DSG; */ 10239566063dSJacob Faibussowitsch PetscCall(MatScale(user->DSG, user->ht)); 10249566063dSJacob Faibussowitsch PetscCall(MatShift(user->DSG, 1.0)); 1025c4762a1bSJed Brown 1026c4762a1bSJed Brown /* Now solve for ytrue */ 10279566063dSJacob Faibussowitsch PetscCall(StateMatInvMult(user->Js, user->q, user->ytrue)); 1028c4762a1bSJed Brown 1029c4762a1bSJed Brown /* Initial guess y0 for state given u0 */ 1030c4762a1bSJed Brown 1031c4762a1bSJed Brown /* First compute Av_u = Av*exp(-u) */ 10329566063dSJacob Faibussowitsch PetscCall(VecSet(user->uwork, 0)); 10339566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->u)); /* Note: user->u */ 10349566063dSJacob Faibussowitsch PetscCall(VecExp(user->uwork)); 10359566063dSJacob Faibussowitsch PetscCall(MatMult(user->Av, user->uwork, user->Av_u)); 1036c4762a1bSJed Brown 1037c4762a1bSJed Brown /* Next form DSG = Div*S*Grad */ 10389566063dSJacob Faibussowitsch PetscCall(MatCopy(user->Div, user->Divwork, SAME_NONZERO_PATTERN)); 10399566063dSJacob Faibussowitsch PetscCall(MatDiagonalScale(user->Divwork, NULL, user->Av_u)); 1040c4762a1bSJed Brown if (user->dsg_formed) { 10419566063dSJacob Faibussowitsch PetscCall(MatProductNumeric(user->DSG)); 1042c4762a1bSJed Brown } else { 10439566063dSJacob Faibussowitsch PetscCall(MatMatMult(user->Div, user->Grad, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &user->DSG)); 1044c20d7725SJed Brown 1045c4762a1bSJed Brown user->dsg_formed = PETSC_TRUE; 1046c4762a1bSJed Brown } 1047c4762a1bSJed Brown /* B = speye(nx^3) + ht*DSG; */ 10489566063dSJacob Faibussowitsch PetscCall(MatScale(user->DSG, user->ht)); 10499566063dSJacob Faibussowitsch PetscCall(MatShift(user->DSG, 1.0)); 1050c4762a1bSJed Brown 1051c4762a1bSJed Brown /* Now solve for y */ 10529566063dSJacob Faibussowitsch PetscCall(StateMatInvMult(user->Js, user->q, user->y)); 1053c4762a1bSJed Brown 1054c4762a1bSJed Brown /* Construct projection matrix Q, a block diagonal matrix consisting of nt copies of Qblock along the diagonal */ 10559566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user->Qblock)); 10569566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user->Qblock, PETSC_DECIDE, PETSC_DECIDE, user->ndata, n)); 10579566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user->Qblock)); 10589566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(user->Qblock, 8, NULL, 8, NULL)); 10599566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(user->Qblock, 8, NULL)); 1060c4762a1bSJed Brown 1061c4762a1bSJed Brown for (i = 0; i < user->mx; i++) { 1062c4762a1bSJed Brown x[i] = h * (i + 0.5); 1063c4762a1bSJed Brown y[i] = h * (i + 0.5); 1064c4762a1bSJed Brown z[i] = h * (i + 0.5); 1065c4762a1bSJed Brown } 1066c4762a1bSJed Brown 10679566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(user->Qblock, &istart, &iend)); 1068*9371c9d4SSatish Balay nx = user->mx; 1069*9371c9d4SSatish Balay ny = user->mx; 1070*9371c9d4SSatish Balay nz = user->mx; 1071c4762a1bSJed Brown for (i = istart; i < iend; i++) { 1072c4762a1bSJed Brown xri = xr[i]; 1073c4762a1bSJed Brown im = 0; 1074c4762a1bSJed Brown xim = x[im]; 1075c4762a1bSJed Brown while (xri > xim && im < nx) { 1076c4762a1bSJed Brown im = im + 1; 1077c4762a1bSJed Brown xim = x[im]; 1078c4762a1bSJed Brown } 1079c4762a1bSJed Brown indx1 = im - 1; 1080c4762a1bSJed Brown indx2 = im; 1081c4762a1bSJed Brown dx1 = xri - x[indx1]; 1082c4762a1bSJed Brown dx2 = x[indx2] - xri; 1083c4762a1bSJed Brown 1084c4762a1bSJed Brown yri = yr[i]; 1085c4762a1bSJed Brown im = 0; 1086c4762a1bSJed Brown yim = y[im]; 1087c4762a1bSJed Brown while (yri > yim && im < ny) { 1088c4762a1bSJed Brown im = im + 1; 1089c4762a1bSJed Brown yim = y[im]; 1090c4762a1bSJed Brown } 1091c4762a1bSJed Brown indy1 = im - 1; 1092c4762a1bSJed Brown indy2 = im; 1093c4762a1bSJed Brown dy1 = yri - y[indy1]; 1094c4762a1bSJed Brown dy2 = y[indy2] - yri; 1095c4762a1bSJed Brown 1096c4762a1bSJed Brown zri = zr[i]; 1097c4762a1bSJed Brown im = 0; 1098c4762a1bSJed Brown zim = z[im]; 1099c4762a1bSJed Brown while (zri > zim && im < nz) { 1100c4762a1bSJed Brown im = im + 1; 1101c4762a1bSJed Brown zim = z[im]; 1102c4762a1bSJed Brown } 1103c4762a1bSJed Brown indz1 = im - 1; 1104c4762a1bSJed Brown indz2 = im; 1105c4762a1bSJed Brown dz1 = zri - z[indz1]; 1106c4762a1bSJed Brown dz2 = z[indz2] - zri; 1107c4762a1bSJed Brown 1108c4762a1bSJed Brown Dx = x[indx2] - x[indx1]; 1109c4762a1bSJed Brown Dy = y[indy2] - y[indy1]; 1110c4762a1bSJed Brown Dz = z[indz2] - z[indz1]; 1111c4762a1bSJed Brown 1112c4762a1bSJed Brown j = indx1 + indy1 * nx + indz1 * nx * ny; 1113c4762a1bSJed Brown v = (1 - dx1 / Dx) * (1 - dy1 / Dy) * (1 - dz1 / Dz); 11149566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1115c4762a1bSJed Brown 1116c4762a1bSJed Brown j = indx1 + indy1 * nx + indz2 * nx * ny; 1117c4762a1bSJed Brown v = (1 - dx1 / Dx) * (1 - dy1 / Dy) * (1 - dz2 / Dz); 11189566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1119c4762a1bSJed Brown 1120c4762a1bSJed Brown j = indx1 + indy2 * nx + indz1 * nx * ny; 1121c4762a1bSJed Brown v = (1 - dx1 / Dx) * (1 - dy2 / Dy) * (1 - dz1 / Dz); 11229566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1123c4762a1bSJed Brown 1124c4762a1bSJed Brown j = indx1 + indy2 * nx + indz2 * nx * ny; 1125c4762a1bSJed Brown v = (1 - dx1 / Dx) * (1 - dy2 / Dy) * (1 - dz2 / Dz); 11269566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1127c4762a1bSJed Brown 1128c4762a1bSJed Brown j = indx2 + indy1 * nx + indz1 * nx * ny; 1129c4762a1bSJed Brown v = (1 - dx2 / Dx) * (1 - dy1 / Dy) * (1 - dz1 / Dz); 11309566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1131c4762a1bSJed Brown 1132c4762a1bSJed Brown j = indx2 + indy1 * nx + indz2 * nx * ny; 1133c4762a1bSJed Brown v = (1 - dx2 / Dx) * (1 - dy1 / Dy) * (1 - dz2 / Dz); 11349566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1135c4762a1bSJed Brown 1136c4762a1bSJed Brown j = indx2 + indy2 * nx + indz1 * nx * ny; 1137c4762a1bSJed Brown v = (1 - dx2 / Dx) * (1 - dy2 / Dy) * (1 - dz1 / Dz); 11389566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1139c4762a1bSJed Brown 1140c4762a1bSJed Brown j = indx2 + indy2 * nx + indz2 * nx * ny; 1141c4762a1bSJed Brown v = (1 - dx2 / Dx) * (1 - dy2 / Dy) * (1 - dz2 / Dz); 11429566063dSJacob Faibussowitsch PetscCall(MatSetValues(user->Qblock, 1, &i, 1, &j, &v, INSERT_VALUES)); 1143c4762a1bSJed Brown } 11449566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(user->Qblock, MAT_FINAL_ASSEMBLY)); 11459566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(user->Qblock, MAT_FINAL_ASSEMBLY)); 1146c4762a1bSJed Brown 11479566063dSJacob Faibussowitsch PetscCall(MatTranspose(user->Qblock, MAT_INITIAL_MATRIX, &user->QblockT)); 11489566063dSJacob Faibussowitsch PetscCall(MatTranspose(user->L, MAT_INITIAL_MATRIX, &user->LT)); 1149c4762a1bSJed Brown 1150c4762a1bSJed Brown /* Add noise to the measurement data */ 11519566063dSJacob Faibussowitsch PetscCall(VecSet(user->ywork, 1.0)); 11529566063dSJacob Faibussowitsch PetscCall(VecAYPX(user->ywork, user->noise, user->ytrue)); 11539566063dSJacob Faibussowitsch PetscCall(Scatter_i(user->ywork, user->yiwork, user->yi_scatter, user->nt)); 1154c4762a1bSJed Brown for (j = 0; j < user->ns; j++) { 1155c4762a1bSJed Brown i = user->sample_times[j]; 11569566063dSJacob Faibussowitsch PetscCall(MatMult(user->Qblock, user->yiwork[i], user->di[j])); 1157c4762a1bSJed Brown } 11589566063dSJacob Faibussowitsch PetscCall(Gather_i(user->d, user->di, user->di_scatter, user->ns)); 1159c4762a1bSJed Brown 1160c4762a1bSJed Brown /* Now that initial conditions have been set, let the user pass tolerance options to the KSP solver */ 11619566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(user->solver)); 11629566063dSJacob Faibussowitsch PetscCall(PetscFree(x)); 11639566063dSJacob Faibussowitsch PetscCall(PetscFree(y)); 11649566063dSJacob Faibussowitsch PetscCall(PetscFree(z)); 1165c4762a1bSJed Brown PetscFunctionReturn(0); 1166c4762a1bSJed Brown } 1167c4762a1bSJed Brown 1168*9371c9d4SSatish Balay PetscErrorCode ParabolicDestroy(AppCtx *user) { 1169c4762a1bSJed Brown PetscInt i; 1170c4762a1bSJed Brown 1171c4762a1bSJed Brown PetscFunctionBegin; 11729566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Qblock)); 11739566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->QblockT)); 11749566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Div)); 11759566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Divwork)); 11769566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Grad)); 11779566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Av)); 11789566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Avwork)); 11799566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->AvT)); 11809566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->DSG)); 11819566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->L)); 11829566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->LT)); 11839566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&user->solver)); 11849566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Js)); 11859566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->Jd)); 11869566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->JsInv)); 11879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->JsBlock)); 11889566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user->JsBlockPrec)); 11899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->u)); 11909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->uwork)); 11919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->utrue)); 11929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->y)); 11939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->ywork)); 11949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->ytrue)); 11959566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(user->nt, &user->yi)); 11969566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(user->nt, &user->yiwork)); 11979566063dSJacob Faibussowitsch PetscCall(VecDestroyVecs(user->ns, &user->di)); 11989566063dSJacob Faibussowitsch PetscCall(PetscFree(user->yi)); 11999566063dSJacob Faibussowitsch PetscCall(PetscFree(user->yiwork)); 12009566063dSJacob Faibussowitsch PetscCall(PetscFree(user->di)); 12019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->c)); 12029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->cwork)); 12039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->ur)); 12049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->q)); 12059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->d)); 12069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->dwork)); 12079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->lwork)); 12089566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->S)); 12099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->Swork)); 12109566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->Av_u)); 12119566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->Twork)); 12129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->Rwork)); 12139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user->js_diag)); 12149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&user->s_is)); 12159566063dSJacob Faibussowitsch PetscCall(ISDestroy(&user->d_is)); 12169566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&user->state_scatter)); 12179566063dSJacob Faibussowitsch PetscCall(VecScatterDestroy(&user->design_scatter)); 1218*9371c9d4SSatish Balay for (i = 0; i < user->nt; i++) { PetscCall(VecScatterDestroy(&user->yi_scatter[i])); } 1219*9371c9d4SSatish Balay for (i = 0; i < user->ns; i++) { PetscCall(VecScatterDestroy(&user->di_scatter[i])); } 12209566063dSJacob Faibussowitsch PetscCall(PetscFree(user->yi_scatter)); 12219566063dSJacob Faibussowitsch PetscCall(PetscFree(user->di_scatter)); 12229566063dSJacob Faibussowitsch PetscCall(PetscFree(user->sample_times)); 1223c4762a1bSJed Brown PetscFunctionReturn(0); 1224c4762a1bSJed Brown } 1225c4762a1bSJed Brown 1226*9371c9d4SSatish Balay PetscErrorCode ParabolicMonitor(Tao tao, void *ptr) { 1227c4762a1bSJed Brown Vec X; 1228c4762a1bSJed Brown PetscReal unorm, ynorm; 1229c4762a1bSJed Brown AppCtx *user = (AppCtx *)ptr; 1230c4762a1bSJed Brown 1231c4762a1bSJed Brown PetscFunctionBegin; 12329566063dSJacob Faibussowitsch PetscCall(TaoGetSolution(tao, &X)); 12339566063dSJacob Faibussowitsch PetscCall(Scatter(X, user->ywork, user->state_scatter, user->uwork, user->design_scatter)); 12349566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->ywork, -1.0, user->ytrue)); 12359566063dSJacob Faibussowitsch PetscCall(VecAXPY(user->uwork, -1.0, user->utrue)); 12369566063dSJacob Faibussowitsch PetscCall(VecNorm(user->uwork, NORM_2, &unorm)); 12379566063dSJacob Faibussowitsch PetscCall(VecNorm(user->ywork, NORM_2, &ynorm)); 12389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(MPI_COMM_WORLD, "||u-ut||=%g ||y-yt||=%g\n", (double)unorm, (double)ynorm)); 1239c4762a1bSJed Brown PetscFunctionReturn(0); 1240c4762a1bSJed Brown } 1241c4762a1bSJed Brown 1242c4762a1bSJed Brown /*TEST 1243c4762a1bSJed Brown 1244c4762a1bSJed Brown build: 1245c4762a1bSJed Brown requires: !complex 1246c4762a1bSJed Brown 1247c4762a1bSJed Brown test: 1248c4762a1bSJed Brown args: -tao_cmonitor -tao_type lcl -ns 1 -tao_gatol 1.e-4 -ksp_max_it 30 1249c4762a1bSJed Brown requires: !single 1250c4762a1bSJed Brown 1251c4762a1bSJed Brown TEST*/ 1252