PetscErrorCode SetupSection(DM dm, AppCtx *user) { PetscSection section; const PetscInt numFields = 1; PetscInt dim = user->dim; PetscInt numBC = 0; PetscInt bcFields[1] = {0}; IS bcPoints[1] = {NULL}; const PetscInt *numFieldDof[1]; PetscInt numComp[1]; PetscInt *numDof; PetscInt f, d; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscFEGetNumComponents(user->fe, &numComp[0]);CHKERRQ(ierr); ierr = PetscFEGetNumDof(user->fe, &numFieldDof[0]);CHKERRQ(ierr); ierr = PetscMalloc(1*(dim+1) * sizeof(PetscInt), &numDof);CHKERRQ(ierr); for (d = 0; d <= dim; ++d) { numDof[0*(dim+1)+d] = numFieldDof[0][d]; } for (f = 0; f < numFields; ++f) { for (d = 1; d < dim; ++d) { if ((numDof[f*(dim+1)+d] > 0) && !user->interpolate) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); } } ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, §ion);CHKERRQ(ierr); ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); ierr = PetscFree(numDof);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* There is a problem here with uninterpolated meshes. The index in numDof[] is not dimension in this case, but sieve depth. */ PetscErrorCode SetupSection(DM dm, AppCtx *user) { PetscSection section; const PetscInt numFields = NUM_FIELDS; PetscInt dim = user->dim; PetscInt numBC = 0; PetscInt bcFields[1] = {0}; IS bcPoints[1] = {NULL}; PetscInt numComp[NUM_FIELDS]; const PetscInt *numFieldDof[NUM_FIELDS]; PetscInt *numDof; PetscInt f, d; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscFEGetNumComponents(user->fe[0], &numComp[0]);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(user->fe[1], &numComp[1]);CHKERRQ(ierr); ierr = PetscFEGetNumDof(user->fe[0], &numFieldDof[0]);CHKERRQ(ierr); ierr = PetscFEGetNumDof(user->fe[1], &numFieldDof[1]);CHKERRQ(ierr); ierr = PetscMalloc(NUM_FIELDS*(dim+1) * sizeof(PetscInt), &numDof);CHKERRQ(ierr); for (f = 0; f < NUM_FIELDS; ++f) { for (d = 0; d <= dim; ++d) { numDof[f*(dim+1)+d] = numFieldDof[f][d]; } } for (f = 0; f < numFields; ++f) { for (d = 1; d < dim; ++d) { if ((numDof[f*(dim+1)+d] > 0) && !user->interpolate) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); } } if (user->bcType == DIRICHLET) { numBC = 1; ierr = DMPlexGetStratumIS(dm, "marker", 1, &bcPoints[0]);CHKERRQ(ierr); } ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcPoints, §ion);CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 0, "velocity");CHKERRQ(ierr); ierr = PetscSectionSetFieldName(section, 1, "pressure");CHKERRQ(ierr); ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); if (user->bcType == DIRICHLET) { ierr = ISDestroy(&bcPoints[0]);CHKERRQ(ierr); } ierr = PetscFree(numDof);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetupMaterialSection(DM dm, AppCtx *user) { PetscSection section; PetscInt dim = user->dim; PetscInt numBC = 0; PetscInt numComp[1]; const PetscInt *numDof; PetscErrorCode ierr; PetscFunctionBeginUser; if (user->variableCoefficient != COEFF_FIELD) PetscFunctionReturn(0); ierr = PetscFEGetNumComponents(user->feAux[0], &numComp[0]);CHKERRQ(ierr); ierr = PetscFEGetNumDof(user->feAux[0], &numDof);CHKERRQ(ierr); ierr = DMPlexCreateSection(dm, dim, 1, numComp, numDof, numBC, NULL, NULL, NULL, §ion);CHKERRQ(ierr); ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetupElement(DM dm, AppCtx *user) { PetscFE fem; DM K; PetscSpace P; PetscDualSpace Q; PetscReal *B, *D; PetscQuadrature q; const PetscInt dim = user->dim; PetscInt order, numBasisFunc, numBasisComp; PetscErrorCode ierr; PetscFunctionBegin; /* Create space */ ierr = PetscSpaceCreate(PetscObjectComm((PetscObject) dm), &P);CHKERRQ(ierr); ierr = PetscSpaceSetFromOptions(P);CHKERRQ(ierr); ierr = PetscSpacePolynomialSetNumVariables(P, dim);CHKERRQ(ierr); ierr = PetscSpaceSetUp(P);CHKERRQ(ierr); ierr = PetscSpaceGetOrder(P, &order);CHKERRQ(ierr); /* Create dual space */ ierr = PetscDualSpaceCreate(PetscObjectComm((PetscObject) dm), &Q);CHKERRQ(ierr); ierr = PetscDualSpaceCreateReferenceCell(Q, dim, user->simplex, &K);CHKERRQ(ierr); ierr = PetscDualSpaceSetDM(Q, K);CHKERRQ(ierr); ierr = DMDestroy(&K);CHKERRQ(ierr); ierr = PetscDualSpaceSetOrder(Q, order);CHKERRQ(ierr); ierr = PetscDualSpaceSetFromOptions(Q);CHKERRQ(ierr); ierr = PetscDualSpaceSetUp(Q);CHKERRQ(ierr); /* Create quadrature */ ierr = PetscDTGaussJacobiQuadrature(dim, PetscMax(user->qorder, order), -1.0, 1.0, &q);CHKERRQ(ierr); /* Create element */ ierr = PetscFECreate(PetscObjectComm((PetscObject) dm), &fem);CHKERRQ(ierr); ierr = PetscFESetBasisSpace(fem, P);CHKERRQ(ierr); ierr = PetscFESetDualSpace(fem, Q);CHKERRQ(ierr); ierr = PetscFESetNumComponents(fem, user->numComponents);CHKERRQ(ierr); ierr = PetscFESetQuadrature(fem, q);CHKERRQ(ierr); ierr = PetscSpaceDestroy(&P);CHKERRQ(ierr); ierr = PetscDualSpaceDestroy(&Q);CHKERRQ(ierr); ierr = PetscFEGetDimension(fem, &numBasisFunc);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(fem, &numBasisComp);CHKERRQ(ierr); ierr = PetscFEGetDefaultTabulation(fem, &B, &D, NULL);CHKERRQ(ierr); user->fe = fem; PetscFunctionReturn(0); }
int main(int argc, char **argv) { SNES snes; /* nonlinear solver */ DM dm; /* problem definition */ Vec u,r; /* solution, residual vectors */ Mat A,J; /* Jacobian matrix */ MatNullSpace nullSpace; /* May be necessary for pressure */ AppCtx user; /* user-defined work context */ JacActionCtx userJ; /* context for Jacobian MF action */ PetscInt its; /* iterations for convergence */ PetscReal error = 0.0; /* L_2 error in the solution */ PetscInt numComponents = 0, f; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL, help);CHKERRQ(ierr); ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); ierr = SetupElement(dm, &user);CHKERRQ(ierr); for (f = 0; f < NUM_FIELDS; ++f) { PetscInt numComp; ierr = PetscFEGetNumComponents(user.fe[f], &numComp);CHKERRQ(ierr); numComponents += numComp; } ierr = PetscMalloc(NUM_FIELDS * sizeof(void (*)(const PetscReal[], PetscScalar *)), &user.exactFuncs);CHKERRQ(ierr); user.fem.bcFuncs = (void (**)(const PetscReal[], PetscScalar *)) user.exactFuncs; ierr = SetupExactSolution(dm, &user);CHKERRQ(ierr); ierr = SetupSection(dm, &user);CHKERRQ(ierr); ierr = DMPlexCreateClosureIndex(dm, NULL);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr); ierr = VecDuplicate(u, &r);CHKERRQ(ierr); ierr = DMSetMatType(dm,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); if (user.jacobianMF) { PetscInt M, m, N, n; ierr = MatGetSize(J, &M, &N);CHKERRQ(ierr); ierr = MatGetLocalSize(J, &m, &n);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD, &A);CHKERRQ(ierr); ierr = MatSetSizes(A, m, n, M, N);CHKERRQ(ierr); ierr = MatSetType(A, MATSHELL);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatShellSetOperation(A, MATOP_MULT, (void (*)(void))FormJacobianAction);CHKERRQ(ierr); userJ.dm = dm; userJ.J = J; userJ.user = &user; ierr = DMCreateLocalVector(dm, &userJ.u);CHKERRQ(ierr); ierr = DMPlexProjectFunctionLocal(dm, user.fe, user.exactFuncs, INSERT_BC_VALUES, userJ.u);CHKERRQ(ierr); ierr = MatShellSetContext(A, &userJ);CHKERRQ(ierr); } else { A = J; } ierr = CreatePressureNullSpace(dm, &user, &nullSpace);CHKERRQ(ierr); ierr = MatSetNullSpace(J, nullSpace);CHKERRQ(ierr); if (A != J) { ierr = MatSetNullSpace(A, nullSpace);CHKERRQ(ierr); } ierr = DMSNESSetFunctionLocal(dm, (PetscErrorCode (*)(DM,Vec,Vec,void*))DMPlexComputeResidualFEM,&user);CHKERRQ(ierr); ierr = DMSNESSetJacobianLocal(dm, (PetscErrorCode (*)(DM,Vec,Mat,Mat,MatStructure*,void*))DMPlexComputeJacobianFEM,&user);CHKERRQ(ierr); ierr = SNESSetJacobian(snes, A, J, NULL, NULL);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = DMPlexProjectFunction(dm, user.fe, user.exactFuncs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); if (user.showInitial) {ierr = DMVecViewLocal(dm, u, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} if (user.runType == RUN_FULL) { ierr = DMPlexProjectFunction(dm, user.fe, user.initialGuess, INSERT_VALUES, u);CHKERRQ(ierr); if (user.showInitial) {ierr = DMVecViewLocal(dm, u, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} if (user.debug) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes, &its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Number of SNES iterations = %D\n", its);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, u, &error);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %.3g\n", error);CHKERRQ(ierr); if (user.showSolution) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Solution\n");CHKERRQ(ierr); ierr = VecChop(u, 3.0e-9);CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } } else { PetscReal res = 0.0; /* Check discretization error */ ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, u, &error);CHKERRQ(ierr); if (error >= 1.0e-11) { ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n", error);CHKERRQ(ierr); } /* Check residual */ ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); /* Check Jacobian */ { Vec b; MatStructure flag; PetscBool isNull; ierr = SNESComputeJacobian(snes, u, &A, &A, &flag);CHKERRQ(ierr); ierr = MatNullSpaceTest(nullSpace, J, &isNull);CHKERRQ(ierr); if (!isNull) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_PLIB, "The null space calculated for the system operator is invalid."); ierr = VecDuplicate(u, &b);CHKERRQ(ierr); ierr = VecSet(r, 0.0);CHKERRQ(ierr); ierr = SNESComputeFunction(snes, r, b);CHKERRQ(ierr); ierr = MatMult(A, u, r);CHKERRQ(ierr); ierr = VecAXPY(r, 1.0, b);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Au - b = Au + F(0)\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Linear L_2 Residual: %g\n", res);CHKERRQ(ierr); } } if (user.runType == RUN_FULL) { PetscViewer viewer; Vec uLocal; const char *name; ierr = PetscViewerCreate(PETSC_COMM_WORLD, &viewer);CHKERRQ(ierr); ierr = PetscViewerSetType(viewer, PETSCVIEWERVTK);CHKERRQ(ierr); ierr = PetscViewerSetFormat(viewer, PETSC_VIEWER_ASCII_VTK);CHKERRQ(ierr); ierr = PetscViewerFileSetName(viewer, "ex62_sol.vtk");CHKERRQ(ierr); ierr = DMGetLocalVector(dm, &uLocal);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) u, &name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) uLocal, name);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm, u, INSERT_VALUES, uLocal);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm, u, INSERT_VALUES, uLocal);CHKERRQ(ierr); ierr = VecView(uLocal, viewer);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm, &uLocal);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } ierr = PetscFree(user.exactFuncs);CHKERRQ(ierr); ierr = DestroyElement(&user);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); if (user.jacobianMF) { ierr = VecDestroy(&userJ.u);CHKERRQ(ierr); } if (A != J) { ierr = MatDestroy(&A);CHKERRQ(ierr); } ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc, char **argv) { DM dm; /* Problem specification */ DM dmAux; /* Material specification */ SNES snes; /* nonlinear solver */ Vec u,r; /* solution, residual vectors */ Mat A,J; /* Jacobian matrix */ MatNullSpace nullSpace; /* May be necessary for Neumann conditions */ AppCtx user; /* user-defined work context */ JacActionCtx userJ; /* context for Jacobian MF action */ PetscInt its; /* iterations for convergence */ PetscReal error = 0.0; /* L_2 error in the solution */ PetscInt numComponents; PetscErrorCode ierr; ierr = PetscInitialize(&argc, &argv, NULL, help);CHKERRQ(ierr); ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD, &snes);CHKERRQ(ierr); ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); ierr = DMSetApplicationContext(dm, &user);CHKERRQ(ierr); user.fem.fe = user.fe; ierr = PetscFECreateDefault(dm, user.dim, 1, PETSC_TRUE, NULL, -1, &user.fe[0]);CHKERRQ(ierr); if (user.bcType != NEUMANN) { user.fem.feBd = NULL; user.feBd[0] = NULL; } else { user.fem.feBd = user.feBd; ierr = PetscFECreateDefault(dm, user.dim-1, 1, PETSC_TRUE, "bd_", -1, &user.feBd[0]);CHKERRQ(ierr); } ierr = PetscFEGetNumComponents(user.fe[0], &numComponents);CHKERRQ(ierr); ierr = PetscMalloc(NUM_FIELDS * sizeof(void (*)(const PetscReal[], PetscScalar *, void *)), &user.exactFuncs);CHKERRQ(ierr); ierr = SetupProblem(dm, &user);CHKERRQ(ierr); ierr = SetupSection(dm, &user);CHKERRQ(ierr); /* Setup Material */ ierr = DMClone(dm, &dmAux);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(dm, dmAux);CHKERRQ(ierr); if (user.variableCoefficient != COEFF_FIELD) { user.fem.feAux = NULL; user.feAux[0] = NULL; } else { PetscQuadrature q; user.fem.feAux = user.feAux; ierr = PetscFECreateDefault(dmAux, user.dim, 1, PETSC_TRUE, "mat_", -1, &user.feAux[0]);CHKERRQ(ierr); ierr = PetscFEGetQuadrature(user.fe[0], &q);CHKERRQ(ierr); ierr = PetscFESetQuadrature(user.feAux[0], q);CHKERRQ(ierr); } ierr = SetupMaterialSection(dmAux, &user);CHKERRQ(ierr); ierr = SetupMaterial(dm, dmAux, &user);CHKERRQ(ierr); ierr = DMDestroy(&dmAux);CHKERRQ(ierr); ierr = DMCreateGlobalVector(dm, &u);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, "potential");CHKERRQ(ierr); ierr = VecDuplicate(u, &r);CHKERRQ(ierr); ierr = DMSetMatType(dm,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(dm, &J);CHKERRQ(ierr); if (user.jacobianMF) { PetscInt M, m, N, n; ierr = MatGetSize(J, &M, &N);CHKERRQ(ierr); ierr = MatGetLocalSize(J, &m, &n);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD, &A);CHKERRQ(ierr); ierr = MatSetSizes(A, m, n, M, N);CHKERRQ(ierr); ierr = MatSetType(A, MATSHELL);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); #if 0 ierr = MatShellSetOperation(A, MATOP_MULT, (void (*)(void))FormJacobianAction);CHKERRQ(ierr); #endif userJ.dm = dm; userJ.J = J; userJ.user = &user; ierr = DMCreateLocalVector(dm, &userJ.u);CHKERRQ(ierr); ierr = DMPlexProjectFunctionLocal(dm, user.fe, user.exactFuncs, NULL, INSERT_BC_VALUES, userJ.u);CHKERRQ(ierr); ierr = MatShellSetContext(A, &userJ);CHKERRQ(ierr); } else { A = J; } if (user.bcType == NEUMANN) { ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject) dm), PETSC_TRUE, 0, NULL, &nullSpace);CHKERRQ(ierr); ierr = MatSetNullSpace(J, nullSpace);CHKERRQ(ierr); if (A != J) { ierr = MatSetNullSpace(A, nullSpace);CHKERRQ(ierr); } } ierr = DMSNESSetFunctionLocal(dm, (PetscErrorCode (*)(DM,Vec,Vec,void*)) DMPlexComputeResidualFEM, &user);CHKERRQ(ierr); ierr = DMSNESSetJacobianLocal(dm, (PetscErrorCode (*)(DM,Vec,Mat,Mat,void*)) DMPlexComputeJacobianFEM, &user);CHKERRQ(ierr); ierr = SNESSetJacobian(snes, A, J, NULL, NULL);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = DMPlexProjectFunction(dm, user.fe, user.exactFuncs, NULL, INSERT_ALL_VALUES, u);CHKERRQ(ierr); if (user.checkpoint) { #if defined(PETSC_HAVE_HDF5) ierr = PetscViewerHDF5PushGroup(user.checkpoint, "/fields");CHKERRQ(ierr); ierr = VecLoad(u, user.checkpoint);CHKERRQ(ierr); ierr = PetscViewerHDF5PopGroup(user.checkpoint);CHKERRQ(ierr); #endif } ierr = PetscViewerDestroy(&user.checkpoint);CHKERRQ(ierr); if (user.showInitial) { Vec lv; ierr = DMGetLocalVector(dm, &lv);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(dm, u, INSERT_VALUES, lv);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(dm, u, INSERT_VALUES, lv);CHKERRQ(ierr); ierr = DMPrintLocalVec(dm, "Local function", 1.0e-10, lv);CHKERRQ(ierr); ierr = DMRestoreLocalVector(dm, &lv);CHKERRQ(ierr); } if (user.runType == RUN_FULL) { void (*initialGuess[numComponents])(const PetscReal x[], PetscScalar *, void *ctx); PetscInt c; for (c = 0; c < numComponents; ++c) initialGuess[c] = zero; ierr = DMPlexProjectFunction(dm, user.fe, initialGuess, NULL, INSERT_VALUES, u);CHKERRQ(ierr); if (user.debug) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } ierr = SNESSolve(snes, NULL, u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes, &its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Number of SNES iterations = %D\n", its);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, NULL, u, &error);CHKERRQ(ierr); if (error < 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} else {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr);} if (user.showSolution) { ierr = PetscPrintf(PETSC_COMM_WORLD, "Solution\n");CHKERRQ(ierr); ierr = VecChop(u, 3.0e-9);CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } } else if (user.runType == RUN_PERF) { PetscReal res = 0.0; ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); } else { PetscReal res = 0.0; /* Check discretization error */ ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial guess\n");CHKERRQ(ierr); ierr = VecView(u, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = DMPlexComputeL2Diff(dm, user.fe, user.exactFuncs, NULL, u, &error);CHKERRQ(ierr); if (error < 1.0e-11) {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} else {ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Error: %g\n", error);CHKERRQ(ierr);} /* Check residual */ ierr = SNESComputeFunction(snes, u, r);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Initial Residual\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "L_2 Residual: %g\n", res);CHKERRQ(ierr); /* Check Jacobian */ { Vec b; ierr = SNESComputeJacobian(snes, u, A, A);CHKERRQ(ierr); ierr = VecDuplicate(u, &b);CHKERRQ(ierr); ierr = VecSet(r, 0.0);CHKERRQ(ierr); ierr = SNESComputeFunction(snes, r, b);CHKERRQ(ierr); ierr = MatMult(A, u, r);CHKERRQ(ierr); ierr = VecAXPY(r, 1.0, b);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Au - b = Au + F(0)\n");CHKERRQ(ierr); ierr = VecChop(r, 1.0e-10);CHKERRQ(ierr); ierr = VecView(r, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecNorm(r, NORM_2, &res);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD, "Linear L_2 Residual: %g\n", res);CHKERRQ(ierr); } } ierr = VecViewFromOptions(u, NULL, "-vec_view");CHKERRQ(ierr); if (user.bcType == NEUMANN) { ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); } if (user.jacobianMF) { ierr = VecDestroy(&userJ.u);CHKERRQ(ierr); } if (A != J) {ierr = MatDestroy(&A);CHKERRQ(ierr);} ierr = PetscFEDestroy(&user.fe[0]);CHKERRQ(ierr); ierr = PetscFEDestroy(&user.feBd[0]);CHKERRQ(ierr); ierr = PetscFEDestroy(&user.feAux[0]);CHKERRQ(ierr); ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscFree(user.exactFuncs);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode CheckFunctions(DM dm, PetscInt order, Vec u, AppCtx *user) { void (*exactFuncs[1]) (const PetscReal x[], PetscScalar *u, void *ctx); void (*exactFuncDers[1]) (const PetscReal x[], const PetscReal n[], PetscScalar *u, void *ctx); PetscReal n[3] = {1.0, 1.0, 1.0}; PetscReal constants[3] = {1.0, 2.0, 3.0}; void *exactCtxs[3] = {NULL, NULL, NULL}; MPI_Comm comm; PetscInt dim = user->dim, Nc; PetscQuadrature fq; PetscReal error, errorDer, tol = 1.0e-10; PetscBool isPlex, isDA; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) dm, DMPLEX, &isPlex);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) dm, DMDA, &isDA);CHKERRQ(ierr); ierr = PetscFEGetQuadrature(user->fe, &fq);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(user->fe, &Nc);CHKERRQ(ierr); /* Setup functions to approximate */ switch (order) { case 0: exactFuncs[0] = constant; exactFuncDers[0] = constantDer; exactCtxs[0] = &constants[0]; exactCtxs[1] = &constants[1]; exactCtxs[2] = &constants[2]; break; case 1: exactFuncs[0] = linear; exactFuncDers[0] = linearDer; break; case 2: exactFuncs[0] = quadratic; exactFuncDers[0] = quadraticDer; break; default: SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Could not determine functions to test for dimension %d order %d", dim, order); } /* Project function into FE function space */ if (isPlex) { ierr = DMPlexProjectFunction(dm, &user->fe, exactFuncs, exactCtxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); } else if (isDA) { ierr = DMDAProjectFunction(dm, &user->fe, exactFuncs, exactCtxs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "No FEM projection routine for this type of DM"); /* Compare approximation to exact in L_2 */ if (isPlex) { ierr = DMPlexComputeL2Diff(dm, &user->fe, exactFuncs, exactCtxs, u, &error);CHKERRQ(ierr); ierr = DMPlexComputeL2GradientDiff(dm, &user->fe, exactFuncDers, exactCtxs, u, n, &errorDer);CHKERRQ(ierr); } else if (isDA) { ierr = DMDAComputeL2Diff(dm, &user->fe, exactFuncs, exactCtxs, u, &error);CHKERRQ(ierr); } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "No FEM projection routine for this type of DM"); if (error > tol) { ierr = PetscPrintf(comm, "Tests FAIL for order %d at tolerance %g error %g\n", order, tol, error);CHKERRQ(ierr); } else { ierr = PetscPrintf(comm, "Tests pass for order %d at tolerance %g\n", order, tol);CHKERRQ(ierr); } if (errorDer > tol) { ierr = PetscPrintf(comm, "Tests FAIL for order %d derivatives at tolerance %g error %g\n", order, tol, errorDer);CHKERRQ(ierr); } else { ierr = PetscPrintf(comm, "Tests pass for order %d derivatives at tolerance %g\n", order, tol);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode PetscFEGetTabulation_Composite(PetscFE fem, PetscInt npoints, const PetscReal points[], PetscReal *B, PetscReal *D, PetscReal *H) { PetscFE_Composite *cmp = (PetscFE_Composite *) fem->data; DM dm; PetscInt pdim; /* Dimension of FE space P */ PetscInt spdim; /* Dimension of subelement FE space P */ PetscInt dim; /* Spatial dimension */ PetscInt comp; /* Field components */ PetscInt *subpoints; PetscReal *tmpB, *tmpD, *tmpH, *subpoint; PetscInt p, s, d, e, j, k; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscDualSpaceGetDM(fem->dualSpace, &dm);CHKERRQ(ierr); ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = PetscSpaceGetDimension(fem->basisSpace, &spdim);CHKERRQ(ierr); ierr = PetscDualSpaceGetDimension(fem->dualSpace, &pdim);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(fem, &comp);CHKERRQ(ierr); /* Divide points into subelements */ ierr = DMGetWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); ierr = DMGetWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); for (p = 0; p < npoints; ++p) { for (s = 0; s < cmp->numSubelements; ++s) { PetscBool inside; /* Apply transform, and check that point is inside cell */ for (d = 0; d < dim; ++d) { subpoint[d] = -1.0; for (e = 0; e < dim; ++e) subpoint[d] += cmp->invjac[(s*dim + d)*dim+e]*(points[p*dim+e] - cmp->v0[s*dim+e]); } ierr = CellRefinerInCellTest_Internal(cmp->cellRefiner, subpoint, &inside);CHKERRQ(ierr); if (inside) {subpoints[p] = s; break;} } if (s >= cmp->numSubelements) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Point %d was not found in any subelement", p); } ierr = DMRestoreWorkArray(dm, dim, MPIU_REAL, &subpoint);CHKERRQ(ierr); /* Evaluate the prime basis functions at all points */ if (B) {ierr = DMGetWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} if (D) {ierr = DMGetWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} if (H) {ierr = DMGetWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} ierr = PetscSpaceEvaluate(fem->basisSpace, npoints, points, B ? tmpB : NULL, D ? tmpD : NULL, H ? tmpH : NULL);CHKERRQ(ierr); /* Translate to the nodal basis */ if (B) {ierr = PetscMemzero(B, npoints*pdim*comp * sizeof(PetscReal));CHKERRQ(ierr);} if (D) {ierr = PetscMemzero(D, npoints*pdim*comp*dim * sizeof(PetscReal));CHKERRQ(ierr);} if (H) {ierr = PetscMemzero(H, npoints*pdim*comp*dim*dim * sizeof(PetscReal));CHKERRQ(ierr);} for (p = 0; p < npoints; ++p) { const PetscInt s = subpoints[p]; if (B) { /* Multiply by V^{-1} (spdim x spdim) */ for (j = 0; j < spdim; ++j) { const PetscInt i = (p*pdim + cmp->embedding[s*spdim+j])*comp; B[i] = 0.0; for (k = 0; k < spdim; ++k) { B[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpB[p*spdim + k]; } } } if (D) { /* Multiply by V^{-1} (spdim x spdim) */ for (j = 0; j < spdim; ++j) { for (d = 0; d < dim; ++d) { const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim + d; D[i] = 0.0; for (k = 0; k < spdim; ++k) { D[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpD[(p*spdim + k)*dim + d]; } } } } if (H) { /* Multiply by V^{-1} (pdim x pdim) */ for (j = 0; j < spdim; ++j) { for (d = 0; d < dim*dim; ++d) { const PetscInt i = ((p*pdim + cmp->embedding[s*spdim+j])*comp + 0)*dim*dim + d; H[i] = 0.0; for (k = 0; k < spdim; ++k) { H[i] += fem->invV[(s*spdim + k)*spdim+j] * tmpH[(p*spdim + k)*dim*dim + d]; } } } } } ierr = DMRestoreWorkArray(dm, npoints, MPIU_INT, &subpoints);CHKERRQ(ierr); if (B) {ierr = DMRestoreWorkArray(dm, npoints*spdim, MPIU_REAL, &tmpB);CHKERRQ(ierr);} if (D) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim, MPIU_REAL, &tmpD);CHKERRQ(ierr);} if (H) {ierr = DMRestoreWorkArray(dm, npoints*spdim*dim*dim, MPIU_REAL, &tmpH);CHKERRQ(ierr);} PetscFunctionReturn(0); }
PetscErrorCode CheckFunctions(DM dm, PetscInt order, Vec u, AppCtx *user) { void (*exactFuncs[3]) (const PetscReal x[], PetscScalar *u); MPI_Comm comm; PetscInt dim = user->dim, Nc; PetscQuadrature fq; PetscReal error, tol = 1.0e-10; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = PetscFEGetQuadrature(user->fe, &fq);CHKERRQ(ierr); ierr = PetscFEGetNumComponents(user->fe, &Nc);CHKERRQ(ierr); /* Setup functions to approximate */ switch (dim) { case 2: switch (order) { case 0: exactFuncs[0] = constant; exactFuncs[1] = constant; break; case 1: exactFuncs[0] = linear_x; exactFuncs[1] = linear_y; break; case 2: exactFuncs[0] = quadratic_xx; exactFuncs[1] = quadratic_xy; break; default: SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Could not determine functions to test for dimension %d order %d", dim, order); } break; case 3: switch (order) { case 0: exactFuncs[0] = constant; exactFuncs[1] = constant; exactFuncs[2] = constant; break; case 1: exactFuncs[0] = linear_x; exactFuncs[1] = linear_y; exactFuncs[2] = linear_z; break; case 2: exactFuncs[0] = quadratic_xy; exactFuncs[1] = quadratic_yz; exactFuncs[2] = quadratic_zx; break; default: SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Could not determine functions to test for dimension %d order %d", dim, order); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Could not determine functions to test for dimension %d", dim); } /* Project function into FE function space */ ierr = DMPlexProjectFunction(dm, &user->fe, exactFuncs, INSERT_ALL_VALUES, u);CHKERRQ(ierr); /* Compare approximation to exact in L_2 */ ierr = DMPlexComputeL2Diff(dm, &user->fe, exactFuncs, u, &error);CHKERRQ(ierr); if (error > tol) { ierr = PetscPrintf(comm, "Tests FAIL for order %d at tolerance %g error %g\n", order, tol, error);CHKERRQ(ierr); /* SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Input FIAT tabulation cannot resolve functions of order %d, error %g > %g", order, error, tol); */ } else { ierr = PetscPrintf(comm, "Tests pass for order %d at tolerance %g\n", order, tol);CHKERRQ(ierr); } PetscFunctionReturn(0); }