Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Examples/Tests/collision/analysis_collision_rz.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#! /usr/bin/env python

# Copyright 2019-2020 Yinjian Zhao
#
# This file is part of WarpX.
#
# License: BSD-3-Clause-LBNL

# This script tests the collision module in RZ.
# Electrons are set with the same vr,
# such that correct collisions will not lead to any velocity changes.
# Thus the initial electron momentum will be compared with the final momentum.

# Possible errors:
# tolerance: 1.0e-30
# Possible running time: ~ 1.0 s

import sys
import yt
import numpy as np
from glob import glob
sys.path.insert(1, '../../../../warpx/Regression/Checksum/')
import checksumAPI

tolerance = 1.0e-30

last_fn = sys.argv[1]
if (last_fn[-1] == "/"): last_fn = last_fn[:-1]
fn_list = glob(last_fn[:-5] + "?????")

for fn in fn_list:
# get time index j
j = int(fn[-5:])
if j==0:
# load file
ds = yt.load( fn )
ad = ds.all_data()
px1 = ad['particle_momentum_x'].to_ndarray()
py1 = ad['particle_momentum_y'].to_ndarray()
if j==150:
# load file
ds = yt.load( fn )
ad = ds.all_data()
px2 = ad['particle_momentum_x'].to_ndarray()
py2 = ad['particle_momentum_y'].to_ndarray()

error = np.max( abs(px1-px2)+abs(py1-py2) )

print('error = ', error)
print('tolerance = ', tolerance)
assert(error < tolerance)

test_name = last_fn[:-9] # Could also be os.path.split(os.getcwd())[1]
checksumAPI.evaluate_checksum(test_name, fn, do_particles=False)
56 changes: 56 additions & 0 deletions Examples/Tests/collision/inputs_rz
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#################################
####### GENERAL PARAMETERS ######
#################################
max_step = 150
amr.n_cell = 8 8
amr.max_grid_size = 8
amr.blocking_factor = 8
amr.max_level = 0
geometry.coord_sys = 1
geometry.prob_lo = 0. 0.
geometry.prob_hi = 4.154046151855669e2 4.154046151855669e2

#################################
###### Boundary Condition #######
#################################
boundary.field_lo = none periodic
boundary.field_hi = none periodic

#################################
############ NUMERICS ###########
#################################
warpx.serialize_ics = 1
warpx.verbose = 1
warpx.cfl = 1.0

# Order of particle shape factors
algo.particle_shape = 1

#################################
############ PLASMA #############
#################################
particles.species_names = electron

electron.charge = -q_e
electron.mass = m_e
electron.injection_style = "NUniformPerCell"
electron.num_particles_per_cell_each_dim = 1 10 1
electron.profile = constant
electron.density = 1.0e21
electron.momentum_distribution_type = parse_momentum_function
electron.momentum_function_ux(x,y,z) = "if(x*x+y*y>0.0, 1.0*x/sqrt(x*x+y*y), 0.0)"
electron.momentum_function_uy(x,y,z) = "if(x*x+y*y>0.0, 1.0*y/sqrt(x*x+y*y), 0.0)"
electron.momentum_function_uz(x,y,z) = "0"
electron.do_not_deposit = 1
electron.do_not_push = 1

#################################
############ COLLISION ##########
#################################
collisions.collision_names = collision
collision.species = electron electron
collision.CoulombLog = 15.9

diagnostics.diags_names = diag1
diag1.intervals = 10
diag1.diag_type = Full
13 changes: 13 additions & 0 deletions Regression/Checksum/benchmarks_json/collisionRZ.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"lev=0": {
"Bx": 0.0,
"By": 0.0,
"Bz": 0.0,
"Ex": 0.0,
"Ey": 0.0,
"Ez": 0.0,
"jx": 0.0,
"jy": 0.0,
"jz": 0.0
}
}
18 changes: 18 additions & 0 deletions Regression/WarpX-tests.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1788,6 +1788,24 @@ analysisRoutine = Examples/Tests/collision/analysis_collision_2d.py
aux1File = Regression/PostProcessingUtils/post_processing_utils.py
tolerance = 1.e-14

[collisionRZ]
buildDir = .
inputFile = Examples/Tests/collision/inputs_rz
runtime_params =
dim = 2
addToCompileString = USE_RZ=TRUE USE_PSATD=FALSE
restartTest = 0
useMPI = 1
numprocs = 1
useOMP = 1
numthreads = 1
compileTest = 0
doVis = 0
compareParticles = 0
analysisRoutine = Examples/Tests/collision/analysis_collision_rz.py
aux1File = Regression/PostProcessingUtils/post_processing_utils.py
tolerance = 1.e-30

[Maxwell_Hybrid_QED_solver]
buildDir = .
inputFile = Examples/Tests/Maxwell_Hybrid_QED/inputs_2d
Expand Down
26 changes: 26 additions & 0 deletions Source/Particles/Collision/BinaryCollision/ElasticCollisionPerez.H
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,44 @@ void ElasticCollisionPerez (
amrex::max(n1,n2), T_R(-1.0/3.0) );
lmdD = amrex::max(lmdD, rmin);

#if (defined WARPX_DIM_RZ)
T_R * const AMREX_RESTRICT theta1 = soa_1.m_rdata[PIdx::theta];
T_R * const AMREX_RESTRICT theta2 = soa_2.m_rdata[PIdx::theta];
#endif

// call UpdateMomentumPerezElastic()
{
int i1 = I1s; int i2 = I2s;
for (int k = 0; k < amrex::max(NI1,NI2); ++k)
{

#if (defined WARPX_DIM_RZ)
//When particles are having the same vr, their velocities would change after collision,
//because they may have different azimuth angles, but their velocities are not supposed to be changed.
//To fix this, we rotate one particle to be in parallel with the other particle,
//such that their velocities won't change after collision if they have the same vr.
//Then, we rotate that particle back.
T_R const theta = theta2[I2[i2]]-theta1[I1[i1]];
T_R u1xbuf;
u1xbuf = u1x[I1[i1]];
u1x[I1[i1]] = u1xbuf*std::cos(theta) - u1y[I1[i1]]*std::sin(theta);
u1y[I1[i1]] = u1xbuf*std::sin(theta) + u1y[I1[i1]]*std::cos(theta);
#endif

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why write to the backing arrays rather than just using local variables for these two values? This seems like pointless memory traffic.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so I see these are passed by reference, and updated inside UpdateMomentumPerezElastic. There's still an opportunity to do that write into a stack variable that won't be flushed to memory, and then only write it out once it's potentially been corrected by the following de-rotation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@PhilMiller Hi, thanks for you comments, could you provide more details how to improve the code, I'm not sure if I understand your point. Stack variables also work on GPUs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yin-YinjianZhao#2
Here's a PR against your branch with my suggestion

UpdateMomentumPerezElastic(
u1x[ I1[i1] ], u1y[ I1[i1] ], u1z[ I1[i1] ],
u2x[ I2[i2] ], u2y[ I2[i2] ], u2z[ I2[i2] ],
n1, n2, n12,
q1, m1, w1[ I1[i1] ], q2, m2, w2[ I2[i2] ],
dt, L, lmdD,
engine);

#if (defined WARPX_DIM_RZ)
u1xbuf = u1x[I1[i1]];
u1x[I1[i1]] = u1xbuf*std::cos(-theta) - u1y[I1[i1]]*std::sin(-theta);
u1y[I1[i1]] = u1xbuf*std::sin(-theta) + u1y[I1[i1]]*std::cos(-theta);
#endif

++i1; if ( i1 == static_cast<int>(I1e) ) { i1 = I1s; }
++i2; if ( i2 == static_cast<int>(I2e) ) { i2 = I2s; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ void UpdateMomentumPerezElastic (
amrex::RandomEngine const& engine)
{

T_R const diffx = amrex::Math::abs(u1x-u2x);
T_R const diffy = amrex::Math::abs(u1y-u2y);
T_R const diffz = amrex::Math::abs(u1z-u2z);
T_R const diffm = std::sqrt(diffx*diffx+diffy*diffy+diffz*diffz);
T_R const summm = std::sqrt(u1x*u1x+u1y*u1y+u1z*u1z) + std::sqrt(u2x*u2x+u2y*u2y+u2z*u2z);
// If g = u1 - u2 = 0, do not collide.
if ( amrex::Math::abs(u1x-u2x) < std::numeric_limits<T_R>::min() &&
amrex::Math::abs(u1y-u2y) < std::numeric_limits<T_R>::min() &&
amrex::Math::abs(u1z-u2z) < std::numeric_limits<T_R>::min() )
{ return; }
// Or if the relative difference is less than 1.0e-10.
if ( diffm < std::numeric_limits<T_R>::min() || diffm/summm < 1.0e-10 ) { return; }

T_R constexpr inv_c2 = T_R(1.0) / ( PhysConst::c * PhysConst::c );

Expand Down