ParticleData ============= .. doxygenfile:: ParticleData/ParticleData.cuh :project: uammd :sections: briefdescription ParticleData exposes the following API: .. doxygenclass:: uammd::ParticleData :project: uammd :members: **Example: creating a ParticleData instance** .. code:: c++ auto pd = make_shared(numberParticles); Getting a handle get a certain property ------------------------------------------ You can access a property via :cpp:any:`ParticleData` in GPU or CPU memory. You must specify the kind of access (read, write, readwrite). .. doxygenstruct:: uammd::access :project: uammd :members: :undoc-members: .. note:: The enumerators :cpp:enum:`access::location` and :cpp:enum:`access::mode` can be used without the second scope. In other words, you can write :cpp:any:`access::gpu` instead of :cpp:any:`access::location::gpu`. The type returned by :cpp:any:`ParticleData::getProperty` is a lightweight standard-library-like pseudo-container defined as .. doxygenclass:: uammd::property_ptr :project: uammd :members: Example ~~~~~~~~~ .. code:: cpp auto pd = std::make_shared(numberParticles); auto radius = pd->getRadius(access::gpu, access::write); thrust::fill(thrust::cuda::par, radius.begin(), radius.end(), 1.0); auto force = pd->getForce(access::cpu, access::write); std::fill(force.begin(), force.end(), real4()); auto id = pd->getId(access::cpu, access::read); //It is not legal to write to ID, one can only read from it. int* raw_id_property_pointer = id.raw(); If the mode is set to write, the handle will gain exclusivity and no one else will be able to access it until it is released (the handle is deleted). .. note:: There is no real difference between :cpp:any:`access::write` and :cpp:any:`access::readwrite` (at the moment) beyond informing the reader of the intention of modifying the contents (readwrite) vs ignoring the current contents and overwriting (write). .. warning:: UAMMD cannot write to a property that is currently being read and cannot read from a property that is currently being written to. **It is important to control the scope of the property handles**, deleting them as soon as possible and never storing them (store a pointer to :cpp:any:`ParticleData` instead). Handles are compatible with std and thrust algorithms and can be considered c++ iterators for all intents and purposes. .. _list-of-available-properties: List of available properties ----------------------------- The beginning of ParticleData.cuh contains a list of available per particle properties (such as positons, velocities, forces...). You can see a list of all the available ones and add more properties by appending to the macro :cpp:any:`ALL_PROPERTIES_LIST`. A family of access functions will be autogenerated for each property inside this macro (such as get[Name] (), [Name]WrittenSignal(), ...). For instance, ParticleData holds the positions of the particles in :cpp:type:`real4` variables in an array named "pos". Thus, the function :cpp:`property_ptr ParticleData::getPos()` is available. Basic properties include (type name): * :cpp:`real4 pos` * :cpp:`real3 vel` * :cpp:`real4 force` * :cpp:`real energy` * :cpp:`real virial` * :cpp:`real mass` * :cpp:`real charge` * And more defined in ParticleData.cuh .. doxygendefine:: ALL_PROPERTIES_LIST :project: uammd .. _particle_id_assignation: Particle id assignation ------------------------ When added each particle is assigned an unique id or name (which corresponds to its position in the underlying container just after ParticleData creation). At this moment one can access the position of particle with id=i at pos[i]. A reordering or some other internal processes may alter this fact, making the index of the particle with id=i not correspond to i anymore. While the location of each particle in the internal containers might change, the particles ids (names) will never change. The current ids are available through the property "Id" in ParticleData: .. code:: cpp auto index2id = pd->getId(access::cpu, access::read); int someIndex=0; int nameOfParticleAtSomeIndex = index2id[someIndex]; The opposite indirection is also accessible through ParticleData. That is finding the current index of a certain particle through its id (name): .. cpp:function:: const int* ParticleData::getIdOrderedIndices(access::location loc); Returns an array with memory residing at the given location with the current indices of the particles given their id. .. code:: cpp auto id2index = pd->getIdOrderedIndices(access::cpu); int someId=0; int indexOfParticleWithSomeId = id2index[someId]; Thrust offers a permutation_iterator that can be used to mask this behavior to access a certain property by either id or index: .. code:: cpp auto positionWithArbitraryOrder = pd->getPos(access::cpu, access::read); //Accessing particles when order is not important int someIndex = 0; real4 positionOfParticleAtSomeIndex = pos[someIndex]; auto index2id = pd->getId(access::cpu, access::read); int idOfParticleAtSomeIndex = index2id[someIndex]; //Accessing particles so index = name int someId = 0; auto id2Index = pd->getIdOrderedIndices(access::cpu); //Using a simple indirection real4 positionOfParticleWithSomeId = positionWithArbitraryOrder[id2index[someId]]; //Using a permutation iterator auto positionOrderedById = thrust::make_permutation_iterator(positionWithArbitraryOrder, id2index); real4 positionOfParticleWithSomeId = positionOrderedById[someId]; Advanced usage --------------- Triggering a sorting ~~~~~~~~~~~~~~~~~~~~~~ One can trigger a global sorting of the particles in ParticleData by calling :cpp:`ParticleData::sortParticles()`. This will reorder the particles in the internal containers and update the indices accordingly. .. cpp:function:: void ParticleData::hintSortByHash(Box box, real3 typicalDistance) Informs :cpp:class:`ParticleData` of the simulation domain and the typical distance of the interactions in each direction. ParticleData will use this information to improve the effectiveness of the spatial hashing. Signals ~~~~~~~~~~~ ParticleData broadcasts a signal every time some internal processes undergo, such as a particle reordering or a resize. One can subscribe to these signals like this: .. code:: cpp class User{ connection reorderConnection, numParticlesChangedConnection; public: User(std::shared_ptr pd){ reorderConnection = pd->getReorderSignal()-> connect([this](){this->handle_reorder();}); numParticlesChangedConnection = pd->getNumParticlesChangedSignal()->connect([this](int Nnew){this->handle_numChanged(Nnew);}); } ~User(){ reorderConnection.disconnect(); numParticlesChangedConnection.disconnect(); } void handle_reorder(){ std::cout<<"A reorder occured!!"`_. .. cpp:type:: template signal = nod::unsafe_signal UAMMD's signal class. Must be specialized with a function signature, for instance :cpp:`using non_broadcasting_signal = signal`. .. cpp:type:: connection = nod::connection Keeps track of an open signal connection. Its main use is to be able to safely detach from a signal via :cpp:`connection::disconnect()` A list of available signals is available in the :cpp:any:`ParticleData` class documentation. Saving and restoring from a file %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .. cpp:function:: void saveParticleData(std::string fileName, std::shared_ptr pd); Writes all allocated properties in :code:`pd` to the file (overwrites if existing); .. cpp:function:: std::shared_ptr restoreParticleData(std::string fileName, std::shared_ptr sys); Loads the :code:`ParticleData` instance stored by :code:`saveParticleData` in the file :code:`fileName`.