Hi Yves,
First I'd like to thank you for posting some of our prior discussions here.
It might help inspire others.
It seems you are still looking for a "portal" type boundary with tracking
numbers ability. While it's on the list of features that I wanted to add,
right now I have a few ideas to achieve the same, besides the ones you
proposed. If we have the chance, we can talk about them in the follow-up
posts.
However, I have a question regarding the first idea you proposed. It is a
smart way to utilize *CorrectFamilyXXX *methods to isolate those elements
that need to be reinserted and randomly re-position them, and I think it
should work. However, since *CorrectFamilyXXX *methods check the
conditions every step, unless the physics naturally leads to quick-session
reinsertions (like having a huge outlet orifice), there should not be "way
too many of these spheres that are trying to be reinserted" at any given
time.
Can you explain why the line "bool need_reset = ((Z > {z_discharge}) ||
(max_v > {recirculation_vmax}));" has Z > {z_discharge}, rather than Z <
{z_discharge}? If it is >, wouldn't you have almost all elements in the
simulation trying to be reinserted at the same time?
Can you explain this first and then let me know whether you expect the
simulation to naturally have quick-session reinsertions by the nature of
the governing physics, then we can continue the discussion.
Thank you,
Ruochun
On Tuesday, February 20, 2024 at 11:58:23 PM UTC+8 [email protected]
wrote:
> 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/f17b3c71-2e3e-42b1-866a-19aa53e957b3n%40googlegroups.com.