Skip to content

Commit ad404d1

Browse files
committed
Merge pull request #22 from PyCOMPLETE/develop
PyHEADTAIL v1.5.0 Merry Christmas! :-) New features: - UniformBinSlicer allows for specified sampling points (for wakes) - RFSystems can remove kicks - KV 1D and 2D distribution included into generators - Particles can sort their arrays and apply given permutations - a first version of the GPU module enters PyHEADTAIL (Particles, Slicing etc on GPU) - CUDA thrust library interface for specific functions - ParticlesGPU implements sorting via thrust - slicing with PyPIC (e.g. for GPU usage) - RFBucketMatcher allows for margin along separatrix - optimised RFBucketMatcher generation (much quicker!) - longitudinal wrapping to keep z within circumference - pre-commit hooks (make sure to include these in your GIT config!) - ParticleGenerator interface change (linear_matcher removed) - pure python RFQ implementation (besides existing cython version) - adaptation of Bunch-/SliceMonitor for GPU usage
2 parents b236a86 + 5bdfd10 commit ad404d1

37 files changed

+8653
-12162
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,11 @@ In [1]: import PyHEADTAIL
3434

3535
PyHEADTAIL v1.4.0-0-g8422af8081
3636

37+
38+
-------------------------------------------------------------------------------
39+
40+
Please use the pre-push script 'pre-push.py' if you want to contribute
41+
to the repository. It only lets you push to the develop and master branch if
42+
no unit tests fail.
43+
44+
To install (creates a symlink): ln -s ../../pre-push.py .git/hooks/pre-push

field_maps/Transverse_Efield_map.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import numpy as np
2-
from scipy.constants import c, e
2+
from scipy.constants import c
33

44
from PyHEADTAIL.particles.slicing import UniformBinSlicer
55
from PyPIC.PyPIC_Scatter_Gather import PyPIC_Scatter_Gather

general/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,8 @@ def __repr__(self):
6868

6969
def __len__(self):
7070
return len(self._list_of_objects)
71+
72+
def pop(self, index):
73+
'''Remove the object from the internal list and return the
74+
corresponding attribute, analogous to list.pop .'''
75+
return getattr(self._list_of_objects.pop(index), self._attr_name)

gpu/__init__.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
from .. import Element
2+
from .. import __version__
3+
4+
# monkey patching default classes with GPU variants
5+
# is done on importing this module!
6+
7+
from skcuda.misc import mean, std, diff
8+
from pycuda import gpuarray
9+
from pycuda import cumath
10+
11+
# I. subjects to monkey patching:
12+
from ..particles import particles as def_particles
13+
from ..particles import slicing as def_slicing
14+
from ..trackers import simple_long_tracking as def_simple_long_tracking
15+
from ..trackers import wrapper as def_wrapper
16+
17+
# II. actual monkey patching
18+
19+
# a) Particles rebindings for GPU
20+
from .particles import ParticlesGPU
21+
22+
def_particles.Particles = ParticlesGPU
23+
def_particles.mean = lambda *args, **kwargs: mean(*args, **kwargs).get()
24+
def_particles.std = lambda *args, **kwargs: std(*args, **kwargs).get()
25+
26+
# b) Slicing rebindings for GPU
27+
# def_slicing.min_ = lambda *args, **kwargs: gpuarray.min(*args, **kwargs).get()
28+
# def_slicing.max_ = lambda *args, **kwargs: gpuarray.max(*args, **kwargs).get()
29+
# def_slicing.diff = diff
30+
31+
from .slicing import SlicerGPU
32+
33+
# # to be replaced: find a better solution than monkey patching base classes!
34+
# # (to solve the corresponding need to replace all inheriting classes' parent!)
35+
# def_slicing.Slicer = SlicerGPU
36+
# def_slicing.UniformBinSlicer.__bases__ = (SlicerGPU,)
37+
38+
# c) Longitudinal tracker rebindings for GPU
39+
def_simple_long_tracking.sin = cumath.sin
40+
41+
# d) Wrapper rebindings for GPU
42+
from .wrapper import LongWrapperGPU
43+
def_wrapper.LongWrapper = LongWrapperGPU

gpu/particles.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# default classes imports from modules as assigned in gpu/__init__.py
2+
from . import def_particles
3+
4+
import numpy as np
5+
6+
from pycuda import gpuarray
7+
8+
import thrust_interface
9+
thrust = thrust_interface.compiled_module
10+
11+
class ParticlesGPU(def_particles.Particles):
12+
'''Implementation of the Particles with data stored on the GPU.'''
13+
def __init__(self, *args, **kwargs):
14+
super(ParticlesGPU, self).__init__(*args, **kwargs)
15+
16+
for coord in self.coords_n_momenta:
17+
device_array = gpuarray.to_gpu(getattr(self, coord))
18+
setattr(self, coord, device_array)
19+
self.id = gpuarray.to_gpu(self.id)
20+
21+
def transfer_to_host(self):
22+
'''Transfers all GPU device data back to the host RAM.'''
23+
for coord in self.coords_n_momenta:
24+
device_array = getattr(self, coord).get()
25+
setattr(self, coord, device_array)
26+
self.id = self.id.get()
27+
28+
def sort_for(self, attr):
29+
'''Sort the named particle attribute (coordinate / momentum)
30+
array and reorder all particles accordingly.
31+
'''
32+
permutation = gpuarray.empty(self.macroparticlenumber, dtype=np.int32)
33+
thrust.get_sort_perm_double(getattr(self, attr), permutation)
34+
self.reorder(permutation, except_for_attrs=[attr])
35+
36+
def reorder(self, permutation, except_for_attrs=[]):
37+
'''Reorder all particle coordinate and momentum arrays
38+
(in self.coords_n_momenta) and ids except for except_for_attrs
39+
according to the given index array permutation.
40+
'''
41+
tmp = gpuarray.empty(self.macroparticlenumber, dtype=np.float64)
42+
for attr in self.coords_n_momenta:
43+
if attr in except_for_attrs:
44+
continue
45+
unordered = getattr(self, attr)
46+
thrust.apply_sort_perm_double(unordered, tmp, permutation)
47+
setattr(self, attr, tmp)
48+
tmp = unordered
49+
del tmp
50+
tmp = gpuarray.empty(self.macroparticlenumber, dtype=self.id.dtype)
51+
thrust.apply_sort_perm_int(self.id, tmp, permutation)
52+
self.id = tmp
53+
54+

0 commit comments

Comments
 (0)