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 84cd81d59SMatthew G. Knepley int main(int argc, char **argv) 94cd81d59SMatthew G. Knepley { 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 25*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc, &argv, NULL,help)); 264cd81d59SMatthew G. Knepley /* Create a mesh */ 275f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PETSC_COMM_WORLD, &dm)); 285f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(dm, DMPLEX)); 295f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(dm)); 305f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(dm, NULL, "-dm_view")); 3130602db0SMatthew G. Knepley 325f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetDimension(dm, &dim)); 3330602db0SMatthew G. Knepley i = dim; 345f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetIntArray(NULL, NULL, "-dm_plex_box_faces", faces, &i, NULL)); 355f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL, NULL, "-np", &Np, NULL)); 365f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetBoundingBox(dm, lo, hi)); 3730602db0SMatthew G. Knepley for (i=0;i<dim;i++) { 3830602db0SMatthew G. Knepley h[i] = (hi[i] - lo[i])/faces[i]; 395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF," lo = %g hi = %g n = %D h = %g\n",lo[i],hi[i],faces[i],h[i])); 4030602db0SMatthew G. Knepley } 4130602db0SMatthew G. Knepley 425f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim, Nc, PETSC_FALSE, "", PETSC_DECIDE, &fe)); 435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFESetFromOptions(fe)); 445f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)fe, "fe")); 455f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetField(dm, field, NULL, (PetscObject)fe)); 465f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateDS(dm)); 475f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFEDestroy(&fe)); 484cd81d59SMatthew G. Knepley /* Create particle swarm */ 495f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreate(PETSC_COMM_SELF, &sw)); 505f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetType(sw, DMSWARM)); 515f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetDimension(sw, dim)); 525f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmSetType(sw, DMSWARM_PIC)); 535f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmSetCellDM(sw, dm)); 545f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmRegisterPetscDatatypeField(sw, "w_q", Nc, PETSC_SCALAR)); 555f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmFinalizeFieldRegister(sw)); 565f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmSetLocalSizes(sw, Np, zero)); 575f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(sw)); 585f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void**)&wq)); 595f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords)); 603c611800SMark Adams for (p=0,energy_0=0;p<Np;p++) { 614cd81d59SMatthew G. Knepley coords[p*2+0] = -PetscCosReal((PetscReal)(p+1)/(PetscReal)(Np+1) * PETSC_PI); 624cd81d59SMatthew G. Knepley coords[p*2+1] = PetscSinReal((PetscReal)(p+1)/(PetscReal)(Np+1) * PETSC_PI); 634cd81d59SMatthew G. Knepley wq[p] = 1.0; 643c611800SMark Adams energy_0 += wq[p]*(PetscSqr(coords[p*2+0])+PetscSqr(coords[p*2+1])); 654cd81d59SMatthew G. Knepley } 665f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords)); 675f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void**)&wq)); 685f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmMigrate(sw, removePoints)); 695f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)sw, "Particle Grid")); 705f80ce2aSJacob Faibussowitsch CHKERRQ(DMViewFromOptions(sw, NULL, "-swarm_view")); 713c611800SMark Adams 724cd81d59SMatthew G. Knepley /* Project particles to field */ 734cd81d59SMatthew G. Knepley /* This gives M f = \int_\Omega \phi f, which looks like a rhs for a PDE */ 745f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMassMatrix(sw, dm, &M_p)); 755f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm, &rho)); 765f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)rho, "rho")); 773c611800SMark Adams 785f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmCreateGlobalVectorFromField(sw, "w_q", &f)); 795f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectSetName((PetscObject)f, "weights")); 805f80ce2aSJacob Faibussowitsch CHKERRQ(MatMultTranspose(M_p, f, rho)); 814cd81d59SMatthew G. Knepley 824cd81d59SMatthew G. Knepley /* Visualize mesh field */ 835f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetOutputSequenceNumber(dm, timestep, time)); 845f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(rho, NULL, "-rho_view")); 854cd81d59SMatthew G. Knepley 864cd81d59SMatthew G. Knepley /* Project field to particles */ 874cd81d59SMatthew G. Knepley /* This gives f_p = M_p^+ M f */ 885f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(dm, &rhs)); 895f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(rho, rhs)); /* Identity: M^1 M rho */ 903c611800SMark Adams 915f80ce2aSJacob Faibussowitsch CHKERRQ(KSPCreate(PETSC_COMM_WORLD, &ksp)); 925f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOptionsPrefix(ksp, "ftop_")); 935f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetFromOptions(ksp)); 945f80ce2aSJacob Faibussowitsch CHKERRQ(KSPGetPC(ksp,&pc)); 95*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&is_bjac)); 963c611800SMark Adams if (is_bjac) { 975f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmCreateMassMatrixSquare(sw, dm, &PM_p)); 985f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp, M_p, PM_p)); 993c611800SMark Adams } else { 1005f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSetOperators(ksp, M_p, M_p)); 1013c611800SMark Adams } 1025f80ce2aSJacob Faibussowitsch CHKERRQ(KSPSolveTranspose(ksp, rhs, f)); 1035f80ce2aSJacob Faibussowitsch CHKERRQ(KSPDestroy(&ksp)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rhs)); 1054cd81d59SMatthew G. Knepley 1064cd81d59SMatthew G. Knepley /* Visualize particle field */ 1075f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetOutputSequenceNumber(sw, timestep, time)); 1085f80ce2aSJacob Faibussowitsch CHKERRQ(VecViewFromOptions(f, NULL, "-weights_view")); 1095f80ce2aSJacob Faibussowitsch CHKERRQ(VecNorm(f,NORM_1,&norm)); 1105f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmDestroyGlobalVectorFromField(sw, "w_q", &f)); 1113c611800SMark Adams 1123c611800SMark Adams /* compute energy */ 1135f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmGetField(sw, "w_q", &bs, &dtype, (void**)&wq)); 1145f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmGetField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords)); 1153c611800SMark Adams for (p=0,energy_1=0;p<Np;p++) { 1163c611800SMark Adams energy_1 += wq[p]*(PetscSqr(coords[p*2+0])+PetscSqr(coords[p*2+1])); 1173c611800SMark Adams } 1185f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmRestoreField(sw, "DMSwarmPIC_coor", &bs, &dtype, (void**)&coords)); 1195f80ce2aSJacob Faibussowitsch CHKERRQ(DMSwarmRestoreField(sw, "w_q", &bs, &dtype, (void**)&wq)); 1205f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"Total number = %20.12e. energy = %20.12e error = %20.12e\n", norm, energy_0, (energy_1-energy_0)/energy_0)); 1213c611800SMark Adams /* Cleanup */ 1225f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&M_p)); 1235f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&PM_p)); 1245f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&rho)); 1255f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&sw)); 1265f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&dm)); 127*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 128*b122ec5aSJacob Faibussowitsch return 0; 1294cd81d59SMatthew G. Knepley } 1304cd81d59SMatthew G. Knepley 1314cd81d59SMatthew G. Knepley /*TEST 1324cd81d59SMatthew G. Knepley 1334cd81d59SMatthew G. Knepley build: 1344cd81d59SMatthew G. Knepley requires: !complex 1354cd81d59SMatthew G. Knepley 1364cd81d59SMatthew G. Knepley test: 1374cd81d59SMatthew G. Knepley suffix: 0 1383c611800SMark Adams requires: double triangle 1393c611800SMark 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 1403c611800SMark Adams filter: grep -v DM_ | grep -v atomic 1413c611800SMark Adams 1423c611800SMark Adams test: 1433c611800SMark Adams suffix: bjacobi 1443c611800SMark Adams requires: double triangle 1453c611800SMark 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 1464cd81d59SMatthew G. Knepley filter: grep -v DM_ | grep -v atomic 1474cd81d59SMatthew G. Knepley 1484cd81d59SMatthew G. Knepley TEST*/ 149