EDEM API: Custom particle factory

Bharath Rangavittal
Bharath Rangavittal Altair Community Member
edited November 2022 in Community Q&A

Hi,

 

I am looking to employ a custom particle factory depending on the height of the packed bed. I have a vertical column of a packed bed of particles. The height of the bed starts to reduce in the column as the particles are removed from the bottom. As the bed height falls below a certain level, I would like a certain amount of particles to be injected into the column at the top so that the bed height is increased again. I was thinking of accessing the location of particle to get an estimate of the bed height. Could anyone guide me on how to gain access to location of the particles using Factory API?

Tagged:

Answers

  • RWood
    RWood
    Altair Employee
    edited November 2022

    Hi,

    You can't do that with a custom factory alone. If you want access to the particle data for particles currently in the simulation then you will need a particle body force as well (you could also do it with a contact model but I don't think that's what you want here). 

    From within a body force plugin you can get access to all the particle location data. From there, you could track the maximum z (or whatever your 'height' variable is) and store as a simulation custom property, which can be accessed from the custom factory. So something like:

    PBF

    • Find the 'highest' particle each timestep
    • Store this value as a simulation custom property

    Factory

    • Recover simulation custom property
    • Create particles based on whatever condition you like around the property

     

    Cheers,

    Richard

  • Bharath Rangavittal
    Bharath Rangavittal Altair Community Member
    edited November 2022

    Hi,

    You can't do that with a custom factory alone. If you want access to the particle data for particles currently in the simulation then you will need a particle body force as well (you could also do it with a contact model but I don't think that's what you want here). 

    From within a body force plugin you can get access to all the particle location data. From there, you could track the maximum z (or whatever your 'height' variable is) and store as a simulation custom property, which can be accessed from the custom factory. So something like:

    PBF

    • Find the 'highest' particle each timestep
    • Store this value as a simulation custom property

    Factory

    • Recover simulation custom property
    • Create particles based on whatever condition you like around the property

     

    Cheers,

    Richard

    Hi Richard,

     

    Thanks for your suggestion.

     

    Are there any examples that I can refer for implimenting your suggestion?

     

    Regards,

    Bharath

  • RWood
    RWood
    Altair Employee
    edited November 2022

    Hi Richard,

     

    Thanks for your suggestion.

     

    Are there any examples that I can refer for implimenting your suggestion?

     

    Regards,

    Bharath

    I would suggest going through the API tutorials, which you can find on the Community website. If you search for "EDEM Api Tutorial" you should get hits on them all. Tutorial 5 in particular introduces the use of custom properties:

    https://community.altair.com/community?id=kb_article&sysparm_article=KB0037693

    Richard

     

  • Bharath Rangavittal
    Bharath Rangavittal Altair Community Member
    edited November 2022

    Hi Richard,

     

    Thanks for your guidance. I have been following the tutorial. I was able to succesfully compile and load the plugin into EDEM simulation. Basically, I have used particle body force plugin (V2_0_0) and have tried to get the height of the bed based on maximum z position of particle and the rest of the code is shown below:

     

    //variable intialised for bed_height

    double bed_height=0;

    NApi::ECalculateResult CNewPBF::externalForce(
    int threadId, double time, double timestep,
    int id, const char type[], double mass,
    double volume, double density, unsigned int surfaces,
    double posX, double posY, double posZ,
    double velX, double velY, double velZ,
    double angVelX, double angVelY, double angVelZ,
    double charge, const double orientation[9],
    NApiCore::ICustomPropertyDataApi_1_0* particlePropData,
    NApiCore::ICustomPropertyDataApi_1_0* simulationPropData,
    double& calculatedForceX, double& calculatedForceY, double& calculatedForceZ,
    double& calculatedTorqueX, double& calculatedTorqueY, double& calculatedTorqueZ)
    {

    //assign Z position of particle to a variable bed_height if the condition is satisfied
    if (posZ > bed_height)
    {
    bed_height=posZ;
    }

    //assign bed_height to simulation custom property

    double* simHeight = simulationPropData->getDelta(HEIGHT_BED.c_str());
    *simHeight = bed_height;

    return eSuccess;
    }

    This code shows an unreasonable value for simulation custom property in the order of 10^6 or 10^7. (I expect it to be between -5 and 5)  Could you tell me what the issue is with the code? I am assuming that the method externalForce() is implimented on each particle in a loop for each time step. Correct me if I am wrong. 

    It will be really helpful if you could point out what the issue is. 

    Thanks,

    Bharath

     

  • RWood
    RWood
    Altair Employee
    edited November 2022

    Hi Richard,

     

    Thanks for your guidance. I have been following the tutorial. I was able to succesfully compile and load the plugin into EDEM simulation. Basically, I have used particle body force plugin (V2_0_0) and have tried to get the height of the bed based on maximum z position of particle and the rest of the code is shown below:

     

    //variable intialised for bed_height

    double bed_height=0;

    NApi::ECalculateResult CNewPBF::externalForce(
    int threadId, double time, double timestep,
    int id, const char type[], double mass,
    double volume, double density, unsigned int surfaces,
    double posX, double posY, double posZ,
    double velX, double velY, double velZ,
    double angVelX, double angVelY, double angVelZ,
    double charge, const double orientation[9],
    NApiCore::ICustomPropertyDataApi_1_0* particlePropData,
    NApiCore::ICustomPropertyDataApi_1_0* simulationPropData,
    double& calculatedForceX, double& calculatedForceY, double& calculatedForceZ,
    double& calculatedTorqueX, double& calculatedTorqueY, double& calculatedTorqueZ)
    {

    //assign Z position of particle to a variable bed_height if the condition is satisfied
    if (posZ > bed_height)
    {
    bed_height=posZ;
    }

    //assign bed_height to simulation custom property

    double* simHeight = simulationPropData->getDelta(HEIGHT_BED.c_str());
    *simHeight = bed_height;

    return eSuccess;
    }

    This code shows an unreasonable value for simulation custom property in the order of 10^6 or 10^7. (I expect it to be between -5 and 5)  Could you tell me what the issue is with the code? I am assuming that the method externalForce() is implimented on each particle in a loop for each time step. Correct me if I am wrong. 

    It will be really helpful if you could point out what the issue is. 

    Thanks,

    Bharath

     

    Hi,

    " I am assuming that the method externalForce() is implimented on each particle in a loop for each time step"

    That's correct.

    I don't know the finer details of your simulation but it looks like if you have multiple particles above the bed height then you will be adding to the delta multiple times. I'd double check that you're not entering your if block more than once by debugging your code.

    However I think the main issue is you're not subtracting the current value of the property. You're constantly adding to the property but not taking anything away. The value doesn't reset to zero per timestep. To reset the value back to zero you need to have delta -= value, but only once. To do this you can use the configForTimestep( ) function, which is only called once per timestep.

    If you're working with particle properties then you can often just have:

    delta = whatever - value

    and it's fine. For a simulation property in a PBF this won't work because you'd be doing -value for every particle.

    Hope that makes sense.

    Richard

  • Bharath Rangavittal
    Bharath Rangavittal Altair Community Member
    edited November 2022

    Hi Richard,

    Thanks for your patience. I have almost understood everything you had mentioned.

    I just have one final question, I modified the code in the following way:

    //method to assign maximum z position to delta (added to custom property value at the end of timestep) in external force(). Please note that I am not adding the delta values,but just changing it. 

    if (posZ > bed_height)
    {
    bed_height = posZ;
    double* tempHeight = simulationPropData->getDelta(m_bedHeighIndex);
    *tempHeight = bed_height;
    }

    //method to reset the  custom property value to 0 using configForTimeStep()

    {
    double* temp = simData->getDelta(m_bedHeighIndex);
    *temp = *temp- *simData->getValue(m_bedHeighIndex) ;
    }

     

    This give the simulation custom property value as 0 at all time steps. If my understanding is right, the value held by the custom property (which is 0) after the configForTimeStep() is shown in simulation. If yes, could you tell me how I could change the code to show the value calculated at the end of each time step (after externalforce())? 

    I am sorry. I am using custom property API for the first time. So it is taking some time to understand the different functionality.

     

    Thank you!

    Bharath

     

     

  • Bharath Rangavittal
    Bharath Rangavittal Altair Community Member
    edited November 2022

    Hi Richard,

     

    I was able to solve the issue. I assigned a value to the delta in configForTimeStep() rather than in external force(). The modified code is as follows:

    //method to find out the maximum z position of particle at each time step in in external force()

    if (posZ > bed_height)
    {
    bed_height = posZ;
    }

     

    //method to assign this maximum z position to simulation custom property in configForTimeStep()

    {
    double* temp = simData->getDelta(m_bedHeighIndex);
    *temp = *temp +bed_height-*simData->getValue(m_bedHeighIndex);
    bed_height = 0;
    }

     

    Thanks a lot for your help!

  • RWood
    RWood
    Altair Employee
    edited November 2022

    Hi Richard,

     

    I was able to solve the issue. I assigned a value to the delta in configForTimeStep() rather than in external force(). The modified code is as follows:

    //method to find out the maximum z position of particle at each time step in in external force()

    if (posZ > bed_height)
    {
    bed_height = posZ;
    }

     

    //method to assign this maximum z position to simulation custom property in configForTimeStep()

    {
    double* temp = simData->getDelta(m_bedHeighIndex);
    *temp = *temp +bed_height-*simData->getValue(m_bedHeighIndex);
    bed_height = 0;
    }

     

    Thanks a lot for your help!

    No problem. Good job getting it working.

    Richard