MPI-AMRVAC 3.1
The MPI - Adaptive Mesh Refinement - Versatile Advection Code (development version)
Loading...
Searching...
No Matches
mod_particle_sample.t
Go to the documentation of this file.
1!> Scattered sampling based on fixed- or moving-particle interpolation
2!> By Fabio Bacchini (2020)
5
6 private
7
8 public :: sample_init
10
11contains
12
13 subroutine sample_init()
15 integer :: idir
16
17 ngridvars=nw
18
19 particles_fill_gridvars => sample_fill_gridvars
20
21 if (associated(particles_define_additional_gridvars)) then
23 end if
24
25 particles_integrate => sample_integrate_particles
26
27 end subroutine sample_init
28
30 ! initialise the particles (=fixed interpolation points)
34
35 double precision :: x(3, num_particles)
36 double precision :: v(3, num_particles)
37 double precision :: q(num_particles)
38 double precision :: m(num_particles)
39 double precision :: rrd(num_particles,ndir)
40 double precision :: w(ixg^t,1:nw)
41 double precision :: defpayload(ndefpayload)
42 double precision :: usrpayload(nusrpayload)
43 integer :: n, idir, igrid, ipe_particle, nparticles_local
44 logical :: follow(num_particles), check
45
46 follow = .false.
47 x = 0.0d0
48
49 if (mype==0) then
50 if (.not. associated(usr_create_particles)) then
51 ! Randomly distributed
52 do idir=1,ndir
53 do n = 1, num_particles
54 rrd(n,idir) = rng%unif_01()
55 end do
56 end do
57 do n=1, num_particles
58 {^d&x(^d,n) = xprobmin^d + rrd(n+1,^d) * (xprobmax^d - xprobmin^d)\}
59 end do
60 else
61 call usr_create_particles(num_particles, x, v, q, m, follow)
62 end if
63 end if
64
65 call mpi_bcast(x,3*num_particles,mpi_double_precision,0,icomm,ierrmpi)
66 call mpi_bcast(follow,num_particles,mpi_logical,0,icomm,ierrmpi)
67
68 nparticles_local = 0
69
70 do n=1,num_particles
71 call find_particle_ipe(x(:,n),igrid,ipe_particle)
72 particle(n)%igrid = igrid
73 particle(n)%ipe = ipe_particle
74
75 if(ipe_particle == mype) then
76 check = .true.
77
78 ! Check for user-defined modifications or rejection conditions
79 if (associated(usr_check_particle)) call usr_check_particle(igrid, x(:,n), v(:,n), q(n), m(n), follow(n), check)
80 if (check) then
82 else
83 cycle
84 end if
85
86 nparticles_local = nparticles_local + 1
87
88 allocate(particle(n)%self)
89 particle(n)%self%follow = follow(n)
90 particle(n)%self%index = n
91 particle(n)%self%time = global_time
92 particle(n)%self%dt = 0.0d0
93 particle(n)%self%x = 0.d0
94 particle(n)%self%x(:) = x(:,n)
95 particle(n)%self%u(:) = 0.d0
96
97 allocate(particle(n)%payload(npayload))
98 call sample_update_payload(igrid,x(:,n),v(:,n),q(n),m(n),defpayload,ndefpayload,0.d0)
99 particle(n)%payload(1:ndefpayload) = defpayload
100 if (associated(usr_update_payload)) then
101 call usr_update_payload(igrid,x(:,n),v(:,n),q(n),m(n),usrpayload,nusrpayload,0.d0)
102 particle(n)%payload(ndefpayload+1:npayload)=usrpayload
103 end if
104 end if
105
106 end do
107
108 call mpi_allreduce(nparticles_local,nparticles,1,mpi_integer,mpi_sum,icomm,ierrmpi)
109
110 ! write the first csv file of particles
114
115 end subroutine sample_create_particles
116
117 subroutine sample_fill_gridvars
119
120 double precision, dimension(ixG^T,1:nw) :: w
121 integer :: igrid, iigrid, idir
122
123 do iigrid=1,igridstail; igrid=igrids(iigrid);
124
125 ^d&dxlevel(^d)=rnode(rpdx^d_,igrid);
126 w(ixg^t,1:nw) = ps(igrid)%w(ixg^t,1:nw)
127 call phys_to_primitive(ixg^ll,ixg^ll,w,ps(igrid)%x)
128 ! fill all variables:
129 gridvars(igrid)%w(ixg^t,1:ngridvars) = w(ixg^t,1:ngridvars)
130
131 end do
132
133 end subroutine sample_fill_gridvars
134
135 subroutine sample_integrate_particles(end_time)
136 ! this interpolates the HD/MHD quantities at the particle positions
139 double precision, intent(in) :: end_time
140
141 double precision, dimension(1:ndir) :: v, x
142 double precision :: defpayload(ndefpayload)
143 double precision :: usrpayload(nusrpayload)
144 double precision :: tloc, tlocnew, dt_p, h1
145 double precision,parameter :: eps=1.0d-6, hmin=1.0d-8
146 integer :: ipart, iipart, igrid
147 integer :: nok, nbad, ierror
148
149 do iipart=1,nparticles_active_on_mype
150 ipart = particles_active_on_mype(iipart);
151 dt_p = sample_get_particle_dt(particle(ipart), end_time)
152 particle(ipart)%self%dt = dt_p
153
154 igrid = particle(ipart)%igrid
155 igrid_working = igrid
156 tloc = particle(ipart)%self%time
157 x(1:ndir) = particle(ipart)%self%x(1:ndir)
158 tlocnew = tloc+dt_p
159
160 ! Position update (if defined)
161 ! TODO: this may create problems with interpolation out of boundaries
162 if (associated(usr_particle_position)) call usr_particle_position(x,particle(ipart)%self%index,tloc,tlocnew)
163 particle(ipart)%self%x(1:ndir) = x
164
165 ! Time update
166 particle(ipart)%self%time = tlocnew
167
168 ! Update payload
169 call sample_update_payload(igrid,x,v,0.d0,0.d0,defpayload,ndefpayload,tlocnew)
170 particle(ipart)%payload(1:ndefpayload) = defpayload
171 if (associated(usr_update_payload)) then
172 call usr_update_payload(igrid,x,v,0.d0,0.d0,usrpayload,nusrpayload,tlocnew)
173 particle(ipart)%payload(ndefpayload+1:npayload) = usrpayload
174 end if
175
176 end do
177
178 end subroutine sample_integrate_particles
179
180 !> Payload update
181 subroutine sample_update_payload(igrid,xpart,upart,qpart,mpart,mypayload,mynpayload,particle_time)
183 integer, intent(in) :: igrid,mynpayload
184 double precision, intent(in) :: xpart(1:ndir),upart(1:ndir),qpart,mpart,particle_time
185 double precision, intent(out) :: mypayload(mynpayload)
186 double precision :: myw(ixg^t,1:nw),mywold(ixg^t,1:nw)
187 double precision :: wp, wpold, td
188 integer :: ii
189
190
191 ! There are npayload=nw payloads, one for each primitive fluid quantity
192 myw(ixg^t,1:nw) = gridvars(igrid)%w(ixg^t,1:nw)
193 if (time_advance) mywold(ixg^t,1:nw) = gridvars(igrid)%wold(ixg^t,1:nw)
194
195 if (.not.saveprim) then
196 call phys_to_conserved(ixg^ll,ixg^ll,myw,ps(igrid)%x)
197 if (time_advance) call phys_to_conserved(ixg^ll,ixg^ll,mywold,ps(igrid)%x)
198 end if
199
200 do ii=1,mynpayload
201 call interpolate_var(igrid,ixg^ll,ixm^ll,myw(ixg^t,ii),ps(igrid)%x,xpart,wp)
202 if (time_advance) then
203 td = (particle_time - global_time) / dt
204 call interpolate_var(igrid,ixg^ll,ixm^ll,mywold(ixg^t,ii),ps(igrid)%x,xpart,wpold)
205 wp = wpold * (1.0d0 - td) + wp * td
206 end if
207 mypayload(ii) = wp*w_convert_factor(ii)
208 end do
209
210 end subroutine sample_update_payload
211
212 function sample_get_particle_dt(partp, end_time) result(dt_p)
214 use mod_geometry
216 type(particle_ptr), intent(in) :: partp
217 double precision, intent(in) :: end_time
218 double precision :: dt_p
219 double precision :: tout, dt_cfl
220 double precision :: v(1:ndir), xp(3), told, tnew
221 integer :: ipart, iipart, nout, id
222
223 if (const_dt_particles > 0) then
224 dt_p = const_dt_particles
225 return
226 end if
227
228 dt_p = dtsave_particles
229
230 ! Make sure the user-defined particle movement doesn't break communication
231 if (associated(usr_particle_position)) then
232 xp = partp%self%x
233 told = partp%self%time
234 tnew = told+dt_p
235 call usr_particle_position(xp, partp%self%index, told, tnew)
236 do while (.not. point_in_igrid_ghostc(xp,partp%igrid,1))
237 dt_p = dt_p/10.d0
238 xp = partp%self%x
239 tnew = told+dt_p
240 call usr_particle_position(xp, partp%self%index, told, tnew)
241 end do
242 end if
243
244 ! Make sure we don't advance beyond end_time
245 call limit_dt_endtime(end_time - partp%self%time, dt_p)
246
247 end function sample_get_particle_dt
248
249end module mod_particle_sample
Module with geometry-related routines (e.g., divergence, curl)
Definition mod_geometry.t:2
This module contains definitions of global parameters and variables and some generic functions/subrou...
double precision, dimension(:), allocatable w_convert_factor
Conversion factors the primitive variables.
double precision global_time
The global simulation time.
logical saveprim
If true, convert from conservative to primitive variables in output.
integer icomm
The MPI communicator.
integer mype
The rank of the current MPI task.
double precision, dimension(:), allocatable, parameter d
double precision dt
global time step
integer ndir
Number of spatial dimensions (components) for vector variables.
integer ixm
the mesh range of a physical block without ghost cells
integer ierrmpi
A global MPI error return code.
logical time_advance
do time evolving
double precision, dimension(:,:), allocatable rnode
Corner coordinates.
double precision, dimension(^nd) dxlevel
store unstretched cell size of current level
Module with shared functionality for all the particle movers.
pure subroutine limit_dt_endtime(t_left, dt_p)
integer num_particles
Number of particles.
double precision const_dt_particles
If positive, a constant time step for the particles.
subroutine write_particle_output()
double precision dtsave_particles
Time interval to save particles.
integer ngridvars
Number of variables for grid field.
integer nusrpayload
Number of user-defined payload variables for a particle.
subroutine find_particle_ipe(x, igrid_particle, ipe_particle)
integer npayload
Number of total payload variables for a particle.
integer, dimension(:), allocatable particles_active_on_mype
Array of identity numbers of active particles in current processor.
subroutine push_particle_into_particles_on_mype(ipart)
integer nparticles_active_on_mype
Number of active particles in current processor.
procedure(sub_define_additional_gridvars), pointer particles_define_additional_gridvars
integer nparticles
Identity number and total number of particles.
type(particle_ptr), dimension(:), allocatable particle
procedure(sub_integrate), pointer particles_integrate
procedure(sub_fill_gridvars), pointer particles_fill_gridvars
double precision t_next_output
Time to write next particle output.
integer ndefpayload
Number of default payload variables for a particle.
logical function point_in_igrid_ghostc(x, igrid, ngh)
Quick check if particle coordinate is inside igrid (ghost cells included, except the last ngh)
integer igrid_working
set the current igrid for the particle integrator:
subroutine interpolate_var(igrid, ixil, ixol, gf, x, xloc, gfloc)
Scattered sampling based on fixed- or moving-particle interpolation By Fabio Bacchini (2020)
subroutine, public sample_init()
subroutine, public sample_create_particles()
Module with all the methods that users can customize in AMRVAC.
procedure(particle_position), pointer usr_particle_position
procedure(check_particle), pointer usr_check_particle
procedure(create_particles), pointer usr_create_particles
procedure(update_payload), pointer usr_update_payload