xref: /petsc/src/dm/impls/swarm/tutorials/ex1.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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