Reconstruct particles from ct images
Hello!
I have a question about generating clumps from '.gts' files. I have almost 800 gts files. The issue was that the generated clump had a smaller volume than the original GTS file, causing the sample to shrink in the height direction. The inherent contact force chains were also altered as a result of this phenomenon. Can anyone assist me with this problem?
Best Kyle
Question information
- Language:
- English Edit question
- Status:
- Solved
- For:
- Yade Edit question
- Assignee:
- No assignee Edit question
- Solved by:
- Ruidong LI
- Solved:
- Last query:
- Last reply:
Revision history for this message
|
#1 |
Hi Kyle,
I think that you need to be much more specific. For example, is each of the 800 gts files modelling a single particle? Do you try to reproduce the exact shape of the sample (particles in their corresponding locations from the very beginning)? What code do you use to generate clumps? Can you prepare the MVE[1]? If not possible, please describe your workflow. What do you mean that the sample shrinks in the height direction? Smaller than expected after deposition, or did something actually shrink?
Best wishes,
Karol
Revision history for this message
|
#2 |
Karol, Thanks for your reply.
---I think that you need to be much more specific. For example, is each of the 800 gts files modelling a single particle?
---Yes. Each GTS file denotes one single particle.
---Do you try to reproduce the exact shape of the sample (particles in their corresponding locations from the very beginning)? What code do you use to generate clumps?
---Yes. I'd like to reproduce the exact shape of the sample (particles in their corresponding locations from the very beginning). The code I used to generate the clump is presented below:
def createSphere(pred, ndivmin, spacing):
aabb = pred.aabb()
dim0 = aabb[1][0] - aabb[0][0]
bodyList = []
ndiv = ndivmin
while len(bodyList)==0:
radius = dim0 / ndiv # get some characteristic dimension, use it for radius
bodyList = O.bodies.
ndiv = ndiv + spacing
---Can you prepare the MVE[1]? If not possible, please describe your workflow.
--- I can provide the MVE. But I don't know how to provide my GTS. I just imported gts files into Yade and created the surface, then generate spheres using the 'pack.regularHexa' function.
---What do you mean that the sample shrinks in the height direction? Smaller than expected after deposition, or did something actually shrink?
--- This means that when the unbalanced force ratio tends to be stable, the height of the sample is smaller than the real value. The reason behind this, I guess, is the voids between clumps since clumps are smaller than the gts surface.
Revision history for this message
|
#3 |
Are the particles somehow bonded (I mean grains in the sample)? If not, I think that particles rearrange and change the height of the sample.
If you want to adjust the size of the particles, you can expand spheres in the packing a little bit after generation.
Cheers,
Karol
Revision history for this message
|
#4 |
or use a different packing method than regularHexa, see e.g. [Kozicki2012] [2]
Cheers
Jan
Revision history for this message
|
#5 |
Thanks for your reply, Karol.
>Are the particles somehow bonded (I mean grains in the sample)?
--What do you mean particles are bonded? The particles in a clump are bonded. But the particle surfaces (gts) are separated from each other with a small gap (one-pixel distance in the ct image).
>If not, I think that particles rearrange and change the height of the sample.
--Yes. I think so. The rearrangement of particle positions and gaps between clumps changed the height of the sample.
>If you want to adjust the size of the particles, you can expand spheres in the packing a little bit after generation.
--Yes, I have tried this method. I have increased the z-coordinates (the direction of height) of each point in the gts file by 1.2 times. But the result indicates that the height of the sample is still not insufficient. My target is 40mm, and the obtained one is 37.5mm (multiple 1.2 times in z coordinates). By doing so, the unbalanced force ratio always stands at a high level (>0.25).
Do you have any other recommendations?
Best
Kyle
Revision history for this message
|
#6 |
Thanks for your reply, Jan.
>or use a different packing method than regularHexa, see e.g. [Kozicki2012] [2]
-- I have looked through your recommended paper. But in my opinion, maybe the method mentioned in this paper is more suitable for regular shapes. What I have are irregular-shaped particles with interior holes.
Do you have any other recommendations?
Best
Kyle
Revision history for this message
|
#7 |
I can also recommend Matlab code for clumo generation developed by Angelidakis et al. It is described in [3].
[3] Angelidakis et al. 2021 CLUMP: A Code Library to generate Universal Multi-sphere Particles, Softwarex
Revision history for this message
|
#8 |
Yes, [Kozicki2012] uses "regular" (symmetric) shapes.
Just an idea to use this concept of "suitably" overlapping spheres, which would represent more realistically the actual shape then cropped regular hexa packing.
Of course, it would need some development, with uncertain result :-)
Cheers
Jan
Revision history for this message
|
#9 |
Thanks for your reply, Karol.
>I can also recommend Matlab code for clumo generation developed by Angelidakis et al. It is described in [3].
[3] Angelidakis et al. 2021 CLUMP: A Code Library to generate Universal Multi-sphere Particles, Softwarex
--I will try and respond to you ASAP. Many thanks.
Best
Kyle
Revision history for this message
|
#10 |
Thanks for your reply, Jan.
>Just an idea to use this concept of "suitably" overlapping spheres, which would represent more realistically the actual shape then cropped regular hexa packing. Of course, it would need some development, with uncertain result :-)
-- yes. I will try and respond to you ASAP. Many thanks.
Best
Kyle
Revision history for this message
|
#11 |
Thanks for your reply, Karol.
>I can also recommend Matlab code for clumo generation developed by Angelidakis et al. It is described in [3].
[3] Angelidakis et al. 2021 CLUMP: A Code Library to generate Universal Multi-sphere Particles, Softwarex
--By the way, I'd like to ask how can I import the position and radius of generated spheres into Yade. I mean once I obtain the positions and radius of spheres forming a clump externally such as your recommendation [1]. I can use the function 'O.bodies.
[1] Angelidakis et al. 2021 CLUMP: A Code Library to generate Universal Multi-sphere Particles, Softwarex
Best
Kyle
Revision history for this message
|
#12 |
Hi Kyle,
You can use something like:
c1 = ymport.
O.bodies.
where yourClump.txt file should be in the format: x y z r, i.e. center and radius of each sphere, like here (for a three-sphere rod):
0 0 0 1
1 0 0 1
2 0 0 1
If you have all of your clump files in a the same directory, it should be easy to iterate through them in a loop.
Hope this helps,
Vasileios
Revision history for this message
|
#13 |
Dear Vasileios,
Thanks for your answer. I have tried your code.
The error is below:
unning script /home/kyle/
Traceback (most recent call last):
File "./yade-Unknown", line 343, in runScript
execfile(
File "/usr/lib/
exec_(code, myglobals, mylocals)
File "/home/
O.bodies.
TypeError: No registered converter was able to produce a C++ rvalue of type boost::
My code is:
inputfile = '/home/
spheres = ymport.
O.bodies.
The file in the 'inputfile' is like this (contain many clumps):
0.068037 0.02416 0.0017637 0.0011423 1
0.068615 0.022601 0.0014278 0.00077244 1
0.069542 0.023528 0.0017906 0.00071539 1
0.066801 0.025141 0.0019788 0.0006786 1
0.049731 0.03499 0.0017112 0.00070436 10
0.048747 0.034309 0.0013637 0.00063928 10
0.047719 0.034628 0.0014651 0.00056027 10
0.047299 0.035323 0.0020008 0.00052311 10
Sorry to trouble you. But do you know what's wrong with this?
Best,
Kyle
Revision history for this message
|
#14 |
Hi Kyle,
In your code, you do not need the "O.bodies.
Best,
Vasileios
[1] https:/
Revision history for this message
|
#15 |
Dear Vasileios,
Thanks for your answer. I have tried your code. So I just need to create a text for each clump and import them iteratively, right? Just using the 'ymport.textClumps statement'.
Best,
Kyle
Revision history for this message
|
#16 |
Dear Kyle,
If you used my suggestion from answer #12 of this discussion you would need iterations (not good).
You actually have a better solution in answer #13.
Can you please run your script:
spheres = ymport.
O.bodies.
In your inputfile you have 2 clumps in one file, so your solution does not require iterations. Is something still unclear?
Best,
Vasileios
Revision history for this message
|
#17 |
Dear Vasileios,
Thanks for your answer.
I am so confused. In my opinion, the statement 'ymport.textClumps' is enough. is Adding the statement 'O.bodies.
Moreover, What I want to do is import multiple grains with different colour (same colour for spheres in the same clump). This can be done with the statement 'ymport.textClumps' but requires an iteration of loading text.
If I put all clump information into one single text like this answer #13. Can I still distinguish clumps by assigning different colours?
Best,
Kyle
Revision history for this message
|
#18 |
Hi Kyle,
If you use ymport.text() function, you don't have to append bodies (it is included in the function).
If you want to differentiate between clump properties, you can do it in two ways (at least):
1) put each clump in a separate file and load it with different keyword arguments passed to ymport.text() function.
2) put all the clumps in one file, and load them at once. Next, iterate over bodies in the simulation and apply required properties.
Please see example of using the second approach below:
####### input file with clumps "clumps.txt"
0.068037 0.02416 0.0017637 0.0011423 1
0.068615 0.022601 0.0014278 0.00077244 1
0.069542 0.023528 0.0017906 0.00071539 1
0.066801 0.025141 0.0019788 0.0006786 1
0.049731 0.03499 0.0017112 0.00070436 10
0.048747 0.034309 0.0013637 0.00063928 10
0.047719 0.034628 0.0014651 0.00056027 10
0.047299 0.035323 0.0020008 0.00052311 10
##### Yade script
from yade import ymport
spheres = ymport.
currentClumpId = O.bodies[0].clumpId
color = randomColor()
for b in O.bodies:
if b.clumpId != currentClumpId:
color = randomColor()
if isinstance(
###
Cheers,
Karol
Revision history for this message
|
#19 |
Dear Karol,
Many thanks. Your suggestion sovled my problem.
Cheers,
Kyle
Revision history for this message
|
#20 |
Hi, Karol.
I wonder that what the '1' and '10' mean in the 'clumps.txt'
####### input file with clumps "clumps.txt"
0.068037 0.02416 0.0017637 0.0011423 1
0.068615 0.022601 0.0014278 0.00077244 1
0.069542 0.023528 0.0017906 0.00071539 1
0.066801 0.025141 0.0019788 0.0006786 1
0.049731 0.03499 0.0017112 0.00070436 10
0.048747 0.034309 0.0013637 0.00063928 10
0.047719 0.034628 0.0014651 0.00056027 10
0.047299 0.035323 0.0020008 0.00052311 10