Update to allow accumulators in CIC projection

This commit is contained in:
Guilhem Lavaux 2021-08-05 08:50:31 +03:00
parent a16ae60382
commit 6cafdd50b2
3 changed files with 167 additions and 148 deletions

View file

@ -31,7 +31,7 @@ cdef extern from "loadSimu.hpp" namespace "CosmoTool":
bool noAuto
cdef const int NEED_GADGET_ID
cdef const int NEED_GADGET_ID
cdef const int NEED_POSITION
cdef const int NEED_VELOCITY
cdef const int NEED_TYPE
@ -57,36 +57,36 @@ class PySimulationBase(object):
"""
This is the base class to representation Simulation in CosmoTool/python.
"""
def getPositions(self):
"""
getPositions(self)
Returns:
A list of three arrays holding the positions of the particles.
A list of three arrays holding the positions of the particles.
The i-th element is the i-th coordinate of each particle.
It may be None if the positions were not requested.
"""
raise NotImplementedError("getPositions is not implemented")
def getVelocities(self):
"""
getVelocities(self)
Returns:
A list of three arrays holding the velocities of the particles.
A list of three arrays holding the velocities of the particles.
The i-th element is the i-th coordinate of each particle.
It may be None if the velocities were not requested.
"""
raise NotImplementedError("getVelocities is not implemented")
def getIdentifiers(self):
"""
getIdentifiers(self)
Returns:
Returns an integer array that hold the unique identifiers of
each particle.
each particle.
It may be None if the identifiers were not requested.
"""
raise NotImplementedError("getIdentifiers is not implemented")
@ -94,10 +94,10 @@ class PySimulationBase(object):
def getTypes(self):
"""
getTypes(self)
Returns:
Returns an integer array that hold the type of
each particle.
each particle.
It may be None if the types were not requested.
"""
raise NotImplementedError("getTypes is not implemented")
@ -105,27 +105,27 @@ class PySimulationBase(object):
def getOmega_M(self):
"""
getOmega_M(self)
Returns:
the mean matter density in the simulation, with respect
to the critical density.
"""
"""
raise NotImplementedError("getOmega_M is not implemented")
def getOmega_Lambda(self):
"""
getOmega_Lambda(self)
Returns:
the mean dark energy density in the simulation, with respect
to the critical density.
"""
"""
raise NotImplementedError("getOmega_Lambda is not implemented")
def getTime(self):
"""
getTime(self)
Returns:
the time the snapshot was taken in the simulation. It can
have various units depending on the file format.
@ -135,7 +135,7 @@ class PySimulationBase(object):
def getHubble(self):
"""
getHubble(self)
Returns:
the hubble constant in unit of 100 km/s/Mpc
"""
@ -144,7 +144,7 @@ class PySimulationBase(object):
def getBoxsize(self):
"""
getBoxsize(self)
Returns:
the size of the simulation box. The length unit is not fixed,
though it is customary to have it in Mpc/h if the loader has
@ -155,7 +155,7 @@ class PySimulationBase(object):
def getMasses(self):
"""
getMasses(self)
Returns:
an array with the masses of each particles, in unspecified unit that
depend on the loader.
@ -165,7 +165,7 @@ class PySimulationBase(object):
cdef class Simulation:
"""
Simulation()
Class that directly manages internal loaded data obtained from a loader
"""
@ -180,7 +180,7 @@ cdef class Simulation:
property BoxSize:
def __get__(Simulation self):
return self.data.BoxSize
property time:
def __get__(Simulation self):
return self.data.time
@ -192,15 +192,15 @@ cdef class Simulation:
property Omega_M:
def __get__(Simulation self):
return self.data.Omega_M
property Omega_Lambda:
def __get__(Simulation self):
return self.data.Omega_Lambda
property positions:
def __get__(Simulation self):
return self.positions
property velocities:
def __get__(Simulation self):
return self.velocities
@ -216,7 +216,7 @@ cdef class Simulation:
property masses:
def __get__(Simulation self):
return self.masses
property numParticles:
def __get__(Simulation self):
return self.data.NumPart
@ -228,7 +228,7 @@ cdef class Simulation:
def __cinit__(Simulation self):
self.data = <SimuData *>0
def __dealloc__(Simulation self):
if self.data != <SimuData *>0:
del self.data
@ -237,40 +237,43 @@ cdef class Simulation:
class PySimulationAdaptor(PySimulationBase):
"""
PySimulationAdaptor(PySimulationBase_)
This class is an adaptor for an internal type to the loader. It defines
all the methods of PySimulationBase.
Attributes:
simu: a Simulation_ object
"""
def __init__(self,sim):
self.simu = sim
def getNumParticles(self):
return self.simu.numParticles
def getBoxsize(self):
return self.simu.BoxSize
def getPositions(self):
return self.simu.positions
def getTypes(self):
return self.simu.types
def getVelocities(self):
return self.simu.velocities
def getIdentifiers(self):
return self.simu.identifiers
def getTime(self):
return self.simu.time
def getHubble(self):
return self.simu.Hubble
def getOmega_M(self):
return self.simu.Omega_M
def getOmega_Lambda(self):
return self.simu.Omega_Lambda
@ -281,7 +284,7 @@ cdef class ArrayWrapper:
cdef void* data_ptr
cdef np.uint64_t size
cdef int type_array
cdef set_data(self, np.uint64_t size, int type_array, void* data_ptr):
""" Set the data of the array
This cannot be done in the constructor as it must recieve C-level
@ -294,22 +297,22 @@ cdef class ArrayWrapper:
self.data_ptr = data_ptr
self.size = size
self.type_array = type_array
def __array__(self):
""" Here we use the __array__ method, that is called when numpy
tries to get an array from the object."""
cdef np.npy_intp shape[1]
shape[0] = <np.npy_intp> self.size
# Create a 1D array, of length 'size'
ndarray = np.PyArray_SimpleNewFromData(1, shape, self.type_array, self.data_ptr)
return ndarray
def __dealloc__(self):
""" Frees the array. This is called by Python when all the
references to the object are gone. """
pass
cdef object wrap_array(void *p, np.uint64_t s, int typ):
cdef np.ndarray ndarray
cdef ArrayWrapper wrapper
@ -319,7 +322,7 @@ cdef object wrap_array(void *p, np.uint64_t s, int typ):
ndarray = np.array(wrapper, copy=False)
ndarray.base = <PyObject*> wrapper
Py_INCREF(wrapper)
return ndarray
@ -368,7 +371,7 @@ def loadGadget(str filename, int snapshot_id, int gadgetFormat = 1, bool loadPos
"""loadGadget(filename, snapshot_id, gadgetFormat = 1, loadPosition=True, loadVelocity=False, loadId=False, loadType=False)
This function loads Gadget-1 snapshot format.
If snapshot_id is negative then the snapshot is considered not to be part of
a set of snapshots written by different cpu. Otherwise the filename is modified
to reflect the indicated snapshot_id.
@ -376,16 +379,16 @@ def loadGadget(str filename, int snapshot_id, int gadgetFormat = 1, bool loadPos
Arguments:
filename (str): input filename
snapshot_id (int): identifier of the gadget file if it is a multi-file snapshot
Keyword arguments:
loadPosition (bool): whether to load positions
loadVelocity (bool): whether to load velocities
loadId (bool): whether to load unique identifiers
loadType (bool): whether to set types to particles
loadMass (bool): whether to set the mass of particles
Returns:
an PySimulationAdaptor instance.
an PySimulationAdaptor instance.
"""
cdef int flags
@ -419,13 +422,13 @@ def loadParallelGadget(object filename_list, int gadgetFormat = 1, bool loadPosi
Arguments:
filename (list): a list or tuple of filenames to load in parallel
Keyword arguments:
loadPosition (bool): indicate to load positions
loadVelocity (bool): indicate to load velocities
loadId (bool): indicate to load id
loadType (bool): indicate to load particle types
Returns:
It loads a gadget-1 snapshot and return a cosmotool.PySimulationBase_ object.
"""
@ -453,16 +456,16 @@ def loadParallelGadget(object filename_list, int gadgetFormat = 1, bool loadPosi
data = alloc_simudata(num_files)
for i,l in enumerate(filename_list):
filenames[i] = l.encode('utf-8')
with nogil:
for i in prange(num_files):
local_data = loadGadgetMulti_safe(filenames[i], flags, gadgetFormat)
data[i] = local_data
# data[i] = loadGadgetMulti(filenames[i].c_str(), -1, flags)
out_arrays = []
for i in xrange(num_files):
if data[i] == <SimuData*>0:
if data[i] == <SimuData*>0:
out_arrays.append(None)
else:
out_arrays.append(PySimulationAdaptor(wrap_simudata(data[i], flags)))
@ -473,10 +476,10 @@ def loadParallelGadget(object filename_list, int gadgetFormat = 1, bool loadPosi
def writeGadget(str filename, object simulation):
"""writeGadget(filename, simulation)
This function attempts to write the content of the simulation object into
This function attempts to write the content of the simulation object into
a file named `filename` using a Gadget-1 file format.
Arguments:
filename (str): output filename
simulation (PySimulationBase): a simulation object
@ -486,23 +489,23 @@ def writeGadget(str filename, object simulation):
cdef np.ndarray[np.int64_t, ndim=1] ids
cdef np.int64_t NumPart
cdef int j
if not isinstance(simulation,PySimulationBase):
raise TypeError("Second argument must be of type SimulationBase")
NumPart = simulation.positions[0].size
simdata.noAuto = True
for j in xrange(3):
pos = simulation.getPositions()[j]
vel = simulation.getVelocities()[j]
if pos.size != NumPart or vel.size != NumPart:
raise ValueError("Invalid number of particles")
simdata.Pos[j] = <float *>pos.data
simdata.Vel[j] = <float *>vel.data
ids = simulation.getIdentifiers()
simdata.Id = <int64_t *>ids.data
simdata.BoxSize = simulation.getBoxsize()
@ -519,21 +522,21 @@ def writeGadget(str filename, object simulation):
def loadRamses(str basepath, int snapshot_id, int cpu_id, bool doublePrecision = False, bool loadPosition = True, bool loadVelocity = False, bool loadId = False, bool loadMass = False):
""" loadRamses(basepath, snapshot_id, cpu_id, doublePrecision = False, loadPosition = True, loadVelocity = False)
Loads the indicated snapshot based on the cpu id, snapshot id and basepath. It is important to specify the correct precision in doublePrecision otherwise the loading will fail. There is no way of auto-detecting properly the precision of the snapshot file.
Args:
basepath (str): the base directory of the snapshot
snapshot_id (int): the snapshot id
cpu_id (int): the cpu id of the file to load
Keyword args:
doublePrecision (bool): By default it is False, thus singlePrecision
loadPosition (bool): Whether to load positions
loadVelocity (bool): Whether to load velocities
loadId (bool): Whether to load identifiers
loadMass (bool): Whether to load mass value
loadMass (bool): Whether to load mass value
Returns:
An object derived from PySimulationBase_.
An object derived from PySimulationBase_.
"""
cdef int flags
cdef SimuData *data
@ -549,7 +552,7 @@ def loadRamses(str basepath, int snapshot_id, int cpu_id, bool doublePrecision =
if loadMass:
flags |= NEED_MASS
encpath = basepath.encode('utf-8')
encpath = basepath.encode('utf-8')
try:
data = loadRamsesSimu(encpath, snapshot_id, cpu_id, doublePrecision, flags)
if data == <SimuData*>0:
@ -558,4 +561,4 @@ def loadRamses(str basepath, int snapshot_id, int cpu_id, bool doublePrecision =
raise RuntimeError(str(e) + ' (check the float precision in snapshot)')
return PySimulationAdaptor(wrap_simudata(data, flags))