# Particles in a Pipe

Warning

All these features related to particles are supported only in the particle branch

## Case

The case consists of 5 balls of radious 30, placed along Y axis, connected by a narrowing cone, like on a picture:

The particles will be placed in the wide section, and driven by the force applied to the flow.

## Geometry

We will use the OpenSCAD software to create the geometry. It will consist of four balls connected by a narrowing channel.

sudo apt install openscad


The OpenSCAD allow us to create geometries with a script.

R=30;
D=60;
translate([R,0,R]) {
sphere(d=R*2);
for (x=[1:4]) {
translate([0,x*D,0]) {
sphere(d=R*2);
}
}
rotate([-90,0,0]) cylinder(h=8*R,r1=R,r2=R/2);
rotate([90,0,0]) cylinder(h=3*R,r1=R,r2=R);
translate([0,4*D,0]) rotate([-90,0,0]) cylinder(h=3*R,r1=R,r2=R);
}


You should get a geometry like this:

From OpenSCAD you can export into several file formats. Export an ASCII STL file "pipe_txt.stl". Sadly, it is rare for any software to support ASCII STL files (which is also the case with TCLB). To create both binary stl file and MSH file for ESYS-Particle with a util program provided with TCLB:

tools/stlutil -f pipe_txt.stl -o pipe.stl
tools/stlutil -f pipe_txt.stl -o pipe.msh


## ESYS-Particle simulation

Note

For installation of ESYS-Particle, please refer to the reference

### Configuration

The ESYS-Particle is simulation is set up in a python script "pipe.py". At the begining of the script we have to initialize the sim object:

from esys.lsm import *
from esys.lsm.util import Vec3, BoundingBox
from esys.lsm.geometry import *

sim = LsmMpi(numWorkerProcesses=1, mpiDimList=[1,1,1])
sim.initNeighbourSearch( particleType="RotSphere", gridSpacing=38, verletDist=0.7 )
sim.setSpatialDomain(
BoundingBox(Vec3(0,0,0), Vec3(64,240,64)),
circDimList = [False, False, False]
)
sim.setTimeStepSize(1)
sim.setNumTimeSteps(10000)


First we read in the mesh:

sim.readMesh(
fileName = "pipe.msh",
meshName = "floor_mesh_wall"
)


Then we add a set of particles, randomly packed in a rectangle:

geoRandomBlock = RandomBoxPacker(
maxInsertFails = 1000,
bBox = BoundingBox(
Vec3(9.0000, 2.0000, 9.0000),
Vec3(51.0000, 60.0000, 51.0000)
),
circDimList = [False, False, False],
tolerance = 1.0000e-05
)
geoRandomBlock.generate()
geoRandomBlock_particles = geoRandomBlock.getSimpleSphereCollection()
sim.createParticles(geoRandomBlock_particles)


We add friction interaction between particles:

normalK = 3;
sim.createInteractionGroup (
RotFrictionPrms (
name = "friction",
normalK = normalK,
dynamicMu = 0.6,
shearK = normalK/10.0,
staticMu = 0.6,
scaling = True
)
)


and elastic interaction between particles and mesh wall:

sim.createInteractionGroup (
NRotElasticTriMeshPrms (
name = "floorWall_repell",
meshName = "floor_mesh_wall",
normalK = normalK
)
)


To start up the movement we add a small acceleration ($10^{-5}$):

sim.createInteractionGroup (
GravityPrms (
name = "gravity",
acceleration = Vec3(0.0000, 1e-5, 0.0000)
)
)


To visualize the results, we add a check-pointer, which will write dump files:

sim.createCheckPointer (
CheckPointPrms (
fileNamePrefix = "flow_data",
beginTimeStep = 0,
endTimeStep = 20000,
timeStepIncr = 100
)
)


Finnaly, we finish the "pipe.py" file with the execution of the simulation:

sim.run()


### Running ESYS-Particle

We declared that we will use 1 worker process. ESYS works in a master-slave architecture, where master process is a python interpreter. That means that we need to run our simulation with two processes:

mpirun -np 2 esysparticle pipe.py


Post-Processing

To learn how to post-process results from ESYS-Particle please refer to another section of this manual

## TCLB Simulation

The fluid flow simulation will be a simple periodic flow in a pipe with gravity force.

To run the example we will use the d3q27_cumulant_part model.

make -j 4 d3q27_cumulant_part


Compilation

For instructions on how to compile and run TCLB please refer to the Getting Started guide

### Configuration

Like any TCLB configuration (pipe.xml) we start with declaring the output directory, size of domain and initialize the domain with the collision operator:

<CLBConfig version="2.0" output="output/3D/">
<Geometry nx="64" ny="240" nz="64">
<MRT><Box/></MRT>


Now we can add our STL geometry. We want mark all elements outside of the geometry with Wall elements (and switch off collision):

                <Wall mask="ALL">
<STL file="pipe.stl" side="out"/>
</Wall>


We now close the geometry element and begin to set up the simulation settings:

        </Geometry>
<Model>
<Params ForceY="0.0001"/>
<Params omega="1.0"/>
</Model>


After that we have everything ready. We can declare what output we need and how many iterations we wan to execute:

        <Failcheck Iterations="1000"/>
<VTK/>
<VTK Iterations="1000" what="U,Solid"/>
<Solve Iterations="10000"/>
</CLBConfig>


### Running TCLB

If we are running on GPU, at this stage we can use a single GPU:

CLB/d3q27_cumulant_part/main pipe.xml


If you are running on CPU, it's probably best to use all the avaliable CPU cores:

mpirun -np 4 CLB/d3q27_cumulant_part/main pipe.xml


### Results

In ParaView you can inspect the results. The initiali VTK drop includes all fields, which means that you can check if the boudaries are in the right places etc. You can also check what is the maximal velocity.

## Combining TCLB and ESYS simulations

### Configuration

To combine the two simulations we add the <RemoteForceInterface> element to the configuration file (say pipe_dem.xml) to the <Model> container. This will include our settings for the particle simulation:

        <RemoteForceInterface Iterations="10000" particle="RotSphere" verletDist="0.7" gridSpacing="38">
fileName = "pipe.msh",
meshName = "floor_mesh_wall"
)

geoRandomBlock = RandomBoxPacker(
maxInsertFails = 1000,
bBox = BoundingBox(
Vec3(9.0000, 2.0000, 9.0000),
Vec3(51.0000, 60.0000, 51.0000)
),
circDimList = [False, False, False],
tolerance = 1.0000e-05
)
geoRandomBlock.generate()
geoRandomBlock_particles = geoRandomBlock.getSimpleSphereCollection()
sim.createParticles(geoRandomBlock_particles)
sim.setParticleDensity (   tag = 0,   mask = -1,   Density = 2.0)

normalK = 3;

sim.createInteractionGroup (
RotFrictionPrms (
name = "friction",
normalK = normalK,
dynamicMu = 0.6,
shearK = normalK/10.0,
staticMu = 0.6,
scaling = True
)
)

sim.createInteractionGroup (
NRotElasticTriMeshPrms (
name = "floorWall_repell",
meshName = "floor_mesh_wall",
normalK = normalK
)
)

sim.createInteractionGroup (
GravityPrms (
name = "gravity",
acceleration = Vec3(0.0000, 1e-5, 0.0000)
)
)

sim.createCheckPointer (
CheckPointPrms (
fileNamePrefix = "flow_data",
beginTimeStep = 0,
endTimeStep = 20000,
timeStepIncr = 100
)
)
</RemoteForceInterface>


We deleted the now the gravity force acting on the particles, and rely only on the force applied to the fluid flow.

### Running TCLB and ESYS

Our simulation is set up to be executed in a Spawning approach. This means that we will run TCLB, and TCLB will dynamically spawn ESYS-Particle code.

To say to MPI that we have a limited number of slots for process execution (cores), we need to create a hostfile:

localhost
localhost
localhost
localhost


This hostfile is very simple, and just says that we have 4 avaliable slots on our computer (localhost). In a multi-computer setup (eg. cluster), we would specify all the nodes involved.

Now we can run TCLB with:

mpirun -hostfile hostfile -np 1 CLB/d3q27_cumulant_part/main pipe.xml


This will execute a single process of TCLB, which will in turn spawn 3 processes of ESYS (it will fill up the avaliable space). This means that it will run a single master process and 2 worker processes. It will also generate the Python setup file for ESYS, with appropriate division of the domain and number of processes. You can inspect the generated file, which is it output/pipe_ESYS.py.

#### MPMD

We can also run the case in a Multiple Program Multiple Data (MPMD) approach. This means executing both programs at the same time. As ESYS is executed immediately, we have to provide our own Python configuration file. In our case, we can use the output/pipe_ESYS.py as the template.

To run the both codes we use the runmpi's MPMD syntax:

mpirun -np 1 CLB/d3q27_cumulant_part/main pipe.xml : -np 3 esysparticle pipe.py


As the configuration for ESYS is not generated we can delete all contents of the <RemoteForceInterface> XML element (but we have to keep it, so that TCLB knows we want to connect with ESYS.

### Results

Both the fluid results and particle data can be loaded into ParaView. ParaView also reads stl files. The example results look like this: