1*53b735f8SJames Wright static char help[] = "Verify isoperiodic cone corrections"; 2*53b735f8SJames Wright 3*53b735f8SJames Wright #include <petscdmplex.h> 4*53b735f8SJames Wright 5*53b735f8SJames Wright // Creates periodic solution on a [0,1] x D domain for D dimension 6*53b735f8SJames Wright static PetscErrorCode project_function(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 7*53b735f8SJames Wright { 8*53b735f8SJames Wright PetscReal x_tot = 0; 9*53b735f8SJames Wright 10*53b735f8SJames Wright PetscFunctionBeginUser; 11*53b735f8SJames Wright for (PetscInt d = 0; d < dim; d++) x_tot += x[d]; 12*53b735f8SJames Wright for (PetscInt c = 0; c < Nc; c++) { 13*53b735f8SJames Wright PetscScalar value = PetscSinReal(2 * M_PI * x_tot); 14*53b735f8SJames Wright if (PetscAbsScalar(value) < 1e-7) value = 0.; 15*53b735f8SJames Wright u[c] = value; 16*53b735f8SJames Wright } 17*53b735f8SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 18*53b735f8SJames Wright } 19*53b735f8SJames Wright 20*53b735f8SJames Wright PetscErrorCode CreateFEField(DM dm) 21*53b735f8SJames Wright { 22*53b735f8SJames Wright PetscInt degree; 23*53b735f8SJames Wright 24*53b735f8SJames Wright PetscFunctionBeginUser; 25*53b735f8SJames Wright { // Get degree of the coords section 26*53b735f8SJames Wright PetscFE fe_coords; 27*53b735f8SJames Wright PetscSpace coord_space; 28*53b735f8SJames Wright DM cdm; 29*53b735f8SJames Wright 30*53b735f8SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 31*53b735f8SJames Wright PetscCall(DMGetField(cdm, 0, NULL, (PetscObject *)&fe_coords)); 32*53b735f8SJames Wright PetscCall(PetscFEGetBasisSpace(fe_coords, &coord_space)); 33*53b735f8SJames Wright PetscCall(PetscSpaceGetDegree(coord_space, °ree, NULL)); 34*53b735f8SJames Wright } 35*53b735f8SJames Wright 36*53b735f8SJames Wright PetscCall(DMClearFields(dm)); 37*53b735f8SJames Wright PetscCall(DMSetLocalSection(dm, NULL)); // See https://gitlab.com/petsc/petsc/-/issues/1669 38*53b735f8SJames Wright 39*53b735f8SJames Wright { // Setup fe to load in the initial condition data 40*53b735f8SJames Wright PetscFE fe; 41*53b735f8SJames Wright PetscInt dim; 42*53b735f8SJames Wright 43*53b735f8SJames Wright PetscCall(DMGetDimension(dm, &dim)); 44*53b735f8SJames Wright PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, 1, PETSC_FALSE, degree, PETSC_DETERMINE, &fe)); 45*53b735f8SJames Wright PetscCall(DMAddField(dm, NULL, (PetscObject)fe)); 46*53b735f8SJames Wright PetscCall(DMCreateDS(dm)); 47*53b735f8SJames Wright PetscCall(PetscFEDestroy(&fe)); 48*53b735f8SJames Wright } 49*53b735f8SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 50*53b735f8SJames Wright } 51*53b735f8SJames Wright 52*53b735f8SJames Wright int main(int argc, char **argv) 53*53b735f8SJames Wright { 54*53b735f8SJames Wright MPI_Comm comm; 55*53b735f8SJames Wright DM dm = NULL; 56*53b735f8SJames Wright Vec V, V_G2L, V_local; 57*53b735f8SJames Wright PetscReal norm; 58*53b735f8SJames Wright PetscErrorCode (*funcs)(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) = {project_function}; 59*53b735f8SJames Wright 60*53b735f8SJames Wright PetscFunctionBeginUser; 61*53b735f8SJames Wright PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 62*53b735f8SJames Wright comm = PETSC_COMM_WORLD; 63*53b735f8SJames Wright 64*53b735f8SJames Wright PetscCall(DMCreate(comm, &dm)); 65*53b735f8SJames Wright PetscCall(DMSetType(dm, DMPLEX)); 66*53b735f8SJames Wright PetscCall(PetscObjectSetName((PetscObject)dm, "ex101_dm")); 67*53b735f8SJames Wright PetscCall(DMSetFromOptions(dm)); 68*53b735f8SJames Wright PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 69*53b735f8SJames Wright PetscCall(CreateFEField(dm)); 70*53b735f8SJames Wright 71*53b735f8SJames Wright // Verify that projected function on global vector (then projected onto local vector) is equal to projected function onto a local vector 72*53b735f8SJames Wright PetscCall(DMGetLocalVector(dm, &V_G2L)); 73*53b735f8SJames Wright PetscCall(DMGetGlobalVector(dm, &V)); 74*53b735f8SJames Wright PetscCall(DMProjectFunction(dm, 0, &funcs, NULL, INSERT_VALUES, V)); 75*53b735f8SJames Wright PetscCall(DMGlobalToLocal(dm, V, INSERT_VALUES, V_G2L)); 76*53b735f8SJames Wright 77*53b735f8SJames Wright PetscCall(DMGetLocalVector(dm, &V_local)); 78*53b735f8SJames Wright PetscCall(DMProjectFunctionLocal(dm, 0, &funcs, NULL, INSERT_VALUES, V_local)); 79*53b735f8SJames Wright 80*53b735f8SJames Wright PetscCall(VecAXPY(V_local, -1, V_G2L)); 81*53b735f8SJames Wright PetscCall(VecNorm(V_local, NORM_2, &norm)); 82*53b735f8SJames Wright PetscReal tol = PetscDefined(USE_REAL___FLOAT128) ? 1e-12 : 1e4 * PETSC_MACHINE_EPSILON; 83*53b735f8SJames Wright PetscCheck(norm < tol, PETSC_COMM_SELF, PETSC_ERR_PLIB, "GlobalToLocal result does not match Local projection by norm %g", (double)norm); 84*53b735f8SJames Wright 85*53b735f8SJames Wright PetscCall(DMRestoreGlobalVector(dm, &V)); 86*53b735f8SJames Wright PetscCall(DMRestoreLocalVector(dm, &V_G2L)); 87*53b735f8SJames Wright PetscCall(DMRestoreLocalVector(dm, &V_local)); 88*53b735f8SJames Wright PetscCall(DMDestroy(&dm)); 89*53b735f8SJames Wright 90*53b735f8SJames Wright PetscCall(PetscFinalize()); 91*53b735f8SJames Wright return 0; 92*53b735f8SJames Wright } 93*53b735f8SJames Wright 94*53b735f8SJames Wright /*TEST 95*53b735f8SJames Wright 96*53b735f8SJames Wright test: 97*53b735f8SJames Wright nsize: 2 98*53b735f8SJames Wright args: -dm_plex_shape zbox -dm_plex_simplex 0 -dm_plex_dim 3 -dm_plex_box_faces 1,2,3 -dm_coord_space -dm_coord_petscspace_degree 3 99*53b735f8SJames Wright args: -dm_plex_box_bd periodic,periodic,periodic -dm_view ::ascii_info_detail -petscpartitioner_type simple 100*53b735f8SJames Wright 101*53b735f8SJames Wright test: 102*53b735f8SJames Wright requires: cgns 103*53b735f8SJames Wright suffix: cgns 104*53b735f8SJames Wright nsize: 3 105*53b735f8SJames Wright args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/2x2x2_Q3_wave.cgns -dm_plex_cgns_parallel -dm_view ::ascii_info_detail -dm_plex_box_label true -dm_plex_box_label_bd periodic,periodic,periodic -petscpartitioner_type simple 106*53b735f8SJames Wright 107*53b735f8SJames Wright TEST*/ 108