1c4762a1bSJed Brown static char help[] = "Reduced formulation of the mother problem of PDE-constrained optimisation.\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown /*F 4c4762a1bSJed Brown We solve the mother problem 5c4762a1bSJed Brown 6c4762a1bSJed Brown min 1/2 || y - y_d ||^2_2 + \alpha/2 || u ||^2_2 7c4762a1bSJed Brown 8c4762a1bSJed Brown subject to 9c4762a1bSJed Brown 10c4762a1bSJed Brown - \laplace y = u on \Omega 11c4762a1bSJed Brown y = 0 on \Gamma 12c4762a1bSJed Brown 13c4762a1bSJed Brown where u is in L^2 and y is in H^1_0. 14c4762a1bSJed Brown 15c4762a1bSJed Brown We formulate the reduced problem solely in terms of the control 16c4762a1bSJed Brown by using the state equation to express y in terms of u, and then 17c4762a1bSJed Brown apply LMVM/BLMVM to the resulting reduced problem. 18c4762a1bSJed Brown 19c4762a1bSJed Brown Mesh independence is achieved by configuring the Riesz map for the control 20c4762a1bSJed Brown space. 21c4762a1bSJed Brown 22c4762a1bSJed Brown Example meshes where the Riesz map is crucial can be downloaded from the 23c4762a1bSJed Brown http://people.maths.ox.ac.uk/~farrellp/meshes.tar.gz 24c4762a1bSJed Brown 25c4762a1bSJed Brown Contributed by: Patrick Farrell <patrick.farrell@maths.ox.ac.uk> 26c4762a1bSJed Brown 27c4762a1bSJed Brown Run with e.g.: 28c4762a1bSJed Brown ./ex3 -laplace_ksp_type cg -laplace_pc_type hypre -mat_lmvm_ksp_type cg -mat_lmvm_pc_type gamg -laplace_ksp_monitor_true_residual -tao_monitor -petscspace_degree 1 -tao_converged_reason -tao_gatol 1.0e-9 -dm_view hdf5:solution.h5 -sol_view hdf5:solution.h5::append -use_riesz 1 -f $DATAFILESPATH/meshes/mesh-1.h5 29c4762a1bSJed Brown 30c4762a1bSJed Brown and visualise in paraview with ../../../../petsc_gen_xdmf.py solution.h5. 31c4762a1bSJed Brown 32c4762a1bSJed Brown Toggle the Riesz map (-use_riesz 0) to see the difference setting the Riesz maps makes. 33c4762a1bSJed Brown 34c4762a1bSJed Brown TODO: broken for parallel runs 35c4762a1bSJed Brown F*/ 36c4762a1bSJed Brown 37c4762a1bSJed Brown #include <petsc.h> 38c4762a1bSJed Brown #include <petscfe.h> 39c4762a1bSJed Brown #include <petscviewerhdf5.h> 40c4762a1bSJed Brown 41c4762a1bSJed Brown typedef struct { 42c4762a1bSJed Brown DM dm; 43c4762a1bSJed Brown Mat mass; 44c4762a1bSJed Brown Vec data; 45c4762a1bSJed Brown Vec state; 46c4762a1bSJed Brown Vec tmp1; 47c4762a1bSJed Brown Vec tmp2; 48c4762a1bSJed Brown Vec adjoint; 49c4762a1bSJed Brown Mat laplace; 50c4762a1bSJed Brown KSP ksp_laplace; 51c4762a1bSJed Brown PetscInt num_bc_dofs; 52c4762a1bSJed Brown PetscInt* bc_indices; 53c4762a1bSJed Brown PetscScalar* bc_values; 54c4762a1bSJed Brown PetscBool use_riesz; 55c4762a1bSJed Brown } AppCtx; 56c4762a1bSJed Brown 57c4762a1bSJed Brown static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 58c4762a1bSJed Brown { 59c4762a1bSJed Brown PetscBool flg; 6030602db0SMatthew G. Knepley char filename[2048]; 6130602db0SMatthew G. Knepley PetscErrorCode ierr; 62c4762a1bSJed Brown 63c4762a1bSJed Brown PetscFunctionBeginUser; 64c4762a1bSJed Brown filename[0] = '\0'; 65c4762a1bSJed Brown user->use_riesz = PETSC_TRUE; 66c4762a1bSJed Brown 6730602db0SMatthew G. Knepley ierr = PetscOptionsBegin(comm, "", "Poisson mother problem options", "DMPLEX");CHKERRQ(ierr); 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-use_riesz", "Use the Riesz map to achieve mesh independence", "ex3.c", user->use_riesz, &user->use_riesz, NULL)); 69*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-f", "filename to read", "ex3.c", filename, filename, sizeof(filename), &flg)); 70c4762a1bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 71c4762a1bSJed Brown 72c4762a1bSJed Brown if (!flg) { 73*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(comm, dm)); 74*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(*dm, DMPLEX)); 75c4762a1bSJed Brown } else { 7630602db0SMatthew G. Knepley /* TODO Eliminate this in favor of DMLoad() in new code */ 77c4762a1bSJed Brown #if defined(PETSC_HAVE_HDF5) 78c4762a1bSJed Brown const PetscInt vertices_per_cell = 3; 79c4762a1bSJed Brown PetscViewer viewer; 80c4762a1bSJed Brown Vec coordinates; 81c4762a1bSJed Brown Vec topology; 8230602db0SMatthew G. Knepley PetscInt dim = 2, numCells; 83c4762a1bSJed Brown PetscInt numVertices; 84c4762a1bSJed Brown PetscScalar* coords; 85c4762a1bSJed Brown PetscScalar* topo_f; 86c4762a1bSJed Brown PetscInt* cells; 87c4762a1bSJed Brown PetscInt j; 88c4762a1bSJed Brown DMLabel label; 89c4762a1bSJed Brown 90c4762a1bSJed Brown /* Read in FEniCS HDF5 output */ 91*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerHDF5Open(comm, filename, FILE_MODE_READ, &viewer)); 92c4762a1bSJed Brown 93c4762a1bSJed Brown /* create Vecs to read in the data from H5 */ 94*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm, &coordinates)); 95*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 96*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(coordinates, dim)); 97*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreate(comm, &topology)); 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)topology, "topology")); 99*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetBlockSize(topology, vertices_per_cell)); 100c4762a1bSJed Brown 101c4762a1bSJed Brown /* navigate to the right group */ 102*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerHDF5PushGroup(viewer, "/Mesh/mesh")); 103c4762a1bSJed Brown 104c4762a1bSJed Brown /* Read the Vecs */ 105*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad(coordinates, viewer)); 106*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad(topology, viewer)); 107c4762a1bSJed Brown 108c4762a1bSJed Brown /* do some ugly calculations */ 109*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(topology, &numCells)); 110c4762a1bSJed Brown numCells = numCells / vertices_per_cell; 111*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetSize(coordinates, &numVertices)); 112c4762a1bSJed Brown numVertices = numVertices / dim; 113c4762a1bSJed Brown 114*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(coordinates, &coords)); 115*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(topology, &topo_f)); 116c4762a1bSJed Brown /* and now we have to convert the double representation to integers to pass over, argh */ 117*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(numCells*vertices_per_cell, &cells)); 118c4762a1bSJed Brown for (j = 0; j < numCells*vertices_per_cell; j++) { 119c4762a1bSJed Brown cells[j] = (PetscInt) topo_f[j]; 120c4762a1bSJed Brown } 121c4762a1bSJed Brown 122c4762a1bSJed Brown /* Now create the DM */ 123*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCreateFromCellListPetsc(comm, dim, numCells, numVertices, vertices_per_cell, PETSC_TRUE, cells, dim, coords, dm)); 124c4762a1bSJed Brown /* Check for flipped first cell */ 125c4762a1bSJed Brown { 126c4762a1bSJed Brown PetscReal v0[3], J[9], invJ[9], detJ; 127c4762a1bSJed Brown 128*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(*dm, 0, NULL, v0, J, invJ, &detJ)); 129c4762a1bSJed Brown if (detJ < 0) { 130*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexOrientPoint(*dm, 0, -1)); 131*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexComputeCellGeometryFEM(*dm, 0, NULL, v0, J, invJ, &detJ)); 1323c859ba3SBarry Smith PetscCheck(detJ >= 0,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Something is wrong"); 133c4762a1bSJed Brown } 134c4762a1bSJed Brown } 135*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexOrient(*dm)); 136*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateLabel(*dm, "marker")); 137*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(*dm, "marker", &label)); 138*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexMarkBoundaryFaces(*dm, 1, label)); 139*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexLabelComplete(*dm, label)); 140c4762a1bSJed Brown 141*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 142*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(coordinates, &coords)); 143*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(topology, &topo_f)); 144*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(cells)); 145*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&coordinates)); 146*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&topology)); 147c4762a1bSJed Brown #else 148c4762a1bSJed Brown SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Reconfigure PETSc with --download-hdf5"); 149c4762a1bSJed Brown #endif 150c4762a1bSJed Brown } 151*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(*dm)); 152*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view")); 153c4762a1bSJed Brown PetscFunctionReturn(0); 154c4762a1bSJed Brown } 155c4762a1bSJed Brown 156c4762a1bSJed Brown void mass_kernel(PetscInt dim, PetscInt Nf, PetscInt NfAux, 157c4762a1bSJed Brown const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 158c4762a1bSJed Brown const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 159c4762a1bSJed Brown PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 160c4762a1bSJed Brown { 161c4762a1bSJed Brown g0[0] = 1.0; 162c4762a1bSJed Brown } 163c4762a1bSJed Brown 164c4762a1bSJed Brown void laplace_kernel(PetscInt dim, PetscInt Nf, PetscInt NfAux, 165c4762a1bSJed Brown const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 166c4762a1bSJed Brown const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 167c4762a1bSJed Brown PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g3[]) 168c4762a1bSJed Brown { 169c4762a1bSJed Brown PetscInt d; 170c4762a1bSJed Brown for (d = 0; d < dim; ++d) g3[d*dim+d] = 1.0; 171c4762a1bSJed Brown } 172c4762a1bSJed Brown 173c4762a1bSJed Brown /* data we seek to match */ 174c4762a1bSJed Brown PetscErrorCode data_kernel(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *y, void *ctx) 175c4762a1bSJed Brown { 176c4762a1bSJed Brown *y = 1.0/(2*PETSC_PI*PETSC_PI) * PetscSinReal(PETSC_PI*x[0]) * PetscSinReal(PETSC_PI*x[1]); 177c4762a1bSJed Brown /* the associated control is sin(pi*x[0])*sin(pi*x[1]) */ 178c4762a1bSJed Brown return 0; 179c4762a1bSJed Brown } 180c4762a1bSJed Brown PetscErrorCode zero(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx) 181c4762a1bSJed Brown { 182c4762a1bSJed Brown *u = 0.0; 183c4762a1bSJed Brown return 0; 184c4762a1bSJed Brown } 185c4762a1bSJed Brown 186c4762a1bSJed Brown PetscErrorCode CreateCtx(DM dm, AppCtx* user) 187c4762a1bSJed Brown { 188c4762a1bSJed Brown 189c4762a1bSJed Brown DM dm_mass; 190c4762a1bSJed Brown DM dm_laplace; 191c4762a1bSJed Brown PetscDS prob_mass; 192c4762a1bSJed Brown PetscDS prob_laplace; 193c4762a1bSJed Brown PetscFE fe; 194c4762a1bSJed Brown DMLabel label; 195c4762a1bSJed Brown PetscSection section; 196c4762a1bSJed Brown PetscInt n, k, p, d; 197c4762a1bSJed Brown PetscInt dof, off; 198c4762a1bSJed Brown IS is; 199c4762a1bSJed Brown const PetscInt* points; 200c4762a1bSJed Brown const PetscInt dim = 2; 201c4762a1bSJed Brown const PetscInt id = 1; 202c4762a1bSJed Brown PetscErrorCode (**wtf)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx); 203c4762a1bSJed Brown 204c4762a1bSJed Brown PetscFunctionBeginUser; 205c4762a1bSJed Brown 206c4762a1bSJed Brown /* make the data we seek to match */ 207*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PetscObjectComm((PetscObject) dm), dim, 1, PETSC_TRUE, NULL, 4, &fe)); 208c4762a1bSJed Brown 209*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(dm, 0, NULL, (PetscObject) fe)); 210*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(dm)); 211*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm, &user->data)); 212c4762a1bSJed Brown 213c4762a1bSJed Brown /* ugh, this is hideous */ 214c4762a1bSJed Brown /* y_d = interpolate(Expression("sin(x[0]) + .."), V) */ 215*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc(1 * sizeof(void (*)(const PetscReal[], PetscScalar *, void *)), &wtf)); 216c4762a1bSJed Brown wtf[0] = data_kernel; 217*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMProjectFunction(dm, 0.0, wtf, NULL, INSERT_VALUES, user->data)); 218*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(wtf)); 219c4762a1bSJed Brown 220c4762a1bSJed Brown /* assemble(inner(u, v)*dx), almost */ 221*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, &dm_mass)); 222*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, dm_mass)); 223*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetNumFields(dm_mass, 1)); 224*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, dm_mass)); /* why do I have to do this separately? */ 225*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm_mass, &prob_mass)); 226*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob_mass, 0, 0, mass_kernel, NULL, NULL, NULL)); 227*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetDiscretization(prob_mass, 0, (PetscObject) fe)); 228*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(dm_mass, &user->mass)); 229*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSNESComputeJacobianFEM(dm_mass, user->data, user->mass, user->mass, NULL)); 230*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(user->mass, MAT_SYMMETRIC, PETSC_TRUE)); 231*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dm_mass)); 232c4762a1bSJed Brown 233c4762a1bSJed Brown /* inner(grad(u), grad(v))*dx with homogeneous Dirichlet boundary conditions */ 234*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMClone(dm, &dm_laplace)); 235*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCopyDisc(dm, dm_laplace)); 236*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetNumFields(dm_laplace, 1)); 237*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexCopyCoordinates(dm, dm_laplace)); 238*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDS(dm_laplace, &prob_laplace)); 239*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetJacobian(prob_laplace, 0, 0, NULL, NULL, NULL, laplace_kernel)); 240*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscDSSetDiscretization(prob_laplace, 0, (PetscObject) fe)); 241*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(dm_laplace, &user->laplace)); 242*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMPlexSNESComputeJacobianFEM(dm_laplace, user->data, user->laplace, user->laplace, NULL)); 243c4762a1bSJed Brown 244c4762a1bSJed Brown /* Code from Matt to get the indices associated with the boundary dofs */ 245*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLabel(dm_laplace, "marker", &label)); 246*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMAddBoundary(dm_laplace, DM_BC_ESSENTIAL, "wall", label, 1, &id, 0, 0, NULL, (void (*)(void)) zero, NULL, NULL, NULL)); 247*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalSection(dm_laplace, §ion)); 248*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumSize(label, 1, &n)); 249*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMLabelGetStratumIS(label, 1, &is)); 250*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISGetIndices(is, &points)); 251c4762a1bSJed Brown user->num_bc_dofs = 0; 252c4762a1bSJed Brown for (p = 0; p < n; ++p) { 253*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[p], &dof)); 254c4762a1bSJed Brown user->num_bc_dofs += dof; 255c4762a1bSJed Brown } 256*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(user->num_bc_dofs, &user->bc_indices)); 257c4762a1bSJed Brown for (p = 0, k = 0; p < n; ++p) { 258*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetDof(section, points[p], &dof)); 259*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSectionGetOffset(section, points[p], &off)); 260c4762a1bSJed Brown for (d = 0; d < dof; ++d) user->bc_indices[k++] = off+d; 261c4762a1bSJed Brown } 262*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISRestoreIndices(is, &points)); 263*5f80ce2aSJacob Faibussowitsch CHKERRQ(ISDestroy(&is)); 264*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dm_laplace)); 265c4762a1bSJed Brown 266c4762a1bSJed Brown /* This is how I handle boundary conditions. I can't figure out how to get 267c4762a1bSJed Brown plex to play with the way I want to impose the BCs. This loses symmetry, 268c4762a1bSJed Brown but not in a disastrous way. If someone can improve it, please do! */ 269*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroRows(user->laplace, user->num_bc_dofs, user->bc_indices, 1.0, NULL, NULL)); 270*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscCalloc1(user->num_bc_dofs, &user->bc_values)); 271c4762a1bSJed Brown 272c4762a1bSJed Brown /* also create the KSP for solving the Laplace system */ 273*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PETSC_COMM_WORLD, &user->ksp_laplace)); 274*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(user->ksp_laplace, user->laplace, user->laplace)); 275*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(user->ksp_laplace, "laplace_")); 276*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(user->ksp_laplace)); 277c4762a1bSJed Brown 278c4762a1bSJed Brown /* A bit of setting up the user context */ 279c4762a1bSJed Brown user->dm = dm; 280*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(user->data, &user->state)); 281*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(user->data, &user->adjoint)); 282*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(user->data, &user->tmp1)); 283*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(user->data, &user->tmp2)); 284c4762a1bSJed Brown 285*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 286c4762a1bSJed Brown 287c4762a1bSJed Brown PetscFunctionReturn(0); 288c4762a1bSJed Brown } 289c4762a1bSJed Brown 290c4762a1bSJed Brown PetscErrorCode DestroyCtx(AppCtx* user) 291c4762a1bSJed Brown { 292c4762a1bSJed Brown PetscFunctionBeginUser; 293c4762a1bSJed Brown 294*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&user->mass)); 295*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&user->laplace)); 296*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&user->ksp_laplace)); 297*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->data)); 298*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->state)); 299*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->adjoint)); 300*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->tmp1)); 301*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&user->tmp2)); 302*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(user->bc_indices)); 303*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(user->bc_values)); 304c4762a1bSJed Brown 305c4762a1bSJed Brown PetscFunctionReturn(0); 306c4762a1bSJed Brown } 307c4762a1bSJed Brown 308c4762a1bSJed Brown PetscErrorCode ReducedFunctionGradient(Tao tao, Vec u, PetscReal* func, Vec g, void* userv) 309c4762a1bSJed Brown { 310c4762a1bSJed Brown AppCtx* user = (AppCtx*) userv; 311c4762a1bSJed Brown const PetscReal alpha = 1.0e-6; /* regularisation parameter */ 312c4762a1bSJed Brown PetscReal inner; 313c4762a1bSJed Brown 314c4762a1bSJed Brown PetscFunctionBeginUser; 315c4762a1bSJed Brown 316*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(user->mass, u, user->tmp1)); 317*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(u, user->tmp1, &inner)); /* regularisation contribution to */ 318c4762a1bSJed Brown *func = alpha * 0.5 * inner; /* the functional */ 319c4762a1bSJed Brown 320*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(g, 0.0)); 321*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(g, alpha, user->tmp1)); /* regularisation contribution to the gradient */ 322c4762a1bSJed Brown 323c4762a1bSJed Brown /* Now compute the forward state. */ 324*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(user->tmp1, user->num_bc_dofs, user->bc_indices, user->bc_values, INSERT_VALUES)); 325*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(user->tmp1)); 326*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(user->tmp1)); 327*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(user->ksp_laplace, user->tmp1, user->state)); /* forward solve */ 328c4762a1bSJed Brown 329c4762a1bSJed Brown /* Now compute the adjoint state also. */ 330*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(user->state, user->tmp1)); 331*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(user->tmp1, -1.0, user->data)); 332*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(user->mass, user->tmp1, user->tmp2)); 333*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(user->tmp1, user->tmp2, &inner)); /* misfit contribution to */ 334c4762a1bSJed Brown *func += 0.5 * inner; /* the functional */ 335c4762a1bSJed Brown 336*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValues(user->tmp2, user->num_bc_dofs, user->bc_indices, user->bc_values, INSERT_VALUES)); 337*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(user->tmp2)); 338*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(user->tmp2)); 339*5f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolve(user->ksp_laplace, user->tmp2, user->adjoint)); /* adjoint solve */ 340c4762a1bSJed Brown 341c4762a1bSJed Brown /* And bring it home with the gradient. */ 342*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatMult(user->mass, user->adjoint, user->tmp1)); 343*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(g, 1.0, user->tmp1)); /* adjoint contribution to the gradient */ 344c4762a1bSJed Brown 345c4762a1bSJed Brown PetscFunctionReturn(0); 346c4762a1bSJed Brown } 347c4762a1bSJed Brown 348c4762a1bSJed Brown int main(int argc, char **argv) 349c4762a1bSJed Brown { 350c4762a1bSJed Brown DM dm; 351c4762a1bSJed Brown Tao tao; 352c4762a1bSJed Brown Vec u, lb, ub; 353c4762a1bSJed Brown AppCtx user; 354c4762a1bSJed Brown PetscErrorCode ierr; 355c4762a1bSJed Brown 356c4762a1bSJed Brown ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 358*5f80ce2aSJacob Faibussowitsch CHKERRQ(CreateCtx(dm, &user)); 359c4762a1bSJed Brown 360*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm, &u)); 361*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(u, 0.0)); 362*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &lb)); 363*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(u, &ub)); 364*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(lb, 0.0)); /* satisfied at the minimum anyway */ 365*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(ub, 0.8)); /* a nontrivial upper bound */ 366c4762a1bSJed Brown 367*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoCreate(PETSC_COMM_WORLD, &tao)); 368*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetSolution(tao, u)); 369*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetObjectiveAndGradient(tao,NULL, ReducedFunctionGradient, &user)); 370*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetVariableBounds(tao, lb, ub)); 371*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetType(tao, TAOBLMVM)); 372*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetFromOptions(tao)); 373c4762a1bSJed Brown 374c4762a1bSJed Brown if (user.use_riesz) { 375*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoLMVMSetH0(tao, user.mass)); /* crucial for mesh independence */ 376*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetGradientNorm(tao, user.mass)); 377c4762a1bSJed Brown } 378c4762a1bSJed Brown 379*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSolve(tao)); 380c4762a1bSJed Brown 381*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(dm, NULL, "-dm_view")); 382*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(u, NULL, "-sol_view")); 383c4762a1bSJed Brown 384*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoDestroy(&tao)); 385*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dm)); 386*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&u)); 387*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&lb)); 388*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&ub)); 389*5f80ce2aSJacob Faibussowitsch CHKERRQ(DestroyCtx(&user)); 390c4762a1bSJed Brown ierr = PetscFinalize(); 391c4762a1bSJed Brown return ierr; 392c4762a1bSJed Brown } 393c4762a1bSJed Brown 394c4762a1bSJed Brown /*TEST 395c4762a1bSJed Brown 396c4762a1bSJed Brown build: 397c4762a1bSJed Brown requires: !complex !single 398c4762a1bSJed Brown 399c4762a1bSJed Brown test: 400dfd57a17SPierre Jolivet requires: hdf5 double datafilespath !defined(PETSC_USE_64BIT_INDICES) hypre 40173f7197eSJed Brown args: -laplace_ksp_type cg -laplace_pc_type hypre -laplace_ksp_monitor_true_residual -laplace_ksp_max_it 5 -mat_lmvm_ksp_type cg -mat_lmvm_ksp_rtol 1e-5 -mat_lmvm_pc_type gamg -tao_monitor -petscspace_degree 1 -tao_converged_reason -tao_gatol 1.0e-6 -dm_view hdf5:solution.h5 -sol_view hdf5:solution.h5::append -use_riesz 1 -f $DATAFILESPATH/meshes/mesh-1.h5 402c4762a1bSJed Brown filter: sed -e "s/-nan/nan/g" 403c4762a1bSJed Brown 404c4762a1bSJed Brown test: 405c4762a1bSJed Brown suffix: guess_pod 406c4762a1bSJed Brown requires: double triangle 407074aec55SMark Adams args: -laplace_ksp_type cg -laplace_pc_type gamg -laplace_ksp_monitor_true_residual -laplace_ksp_max_it 8 -laplace_pc_gamg_esteig_ksp_type cg -laplace_pc_gamg_esteig_ksp_max_it 5 -laplace_mg_levels_ksp_chebyshev_esteig 0,0.25,0,1.0 -laplace_ksp_converged_reason -mat_lmvm_ksp_type cg -mat_lmvm_ksp_rtol 1e-5 -mat_lmvm_pc_type gamg -mat_lmvm_pc_gamg_esteig_ksp_type cg -mat_lmvm_pc_gamg_esteig_ksp_max_it 3 -tao_monitor -petscspace_degree 1 -tao_converged_reason -dm_refine 0 -laplace_ksp_guess_type pod -tao_gatol 1e-6 40873f7197eSJed Brown filter: sed -e "s/-nan/nan/g" -e "s/-NaN/nan/g" -e "s/NaN/nan/g" -e "s/CONVERGED_RTOL iterations 9/CONVERGED_RTOL iterations 8/g" -e "s/CONVERGED_RTOL iterations 4/CONVERGED_RTOL iterations 3/g" 409c4762a1bSJed Brown 410c4762a1bSJed Brown TEST*/ 411