User Data UDF
The input data structs ParticleData_UDF, PassThroughUDF_ParticleData and CollisionData_UDF contain a void* pointer to a user defined data struct. This allows you to attach arbitrary data to a particle. You can modified and use this data in each of the UDFs. For example, a particle-wall collision may change the internal state of the particle, and this may change the particle motion afterwards.
The sample files UDFUserData.h and UDFUserData.cpp can be used to define and initialize the user defined struct. An example struct is defined in the file UDFUserData.h
struct UserData { int number; double value; char string[32]; }; |
|
You may change, add or remove any suitable data to this struct. Each particle will carry its own UserData while its movement is simulated, the data is not shared between different particles. This struct must contain static data and never change in size during the simulation, which excludes the use of std::vector or similar classes, that allocate memory dynamically at runtime.
Two functions will be called during the life of a particle. The startParticle function will be called at the start of a particle run, such that the UserData may be initialized. The endParticle function will be called at the end of a particle run, such that UserData can be printed or saved to a file.
To activate the user date UDF, open Settings - Edit Expert Settings in the main menu. There, click Add Row, select the appropriate FilterDict command and enter the file path to the .so (Linux) or .dll (Windows) file.

A User Data UDF must contain three functions.
The data can then be used in other UDFs. As example, the file CollisionUDF-Hamaker.cpp shows how to access the user data.
At first, the void* pointer has to be casted to the actual struct. Afterwards, it can be used to access the variables. This example simply counts the number variable up.
CollisionResult_UDF udf_collision( const ParticleData_UDF& p, const CollisionData_UDF& c, const double* mp ){ |
|
if (p.userData != nullptr) { |
// make sure userData is initialized |
UserData* userData = (UserData *)p.userData; |
// cast void* pointer to struct |
userData->number += 1; } |
|
// continue with function |
|
} |
|