Hello,

I am looking for the most efficient way to discharge spheres and reinsert 
them within the geometry with DEM-Engine.

My ideal goal would be to take the lowest spheres in a sphere stack one by 
one and reinsert them (one by one) from the top of the geometry. It can be 
relaxed in reinserting the spheres from a pipe that can contain a few 
spheres. My application also requires that I track the number of 
discharged/reinserted spheres, and to be as fast as possible in solving 
each iteration. However, I have not been able so far to do it.

My first attempt was to make it as simple as possible, but I sacrificed too 
many requirements. In that attempt, I make a discharge plane, and spheres 
that are below the plane have their positions reset at the top of the 
geometry:

[...]
recirculation_vmax = 100 # "Explosion" safety when colliding -> reset
vel_reinsertion = [0,0,0] # How fast we reinsert the sphere
z_discharge = sphere['equivalent_radius'] # How high we want the spheres to 
be discharged
pipe_height = world_height - 4*sphere['equivalent_radius'] # How high do we 
want the pipe in which the sphere is reinserted
pipe_radius = 2*sphere['equivalent_radius'] # How wide the "pipe" that 
reinserts the spheres is

# Make the position block: for a given sphere, precalculate the x,y,z of 
the re-insertion when the test is satisfied
# Note: the test is satisfied if the sphere is below the recirculation 
plane, or if the velocity is too high
pos_block = f'''curandState state;
float Zmin, Zmax, Rmax, x, y, z, radius, radius_squared, angle;
curand_init(1234, ownerID, 0, &state);
float random_number = curand_uniform(&state);
float max_v = max(max(vX, vY), vZ);;
bool need_reset = ((Z > {z_discharge}) || (max_v > {recirculation_vmax}));
if (need_reset) 
{{
    Zmin = {world_height - pipe_height + sphere['equivalent_radius']};
    Zmax = {world_height - sphere['equivalent_radius']};
    Rmax = {pipe_radius - sphere['equivalent_radius']};

    radius_squared = curand_uniform(&state) * std::pow(Rmax, 2.0f);
    radius = std::pow(radius_squared, 0.5f);
    angle =  curand_uniform(&state) * 3.14 * 2;
    x = radius * sin(angle);
    y = radius * cos(angle);
    z = Zmin + curand_uniform(&state)*(Zmax-Zmin);
}}'''

# Make the velocity block. No calculation is needed, just the same check
vel_block = f'''float max_v = max(max(vX, vY), vZ);;
bool need_reset = ((Z > {z_discharge}) || (max_v > 
{recirculation_vmax}));'''

# Apply rules to the spheres' family (1)
DEMSim.CorrectFamilyPosition(1, '(need_reset) ? x : X', '(need_reset) ? y : 
Y', '(need_reset) ? z : Z', pos_block)
DEMSim.CorrectFamilyLinVel(1, f'(need_reset) ? {vel_reinsertion[0]} : vX', 
f'(need_reset) ? {vel_reinsertion[1]} : vY', f'(need_reset) ? {
vel_reinsertion[2]} : vZ', vel_block)
[...]

A few issues arise here: I cannot control how many spheres are discharged, 
so there are way too many of these spheres that are trying to be reinserted 
at the same time, without the possibility of avoiding collisions when 
sampling the new positions, and the reset condition is not enough.

Another idea would be to play with families. I could use ChangeClumpFamily 
for a box with the same discharge plane (DEMSim.ChangeClumpFamily(100, 
Z=[-1e99, z_discharge], orig_fam=1)), but that does not resolve my issue 
much further. It allows me to change z_discharge dynamically but requires 
me to extract and sort the elevation of each sphere which seems highly 
inefficient.

What could be good would be to "force" a discharge rate, but that seems 
impossible as is. The last idea would be to delete the spheres at the 
bottom and create new ones at the top. That would still require tracking in 
some way that I am not aware of, but also would require calling 
UpdateClumps() regularly (as discussed in one of my previous posts) and 
would keep increasing memory/time as the calculation goes.

Therefore, my question is: is there a way to select the lowest spheres and 
re-circulate them from the top at a given rate with collision prevention, 
while being as efficient as possible?

Thank you!

-- 
You received this message because you are subscribed to the Google Groups 
"ProjectChrono" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/projectchrono/62c190c2-9f81-43b5-bc69-4fa7e435318dn%40googlegroups.com.

Reply via email to