14cd81d59SMatthew G. Knepley static char help[] = "Example program demonstrating projection between particle and finite element spaces\n\n"; 24cd81d59SMatthew G. Knepley 34cd81d59SMatthew G. Knepley #include "petscdmplex.h" 44cd81d59SMatthew G. Knepley #include "petscds.h" 54cd81d59SMatthew G. Knepley #include "petscdmswarm.h" 64cd81d59SMatthew G. Knepley #include "petscksp.h" 74cd81d59SMatthew G. Knepley 8*d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv) 9*d71ae5a4SJacob Faibussowitsch { 103c611800SMark Adams DM dm, sw; 114cd81d59SMatthew G. Knepley PetscFE fe; 124cd81d59SMatthew G. Knepley KSP ksp; 133c611800SMark Adams PC pc; 143c611800SMark Adams Mat M_p, PM_p = NULL; 153c611800SMark Adams Vec f, rho, rhs; 163c611800SMark Adams PetscInt dim, Nc = 1, timestep = 0, i, faces[3]; 1730602db0SMatthew G. Knepley PetscInt Np = 10, p, field = 0, zero = 0, bs; 183c611800SMark Adams PetscReal time = 0.0, norm, energy_0, energy_1; 1930602db0SMatthew G. Knepley PetscReal lo[3], hi[3], h[3]; 2030602db0SMatthew G. Knepley PetscBool removePoints = PETSC_TRUE; 2130602db0SMatthew G. Knepley PetscReal *wq, *coords; 224cd81d59SMatthew G. Knepley PetscDataType dtype; 233c611800SMark Adams PetscBool is_bjac; 244cd81d59SMatthew G. Knepley 25327415f7SBarry Smith PetscFunctionBeginUser; 269566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 274cd81d59SMatthew G. Knepley /* Create a mesh */ 289566063dSJacob Faibussowitsch PetscCall(DMCreate(PETSC_COMM_WORLD, &dm)); 299566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 309566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(dm)); 319566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 3230602db0SMatthew G. Knepley 339566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3430602db0SMatthew G. Knepley i = dim; 359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetIntArray(NULL, NULL, "-dm_plex_box_faces", faces, &i, NULL)); 369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetInt(NULL, NULL, "-np", &Np, NULL)); 379566063dSJacob Faibussowitsch PetscCall(DMGetBoundingBox(dm, lo, hi)); 3830602db0SMatthew G. Knepley for (i = 0; i < dim; i++) { 3930602db0SMatthew G. Knepley h[i] = (hi[i] - lo[i]) / faces[i]; 4063a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, " lo = %g hi = %g n = %" PetscInt_FMT " h = %g\n", (double)lo[i], (double)hi[i], faces[i], (double)h[i])); 4130602db0SMatthew G. Knepley } 4230602db0SMatthew G. Knepley 439566063dSJacob Faibussowitsch PetscCall(PetscFECreateDefault(PETSC_COMM_SELF, dim, Nc, PETSC_FALSE, "", PETSC_DECIDE, &fe)); 449566063dSJacob Faibussowitsch PetscCall(PetscFESetFromOptions(fe)); 459566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)fe, "fe")); 469566063dSJacob Faibussowitsch PetscCall(DMSetField(dm, field, NULL, (PetscObject)fe)); 479566063dSJacob Faibussowitsch PetscCall(DMCreateDS(dm)); 489566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 494cd81d59SMatthew G. Knepley /* Create particle swarm */ 509566063dSJacob Faibussowitsch PetscCall(DMCreate(PETSC_COMM_SELF, &sw)); 519566063dSJacob Faibussowitsch PetscCall(DMSetType(sw, DMSWARM)); 529566063dSJacob Faibussowitsch PetscCall(DMSetDimension(sw, dim)); 539566063dSJacob Faibussowitsch PetscCall(DMSwarmSetType(sw, DMSWARM_PIC)); 549566063dSJacob Faibussowitsch PetscCall(DMSwarmSetCellDM(sw, dm)); 559566063dSJacob Faibussowitsch PetscCall(DMSwarmRegisterPetscDatatypeField(sw, "w_q", Nc, PETSC_SCALAR)); 569566063dSJacob Faibussowitsch PetscCall(DMSwarmFinalizeFieldRegister(sw)); 579566063dSJacob Faibussowitsch PetscCall(DMSwarmSetLocalSizes(sw, Np, zero)); 589566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sw)); 599566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **)&wq)); 609566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **)&coords)); 613c611800SMark Adams for (p = 0, energy_0 = 0; p < Np; p++) { 624cd81d59SMatthew G. Knepley coords[p * 2 + 0] = -PetscCosReal((PetscReal)(p + 1) / (PetscReal)(Np + 1) * PETSC_PI); 634cd81d59SMatthew G. Knepley coords[p * 2 + 1] = PetscSinReal((PetscReal)(p + 1) / (PetscReal)(Np + 1) * PETSC_PI); 644cd81d59SMatthew G. Knepley wq[p] = 1.0; 653c611800SMark Adams energy_0 += wq[p] * (PetscSqr(coords[p * 2 + 0]) + PetscSqr(coords[p * 2 + 1])); 664cd81d59SMatthew G. Knepley } 679566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **)&coords)); 689566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void **)&wq)); 699566063dSJacob Faibussowitsch PetscCall(DMSwarmMigrate(sw, removePoints)); 709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sw, "Particle Grid")); 719566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sw, NULL, "-swarm_view")); 723c611800SMark Adams 734cd81d59SMatthew G. Knepley /* Project particles to field */ 744cd81d59SMatthew G. Knepley /* This gives M f = \int_\Omega \phi f, which looks like a rhs for a PDE */ 759566063dSJacob Faibussowitsch PetscCall(DMCreateMassMatrix(sw, dm, &M_p)); 769566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &rho)); 779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rho, "rho")); 783c611800SMark Adams 799566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)f, "weights")); 819566063dSJacob Faibussowitsch PetscCall(MatMultTranspose(M_p, f, rho)); 824cd81d59SMatthew G. Knepley 834cd81d59SMatthew G. Knepley /* Visualize mesh field */ 849566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(dm, timestep, time)); 859566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(rho, NULL, "-rho_view")); 864cd81d59SMatthew G. Knepley 874cd81d59SMatthew G. Knepley /* Project field to particles */ 884cd81d59SMatthew G. Knepley /* This gives f_p = M_p^+ M f */ 899566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector(dm, &rhs)); 909566063dSJacob Faibussowitsch PetscCall(VecCopy(rho, rhs)); /* Identity: M^1 M rho */ 913c611800SMark Adams 929566063dSJacob Faibussowitsch PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp)); 939566063dSJacob Faibussowitsch PetscCall(KSPSetOptionsPrefix(ksp, "ftop_")); 949566063dSJacob Faibussowitsch PetscCall(KSPSetFromOptions(ksp)); 959566063dSJacob Faibussowitsch PetscCall(KSPGetPC(ksp, &pc)); 969566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCBJACOBI, &is_bjac)); 973c611800SMark Adams if (is_bjac) { 989566063dSJacob Faibussowitsch PetscCall(DMSwarmCreateMassMatrixSquare(sw, dm, &PM_p)); 999566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, M_p, PM_p)); 1003c611800SMark Adams } else { 1019566063dSJacob Faibussowitsch PetscCall(KSPSetOperators(ksp, M_p, M_p)); 1023c611800SMark Adams } 1039566063dSJacob Faibussowitsch PetscCall(KSPSolveTranspose(ksp, rhs, f)); 1049566063dSJacob Faibussowitsch PetscCall(KSPDestroy(&ksp)); 1059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rhs)); 1064cd81d59SMatthew G. Knepley 1074cd81d59SMatthew G. Knepley /* Visualize particle field */ 1089566063dSJacob Faibussowitsch PetscCall(DMSetOutputSequenceNumber(sw, timestep, time)); 1099566063dSJacob Faibussowitsch PetscCall(VecViewFromOptions(f, NULL, "-weights_view")); 1109566063dSJacob Faibussowitsch PetscCall(VecNorm(f, NORM_1, &norm)); 1119566063dSJacob Faibussowitsch PetscCall(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 1123c611800SMark Adams 1133c611800SMark Adams /* compute energy */ 1149566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void **)&wq)); 1159566063dSJacob Faibussowitsch PetscCall(DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **)&coords)); 116ad540459SPierre Jolivet for (p = 0, energy_1 = 0; p < Np; p++) energy_1 += wq[p] * (PetscSqr(coords[p * 2 + 0]) + PetscSqr(coords[p * 2 + 1])); 1179566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void **)&coords)); 1189566063dSJacob Faibussowitsch PetscCall(DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void **)&wq)); 11963a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "Total number = %20.12e. energy = %20.12e error = %20.12e\n", (double)norm, (double)energy_0, (double)((energy_1 - energy_0) / energy_0))); 1203c611800SMark Adams /* Cleanup */ 1219566063dSJacob Faibussowitsch PetscCall(MatDestroy(&M_p)); 1229566063dSJacob Faibussowitsch PetscCall(MatDestroy(&PM_p)); 1239566063dSJacob Faibussowitsch PetscCall(VecDestroy(&rho)); 1249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sw)); 1259566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dm)); 1269566063dSJacob Faibussowitsch PetscCall(PetscFinalize()); 127b122ec5aSJacob Faibussowitsch return 0; 1284cd81d59SMatthew G. Knepley } 1294cd81d59SMatthew G. Knepley 1304cd81d59SMatthew G. Knepley /*TEST 1314cd81d59SMatthew G. Knepley 1324cd81d59SMatthew G. Knepley build: 1334cd81d59SMatthew G. Knepley requires: !complex 1344cd81d59SMatthew G. Knepley 1354cd81d59SMatthew G. Knepley test: 1364cd81d59SMatthew G. Knepley suffix: 0 1373c611800SMark Adams requires: double triangle 1383c611800SMark Adams args: -dm_plex_simplex 0 -dm_plex_box_faces 4,2 -np 50 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -petscspace_degree 2 -ftop_ksp_type lsqr -ftop_pc_type none -dm_view -swarm_view -ftop_ksp_rtol 1.e-14 1393c611800SMark Adams filter: grep -v DM_ | grep -v atomic 1403c611800SMark Adams 1413c611800SMark Adams test: 1423c611800SMark Adams suffix: bjacobi 1433c611800SMark Adams requires: double triangle 1443c611800SMark Adams args: -dm_plex_simplex 0 -dm_plex_box_faces 4,2 -np 50 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -petscspace_degree 2 -dm_plex_hash_location -ftop_ksp_type lsqr -ftop_pc_type bjacobi -ftop_sub_pc_type lu -ftop_sub_pc_factor_shift_type nonzero -dm_view -swarm_view -ftop_ksp_rtol 1.e-14 1454cd81d59SMatthew G. Knepley filter: grep -v DM_ | grep -v atomic 1464cd81d59SMatthew G. Knepley 1474cd81d59SMatthew G. Knepley TEST*/ 148