Actual source code: ex1f90.F90
1: ! Example program demonstrating projection between particle and finite element spaces
2: program DMSwarmTestProjection
3: #include <petsc/finclude/petscdmplex.h>
4: #include <petsc/finclude/petscdmswarm.h>
5: #include <petsc/finclude/petscksp.h>
6: use petscdmplex
7: use petscdmswarm
8: use petscksp
9: implicit none
11: DM :: dm, sw
12: PetscFE :: fe
13: KSP :: ksp
14: Mat :: M_p, M
15: Vec :: f, rho, rhs
16: PetscInt :: dim, Nc = 1, degree = 1, timestep = 0
17: PetscInt :: Np = 100, p, field = 0, zero = 0, bs
18: PetscReal :: time = 0.0, norm
19: PetscBool :: removePoints = PETSC_TRUE
20: PetscDataType :: dtype
21: PetscScalar, pointer :: coords(:)
22: PetscScalar, pointer :: wq(:)
23: PetscErrorCode :: ierr
25: PetscCallA(PetscInitialize(PETSC_NULL_CHARACTER, ierr))
26: PetscCallA(DMCreate(PETSC_COMM_WORLD, dm, ierr))
27: PetscCallA(DMSetType(dm, DMPLEX, ierr))
28: PetscCallA(DMSetFromOptions(dm, ierr))
29: PetscCallA(DMGetDimension(dm, dim, ierr))
30: PetscCallA(DMViewFromOptions(dm, PETSC_NULL_OBJECT, '-dm_view', ierr))
32: ! Create finite element space
33: PetscCallA(PetscFECreateLagrange(PETSC_COMM_SELF, dim, Nc, PETSC_FALSE, degree, PETSC_DETERMINE, fe, ierr))
34: PetscCallA(DMSetField(dm, field, PETSC_NULL_DMLABEL, PetscObjectCast(fe), ierr))
35: PetscCallA(DMCreateDS(dm, ierr))
36: PetscCallA(PetscFEDestroy(fe, ierr))
38: ! Create particle swarm
39: PetscCallA(DMCreate(PETSC_COMM_WORLD, sw, ierr))
40: PetscCallA(DMSetType(sw, DMSWARM, ierr))
41: PetscCallA(DMSetDimension(sw, dim, ierr))
42: PetscCallA(DMSwarmSetType(sw, DMSWARM_PIC, ierr))
43: PetscCallA(DMSwarmSetCellDM(sw, dm, ierr))
44: PetscCallA(DMSwarmRegisterPetscDatatypeField(sw, 'w_q', Nc, PETSC_SCALAR, ierr))
45: PetscCallA(DMSwarmFinalizeFieldRegister(sw, ierr))
46: PetscCallA(DMSwarmSetLocalSizes(sw, Np, zero, ierr))
47: PetscCallA(DMSetFromOptions(sw, ierr))
48: PetscCallA(DMSwarmGetField(sw, 'w_q', bs, dtype, wq, ierr))
49: PetscCallA(DMSwarmGetField(sw, 'DMSwarmPIC_coor', bs, dtype, coords, ierr))
50: do p = 1, Np
51: coords(p*2-1) = -cos(dble(p)/dble(Np+1) * PETSC_PI)
52: coords(p*2-0) = sin(dble(p)/dble(Np+1) * PETSC_PI)
53: wq(p) = 1.0
54: end do
55: PetscCallA(DMSwarmRestoreField(sw, 'DMSwarmPIC_coor', bs, dtype, coords, ierr))
56: PetscCallA(DMSwarmRestoreField(sw, 'w_q', bs, dtype, wq, ierr))
57: PetscCallA(DMSwarmMigrate(sw, removePoints, ierr))
58: PetscCallA(DMSwarmVectorDefineField(sw, 'w_q', ierr))
59: PetscCallA(DMViewFromOptions(sw, PETSC_NULL_OBJECT, '-swarm_view', ierr))
61: ! Project particles to field
62: ! This gives M f = \int_\Omega \phi f, which looks like a rhs for a PDE
63: PetscCallA(DMCreateMassMatrix(sw, dm, M_p, ierr))
64: PetscCallA(DMCreateGlobalVector(dm, rho, ierr))
65: PetscCallA(DMSwarmCreateGlobalVectorFromField(sw, 'w_q', f, ierr))
66: PetscCallA(MatMultTranspose(M_p, f, rho, ierr))
68: ! Visualize mesh field
69: PetscCallA(DMSetOutputSequenceNumber(dm, timestep, time, ierr))
70: PetscCallA(PetscObjectViewFromOptions(PetscObjectCast(rho), PETSC_NULL_OBJECT, '-rho_view', ierr))
72: ! Project field to particles
73: ! This gives f_p = M_p^+ M f
74: PetscCallA(DMCreateMassMatrix(dm, dm, M, ierr))
75: PetscCallA(DMCreateGlobalVector(dm, rhs, ierr))
76: if (.false.) then
77: PetscCallA(MatMult(M, rho, rhs, ierr)) ! this is what you would do for and FE solve
78: else
79: PetscCallA(VecCopy(rho, rhs, ierr)) ! Identity: M^1 M rho
80: end if
81: PetscCallA(KSPCreate(PETSC_COMM_WORLD, ksp, ierr))
82: PetscCallA(KSPSetOptionsPrefix(ksp, 'ftop_', ierr))
83: PetscCallA(KSPSetFromOptions(ksp, ierr))
84: PetscCallA(KSPSetOperators(ksp, M_p, M_p, ierr))
85: PetscCallA(KSPSolveTranspose(ksp, rhs, f, ierr))
86: PetscCallA(KSPDestroy(ksp, ierr))
87: PetscCallA(VecDestroy(rhs, ierr))
88: PetscCallA(MatDestroy(M_p, ierr))
89: PetscCallA(MatDestroy(M, ierr))
91: ! Visualize particle field
92: PetscCallA(DMSetOutputSequenceNumber(sw, timestep, time, ierr))
93: PetscCallA(PetscObjectViewFromOptions(PetscObjectCast(f), PETSC_NULL_OBJECT, '-weights_view', ierr))
94: PetscCallA(VecNorm(f,NORM_1,norm,ierr))
95: print *, 'Total number density = ', norm
96: ! Cleanup
97: PetscCallA(DMSwarmDestroyGlobalVectorFromField(sw, 'w_q', f, ierr))
98: PetscCallA(VecDestroy(rho, ierr))
99: PetscCallA(DMDestroy(sw, ierr))
100: PetscCallA(DMDestroy(dm, ierr))
102: PetscCallA(PetscFinalize(ierr))
103: end program DMSwarmTestProjection
105: !/*TEST
106: ! build:
107: ! requires: defined(PETSC_USING_F90FREEFORM) double !complex
108: !
109: ! test:
110: ! suffix: 0
111: ! requires: double
112: ! args: -dm_plex_simplex 0 -dm_plex_box_faces 40,20 -dm_plex_box_lower -2.0,0.0 -dm_plex_box_upper 2.0,2.0 -ftop_ksp_type lsqr -ftop_pc_type none -dm_view -swarm_view
113: ! filter: grep -v DM_ | grep -v atomic
114: ! filter_output: grep -v atomic
115: !
116: !TEST*/