1 static char help[] = "First example in homogenization book\n\n"; 2 3 #include <petscsnes.h> 4 #include <petscdmplex.h> 5 #include <petscds.h> 6 #include <petscconvest.h> 7 #include <petscbag.h> 8 9 /* 10 To control the refinement use -dm_plex_box_faces <n> or -dm_refine <k>, or both 11 12 To see the exact and computed solutions 13 14 -compare_view draw -draw_size 500,500 -draw_pause -1 15 16 To see the delay in convergence of the discretization use 17 18 -snes_convergence_estimate -convest_num_refine 7 -convest_monitor 19 20 and to see the proper rate use 21 22 -dm_refine 5 -snes_convergence_estimate -convest_num_refine 2 -convest_monitor 23 */ 24 25 typedef enum {MOD_CONSTANT, MOD_OSCILLATORY, MOD_TANH, NUM_MOD_TYPES} ModType; 26 const char *modTypes[NUM_MOD_TYPES+1] = {"constant", "oscillatory", "tanh", "unknown"}; 27 28 /* Constants */ 29 enum {EPSILON, NUM_CONSTANTS}; 30 31 typedef struct { 32 PetscReal epsilon; /* Wavelength of fine scale oscillation */ 33 } Parameter; 34 35 typedef struct { 36 PetscBag bag; /* Holds problem parameters */ 37 ModType modType; /* Model type */ 38 } AppCtx; 39 40 static PetscErrorCode trig_homogeneous_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 41 { 42 PetscInt d; 43 *u = 1.0; 44 for (d = 0; d < dim; ++d) *u *= PetscSinReal(2.0*PETSC_PI*x[d]); 45 return 0; 46 } 47 48 static PetscErrorCode oscillatory_u(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 49 { 50 Parameter *param = (Parameter *) ctx; 51 const PetscReal eps = param->epsilon; 52 53 u[0] = x[0] - x[0]*x[0] + (eps / (2.*PETSC_PI))*(0.5 - x[0])*PetscSinReal(2.*PETSC_PI*x[0]/eps) + PetscSqr(eps / (2.*PETSC_PI))*(1. - PetscCosReal(2.*PETSC_PI*x[0]/eps)); 54 return 0; 55 } 56 57 static void f0_trig_homogeneous_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 58 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 59 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 60 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 61 { 62 PetscInt d; 63 for (d = 0; d < dim; ++d) { 64 PetscScalar v = 1.; 65 for (PetscInt e = 0; e < dim; e++) { 66 if (e == d) { 67 v *= -4.0*PetscSqr(PETSC_PI)*PetscSinReal(2.0*PETSC_PI*x[d]); 68 } else { 69 v *= PetscSinReal(2.0*PETSC_PI*x[d]); 70 } 71 } 72 f0[0] += v; 73 } 74 } 75 76 static void f1_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 77 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 78 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 79 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 80 { 81 PetscInt d; 82 for (d = 0; d < dim; ++d) f1[d] = u_x[d]; 83 } 84 85 static void g3_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, 86 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 87 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 88 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]) 89 { 90 PetscInt d; 91 for (d = 0; d < dim; ++d) g3[d*dim+d] = 1.0; 92 } 93 94 static void f0_oscillatory_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 95 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 96 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 97 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 98 { 99 f0[0] = -1.; 100 } 101 102 static void f1_oscillatory_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 103 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 104 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 105 PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 106 { 107 const PetscReal eps = PetscRealPart(constants[EPSILON]); 108 109 f1[0] = u_x[0] / (2. + PetscCosReal(2.*PETSC_PI*x[0]/eps)); 110 } 111 112 static void g3_oscillatory_uu(PetscInt dim, PetscInt Nf, PetscInt NfAux, 113 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 114 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 115 PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]) 116 { 117 const PetscReal eps = PetscRealPart(constants[EPSILON]); 118 119 g3[0] = 1. / (2. + PetscCosReal(2.*PETSC_PI*x[0]/eps)); 120 } 121 122 static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 123 { 124 PetscInt mod; 125 PetscErrorCode ierr; 126 127 PetscFunctionBeginUser; 128 options->modType = MOD_CONSTANT; 129 130 ierr = PetscOptionsBegin(comm, "", "Homogenization Problem Options", "DMPLEX");CHKERRQ(ierr); 131 mod = options->modType; 132 ierr = PetscOptionsEList("-mod_type", "The model type", "ex36.c", modTypes, NUM_MOD_TYPES, modTypes[options->modType], &mod, NULL);CHKERRQ(ierr); 133 options->modType = (ModType) mod; 134 ierr = PetscOptionsEnd(); 135 PetscFunctionReturn(0); 136 } 137 138 static PetscErrorCode SetupParameters(MPI_Comm comm, AppCtx *user) 139 { 140 PetscBag bag; 141 Parameter *p; 142 PetscErrorCode ierr; 143 144 PetscFunctionBeginUser; 145 ierr = PetscBagCreate(comm, sizeof(Parameter), &user->bag);CHKERRQ(ierr); 146 ierr = PetscBagGetData(user->bag, (void **) &p);CHKERRQ(ierr); 147 ierr = PetscBagSetName(user->bag, "par", "Homogenization parameters");CHKERRQ(ierr); 148 bag = user->bag; 149 ierr = PetscBagRegisterReal(bag, &p->epsilon, 1.0, "epsilon", "Wavelength of fine scale oscillation");CHKERRQ(ierr); 150 PetscFunctionReturn(0); 151 } 152 153 static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 154 { 155 PetscErrorCode ierr; 156 157 PetscFunctionBeginUser; 158 ierr = DMCreate(comm, dm);CHKERRQ(ierr); 159 ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 160 ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); 161 ierr = DMSetApplicationContext(*dm, user);CHKERRQ(ierr); 162 ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 163 PetscFunctionReturn(0); 164 } 165 166 static PetscErrorCode SetupPrimalProblem(DM dm, AppCtx *user) 167 { 168 PetscDS ds; 169 DMLabel label; 170 PetscSimplePointFunc ex; 171 const PetscInt id = 1; 172 void *ctx; 173 PetscErrorCode ierr; 174 175 PetscFunctionBeginUser; 176 ierr = DMGetDS(dm, &ds);CHKERRQ(ierr); 177 ierr = PetscBagGetData(user->bag, (void **) &ctx);CHKERRQ(ierr); 178 switch (user->modType) { 179 case MOD_CONSTANT: 180 ierr = PetscDSSetResidual(ds, 0, f0_trig_homogeneous_u, f1_u);CHKERRQ(ierr); 181 ierr = PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_uu);CHKERRQ(ierr); 182 ierr = DMGetLabel(dm, "marker", &label);CHKERRQ(ierr); 183 ex = trig_homogeneous_u; 184 ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void)) ex, NULL, ctx, NULL);CHKERRQ(ierr); 185 break; 186 case MOD_OSCILLATORY: 187 ierr = PetscDSSetResidual(ds, 0, f0_oscillatory_u, f1_oscillatory_u);CHKERRQ(ierr); 188 ierr = PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, g3_oscillatory_uu);CHKERRQ(ierr); 189 ierr = DMGetLabel(dm, "marker", &label);CHKERRQ(ierr); 190 ex = oscillatory_u; 191 ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void)) ex, NULL, ctx, NULL);CHKERRQ(ierr); 192 break; 193 default: SETERRQ(PetscObjectComm((PetscObject) ds), PETSC_ERR_ARG_WRONG, "Unsupported model type: %s (%D)", modTypes[PetscMin(user->modType, NUM_MOD_TYPES)], user->modType); 194 } 195 ierr = PetscDSSetExactSolution(ds, 0, ex, ctx);CHKERRQ(ierr); 196 /* Setup constants */ 197 { 198 Parameter *param; 199 PetscScalar constants[NUM_CONSTANTS]; 200 201 ierr = PetscBagGetData(user->bag, (void **) ¶m);CHKERRQ(ierr); 202 203 constants[EPSILON] = param->epsilon; 204 ierr = PetscDSSetConstants(ds, NUM_CONSTANTS, constants);CHKERRQ(ierr); 205 } 206 PetscFunctionReturn(0); 207 } 208 209 static PetscErrorCode SetupDiscretization(DM dm, const char name[], PetscErrorCode (*setup)(DM, AppCtx *), AppCtx *user) 210 { 211 DM cdm = dm; 212 PetscFE fe; 213 PetscBool simplex; 214 PetscInt dim; 215 char prefix[PETSC_MAX_PATH_LEN]; 216 PetscErrorCode ierr; 217 218 PetscFunctionBeginUser; 219 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 220 ierr = DMPlexIsSimplex(dm, &simplex);CHKERRQ(ierr); 221 /* Create finite element */ 222 ierr = PetscSNPrintf(prefix, PETSC_MAX_PATH_LEN, "%s_", name);CHKERRQ(ierr); 223 ierr = PetscFECreateDefault(PETSC_COMM_SELF, dim, 1, simplex, name ? prefix : NULL, -1, &fe);CHKERRQ(ierr); 224 ierr = PetscObjectSetName((PetscObject) fe, name);CHKERRQ(ierr); 225 /* Set discretization and boundary conditions for each mesh */ 226 ierr = DMSetField(dm, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 227 ierr = DMCreateDS(dm);CHKERRQ(ierr); 228 ierr = (*setup)(dm, user);CHKERRQ(ierr); 229 while (cdm) { 230 ierr = DMCopyDisc(dm,cdm);CHKERRQ(ierr); 231 ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); 232 } 233 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 234 PetscFunctionReturn(0); 235 } 236 237 static PetscErrorCode CompareView(Vec u) 238 { 239 DM dm; 240 Vec v[2], lv[2], exact; 241 PetscOptions options; 242 PetscViewer viewer; 243 PetscViewerFormat format; 244 PetscBool flg; 245 PetscInt i; 246 const char *name, *prefix; 247 PetscErrorCode ierr; 248 249 PetscFunctionBeginUser; 250 ierr = VecGetDM(u, &dm);CHKERRQ(ierr); 251 ierr = PetscObjectGetOptions((PetscObject) dm, &options);CHKERRQ(ierr); 252 ierr = PetscObjectGetOptionsPrefix((PetscObject) dm, &prefix);CHKERRQ(ierr); 253 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) dm), options, prefix, "-compare_view", &viewer, &format, &flg); 254 if (flg) { 255 ierr = DMGetGlobalVector(dm, &exact);CHKERRQ(ierr); 256 ierr = DMComputeExactSolution(dm, 0.0, exact, NULL);CHKERRQ(ierr); 257 v[0] = u; 258 v[1] = exact; 259 for (i = 0; i < 2; ++i) { 260 ierr = DMGetLocalVector(dm, &lv[i]);CHKERRQ(ierr); 261 ierr = PetscObjectGetName((PetscObject) v[i], &name);CHKERRQ(ierr); 262 ierr = PetscObjectSetName((PetscObject) lv[i], name);CHKERRQ(ierr); 263 ierr = DMGlobalToLocalBegin(dm, v[i], INSERT_VALUES, lv[i]);CHKERRQ(ierr); 264 ierr = DMGlobalToLocalEnd(dm, v[i], INSERT_VALUES, lv[i]);CHKERRQ(ierr); 265 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, lv[i], 0., NULL, NULL, NULL);CHKERRQ(ierr); 266 } 267 ierr = DMPlexVecView1D(dm, 2, lv, viewer);CHKERRQ(ierr); 268 for (i = 0; i < 2; ++i) {ierr = DMRestoreLocalVector(dm, &lv[i]);CHKERRQ(ierr);} 269 ierr = DMRestoreGlobalVector(dm, &exact);CHKERRQ(ierr); 270 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 271 } 272 PetscFunctionReturn(0); 273 } 274 275 typedef struct 276 { 277 Mat Mcoarse; /* Mass matrix on the coarse space */ 278 Mat Mfine; /* Mass matrix on the fine space */ 279 Mat Ifine; /* Interpolator from coarse to fine */ 280 Vec Iscale; /* Scaling vector for restriction */ 281 KSP kspCoarse; /* Solver for the coarse mass matrix */ 282 Vec tmpfine; /* Temporary vector in the fine space */ 283 Vec tmpcoarse; /* Temporary vector in the coarse space */ 284 } ProjStruct; 285 286 static PetscErrorCode DestroyCoarseProjection(Mat Pi) 287 { 288 ProjStruct *ctx; 289 PetscErrorCode ierr; 290 291 PetscFunctionBegin; 292 ierr = MatShellGetContext(Pi, (void **) &ctx);CHKERRQ(ierr); 293 ierr = MatDestroy(&ctx->Mcoarse);CHKERRQ(ierr); 294 ierr = MatDestroy(&ctx->Mfine);CHKERRQ(ierr); 295 ierr = MatDestroy(&ctx->Ifine);CHKERRQ(ierr); 296 ierr = VecDestroy(&ctx->Iscale);CHKERRQ(ierr); 297 ierr = KSPDestroy(&ctx->kspCoarse);CHKERRQ(ierr); 298 ierr = VecDestroy(&ctx->tmpcoarse);CHKERRQ(ierr); 299 ierr = VecDestroy(&ctx->tmpfine);CHKERRQ(ierr); 300 ierr = PetscFree(ctx);CHKERRQ(ierr); 301 ierr = MatShellSetContext(Pi, NULL);CHKERRQ(ierr); 302 PetscFunctionReturn(0); 303 } 304 305 static PetscErrorCode CoarseProjection(Mat Pi, Vec x, Vec y) 306 { 307 ProjStruct *ctx; 308 PetscErrorCode ierr; 309 310 PetscFunctionBegin; 311 ierr = MatShellGetContext(Pi, (void **) &ctx);CHKERRQ(ierr); 312 ierr = MatMult(ctx->Mfine, x, ctx->tmpfine);CHKERRQ(ierr); 313 ierr = PetscObjectSetName((PetscObject) ctx->tmpfine, "Fine DG RHS");CHKERRQ(ierr); 314 ierr = PetscObjectSetOptionsPrefix((PetscObject) ctx->tmpfine, "fine_dg_");CHKERRQ(ierr); 315 ierr = VecViewFromOptions(ctx->tmpfine, NULL, "-rhs_view");CHKERRQ(ierr); 316 ierr = MatMultTranspose(ctx->Ifine, ctx->tmpfine, ctx->tmpcoarse);CHKERRQ(ierr); 317 ierr = PetscObjectSetName((PetscObject) ctx->tmpcoarse, "Coarse DG RHS");CHKERRQ(ierr); 318 ierr = PetscObjectSetOptionsPrefix((PetscObject) ctx->tmpcoarse, "coarse_dg_");CHKERRQ(ierr); 319 ierr = VecViewFromOptions(ctx->tmpcoarse, NULL, "-rhs_view");CHKERRQ(ierr); 320 ierr = VecPointwiseMult(ctx->tmpcoarse, ctx->Iscale, ctx->tmpcoarse);CHKERRQ(ierr); 321 ierr = VecViewFromOptions(ctx->tmpcoarse, NULL, "-rhs_view");CHKERRQ(ierr); 322 ierr = KSPSolve(ctx->kspCoarse, ctx->tmpcoarse, y);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 326 static PetscErrorCode CreateCoarseProjection(DM dmc, DM dmf, Mat *Pi) 327 { 328 ProjStruct *ctx; 329 PetscInt m, n, M, N; 330 PetscErrorCode ierr; 331 332 PetscFunctionBegin; 333 ierr = PetscMalloc1(1, &ctx);CHKERRQ(ierr); 334 ierr = DMCreateGlobalVector(dmc, &ctx->tmpcoarse);CHKERRQ(ierr); 335 ierr = DMCreateGlobalVector(dmf, &ctx->tmpfine);CHKERRQ(ierr); 336 ierr = VecGetLocalSize(ctx->tmpcoarse, &m);CHKERRQ(ierr); 337 ierr = VecGetSize(ctx->tmpcoarse, &M);CHKERRQ(ierr); 338 ierr = VecGetLocalSize(ctx->tmpfine, &n);CHKERRQ(ierr); 339 ierr = VecGetSize(ctx->tmpfine, &N);CHKERRQ(ierr); 340 ierr = DMCreateMassMatrix(dmc, dmc, &ctx->Mcoarse);CHKERRQ(ierr); 341 ierr = DMCreateMassMatrix(dmf, dmf, &ctx->Mfine);CHKERRQ(ierr); 342 ierr = DMCreateInterpolation(dmc, dmf, &ctx->Ifine, &ctx->Iscale);CHKERRQ(ierr); 343 ierr = KSPCreate(PetscObjectComm((PetscObject) dmc), &ctx->kspCoarse);CHKERRQ(ierr); 344 ierr = PetscObjectSetOptionsPrefix((PetscObject) ctx->kspCoarse, "coarse_");CHKERRQ(ierr); 345 ierr = KSPSetOperators(ctx->kspCoarse, ctx->Mcoarse, ctx->Mcoarse);CHKERRQ(ierr); 346 ierr = KSPSetFromOptions(ctx->kspCoarse);CHKERRQ(ierr); 347 ierr = MatCreateShell(PetscObjectComm((PetscObject) dmc), m, n, M, N, ctx, Pi);CHKERRQ(ierr); 348 ierr = MatShellSetOperation(*Pi, MATOP_DESTROY, (void (*)(void)) DestroyCoarseProjection);CHKERRQ(ierr); 349 ierr = MatShellSetOperation(*Pi, MATOP_MULT, (void (*)(void)) CoarseProjection);CHKERRQ(ierr); 350 PetscFunctionReturn(0); 351 } 352 353 typedef struct 354 { 355 Mat Ifdg; /* Embed the fine space into the DG version */ 356 Mat Pi; /* The L_2 stable projection to the DG coarse space */ 357 Vec tmpc; /* A temporary vector in the DG coarse space */ 358 Vec tmpf; /* A temporary vector in the DG fine space */ 359 } QuasiInterp; 360 361 static PetscErrorCode DestroyQuasiInterpolator(Mat P) 362 { 363 QuasiInterp *ctx; 364 PetscErrorCode ierr; 365 366 PetscFunctionBegin; 367 ierr = MatShellGetContext(P, (void **) &ctx);CHKERRQ(ierr); 368 ierr = MatDestroy(&ctx->Ifdg);CHKERRQ(ierr); 369 ierr = MatDestroy(&ctx->Pi);CHKERRQ(ierr); 370 ierr = VecDestroy(&ctx->tmpc);CHKERRQ(ierr); 371 ierr = VecDestroy(&ctx->tmpf);CHKERRQ(ierr); 372 ierr = PetscFree(ctx);CHKERRQ(ierr); 373 ierr = MatShellSetContext(P, NULL);CHKERRQ(ierr); 374 PetscFunctionReturn(0); 375 } 376 377 static PetscErrorCode QuasiInterpolate(Mat P, Vec x, Vec y) 378 { 379 QuasiInterp *ctx; 380 DM dmcdg, dmc; 381 Vec ly; 382 PetscErrorCode ierr; 383 384 PetscFunctionBegin; 385 ierr = MatShellGetContext(P, (void **) &ctx);CHKERRQ(ierr); 386 ierr = MatMult(ctx->Ifdg, x, ctx->tmpf);CHKERRQ(ierr); 387 388 ierr = PetscObjectSetName((PetscObject) ctx->tmpf, "Fine DG Potential");CHKERRQ(ierr); 389 ierr = PetscObjectSetOptionsPrefix((PetscObject) ctx->tmpf, "fine_dg_");CHKERRQ(ierr); 390 ierr = VecViewFromOptions(ctx->tmpf, NULL, "-vec_view");CHKERRQ(ierr); 391 ierr = MatMult(ctx->Pi, x, ctx->tmpc);CHKERRQ(ierr); 392 393 ierr = PetscObjectSetName((PetscObject) ctx->tmpc, "Coarse DG Potential");CHKERRQ(ierr); 394 ierr = PetscObjectSetOptionsPrefix((PetscObject) ctx->tmpc, "coarse_dg_");CHKERRQ(ierr); 395 ierr = VecViewFromOptions(ctx->tmpc, NULL, "-vec_view");CHKERRQ(ierr); 396 ierr = VecGetDM(ctx->tmpc, &dmcdg);CHKERRQ(ierr); 397 398 ierr = VecGetDM(y, &dmc);CHKERRQ(ierr); 399 ierr = DMGetLocalVector(dmc, &ly);CHKERRQ(ierr); 400 ierr = DMPlexComputeClementInterpolant(dmcdg, ctx->tmpc, ly);CHKERRQ(ierr); 401 ierr = DMLocalToGlobalBegin(dmc, ly, INSERT_VALUES, y);CHKERRQ(ierr); 402 ierr = DMLocalToGlobalEnd(dmc, ly, INSERT_VALUES, y);CHKERRQ(ierr); 403 ierr = DMRestoreLocalVector(dmc, &ly);CHKERRQ(ierr); 404 PetscFunctionReturn(0); 405 } 406 407 static PetscErrorCode CreateQuasiInterpolator(DM dmc, DM dmf, Mat *P) 408 { 409 QuasiInterp *ctx; 410 DM dmcdg, dmfdg; 411 PetscFE fe; 412 Vec x, y; 413 DMPolytopeType ct; 414 PetscInt dim, cStart, m, n, M, N; 415 PetscErrorCode ierr; 416 417 PetscFunctionBegin; 418 ierr = PetscCalloc1(1, &ctx);CHKERRQ(ierr); 419 ierr = DMGetGlobalVector(dmc, &x);CHKERRQ(ierr); 420 ierr = DMGetGlobalVector(dmf, &y);CHKERRQ(ierr); 421 ierr = VecGetLocalSize(x, &m);CHKERRQ(ierr); 422 ierr = VecGetSize(x, &M);CHKERRQ(ierr); 423 ierr = VecGetLocalSize(y, &n);CHKERRQ(ierr); 424 ierr = VecGetSize(y, &N);CHKERRQ(ierr); 425 ierr = DMRestoreGlobalVector(dmc, &x);CHKERRQ(ierr); 426 ierr = DMRestoreGlobalVector(dmf, &y);CHKERRQ(ierr); 427 428 ierr = DMClone(dmf, &dmfdg);CHKERRQ(ierr); 429 ierr = DMGetDimension(dmfdg, &dim);CHKERRQ(ierr); 430 ierr = DMPlexGetHeightStratum(dmfdg, 0, &cStart, NULL);CHKERRQ(ierr); 431 ierr = DMPlexGetCellType(dmfdg, cStart, &ct);CHKERRQ(ierr); 432 ierr = PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, "fine_dg_", PETSC_DETERMINE, &fe);CHKERRQ(ierr); 433 ierr = DMSetField(dmfdg, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 434 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 435 ierr = DMCreateDS(dmfdg);CHKERRQ(ierr); 436 ierr = DMCreateInterpolation(dmf, dmfdg, &ctx->Ifdg, NULL);CHKERRQ(ierr); 437 ierr = DMCreateGlobalVector(dmfdg, &ctx->tmpf);CHKERRQ(ierr); 438 ierr = DMDestroy(&dmfdg);CHKERRQ(ierr); 439 440 ierr = DMClone(dmc, &dmcdg);CHKERRQ(ierr); 441 ierr = DMGetDimension(dmcdg, &dim);CHKERRQ(ierr); 442 ierr = DMPlexGetHeightStratum(dmcdg, 0, &cStart, NULL);CHKERRQ(ierr); 443 ierr = DMPlexGetCellType(dmcdg, cStart, &ct);CHKERRQ(ierr); 444 ierr = PetscFECreateByCell(PETSC_COMM_SELF, dim, 1, ct, "coarse_dg_", PETSC_DETERMINE, &fe);CHKERRQ(ierr); 445 ierr = DMSetField(dmcdg, 0, NULL, (PetscObject) fe);CHKERRQ(ierr); 446 ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); 447 ierr = DMCreateDS(dmcdg);CHKERRQ(ierr); 448 449 ierr = CreateCoarseProjection(dmcdg, dmf, &ctx->Pi);CHKERRQ(ierr); 450 ierr = DMCreateGlobalVector(dmcdg, &ctx->tmpc);CHKERRQ(ierr); 451 ierr = DMDestroy(&dmcdg);CHKERRQ(ierr); 452 453 ierr = MatCreateShell(PetscObjectComm((PetscObject) dmc), m, n, M, N, ctx, P);CHKERRQ(ierr); 454 ierr = MatShellSetOperation(*P, MATOP_DESTROY, (void (*)(void)) DestroyQuasiInterpolator);CHKERRQ(ierr); 455 ierr = MatShellSetOperation(*P, MATOP_MULT, (void (*)(void)) QuasiInterpolate);CHKERRQ(ierr); 456 PetscFunctionReturn(0); 457 } 458 459 static PetscErrorCode CoarseTest(DM dm, Vec u, AppCtx *user) 460 { 461 DM dmc; 462 Mat P; /* The quasi-interpolator to the coarse space */ 463 Vec uc; 464 PetscErrorCode ierr; 465 466 PetscFunctionBegin; 467 if (user->modType == MOD_CONSTANT) PetscFunctionReturn(0); 468 ierr = DMCreate(PetscObjectComm((PetscObject) dm), &dmc);CHKERRQ(ierr); 469 ierr = DMSetType(dmc, DMPLEX);CHKERRQ(ierr); 470 ierr = PetscObjectSetOptionsPrefix((PetscObject) dmc, "coarse_");CHKERRQ(ierr); 471 ierr = DMSetApplicationContext(dmc, user);CHKERRQ(ierr); 472 ierr = DMSetFromOptions(dmc);CHKERRQ(ierr); 473 ierr = DMViewFromOptions(dmc, NULL, "-dm_view");CHKERRQ(ierr); 474 475 ierr = SetupDiscretization(dmc, "potential", SetupPrimalProblem, user);CHKERRQ(ierr); 476 ierr = DMCreateGlobalVector(dmc, &uc);CHKERRQ(ierr); 477 ierr = PetscObjectSetName((PetscObject) uc, "potential");CHKERRQ(ierr); 478 ierr = PetscObjectSetOptionsPrefix((PetscObject) uc, "coarse_");CHKERRQ(ierr); 479 480 ierr = CreateQuasiInterpolator(dmc, dm, &P);CHKERRQ(ierr); 481 #if 1 482 ierr = MatMult(P, u, uc);CHKERRQ(ierr); 483 #else 484 { 485 Mat In; 486 Vec sc; 487 488 ierr = DMCreateInterpolation(dmc, dm, &In, &sc);CHKERRQ(ierr); 489 ierr = MatMultTranspose(In, u, uc);CHKERRQ(ierr); 490 ierr = VecPointwiseMult(uc, sc, uc);CHKERRQ(ierr); 491 ierr = MatDestroy(&In);CHKERRQ(ierr); 492 ierr = VecDestroy(&sc);CHKERRQ(ierr); 493 } 494 #endif 495 ierr = CompareView(uc);CHKERRQ(ierr); 496 497 ierr = MatDestroy(&P);CHKERRQ(ierr); 498 ierr = VecDestroy(&uc);CHKERRQ(ierr); 499 ierr = DMDestroy(&dmc);CHKERRQ(ierr); 500 PetscFunctionReturn(0); 501 } 502 503 int main(int argc, char **argv) 504 { 505 DM dm; /* Problem specification */ 506 SNES snes; /* Nonlinear solver */ 507 Vec u; /* Solutions */ 508 AppCtx user; /* User-defined work context */ 509 PetscErrorCode ierr; 510 511 ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr; 512 ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); 513 ierr = SetupParameters(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); 514 /* Primal system */ 515 ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); 516 ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); 517 ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); 518 ierr = SetupDiscretization(dm, "potential", SetupPrimalProblem, &user);CHKERRQ(ierr); 519 ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr); 520 ierr = VecSet(u, 0.0);CHKERRQ(ierr); 521 ierr = PetscObjectSetName((PetscObject) u, "potential");CHKERRQ(ierr); 522 ierr = DMPlexSetSNESLocalFEM(dm, &user, &user, &user);CHKERRQ(ierr); 523 ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 524 ierr = DMSNESCheckFromOptions(snes, u);CHKERRQ(ierr); 525 ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); 526 ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 527 ierr = VecViewFromOptions(u, NULL, "-potential_view");CHKERRQ(ierr); 528 ierr = CompareView(u);CHKERRQ(ierr); 529 /* Looking at a coarse problem */ 530 ierr = CoarseTest(dm, u, &user);CHKERRQ(ierr); 531 /* Cleanup */ 532 ierr = VecDestroy(&u);CHKERRQ(ierr); 533 ierr = SNESDestroy(&snes);CHKERRQ(ierr); 534 ierr = DMDestroy(&dm);CHKERRQ(ierr); 535 ierr = PetscBagDestroy(&user.bag);CHKERRQ(ierr); 536 ierr = PetscFinalize(); 537 return ierr; 538 } 539 540 /*TEST 541 542 test: 543 suffix: 1d_p1_constant 544 args: -dm_plex_dim 1 -dm_plex_box_faces 4 -potential_petscspace_degree 1 -dmsnes_check 545 546 test: 547 suffix: 1d_p1_constant_conv 548 args: -dm_plex_dim 1 -dm_plex_box_faces 4 -potential_petscspace_degree 1 \ 549 -snes_convergence_estimate -convest_num_refine 2 550 551 test: 552 suffix: 1d_p1_oscillatory 553 args: -mod_type oscillatory -epsilon 0.03125 \ 554 -dm_plex_dim 1 -dm_plex_box_faces 4 -potential_petscspace_degree 1 -dm_refine 2 -dmsnes_check \ 555 -coarse_dm_plex_dim 1 -coarse_dm_plex_box_faces 4 -coarse_dm_plex_hash_location \ 556 -fine_dg_petscspace_degree 1 -fine_dg_petscdualspace_lagrange_continuity 0 \ 557 -coarse_dg_petscspace_degree 1 -coarse_dg_petscdualspace_lagrange_continuity 0 558 559 TEST*/ 560