7 #include "sll_assert.h"
8 #include "sll_errors.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
48 sll_real64,
allocatable :: j_dofs_local(:)
49 sll_real64,
allocatable :: efield_dofs_work(:)
51 sll_int32 :: spline_degree(3)
53 sll_real64 :: x_min(3)
54 sll_real64 :: x_max(3)
58 sll_real64,
pointer :: rhob(:) => null()
59 sll_int32 :: counter_left = 0
60 sll_int32 :: counter_right = 0
68 sll_real64,
intent( in ) :: x(:)
69 sll_real64,
intent( out ) :: y(:)
70 sll_real64,
intent( in ) :: bf(3)
71 sll_real64,
intent( in ) :: jm(3,3)
72 sll_real64,
intent( in ) :: sign
74 sll_real64 :: a,b,c,d,e,f,g,h,i
77 a = 1-sign*( jm(1,1)*(jm(2,1)*bf(3)-jm(3,1)*bf(2)) + jm(2,1)*(jm(3,1)*bf(1)-jm(1,1)*bf(3)) + jm(3,1)*(jm(1,1)*bf(2)-jm(2,1)*bf(1)) )
78 d = -sign*( jm(1,2)*(jm(2,1)*bf(3)-jm(3,1)*bf(2)) + jm(2,2)*(jm(3,1)*bf(1)-jm(1,1)*bf(3)) + jm(3,2)*(jm(1,1)*bf(2)-jm(2,1)*bf(1)) )
79 g = -sign*( jm(1,3)*(jm(2,1)*bf(3)-jm(3,1)*bf(2)) + jm(2,3)*(jm(3,1)*bf(1)-jm(1,1)*bf(3)) + jm(3,3)*(jm(1,1)*bf(2)-jm(2,1)*bf(1)) )
81 b = -sign*( jm(1,1)*(jm(2,2)*bf(3)-jm(3,2)*bf(2)) + jm(2,1)*(jm(3,2)*bf(1)-jm(1,2)*bf(3)) + jm(3,1)*(jm(1,2)*bf(2)-jm(2,2)*bf(1)) )
82 e = 1-sign*( jm(1,2)*(jm(2,2)*bf(3)-jm(3,2)*bf(2)) + jm(2,2)*(jm(3,2)*bf(1)-jm(1,2)*bf(3)) + jm(3,2)*(jm(1,2)*bf(2)-jm(2,2)*bf(1)) )
83 h = -sign*( jm(1,3)*(jm(2,2)*bf(3)-jm(3,2)*bf(2)) + jm(2,3)*(jm(3,2)*bf(1)-jm(1,2)*bf(3)) + jm(3,3)*(jm(1,2)*bf(2)-jm(2,2)*bf(1)) )
85 c = -sign*( jm(1,1)*(jm(2,3)*bf(3)-jm(3,3)*bf(2)) + jm(2,1)*(jm(3,3)*bf(1)-jm(1,3)*bf(3)) + jm(3,1)*(jm(1,3)*bf(2)-jm(2,3)*bf(1)) )
86 f = -sign*( jm(1,2)*(jm(2,3)*bf(3)-jm(3,3)*bf(2)) + jm(2,2)*(jm(3,3)*bf(1)-jm(1,3)*bf(3)) + jm(3,2)*(jm(1,3)*bf(2)-jm(2,3)*bf(1)) )
87 i = 1-sign*( jm(1,3)*(jm(2,3)*bf(3)-jm(3,3)*bf(2)) + jm(2,3)*(jm(3,3)*bf(1)-jm(1,3)*bf(3)) + jm(3,3)*(jm(1,3)*bf(2)-jm(2,3)*bf(1)) )
89 det = a*e*i + b*f*g + c*d*h - c*e*g - a*f*h - b*d*i
91 y(1) = ( x(1)*(e*i - f*h) + x(2)*(c*h - b*i) + x(3)*(b*f - c*e) )/det
92 y(2) = ( x(1)*(f*g - d*i) + x(2)*(a*i - c*g) + x(3)*(c*d - a*f) )/det
93 y(3) = ( x(1)*(d*h - e*g) + x(2)*(b*g - a*h) + x(3)*(a*e - b*d) )/det
101 sll_real64,
intent( inout ) :: xold(3)
102 sll_real64,
intent( inout ) :: xnew(3)
103 sll_real64,
intent( inout ) :: vi(3)
107 if(xnew(1) < self%x_min(1) .or. xnew(1) > self%x_max(1) )
then
108 if(xnew(1) < self%x_min(1) )
then
110 self%counter_left = self%counter_left+1
111 else if(xnew(1) > self%x_max(1))
then
113 self%counter_right = self%counter_right+1
117 select case(self%boundary_particles)
119 xnew(1) = 2._f64*xbar-xnew(1)
123 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
125 print*,
'error: boundary case missing', self%boundary_particles
128 xnew(2:3) = self%x_min(2:3) + modulo(xnew(2:3)-self%x_min(2:3), self%Lx(2:3))
136 sll_real64,
intent( inout ) :: xold(3)
137 sll_real64,
intent( inout ) :: xnew(3)
138 sll_real64,
intent( inout ) :: vi(3)
140 sll_real64 :: xmid(3), xt(3), xbar, dx
141 sll_real64 :: jmatrix(3,3)
143 if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
144 if(xnew(1) < 0._f64 )
then
146 self%counter_left = self%counter_left+1
147 else if(xnew(1) > 1._f64)
then
149 self%counter_right = self%counter_right+1
151 dx = (xbar- xold(1))/(xnew(1)-xold(1))
152 xmid = xold + dx * (xnew-xold)
155 select case(self%boundary_particles)
157 if(xnew(1) < 0._f64 )
then
159 xnew(2) = xnew(2) + 0.5_f64
160 else if(xnew(1) > 1._f64 )
then
161 jmatrix = self%map%jacobian_matrix_inverse_transposed(xmid)
162 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
163 xnew(1) = 2._f64 - xnew(1)
164 xnew(2) = 1._f64 - xnew(2)
168 xt(2:3) = modulo(xt(2:3),1._f64)
169 jmatrix = self%map%jacobian_matrix_inverse_transposed(xt)
170 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
171 xnew(1) = 2._f64*xbar-xnew(1)
174 xnew(1) = modulo(xnew(1), 1._f64)
176 print*,
'error: boundary case missing', self%boundary_particles
178 else if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64 )
then
180 sll_error(
"particle boundary",
"particle out of bound")
182 xnew(2:3) = modulo(xnew(2:3), 1._f64)
190 sll_real64,
intent( in ) :: xold(3)
191 sll_real64,
intent( inout ) :: xnew(3)
192 sll_real64,
intent( inout ) :: vi(3)
193 sll_real64,
intent( in ) :: wi(1)
195 sll_real64 :: xmid(3), xt(3), vt(3), xbar, dx
196 sll_real64 :: jmatrix(3,3)
198 if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
199 if(xnew(1) < 0._f64 )
then
201 self%counter_left = self%counter_left+1
202 else if(xnew(1) > 1._f64)
then
204 self%counter_right = self%counter_right+1
207 dx = (xbar- xold(1))/(xnew(1)-xold(1))
208 xmid = xold + dx * (xnew-xold)
210 vt = (xmid - xold)*wi(1)
211 call self%particle_mesh_coupling%add_current( xold, xmid, vt, self%j_dofs_local )
212 select case(self%boundary_particles)
214 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
215 xmid(2) = xbar + (1._f64-2._f64*xbar)*xmid(2) + 0.5_f64-0.5_f64*xbar
216 call self%particle_mesh_coupling%add_charge(xmid, -wi(1), self%spline_degree, self%rhob)
217 xnew(1) = 2._f64*xbar-xnew(1)
218 xnew(2) = xbar + (1._f64-2._f64*xbar)*xnew(2) + 0.5_f64-0.5_f64*xbar
220 if(xnew(1) > 1._f64 )
then
222 xt(2:3) = modulo(xt(2:3),1._f64)
223 jmatrix = self%map%jacobian_matrix_inverse_transposed(xt)
224 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
228 xt(2:3) = modulo(xt(2:3),1._f64)
229 jmatrix = self%map%jacobian_matrix_inverse_transposed(xt)
230 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
231 xnew(1) = 2._f64*xbar-xnew(1)
233 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
235 xnew(1) = modulo(xnew(1), 1._f64)
236 xmid(1) = 1._f64-xbar
238 print*,
'error: boundary case missing', self%boundary_particles
240 if(xnew(1) >= 0._f64 .and. xnew(1) <= 1._f64)
then
241 vt = (xnew - xmid)*wi(1)
242 call self%particle_mesh_coupling%add_current( xmid, xnew, vt, self%j_dofs_local )
244 else if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)
then
246 sll_error(
"particle boundary",
"particle out of bound")
248 vt = (xnew - xold)*wi(1)
249 call self%particle_mesh_coupling%add_current( xold, xnew, vt, self%j_dofs_local )
251 xnew(2:3) = modulo(xnew(2:3), 1._f64)
259 sll_real64,
intent( in ) :: xold(3)
260 sll_real64,
intent( inout ) :: xnew(3)
261 sll_real64,
intent( inout ) :: vi(3)
262 sll_real64,
intent( in ) :: wi(1)
263 sll_real64,
intent( in ) :: sign
265 sll_real64 :: xmid(3), xt(3), vt(3), xbar, dx
266 sll_real64 :: jmatrix(3,3), jmat(3,3), efield(3)
269 if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
270 if(xnew(1) < 0._f64 )
then
272 self%counter_left = self%counter_left+1
273 else if(xnew(1) > 1._f64)
then
275 self%counter_right = self%counter_right+1
277 dx = (xbar- xold(1))/(xnew(1)-xold(1))
278 xmid = xold + dx * (xnew-xold)
280 vt = (xmid - xold)*wi(1)
281 call self%particle_mesh_coupling%add_current_evaluate( xold, xmid, vt, self%efield_dofs_work, &
282 self%j_dofs_local, efield )
283 jmat = self%map%jacobian_matrix_inverse_transposed(xold)
285 xt(2:3) = modulo(xt(2:3), 1._f64)
286 jmatrix = self%map%jacobian_matrix_inverse_transposed(xt)
288 vi(j) = vi(j) + dx*sign *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2) + (jmatrix(j,3)+ jmat(j,3))*efield(3))
290 select case(self%boundary_particles)
292 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
293 xmid(2) = xbar + (1._f64-2._f64*xbar)*xmid(2) + 0.5_f64-0.5_f64*xbar
294 xt(2:3) = modulo(xt(2:3), 1._f64)
295 jmatrix = self%map%jacobian_matrix_inverse_transposed(xt)
296 call self%particle_mesh_coupling%add_charge(xmid, -wi(1), self%spline_degree, self%rhob)
297 xnew(1) = 2._f64*xbar-xnew(1)
298 xnew(2) = xbar + (1._f64-2._f64*xbar)*xnew(2) + 0.5_f64-0.5_f64*xbar
299 if(xnew(1) > 1._f64 )
then
300 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
303 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
304 xnew(1) = 2._f64*xbar-xnew(1)
306 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
308 xnew(1) = modulo(xnew(1), 1._f64)
309 xmid(1) = 1._f64-xbar
311 print*,
'error: boundary case missing', self%boundary_particles
313 vt = (xnew - xmid)*wi(1)
314 call self%particle_mesh_coupling%add_current_evaluate( xmid, xnew, vt, self%efield_dofs_work, &
315 self%j_dofs_local, efield )
316 xnew(2:3) = modulo(xnew(2:3), 1._f64)
317 jmat = self%map%jacobian_matrix_inverse_transposed(xnew)
319 vi(j) = vi(j) + (1._f64-dx)*sign *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2) + (jmatrix(j,3)+ jmat(j,3))*efield(3))
321 else if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)
then
323 sll_error(
"particle boundary",
"particle out of bound")
325 vt = (xnew - xold)*wi(1)
326 call self%particle_mesh_coupling%add_current_evaluate( xold, xnew, vt, self%efield_dofs_work, &
327 self%j_dofs_local, efield )
328 jmat = self%map%jacobian_matrix_inverse_transposed(xold)
329 xnew(2:3) = modulo(xnew(2:3), 1._f64)
330 jmatrix = self%map%jacobian_matrix_inverse_transposed(xnew)
332 vi(j) = vi(j) + sign *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2) + (jmatrix(j,3)+ jmat(j,3))*efield(3))
345 sll_int32,
intent( in ) :: boundary_particles
346 sll_int32,
intent( inout ) :: counter_left
347 sll_int32,
intent( inout ) :: counter_right
348 sll_real64,
intent( inout ) :: xold(3)
349 sll_real64,
intent( inout ) :: xnew(3)
353 if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64 )
then
355 sll_error(
"particle boundary",
"particle out of bound")
356 else if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
357 if(xnew(1) < 0._f64 )
then
359 counter_left = counter_left+1
360 else if(xnew(1) > 1._f64)
then
362 counter_right = counter_right+1
364 select case(boundary_particles)
366 if(xnew(1) < 0._f64 )
then
368 xnew(2) = xnew(2) + 0.5_f64
369 else if(xnew(1) > 1._f64 )
then
370 xnew(1) = 2._f64 - xnew(1)
371 xnew(2) = 1._f64 - xnew(2)
374 xnew(1) = 2._f64*xbar-xnew(1)
377 xnew(1) = modulo(xnew(1), 1._f64)
379 xnew(1) = modulo(xnew(1), 1._f64)
382 xnew(2:3) = modulo(xnew(2:3), 1._f64)
389 sll_int32,
intent( in ) :: boundary_particles
390 sll_int32,
intent( inout ) :: counter_left
391 sll_int32,
intent( inout ) :: counter_right
393 sll_real64,
intent( inout ) :: xold(3)
394 sll_real64,
intent( inout ) :: xnew(3)
395 sll_real64,
intent( inout ) :: vi(3)
397 sll_real64 :: xmid(3), xt(3), xbar, dx
398 sll_real64 :: jmatrix(3,3)
400 if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
401 if(xnew(1) < 0._f64 )
then
403 counter_left = counter_left+1
404 else if(xnew(1) > 1._f64)
then
406 counter_right = counter_right+1
408 dx = (xbar- xold(1))/(xnew(1)-xold(1))
409 xmid = xold + dx * (xnew-xold)
412 select case(boundary_particles)
414 if(xnew(1) < 0._f64 )
then
416 xnew(2) = xnew(2) + 0.5_f64
417 else if(xnew(1) > 1._f64 )
then
418 jmatrix = map%jacobian_matrix_inverse_transposed(xmid)
419 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
420 xnew(1) = 2._f64 - xnew(1)
421 xnew(2) = 1._f64 - xnew(2)
425 xt(2:3) = modulo(xt(2:3),1._f64)
426 jmatrix = map%jacobian_matrix_inverse_transposed(xt)
427 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
428 xnew(1) = 2._f64*xbar-xnew(1)
431 xnew(1) = modulo(xnew(1), 1._f64)
433 xnew(1) = modulo(xnew(1), 1._f64)
435 else if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64 )
then
437 sll_error(
"particle boundary",
"particle out of bound")
439 xnew(2:3) = modulo(xnew(2:3), 1._f64)
445 subroutine sll_s_compute_particle_boundary_trafo_current(boundary_particles, counter_left, counter_right, map, particle_mesh_coupling, j_dofs_local, spline_degree, rhob, xold, xnew, vi, wi )
446 sll_int32,
intent( in ) :: boundary_particles
447 sll_int32,
intent( inout ) :: counter_left
448 sll_int32,
intent( inout ) :: counter_right
451 sll_real64,
intent( inout ) :: j_dofs_local(:)
452 sll_int32,
intent( in ) :: spline_degree(3)
453 sll_real64,
intent( inout ) :: rhob(:)
454 sll_real64,
intent( in ) :: xold(3)
455 sll_real64,
intent( inout ) :: xnew(3)
456 sll_real64,
intent( inout ) :: vi(3)
457 sll_real64,
intent( in ) :: wi(1)
459 sll_real64 :: xmid(3), xt(3), vh(3), xbar, dx
460 sll_real64 :: jmatrix(3,3)
462 if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )
then
463 if(xnew(1) < 0._f64 )
then
465 counter_left = counter_left+1
466 else if(xnew(1) > 1._f64)
then
468 counter_right = counter_right+1
471 dx = (xbar- xold(1))/(xnew(1)-xold(1))
472 xmid = xold + dx * (xnew-xold)
474 vh = (xmid - xold)*wi(1)
475 call particle_mesh_coupling%add_current( xold, xmid, vh, j_dofs_local )
476 select case(boundary_particles)
478 call particle_mesh_coupling%add_charge(xmid, wi(1), spline_degree, rhob)
479 xmid(2) = xbar + (1._f64-2._f64*xbar)*xmid(2) + 0.5_f64-0.5_f64*xbar
480 call particle_mesh_coupling%add_charge(xmid, -wi(1), spline_degree, rhob)
481 xnew(1) = 2._f64*xbar-xnew(1)
482 xnew(2) = xbar + (1._f64-2._f64*xbar)*xnew(2) + 0.5_f64-0.5_f64*xbar
484 if(xnew(1) > 1._f64 )
then
486 xt(2:3) = modulo(xt(2:3),1._f64)
487 jmatrix = map%jacobian_matrix_inverse_transposed(xt)
488 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
492 xt(2:3) = modulo(xt(2:3),1._f64)
493 jmatrix = map%jacobian_matrix_inverse_transposed(xt)
494 vi = vi-2._f64*(vi(1)*jmatrix(1,1)+vi(2)*jmatrix(2,1)+vi(3)*jmatrix(3,1))*jmatrix(:,1)/sum(jmatrix(:,1)**2)
495 xnew(1) = 2._f64*xbar-xnew(1)
497 call particle_mesh_coupling%add_charge(xmid, wi(1), spline_degree, rhob)
499 xnew(1) = modulo(xnew(1), 1._f64)
500 xmid(1) = 1._f64-xbar
502 xnew(1) = modulo(xnew(1), 1._f64)
503 xmid(1) = 1._f64-xbar
505 else if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64 )
then
507 sll_error(
"particle boundary",
"particle out of bound")
511 vh = (xnew - xmid)*wi(1)
512 call particle_mesh_coupling%add_current( xmid, xnew, vh, j_dofs_local )
513 xnew(2:3) = modulo(xnew(2:3), 1._f64)
Module interfaces for coordinate transformation.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Base class for Hamiltonian splittings.
Particle pusher based on antisymmetric splitting with AVF for 3d3v Vlasov-Maxwell with coordinate tra...
subroutine, public sll_s_compute_particle_boundary_simple(boundary_particles, counter_left, counter_right, xold, xnew)
compute new position
subroutine, public sll_s_compute_particle_boundary_trafo_current(boundary_particles, counter_left, counter_right, map, particle_mesh_coupling, j_dofs_local, spline_degree, rhob, xold, xnew, vi, wi)
Compute particle boundary and current with coordinate transformation.
integer(kind=i32), parameter, public sll_p_boundary_particles_periodic
subroutine, public sll_s_compute_matrix_inverse(x, y, bf, jm, sign)
invert matrix
subroutine compute_particle_boundary_trafo(self, xold, xnew, vi)
compute particle boundary with coordinate transformation
integer(kind=i32), parameter, public sll_p_boundary_particles_reflection
integer(kind=i32), parameter, public sll_p_boundary_particles_absorption
integer(kind=i32), parameter, public sll_p_boundary_particles_singular
subroutine compute_particle_boundary_current_trafo_evaluate(self, xold, xnew, vi, wi, sign)
compute particle boundary and current with coordinate transformation and evaluate efield
subroutine compute_particle_boundary_trafo_current(self, xold, xnew, vi, wi)
compute particle boundary and current with coordinate transformation
subroutine, public sll_s_compute_particle_boundary_trafo(boundary_particles, counter_left, counter_right, map, xold, xnew, vi)
Compute particle boundary with coordinate transformation.
subroutine compute_particle_boundary(self, xold, xnew, vi)
Compute particle boundary.
type collecting functions for analytical coordinate mapping
Basic type of a kernel smoother used for PIC simulations.
Type for Hamiltonian splittings.
Hamiltonian splitting type for Vlasov-Maxwell 3d3v.