|
|
## Test Cases Ready to Use
|
|
|
|
|
|
Many test cases are given to help users to understand how to use the different features offered by the MigFlow Software. Test cases are in the TheGoodPath/MigFlow/testcases directory. They are given to provide users basic tools in order to build computation script for their own applications.
|
|
|
|
|
|
### Test Cases Structure
|
|
|
|
|
|
Let us illustrate the structure of the executable python files with a two dimensional deposit of grains in fluid. This test case is provided in the [testcases/depo-2d/dep.py](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/dep.py) file.
|
|
|
|
|
|
Some steps have to be followed in order to define properly the application you want to solve with the MigFlow Software.
|
|
|
|
|
|
1. Set the problem parametres
|
|
|
In application you have to define a lot of variables that are used to define:
|
|
|
* [fluid and grains properties](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L69)
|
|
|
```python
|
|
|
g = -9.81 # gravity
|
|
|
r = 1e-3 # grains radius
|
|
|
rhop = 1500 # grains density
|
|
|
rho = 1000 # fluid density
|
|
|
nu = 1e-6 # kinematic viscosity
|
|
|
```
|
|
|
* [numerical parametres](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L76)
|
|
|
```python
|
|
|
outf = 5 # number of iterations between output files
|
|
|
dt = 1e-2 # time step
|
|
|
tEnd = 100 # final time
|
|
|
```
|
|
|
* [domain geometry](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L81)
|
|
|
```python
|
|
|
#geometrical parameters
|
|
|
ly = 5e-2 # grains area height
|
|
|
lx = 4e-1 # grains area widht
|
|
|
H = 1.2 # domain height
|
|
|
```
|
|
|
|
|
|
2. Define the positions of the grains matrix and create grains at these positions
|
|
|
|
|
|
* Setting the initial situation require to define the initial positions of the grains. In test cases, this is often achieved by defining a [function](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L37) in which centre positions are defined. The arguments of the function are related to the grains properties and the grains area geometry defined previously. The physical surfaces defined in your mesh.geo file are used to specify the solid boundaries for the grains. Grain objects are created locally and all the information about the innitial condition of the grains are written in an output file.
|
|
|
```python
|
|
|
def genInitialPosition(filename, r, H, ly, lx, rhop) :
|
|
|
"""Set all the particles centre positions and create the particles objects to add in the computing structure
|
|
|
|
|
|
Keyword arguments:
|
|
|
filename -- name of the output file
|
|
|
r -- max radius of the particles
|
|
|
H -- domain height
|
|
|
ly - particles area height
|
|
|
lx -- particles area width
|
|
|
rhop -- particles density
|
|
|
"""
|
|
|
# Particles structure builder
|
|
|
p = scontact.ParticleProblem(2)
|
|
|
# Load mesh.msh file specifying physical boundaries names
|
|
|
p.load_msh_boundaries("mesh.msh", ["Top", "Lateral","Bottom"])
|
|
|
|
|
|
#Definition of the points where the particles are located
|
|
|
x = np.arange(-lx/2+r, lx/2-r, 2*r)
|
|
|
y = np.arange(H/2-r, H/2-ly+r, -2*r)
|
|
|
x, y = np.meshgrid(x, y)
|
|
|
x = x.flat
|
|
|
y = y.flat
|
|
|
# Add a grain at each centre position
|
|
|
for i in range(len(x)) :
|
|
|
p.add_particle((x[i], y[i]), r, r**2 * np.pi * rhop)
|
|
|
p.write_vtk(filename,0,0)
|
|
|
|
|
|
```
|
|
|
|
|
|
* Use the previous function to set the initial condition and write it in the outputdir directory. Then, build the particle structure and [fill](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L86) the global particle structure with the information written in the initial file
|
|
|
```python
|
|
|
genInitialPosition(outputdir, r, H, ly, lx, rhop)
|
|
|
p = scontact.ParticleProblem(2)
|
|
|
p.read_vtk(outputdir,0)
|
|
|
|
|
|
```
|
|
|
|
|
|
3. Create the fluid structure and specify the computational domain (i.e. give the mesh to the fluid class). At this step, all the variables (velocity, pressure...) of the fluid problem and the properties of the fluid are stored in the fluid structure
|
|
|
```python
|
|
|
fluid = fluid.FluidProblem(2,g,[nu*rho],[rho])
|
|
|
# Set the mesh geometry for the fluid computation
|
|
|
fluid.load_msh("mesh.msh")
|
|
|
```
|
|
|
4. Once the fluid variables and properties are created, it is mandatory to set the boundary conditions of the fluid problem. Boundary conditions are of two types:
|
|
|
|
|
|
* [Strong boundaries](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L107) constrain a field variable to a specified value. This is done by suppressing an equation of the linear system to replace it by this constraint :
|
|
|
|
|
|
```pyhton
|
|
|
fluid.set_strong_boundary(Physical boundary tag, field variable item, field value)
|
|
|
```
|
|
|
|
|
|
* [Weak boundaries](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L111) specify the flux at each boundary. The flux terms added by these conditions come from the integration by part arising from the finite element methods and can be suppressed for some weak boundary type. For example, if you consider a wall, it is quite obvious that the velocity flux across the boundary is zero.
|
|
|
|
|
|
```python
|
|
|
fluid.set_weak_boundary(Physical boundary tag, Weak boundary type)
|
|
|
```
|
|
|
|
|
|
5. Coupling between fluid and solid is mainly based on the detection of the mesh cells in which grains are. Computing fluid fraction in a cell or evaluating the fluid velocity at the grain position imply to know where the grains are in the fluid. The tree structure based on mesh cells is used to locate the grains in the fluid.
|
|
|
|
|
|
```python
|
|
|
fluid.set_particles(p.mass(), p.volume(), p.position(), p.velocity())
|
|
|
```
|
|
|
|
|
|
6. At this step, the initial state is completely defined and all the variables and parametres have been created. Then the computation can start. The [computational loop](https://git.immc.ucl.ac.be/fluidparticles/migflow/blob/oneFluid/testcases/depot-2d/depot.py#L121) is composed of three main steps:
|
|
|
|
|
|
* Fluid equations solving
|
|
|
```python
|
|
|
while t < tEnd :
|
|
|
fluid.implicit_euler(dt)
|
|
|
```
|
|
|
* Computation of the new grain free velocities
|
|
|
```python
|
|
|
forces = fluid.compute_node_force(dt)
|
|
|
vn = p.velocity() + forces * dt / p.mass()
|
|
|
```
|
|
|
* Contacts solving using a sub-timestep and grains displacement
|
|
|
```python
|
|
|
for i in range(nsub) :
|
|
|
tol = 1e-6
|
|
|
p.iterate(dt/nsub, forces, tol)
|
|
|
|
|
|
```
|
|
|
The loop also contained instruction to write output files. It is important to note that after moving the grains in computational loop you have to use the _set_particles()_ function to search the new location og the grains in the mesh.
|
|
|
|