diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template_example.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template_example.md index 41a10f3723..9ca6ac1a28 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template_example.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template_example.md @@ -21,7 +21,8 @@ Code related list: - [ ] Lethe documentation is up to date - [ ] The branch is rebased onto master - [ ] Code is indented with indent-all and .prm files (examples and tests) with prm-indent -- [ ] Links are added to parent .rst files. +- [ ] Links are added to parent .rst files +- [ ] The example is following the [standard format](https://chaos-polymtl.github.io/lethe/documentation/contributing.html#general-rules-and-format) Pull request related list: - [ ] Labels are applied diff --git a/contrib/utilities/check_parameter_files_in_examples.sh b/contrib/utilities/check_parameter_files_in_examples.sh index 1df9cb68f5..0981aa31eb 100755 --- a/contrib/utilities/check_parameter_files_in_examples.sh +++ b/contrib/utilities/check_parameter_files_in_examples.sh @@ -45,8 +45,9 @@ lethe_fluid_particles=("examples/unresolved-cfd-dem") for folder in ${lethe_fluid_particles[@]}; do for file in $(find "$folder" -type f -name "*.prm"); do echo $file - # If generator is in the file name this is a lethe-particles file - if [[ "$file" == *"generator"* ]];then + # If "particles" is in the filename this is a + # lethe-particles file + if [[ "$file" == *"particles"* ]];then lethe-parameter-check $file lethe-particles #else we assume it's a CFD-DEM file else diff --git a/doc/source/examples/unresolved-cfd-dem/boycott-effect/boycott-effect.rst b/doc/source/examples/unresolved-cfd-dem/boycott-effect/boycott-effect.rst index 349c14c35e..bd0464f8bc 100644 --- a/doc/source/examples/unresolved-cfd-dem/boycott-effect/boycott-effect.rst +++ b/doc/source/examples/unresolved-cfd-dem/boycott-effect/boycott-effect.rst @@ -20,8 +20,8 @@ Files Used in This Example Both files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/boycott-effect``). +- Parameter file for initial particles generation: ``initial-particles.prm`` - Parameter file for CFD-DEM simulation of the Boycott effect: ``boycott-effect.prm`` -- Parameter file for particle generation and packing: ``particle_generator.prm`` ----------------------- @@ -37,7 +37,7 @@ DEM Parameter File The syntax of this parameter file is flexible. Parameters do not need to be specified in a specific order, but only within the subsection in which they belong. All parameter subsections are described in the `parameter section <../../../parameters/parameters.html>`_ of the documentation. -We introduce the different sections of the parameter file ``dem-packing-in-fluidized-bed.prm`` needed to run this simulation. Most subsections are explained in detail in other CFD-DEM examples such as: `Gas-solid spouted bed <../../../examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.html>`_. Therefore, we will not go over them in detail. +We introduce the different sections of the parameter file ``boycott-effect.prm`` needed to run this simulation. Most subsections are explained in detail in other CFD-DEM examples such as: `Gas-solid spouted bed <../../../examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.html>`_. Therefore, we will not go over them in detail. Mesh ~~~~~ @@ -157,16 +157,16 @@ Launching the simulation is as simple as specifying the executable name and the .. code-block:: text :class: copy-button - lethe-particles particle-generator.prm + lethe-particles initial-particles.prm or in parallel (where 8 represents the number of processors) .. code-block:: text :class: copy-button - mpirun -np 8 lethe-particles particle-generator.prm + mpirun -np 8 lethe-particles initial-particles.prm -The figure below shoes the particles inserted at the top of the channel at the end of the DEM simulation. +The figure below shows the particles inserted at the top of the channel at the end of the DEM simulation. .. image:: images/packing.png :alt: inserted particles at the top of the channel diff --git a/doc/source/examples/unresolved-cfd-dem/cylindrical-packed-bed/cylindrical-packed-bed.rst b/doc/source/examples/unresolved-cfd-dem/cylindrical-packed-bed/cylindrical-packed-bed.rst index d1653d54c6..2133baf455 100644 --- a/doc/source/examples/unresolved-cfd-dem/cylindrical-packed-bed/cylindrical-packed-bed.rst +++ b/doc/source/examples/unresolved-cfd-dem/cylindrical-packed-bed/cylindrical-packed-bed.rst @@ -11,6 +11,7 @@ Features - Solvers: ``lethe-particles`` and ``lethe-fluid-vans`` - Three-dimensional problem +- Uses the VANS solver without the coupling with DEM - Displays the selection of models and physical properties @@ -20,8 +21,8 @@ Files Used in This Example Both files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/cylindrical-packed-bed``). -- Parameter file for CFD-DEM simulation of the packed bed: ``cylindrical-packed-bed/flow-in-bed.prm`` -- Parameter file for particle generation and packing: ``packing-in-cylinder.prm`` +- Parameter file for particle generation and packing: ``packing-particles.prm`` +- Parameter file for CFD-DEM simulation of the packed bed: ``flow-in-bed.prm`` ----------------------- @@ -35,7 +36,8 @@ This example simulates air flow through a packing of particles. First, we use `` DEM Parameter File ------------------- -All parameter subsections are described in the `parameter section <../../../parameters.html>`_ of the documentation. To set-up the cylindrical packed bed case, we first fill the bed with particles. We introduce the different sections of the parameter file (``packing-in-cylinder.prm)`` needed to run this simulation. +All parameter subsections are described in the `parameter section <../../../parameters.html>`_ of the documentation. To set-up the cylindrical packed bed case, we first fill the bed with particles. We introduce the different sections of the parameter file (``packing-particles.prm``) needed to run this simulation. + Mesh ~~~~~ @@ -181,14 +183,14 @@ Launching the simulation is as simple as specifying the executable name and the .. code-block:: text :class: copy-button - lethe-particles packing-in-circle.prm + lethe-particles packing-particles.prm or in parallel (where 8 represents the number of processors) .. code-block:: text :class: copy-button - mpirun -np 8 lethe-particles packing-in-circle.prm + mpirun -np 8 lethe-particles packing-particles.prm Lethe will generate a number of files. The most important one bears the extension ``.pvd``. It can be read by popular visualization programs such as `Paraview `_. diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/dense-pneumatic-conveying.rst b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/dense-pneumatic-conveying.rst new file mode 100644 index 0000000000..91aa20d6a1 --- /dev/null +++ b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/dense-pneumatic-conveying.rst @@ -0,0 +1,656 @@ +================================== +Dense Pneumatic Conveying +================================== + +This example simulates the dense pneumatic conveying of particles in a horizontal periodic pipe. + +---------------------------------- +Features +---------------------------------- + +- Solvers: ``lethe-particles`` and ``lethe-fluid-particles`` +- Three-dimensional problem +- Displays how to insert particles according to a shape with a `solid object <../../../parameters/dem/solid_objects.html>`_ using the `plane insertion method <../../../parameters/dem/insertion_info.html#plane>`_ +- Has `periodic boundary conditions <../../../parameters/dem/boundary_conditions.html>`_ in DEM and CFD-DEM +- Uses a `dynamic flow controller <../../../parameters/cfd/dynamic_flow_control.html>`_ in CFD-DEM +- Uses the `adaptive sparse contacts <../../../parameters/dem/model_parameters.html#adaptive-sparse-contacts-asc>`_ for particle loading in DEM +- Simulates a dense pneumatic conveying system + + +--------------------------- +Files Used in this Example +--------------------------- + +All the files mentioned below are located in the example folder (``examples/unresolved-cfd-dem/dense-pneumatic-conveying``). + +- Parameter files for particle loading and settling: ``loading-particles.prm`` and ``settling-particles.prm`` +- Parameter file for CFD-DEM simulation of the pneumatic conveying: ``pneumatic-conveying.prm`` + + +----------------------- +Description of the Case +----------------------- + +This example simulates the conveying of particles arranged in a plug/slug with a stationary layer. +Since the initial particle layout plays an important role in the regime of the pneumatic conveying, the particles are already forming a plug at the beginning of the CFD-DEM simulation. +Three simulation runs need to be performed. +First, we call ``lethe-particles`` to load the particles with the file ``loading-particles.prm``. +The setup of the simulation is a pipe with a solid object (mesh) that represents the shape of a slug. +The insertion of particles is done using the plane insertion. +Second, we call ``lethe-particles`` to settle the particles with the file ``settling-particles.prm``. Only the direction of gravity is changed. +Finally, we call ``lethe-fluid-particles`` to simulate the dense pneumatic conveying with the file ``pneumatic-conveying.prm`` using periodic boundary conditions. +We enable checkpointing in order to write the DEM checkpoint files which will be used as the starting point of the CFD-DEM simulation. +The geometry of the pipe and the particle properties are based on the work of Lavrinec *et al*. [#lavrinec2021]_ + +.. figure:: images/insertion.png + :alt: insertion + :align: center + + View of the pipe after the loading of particles with the insertion plane. + + +.. figure:: images/pneumatic.png + :alt: pneumatic-conveying + :align: center + + View of the pipe during the pneumatic conveying. + +------------------- +DEM Parameter files +------------------- + +Loading Particles +~~~~~~~~~~~~~~~~~ + +In this section we introduce the different sections of the parameter file ``loading-particles.prm`` needed to load the particles of the simulation. + +Mesh +---- + +In this example, we are simulating a horizontal cylindrical pipe. We use the `custom cylinder `_ of type balanced. We use this type of mesh in order to have uniform cell size in the radial direction. The length of a cell is about 2 times the diameter of the particles in each direction. The classical cylinder mesh of deal.II has smaller cells in the center which restrict the size of the particles. The length of the pipe is 1 m and the diameter is 0.084 m. The conveying is processed in the x-direction through periodic boundary conditions. + +.. code-block:: text + + subsection mesh + set type = cylinder + set grid type = balanced + set grid arguments = 45 : 0.042 : 0.5 + set initial refinement = 1 + set expand particle-wall contact search = true + end + +.. note:: + Note that, since the mesh is cylindrical, ``set expand particle-wall contact search = true``. Details on this in the `DEM mesh parameters guide <../../../parameters/dem/mesh.html>`_. + +A cross-section of the resulting mesh is presented in the following figure. + +.. figure:: images/mesh-particle.png + :alt: Mesh cross-section. + :align: center + + Cross-section of the mesh used in the pneumatic conveying simulation. + +Lagrangian Physical Properties +------------------------------ + +The lagrangian properties were based on the work of Lavrinec *et al*. [#lavrinec2021]_, except for the Young's modulus that was deliberately reduced to get a higher Rayleigh critical time step. +The gravity is set in the x-direction to allow the packing of the particles from the right side of the pipe. +The number of particles in the simulation is 32194. When the example was setup, the number specified in the simulation was higher since the insertion is done with the `plane insertion method <../../../parameters/dem/insertion_info.html#plane>`_, which will insert particles up to when they reach the plane. +In order to avoid confusion with the number of particles in the parameter file, we did give the real number of particles inserted after 30 seconds. + +.. code-block:: text + + subsection lagrangian physical properties + set g = -9.81, 0, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e6 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e6 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 + end + +Insertion Info +-------------- + +As said in the previous section, the particles are inserted with the `plane insertion method <../../../parameters/dem/insertion_info.html#plane>`_. The plane is located at the right side of the pipe. As we can see from the following figure, the plane is positioned at an angle. Since the plane insertion method will insert one particle in a cell that is intersected by the plane, we need to place the plane so it does not intersect the area above the solid object. Particles have an initial velocity in x-direction in order to speed up the packing process and in y-direction to have more collisions and randomness in the distribution. + +.. figure:: images/insertion-plane.png + :alt: insertion. + :align: center + + Side view of the pipe during the insertion of particles in the x-direction with the solid object (green) and the insertion plane (red). + +.. code-block:: text + + subsection insertion info + set insertion method = plane + set insertion frequency = 400 + set insertion plane point = 0.475, -0.0325, 0 + set insertion plane normal vector = -0.25, 4.75, 0 + set insertion maximum offset = 0.001 + set insertion prn seed = 19 + set initial velocity = -0.35, 0.1, 0.0 + end + + +Boundary Conditions DEM +----------------------- + +Periodic boundary conditions need to be setup in the DEM simulation since we use them in the CFD-DEM simulation. They are therefore already configured for compatibility. However, we do not want periodicity during the loading of the particles. + +.. code-block:: text + + subsection DEM boundary conditions + set number of boundary conditions = 1 + + subsection boundary condition 0 + set type = periodic + set periodic id 0 = 1 + set periodic id 1 = 2 + set periodic direction = 0 + end + end + +Floating Walls +-------------- + +In order to avoid particles passing through the periodic boundary conditions, we use floating walls. The floating walls are placed at the left and right side of the pipe. We need this pair of walls because periodic particles do not interact with the walls on the other side of the periodic boundary condition. + +.. code-block:: text + + subsection floating walls + set number of floating walls = 2 + subsection wall 0 + subsection point on wall + set x = -0.5 + set y = 0 + set z = 0 + end + subsection normal vector + set nx = 1 + set ny = 0 + set nz = 0 + end + set start time = 0 + set end time = 30 + end + subsection wall 1 + subsection point on wall + set x = 0.5 + set y = 0 + set z = 0 + end + subsection normal vector + set nx = -1 + set ny = 0 + set nz = 0 + end + set start time = 0 + set end time = 30 + end + end + +Solid Objects +------------- + +The solid object is a simplex surface mesh that represents the shape of a slug. The mesh is generated with the `Gmsh `_ software. +The following figure shows the different parts of the slug. The length of the slug core (where particles fully obstruct the pipe; in green) is 0.5 m, and 45° planes inclined are placed the rear and the front of the slug (in blue). The stationary layer (the layer between periodic slugs; in red) has a height of 0.021 m which represents 20 % of the cross-section area of the pipe. + +.. figure:: images/slug.png + :alt: Slug + :align: center + + Different parts of the slug in a dense pneumatic conveying. + +.. code-block:: text + + subsection solid objects + set number of solids = 1 + subsection solid object 0 + subsection mesh + set type = gmsh + set file name = slug-shape.msh + set simplex = true + end + end + end + +Model Parameters +---------------- + +The model parameters are quite standard for a DEM simulation with the non-linear Hertz-Mindlin contact force model, a constant rolling resistance torque, and the velocity Verlet integration method. + +.. note:: + + Here, we use the `Adaptive Sparse Contacts <../../../parameters/dem/model_parameters.html#adaptive-sparse-contacts-asc>`_ method to speedup the simulation. The method will disabled the contact computation in quasi-static areas which represents a significant part of the domain during the loading of the particles. Weight factor parameters for the ASC status are use in the load balancing method. No further explanation a given about the method, a future example will be added in order to detail it and to compare the performance gain. + +.. code-block:: text + + subsection model parameters + subsection contact detection + set contact detection method = dynamic + set neighborhood threshold = 1.3 + end + subsection load balancing + set load balance method = dynamic_with_sparse_contacts + set threshold = 0.5 + set dynamic check frequency = 8000 + set active weight factor = 0.8 + set inactive weight factor = 0.6 + end + set particle particle contact force method = hertz_mindlin_limit_overlap + set particle wall contact force method = nonlinear + set integration method = velocity_verlet + set rolling resistance torque method = constant_resistance + subsection adaptive sparse contacts + set enable adaptive sparse contacts = true + set enable particle advection = false + set granular temperature threshold = 1e-4 + set solid fraction threshold = 0.4 + end + end + + +Simulation Control +------------------ + +Here, we define the time step and the simulation end time. 30 seconds of simulation are needed to load the particles. This long simulation time is caused by the plane insertion method that inserts only a small number of particles at a time (about 1000 particles per second of simulation). + +.. code-block:: text + + subsection simulation control + set time step = 5e-5 + set time end = 30 + set log frequency = 500 + set output frequency = 1200 + set output path = ./output_dem/ + end + +Restart +------- + +Checkpointing is enabled since we need the output to rerun the DEM solver to settle the particles in the pipe. The checkpointing occurs each 1.5 seconds, in case we need to stop and restart the loading simulation. + +.. code-block:: text + + subsection restart + set checkpoint = true + set frequency = 30000 + set restart = false + set filename = dem + end + + + +Settling Particles +~~~~~~~~~~~~~~~~~~ + +In this section we show the difference in the parameter file ``settling-particles.prm`` needed to settle the particles with the same gravity vector as the pneumatic conveying simulation. Consequently, many sections related to the loading are not needed such as the the insertion info, the floating walls, and the solid objects. + +Simulation Control +------------------ + +Here we allow a 2.5 seconds for the settling of the particles. Since this simulation is a restart of the loading particle simulation, the end time is 32.5 seconds. + +.. code-block:: text + + subsection simulation control + set time step = 5e-5 + set time end = 32.5 + set log frequency = 500 + set output frequency = 1200 + set output path = ./output_dem/ + end + +Restart +~~~~~~~~ + +This simulation reads the restart, meaning this option is set to true. Also, the checkpointing is reduce to 0.5 seconds. + +.. code-block:: text + + subsection restart + set checkpoint = true + set frequency = 10000 + set restart = true + set filename = dem + end + +Lagrangian Physical Properties +------------------------------ + +The main difference in this simulation is the gravity. It changes to the y-direction to be coherent with the next simulation using the CFD-DEM solver. + +.. code-block:: text + + subsection lagrangian physical properties + set g = 0, -9.81, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e6 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e6 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 + end + +---------------------- +CFD-DEM Parameter file +---------------------- + +Pneumatic Conveying Simulation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CFD simulation is to be carried out using the slug generated in the previous step. We will discuss the different sections of the parameter file used for the CFD-DEM simulation. +The mesh and the DEM boundary condition sections are identical to the ones in the DEM simulations and will not be shown again. + +Lagrangian Physical Properties +------------------------------ + +The physical properties of the particles are the same as in the DEM simulations, except for the Young's modulus that was increased to use the same value as the article [#lavrinec2021]_. + +.. code-block:: text + + subsection lagrangian physical properties + set g = 0, -9.81, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e7 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e7 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 + end + +Model Parameters +---------------- + +Model parameters are the same as in the DEM simulation, but we do not use any strategies for performance enhancement, such as load balancing or adaptive sparse contacts. + +.. code-block:: text + + subsection model parameters + subsection contact detection + set contact detection method = dynamic + set neighborhood threshold = 1.3 + end + set particle particle contact force method = hertz_mindlin_limit_overlap + set particle wall contact force method = nonlinear + set integration method = velocity_verlet + set rolling resistance torque method = constant_resistance + end + +Simulation Control +------------------ + +The simulation lasts 5 seconds and the CFD time step is 5e-4 seconds. + +.. code-block:: text + + subsection simulation control + set method = bdf1 + set output name = cfd_dem + set output frequency = 10 + set time end = 5 + set time step = 5e-4 + set output path = ./output/ + end + +Physical Properties +------------------- + +The physical properties of air are the same as Lavrinec *et al*. [#lavrinec2021]_ + +.. code-block:: text + + subsection physical properties + subsection fluid 0 + set kinematic viscosity = 1.5e-5 + set density = 1.205 + end + end + +Boundary Conditions +------------------- + +The boundary condition at the wall of the pipe is a weak function where the Dirichlet condition is weakly imposed as a no-slip condition, since we specify zero velocity. The inlet and the outlet have periodic boundaries. `See here <../../../parameters/cfd/boundary_conditions_cfd.html>`_ for more information about those boundary conditions. + +.. code-block:: text + + subsection boundary conditions + set number = 2 + subsection bc 0 + set id = 0 + set type = function weak + set beta = 100 + subsection u + set Function expression = 0 + end + subsection v + set Function expression = 0 + end + subsection w + set Function expression = 0 + end + end + subsection bc 1 + set id = 1 + set type = periodic + set periodic_id = 2 + set periodic_direction = 0 + end + end + +Flow control +------------ + +Since the simulation has periodic boundary conditions, a correction volumetric force is needed to drive the flow to compensate the pressure drop in the pipe. In other to achieve this, we use the `dynamic flow controller <../../../parameters/cfd/dynamic_flow_control.html>`_. Here, we also apply a proportional force on particles. The average velocity is set to 3 m/s, this correspond to the average over the entire domain considering the void fraction. The flow controller performs well for CFD simulation, but needs some tuning for CFD-DEM simulation. By default, the controller has a high stiffness and aims to correct the flow in the next time step. However, the carrying of particles by the flow leads to a response time that is not taken into account and results in a oscillation of the velocity of the flow. To avoid this, we use the volumetric force threshold ``beta threshold`` and the ``alpha`` relaxation parameter. Here, the volumetric force value will not be updated if the new value is within the 5% of the previous value. Also, the correction to apply to the previous volumetric force value is reduced by a factor of 0.25. This way, the velocity of the flow and the particles are more stable. + +.. code-block:: text + + subsection flow control + set enable = true + set enable beta particle = true + set average velocity = 3 + set flow direction = 0 + set beta threshold = 0.05 + set alpha = 0.25 + set verbosity = verbose + end + +Void Fraction +------------- + +We choose the `quadrature centred method (QCM) <../../../theory/multiphase/cfd_dem/unresolved_cfd-dem.html#the-quadrature-centered-method>`_ to calculate the void fraction. The ``l2 smoothing factor`` we choose is the square of twice the diameter of the particles. + +.. code-block:: text + + subsection void fraction + set mode = qcm + set read dem = true + set dem file name = dem + set l2 smoothing factor = 0.0001 + end + +CFD-DEM +------- + +We use the Di Felice drag model, the Saffman lift force, the buoyancy force, and the pressure force. The coupling frequency is set to 100, which means that the DEM time step is 5e-6 s. The DEM time step is 3.5% of the Rayleigh critical time step. The grad-div stabilization is used with a length scale of 0.084, the diameter of the pipe. + + +.. code-block:: text + + subsection cfd-dem + set grad div = true + set drag model = difelice + set saffman lift force = true + set buoyancy force = true + set pressure force = true + set coupling frequency = 100 + set implicit stabilization = false + set grad-div length scale = 0.084 + set particle statistics = true + end + +Non-linear Solver +----------------- + +We use the inexact Newton non-linear solver to minimize the number of time the matrix of the system is assembled. This is used to increase the speed of the simulation, since the matrix assembly requires significant computations. + +.. code-block:: text + + subsection non-linear solver + subsection fluid dynamics + set solver = inexact_newton + set matrix tolerance = 0.1 + set reuse matrix = true + set tolerance = 1e-4 + set max iterations = 10 + set verbosity = quiet + end + end + +----------------------- +Running the Simulations +----------------------- + +Launching the simulations is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` and ``lethe-fluid-particles`` executables are within your path, the simulations can be launched in parallel as follows: + +.. code-block:: text + :class: copy-button + + mpirun -np 8 lethe-particles loading-particles.prm + +.. code-block:: text + :class: copy-button + + mpirun -np 8 lethe-particles settling-particles.prm + +.. note:: + Running the particle loading simulation using 8 cores takes approximately 30 minutes and the particle settling simulation takes approximately 1 minute. + +Once the previous programs have finished running, you can finally launch the pneumatic conveying simulation and get the simulation log for post-processing with the following command: + +.. code-block:: text + :class: copy-button + + mpirun -np 8 lethe-fluid-particles pneumatic-conveying.prm | tee pneumatic-log.out + +.. note:: + Running the pneumatics conveying simulation using 8 cores takes approximately 2.25 hours. Running all the executables in sequence will take less than 3 hours. + +Lethe will generate a number of files. The most important one bears the extension ``.pvd``. It can be read by popular visualization programs such as `Paraview `_. + +------- +Results +------- + +The particle loading and settling simulation should look like this: + +.. raw:: html + +

+ +The pneumatic conveying simulation should look like this: + +.. raw:: html + +

+ +.. note:: + The pneumatic conveying simulation lasts 5 seconds in this example, but last 10 seconds in the video. You can change the end time in the parameter file. + +Post-processing +~~~~~~~~~~~~~~~ +The data is extracted with the Lethe PyVista tool and post-processed with custom functions in the files ``pyvista_utilities.py`` and ``log_utilities.py``. +Extraction, post-processing and plotting are automated in the script ``pneumatic-conveying_post-processing.py``: + +.. code-block:: text + :class: copy-button + + python3 pneumatic-conveying_post-processing.py + +The script will generate the figure and print the results in the console. If you want to modify the path or the filenames, you have to modify the script. + +Mass Flow Rate and Velocities +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here we show the average velocities for the fluid, the slug and the particles in slug. The beta force, the averaged solid mass flow rate and the slug length over time are also shown. The shaded area represents the transient state. The quasi-steady state is approximated when velocities fluctuate around the same values. + +.. figure:: images/pneumatic-conveying-data.png + :alt: Mass flow rate and velocities + :align: center + :name: data + + Results of the pneumatic conveying simulation. + +The time-averaged values of velocities at quasi-steady state are shown in the following table. + +.. list-table:: Time-averaged velocities at quasi-steady state. + :width: 70.25% + :widths: 35 20 20 20 + :header-rows: 1 + :align: center + + * - + - Fluid + - Slug + - Particles + * - Velocity (m/s) + - 2.98 + - 1.30 + - 0.83 + * - Standard deviation (m/s) + - 0.02 + - 0.02 + - 0.01 + +According to Lavrinec *et al.* [#lavrinec2020]_, the average slug velocity has a linear relationship with the particle in slug velocity and the diameter of the pipe such as: + +.. math:: + + \bar{u}_{\mathrm{slug}} = 0.967 \bar{u}_{\mathrm{particles}} + 0.5\sqrt{gD} + +From this formula, the calculated slug velocity is 1.25 m/s. Considering that this case was simplified for the sake of the example, that the data in quasi-steady state is not computed for a long simulation time (1 s), and especially considering the standard deviation of the results, this value is considered satisfactory. + +The time-averaged solid mass flow rate is 1.40 kg/s (no standard deviation are given since the instant mass flow rate always fluctuates) and the length of the slug is 0.47 ± 0.01 m. + +---------- +References +---------- + +.. [#lavrinec2021] \A. Lavrinec, O. Orozovic, H. Rajabnia, K. Williams, M. Jones & G. Klinzing, “An assessment of steady-state conditions in single slug horizontal pneumatic conveying.” *Particuology*, vol. 58, pp. 187-195, 2021. doi: `10.1016/j.partic.2021.04.007 `_\. + +.. [#lavrinec2020] \A. Lavrinec, O. Orozovic, H. Rajabnia, K. Williams, M. Jones et G. Klinzing, “Velocity and porosity relationships within dense phase pneumatic conveying as studied using coupled CFD-DEM.” *Powder Technology*, vol. 375, pp. 89–100, 2020. doi: `10.1016/j.powtec.2020.07.070 `_\. \ No newline at end of file diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion-plane.png.REMOVED.git-id b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion-plane.png.REMOVED.git-id new file mode 100644 index 0000000000..060f8759ad --- /dev/null +++ b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion-plane.png.REMOVED.git-id @@ -0,0 +1 @@ +fd1713239e2e6c82f9d19c628badc9ae2fe17555 \ No newline at end of file diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion.png.REMOVED.git-id b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion.png.REMOVED.git-id new file mode 100644 index 0000000000..1a1841d5ab --- /dev/null +++ b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/insertion.png.REMOVED.git-id @@ -0,0 +1 @@ +4755c9ced874f5668c4bc918216525d4adce4303 \ No newline at end of file diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/mesh-particle.png b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/mesh-particle.png new file mode 100644 index 0000000000..edbc0f7376 Binary files /dev/null and b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/mesh-particle.png differ diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic-conveying-data.png b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic-conveying-data.png new file mode 100644 index 0000000000..55c086c231 Binary files /dev/null and b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic-conveying-data.png differ diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic.png b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic.png new file mode 100644 index 0000000000..69ad780097 Binary files /dev/null and b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/pneumatic.png differ diff --git a/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/slug.png b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/slug.png new file mode 100644 index 0000000000..b11b52a821 Binary files /dev/null and b/doc/source/examples/unresolved-cfd-dem/dense-pneumatic-conveying/images/slug.png differ diff --git a/doc/source/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/gas-solid-fluidized-bed.rst b/doc/source/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/gas-solid-fluidized-bed.rst index 5c6b1991b1..ad88b96408 100644 --- a/doc/source/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/gas-solid-fluidized-bed.rst +++ b/doc/source/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/gas-solid-fluidized-bed.rst @@ -21,8 +21,8 @@ Files Used in This Example Both files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/gas-solid-fluidized-bed``). +- Parameter file for particle generation and packing: ``packing-particles.prm`` - Parameter file for CFD-DEM simulation of the gas-solid fluidized bed: ``gas-solid-fluidized-bed.prm`` -- Parameter file for particle generation and packing: ``dem-packing-in-fluidized-bed.prm`` ----------------------- @@ -40,7 +40,7 @@ All parameter subsections are described in the `parameter section <../../../para To set-up the square fluidized bed case, we first fill the bed with particles. -We first introduce the different sections of the parameter file ``dem-packing-in-fluidized-bed.prm`` needed to run this simulation. +We first introduce the different sections of the parameter file ``packing-particles.prm`` needed to run this simulation. Mesh ~~~~~ @@ -191,14 +191,14 @@ Launching the simulation is as simple as specifying the executable name and the .. code-block:: text :class: copy-button - lethe-particles dem-packing-in-fluidized-bed.prm + lethe-particles packing-particles.prm or in parallel (where 8 represents the number of processors) .. code-block:: text :class: copy-button - mpirun -np 8 lethe-particles dem-packing-in-fluidized-bed.prm + mpirun -np 8 lethe-particles packing-particles.prm Lethe will generate a number of files. The most important one bears the extension ``.pvd``. It can be read by popular visualization programs such as `Paraview `_. diff --git a/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.rst b/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.rst index 5723617698..cc8bb5947a 100644 --- a/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.rst +++ b/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-bed/gas-solid-spouted-bed.rst @@ -21,9 +21,8 @@ Files Used in This Example Both files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/gas-solid-spouted-bed``). +- Parameter file for particle generation and packing: ``packing-particles.prm`` - Parameter file for CFD-DEM simulation of the spouted bed: ``gas-solid-spouted-bed.prm`` -- Parameter file for particle generation and packing: ``dem-packing-in-spouted-bed.prm`` - ----------------------- @@ -41,7 +40,7 @@ All parameter subsections are described in the `parameter section <../../../para To set-up the rectangular spouted bed case, we first fill the bed with particles. -We introduce the different sections of the parameter file ``dem-packing-in-fluidized-bed.prm`` needed to run this simulation. +We introduce the different sections of the parameter file ``packing-particles.prm`` needed to run this simulation. Mesh ~~~~~ @@ -196,19 +195,12 @@ We need to pack the particles in the bottom of the rectangular bed while prevent --------------------------- Running the DEM Simulation --------------------------- -Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched on a single processor by typing: - -.. code-block:: text - :class: copy-button - - lethe-particles dem-packing-in-spouted-bed.prm - -or in parallel (where 8 represents the number of processors) +Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched in parallel as follows: .. code-block:: text :class: copy-button - mpirun -np 8 lethe-particles dem-packing-in-spouted-bed.prm + mpirun -np 8 lethe-particles packing-particles.prm .. note:: Running the packing should take approximately 10-15 minutes on 8 cores. diff --git a/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed.rst b/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed.rst index 9cba29ddcd..23c79a714d 100644 --- a/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed.rst +++ b/doc/source/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed.rst @@ -18,8 +18,8 @@ Files Used in This Example Both files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed``). +- Parameter file for particle generation and packing: ``packing-particles.prm`` - Parameter file for CFD-DEM simulation of the spouted bed: ``gas-solid-spouted-cylinder-bed.prm`` -- Parameter file for particle generation and packing: ``dem-packing-in-spouted-cylinder-bed.prm`` ----------------------- Description of the Case @@ -136,19 +136,12 @@ When we pack the cylinder with particles, we need to keep them inside and preven --------------------------- Running the DEM Simulation --------------------------- -Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched on a single processor by typing: +Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched in parallel as follows: .. code-block:: text :class: copy-button - lethe-particles dem-packing-in-spouted-cylinder-bed.prm - -or in parallel (where 8 represents the number of processors) - -.. code-block:: text - :class: copy-button - - mpirun -np 8 lethe-particles dem-packing-in-spouted-cylinder-bed.prm + mpirun -np 8 lethe-particles packing-particles.prm .. note:: Running the packing should take approximately 10 hours on 8 cores using Intel(R) Core(TM) i7-9700K. diff --git a/doc/source/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/liquid-solid-fluidized-bed.rst b/doc/source/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/liquid-solid-fluidized-bed.rst index 275bde68ec..8431cbc9fc 100644 --- a/doc/source/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/liquid-solid-fluidized-bed.rst +++ b/doc/source/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/liquid-solid-fluidized-bed.rst @@ -22,8 +22,8 @@ Files Used in This Example All files mentioned below are located in the example's folder (``examples/unresolved-cfd-dem/liquid-solid-fluidized-bed``). +- Parameter file of particles generation and packing: ``packing-particles.prm`` - Parameter file for CFD-DEM simulation of the liquid-solid fluidized bed: ``liquid-solid-fluidized-bed.prm`` -- Parameter file of particles generation and packing: ``dem-packing-in-lsfb.prm`` - Postprocessing Python script: ``lsfb_postprocessing.py`` @@ -53,7 +53,7 @@ All parameter subsections are described in the `Parameters section <../../../par To set-up the cylinder fluidized bed case, we first fill the bed with particles. -We first introduce the different sections of the parameter file ``dem-packing-in-lsfb.prm`` needed to run this simulation. +We first introduce the different sections of the parameter file ``packing-particles.prm`` needed to run this simulation. Mesh ~~~~~ @@ -219,19 +219,12 @@ The volume of the insertion box should be large enough to fit all particles. Als --------------------------- Running the DEM Simulation --------------------------- -Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched on a single processor by typing: +Launching the simulation is as simple as specifying the executable name and the parameter file. Assuming that the ``lethe-particles`` executable is within your path, the simulation can be launched in parallel as follows: .. code-block:: text :class: copy-button - lethe-particles dem-packing-in-fluidized-bed.prm - -or in parallel (where :math:`8` represents the number of processors) - -.. code-block:: text - :class: copy-button - - mpirun -np 8 lethe-particles dem-packing-in-fluidized-bed.prm + mpirun -np 8 lethe-particles packing-particles.prm Lethe will generate a number of files. The most important one bears the extension ``.pvd``. It can be read by popular visualization programs such as `Paraview `_. diff --git a/doc/source/examples/unresolved-cfd-dem/unresolved-cfd-dem.rst b/doc/source/examples/unresolved-cfd-dem/unresolved-cfd-dem.rst index d782b68345..6e5a6363d2 100644 --- a/doc/source/examples/unresolved-cfd-dem/unresolved-cfd-dem.rst +++ b/doc/source/examples/unresolved-cfd-dem/unresolved-cfd-dem.rst @@ -2,7 +2,7 @@ Unresolved CFD-DEM **************************** -This section includes examples related to multiphase fluid-solid flows. We organize the examples from the single phase flow in porous media (packed bed example) to multiphase flows (solid-gas and solid-liquid fluidized beds). The packed bed example uses the ``lethe-fluid-vans`` solver which solves the Volume Average Navier Stokes (VANS) equations. The fluidized bed, the spouted bed and the Boycott effect examples use the ``lethe-fluid-particles`` solver which solves the VANS equations for the fluid phase coupled with the DEM equations for the solid phase. +This section includes examples related to multiphase fluid-solid flows. We organize the examples from the single phase flow in porous media (packed bed example) to multiphase flows (solid-gas, solid-liquid fluidized beds, and pneumatic conveying). The packed bed example uses the ``lethe-fluid-vans`` solver which solves the Volume Average Navier Stokes (VANS) equations. The fluidized bed, the spouted bed, the Boycott effect, and the pneumatic conveying examples use the ``lethe-fluid-particles`` solver which solves the VANS equations for the fluid phase coupled with the DEM equations for the solid phase. .. toctree:: :hidden: @@ -15,6 +15,7 @@ This section includes examples related to multiphase fluid-solid flows. We organ liquid-solid-fluidized-bed/liquid-solid-fluidized-bed boycott-effect/boycott-effect gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed + dense-pneumatic-conveying/dense-pneumatic-conveying .. graphviz:: @@ -38,11 +39,14 @@ This section includes examples related to multiphase fluid-solid flows. We organ cfd_dem_5 [label="Boycott Effect", href="https://chaos-polymtl.github.io/lethe/documentation/examples/unresolved-cfd-dem/boycott-effect/boycott-effect.html"]; cfd_dem_6 [label="Gas-Solid Spouted Cylinder Bed", href="https://chaos-polymtl.github.io/lethe/documentation/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/gas-solid-spouted-cylinder-bed.html"]; - + + cfd_dem_7 [label="Dense Pneumatic Conveying", href="https://chaos-polymtl.github.io/lethe/documentation/examples/unresolved-cfd-dem/dense-pneumatic-conveying/dense-pneumatic-conveying.html"]; + unresolved_cfd_dem -> cfd_dem_1:w; unresolved_cfd_dem -> cfd_dem_2:w; unresolved_cfd_dem -> cfd_dem_3:w; unresolved_cfd_dem -> cfd_dem_4:w; unresolved_cfd_dem -> cfd_dem_5:w; unresolved_cfd_dem -> cfd_dem_6:w; + unresolved_cfd_dem -> cfd_dem_7:w; } diff --git a/doc/source/parameters/cfd/dynamic_flow_control.rst b/doc/source/parameters/cfd/dynamic_flow_control.rst index a0f9e4dd2c..68753a9009 100644 --- a/doc/source/parameters/cfd/dynamic_flow_control.rst +++ b/doc/source/parameters/cfd/dynamic_flow_control.rst @@ -9,7 +9,7 @@ calculates a :math:`\beta` coefficient at each time step that is used as a sourc The main controller of the average velocity is the following equation and is based on approach of Wang `[1] `_: .. math:: - \beta^{n+1} = \beta^n + \frac{\alpha}{\Delta t} \left[ (\bar{U})^{0} - 2(\bar{U})^{n} + (\bar{U})^{n-1} \right] + \beta^{n+1} = \beta^n + \frac{\alpha}{\Delta t} \left[ \bar{U}^{0} - 2\bar{U}^{n} + \bar{U}^{n-1} \right] The default parameters are: @@ -29,7 +29,10 @@ The default parameters are: * The ``enable`` parameter is set to ``true`` to enable an imposed average velocity. -* The ``enable beta particle`` parameter is set to ``true`` to apply a proportional beta force on particles. +* The ``enable beta particle`` parameter is set to ``true`` to apply a proportional beta force on particles: + +.. math:: + \beta^{n+1}_{p} = \frac{\rho}{\rho_{p}}\beta^{n+1} * The ``average velocity`` parameter specifies the targeted average velocity (:math:`m/s`). The value is compared to the calculated value at a boundary (for CFD solvers) or the whole domain (for CFD-DEM solver). diff --git a/doc/source/theory/multiphase/cfd_dem/dem.rst b/doc/source/theory/multiphase/cfd_dem/dem.rst index 37f3295790..cb75484422 100644 --- a/doc/source/theory/multiphase/cfd_dem/dem.rst +++ b/doc/source/theory/multiphase/cfd_dem/dem.rst @@ -169,6 +169,7 @@ Rolling friction models Rolling friction may be computed through a constant torque model or a viscous torque model. It is also possible to ignore the rolling resistance. The corresponding model can be described by the following equations: .. list-table:: Rolling Friction Models used in Lethe. + :width: 80% :widths: 30 30 30 :header-rows: 1 :align: center diff --git a/examples/unresolved-cfd-dem/boycott-effect/particle-generator.prm b/examples/unresolved-cfd-dem/boycott-effect/initial-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/boycott-effect/particle-generator.prm rename to examples/unresolved-cfd-dem/boycott-effect/initial-particles.prm diff --git a/examples/unresolved-cfd-dem/cylindrical-packed-bed/packing-in-cylinder-generator.prm b/examples/unresolved-cfd-dem/cylindrical-packed-bed/packing-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/cylindrical-packed-bed/packing-in-cylinder-generator.prm rename to examples/unresolved-cfd-dem/cylindrical-packed-bed/packing-particles.prm diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/loading-particles.prm b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/loading-particles.prm new file mode 100644 index 0000000000..f5480fa47a --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/loading-particles.prm @@ -0,0 +1,191 @@ +# Listing of Parameters +# --------------------- + +set dimension = 3 + +#--------------------------------------------------- +# Simulation and IO Control +#--------------------------------------------------- + +subsection simulation control + set time step = 5e-5 + set time end = 30 + set log frequency = 500 + set output frequency = 1200 + set output path = ./output_dem/ +end + +#--------------------------------------------------- +# Timer +#--------------------------------------------------- + +subsection timer + set type = iteration +end + +#--------------------------------------------------- +# Restart +#--------------------------------------------------- + +subsection restart + set checkpoint = true + set frequency = 30000 + set restart = false + set filename = dem +end + +#--------------------------------------------------- +# Mesh +#--------------------------------------------------- + +subsection mesh + set type = cylinder + set grid type = balanced + set grid arguments = 45 : 0.042 : 0.5 + set initial refinement = 1 + set expand particle-wall contact search = true +end + +# -------------------------------------------------- +# Model parameters +#--------------------------------------------------- + +subsection model parameters + subsection contact detection + set contact detection method = dynamic + set neighborhood threshold = 1.3 + end + subsection load balancing + set load balance method = dynamic_with_sparse_contacts + set threshold = 0.5 + set dynamic check frequency = 8000 + set active weight factor = 0.8 + set inactive weight factor = 0.6 + end + set particle particle contact force method = hertz_mindlin_limit_overlap + set particle wall contact force method = nonlinear + set integration method = velocity_verlet + set rolling resistance torque method = constant_resistance + subsection adaptive sparse contacts + set enable adaptive sparse contacts = true + set enable particle advection = false + set granular temperature threshold = 1e-4 + set solid fraction threshold = 0.4 + end +end + +#--------------------------------------------------- +# Physical Properties +#--------------------------------------------------- + +subsection lagrangian physical properties + set g = -9.81, 0, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e6 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e6 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 +end + +#--------------------------------------------------- +# Insertion Info +#--------------------------------------------------- + +subsection insertion info + set insertion method = plane + set insertion frequency = 400 + set insertion plane point = 0.475, -0.0325, 0 + set insertion plane normal vector = -0.25, 4.75, 0 + set insertion maximum offset = 0.001 + set insertion prn seed = 19 + set initial velocity = -0.35, 0.1, 0.0 +end + +#--------------------------------------------------- +# Floating Walls +#--------------------------------------------------- + +subsection floating walls + set number of floating walls = 2 + subsection wall 0 + subsection point on wall + set x = -0.5 + set y = 0 + set z = 0 + end + subsection normal vector + set nx = 1 + set ny = 0 + set nz = 0 + end + set start time = 0 + set end time = 30 + end + + subsection wall 1 + subsection point on wall + set x = 0.5 + set y = 0 + set z = 0 + end + subsection normal vector + set nx = -1 + set ny = 0 + set nz = 0 + end + set start time = 0 + set end time = 30 + end +end + +#--------------------------------------------------- +# Solid Objects +#--------------------------------------------------- + +subsection solid objects + subsection solid surfaces + set number of solids = 1 + subsection solid object 0 + subsection mesh + set type = gmsh + set file name = slug-shape.msh + set simplex = true + end + end + end +end + +#--------------------------------------------------- +# Boundary conditions DEM +#--------------------------------------------------- + +subsection DEM boundary conditions + set number of boundary conditions = 1 + + subsection boundary condition 0 + set type = periodic + set periodic id 0 = 1 + set periodic id 1 = 2 + set periodic direction = 0 + end +end + +#--------------------------------------------------- +# DEM Post-Processing +#--------------------------------------------------- + +subsection post-processing + set Lagrangian post-processing = true +end diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/log_utilities.py b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/log_utilities.py new file mode 100644 index 0000000000..dff48ca27a --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/log_utilities.py @@ -0,0 +1,43 @@ +import numpy as np +import pandas as pd + +class LogUtilities: + def __init__(self, log_filename): + with open(log_filename) as f: + self.lines = f.readlines() + + log_data_type = ['time', 'beta', 'fluid_velocity'] + self.log_dataframe = pd.DataFrame(columns=log_data_type) + self.log_dataframe['time'] = self.get_times() + + def get_times(self): + # Find the time in the log file through the keyword "Transient" and some hardcoded indices + time_keyword = "Transient" + time = np.array([0]) + + for line in self.lines: + if time_keyword in line: + time_str = line[36:36 + 6].strip() + time = np.append(time, float(time_str)) + return time + + def get_log_data(self): + return self.log_dataframe + + def flow_monitoring(self): + velocity_keyword = "Fluid space-average" + beta_keyword = "Fluid beta force" + + average_velocity = np.array([0]) + beta = np.array([0]) + + for line in self.lines: + if velocity_keyword in line: + average_velocity = np.append(average_velocity, float(line.split()[-1])) + if beta_keyword in line: + beta = np.append(beta, float(line.split()[-1])) + + self.log_dataframe['fluid_velocity'] = average_velocity + self.log_dataframe['beta'] = beta + + print("Flow monitoring done.") \ No newline at end of file diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output/dummy-file b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output/dummy-file new file mode 100644 index 0000000000..482db144d3 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output/dummy-file @@ -0,0 +1,2 @@ +Dummy file to ensure folder exists + diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output_dem/dummy-file b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output_dem/dummy-file new file mode 100644 index 0000000000..482db144d3 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/output_dem/dummy-file @@ -0,0 +1,2 @@ +Dummy file to ensure folder exists + diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying.prm b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying.prm new file mode 100644 index 0000000000..158b0b5e46 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying.prm @@ -0,0 +1,213 @@ +# Listing of Parameters +# --------------------- + +set dimension = 3 + +# -------------------------------------------------- +# Simulation and IO Control +#--------------------------------------------------- + +subsection simulation control + set method = bdf1 + set output name = cfd_dem + set output frequency = 10 + set time end = 5 + set time step = 5e-4 + set output path = ./output/ +end + +#--------------------------------------------------- +# Timer +#--------------------------------------------------- + +subsection timer + set type = iteration +end + +#--------------------------------------------------- +# Mesh +#--------------------------------------------------- + +subsection mesh + set type = cylinder + set grid type = balanced + set grid arguments = 45 : 0.042 : 0.5 + set initial refinement = 1 + set expand particle-wall contact search = true +end + +#--------------------------------------------------- +# Physical Properties CFD +#--------------------------------------------------- + +subsection physical properties + subsection fluid 0 + set kinematic viscosity = 1.5e-5 + set density = 1.205 + end +end + +#--------------------------------------------------- +# Physical Properties +#--------------------------------------------------- + +subsection lagrangian physical properties + set g = 0, -9.81, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e7 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e7 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 +end + +#--------------------------------------------------- +# Flow control +#--------------------------------------------------- + +subsection flow control + set enable = true + set enable beta particle = true + set average velocity = 3 + set flow direction = 0 + set beta threshold = 0.05 + set alpha = 0.25 + set verbosity = verbose +end + +# -------------------------------------------------- +# Boundary Conditions CFD +#--------------------------------------------------- + +subsection boundary conditions + set number = 2 + subsection bc 0 + set id = 0 + set type = function weak + set beta = 100 + subsection u + set Function expression = 0 + end + subsection v + set Function expression = 0 + end + subsection w + set Function expression = 0 + end + end + subsection bc 1 + set id = 1 + set type = periodic + set periodic_id = 2 + set periodic_direction = 0 + end +end + +#--------------------------------------------------- +# Boundary Conditions DEM +#--------------------------------------------------- + +subsection DEM boundary conditions + set number of boundary conditions = 1 + + subsection boundary condition 0 + set type = periodic + set periodic id 0 = 1 + set periodic id 1 = 2 + set periodic direction = 0 + end +end + +#--------------------------------------------------- +# Void Fraction CFD-DEM +#--------------------------------------------------- + +subsection void fraction + set mode = qcm + set read dem = true + set dem file name = dem + set l2 smoothing factor = 0.0001 +end + +#--------------------------------------------------- +# CFD-DEM +#--------------------------------------------------- + +subsection cfd-dem + set grad div = true + set drag model = difelice + set saffman lift force = true + set buoyancy force = true + set pressure force = true + set coupling frequency = 100 + set implicit stabilization = false + set grad-div length scale = 0.084 + set particle statistics = true +end + +# -------------------------------------------------- +# Model parameters DEM +#--------------------------------------------------- + +subsection model parameters + subsection contact detection + set contact detection method = dynamic + set neighborhood threshold = 1.3 + end + set particle particle contact force method = hertz_mindlin_limit_overlap + set particle wall contact force method = nonlinear + set integration method = velocity_verlet + set rolling resistance torque method = constant_resistance +end + +# -------------------------------------------------- +# Non-Linear Solver Control CFD +#--------------------------------------------------- + +subsection non-linear solver + subsection fluid dynamics + set solver = inexact_newton + set matrix tolerance = 0.1 + set reuse matrix = true + set tolerance = 1e-4 + set max iterations = 10 + set verbosity = quiet + end +end + +# -------------------------------------------------- +# Linear Solver Control CFD +#--------------------------------------------------- + +subsection linear solver + subsection fluid dynamics + set method = gmres + set max iters = 200 + set relative residual = 1e-4 + set minimum residual = 1e-6 + set ilu preconditioner fill = 0 + set ilu preconditioner absolute tolerance = 1e-8 + set ilu preconditioner relative tolerance = 1.00 + set verbosity = quiet + set max krylov vectors = 200 + end +end + +#--------------------------------------------------- +# DEM Post-Processing +#--------------------------------------------------- + +subsection post-processing + set Lagrangian post-processing = true +end diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying_post-processing.py b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying_post-processing.py new file mode 100644 index 0000000000..95a6daa658 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pneumatic-conveying_post-processing.py @@ -0,0 +1,177 @@ +from lethe_pyvista_tools import * +import matplotlib.pyplot as plt +from pyvista_utilities import * +from log_utilities import * + +############################# +# Path and filenames +############################# +simulation_path = "./" +prm_filename = "pneumatic-conveying.prm" +pvd_name = "cfd_dem" +log_filename = "pneumatic-log.out" + +############################# +# Read data and process +############################# +# In this post-processing, we need the ID of the particles, the position, and the velocity, the other data is not +# necessary and takes a lot of memory +ignore_data = ['omega', 'type', 'diameter', 'mass', 'fem_force', 'fem_torque'] + +# Create the particle object +particles = lethe_pyvista_tools(f'{simulation_path}', prm_filename, f'{pvd_name}_particles.pvd', + ignore_data=ignore_data, step=5) +prm_dict = particles.prm_dict +dataframe = [] + +for i in range(len(particles.list_vtu)): + df = particles.get_df(i) + data = pd.DataFrame() + # Get the ID of the particles + data['ID'] = df['ID'].astype(int) + + # Get the position of the particles + data['x'] = df.points[:, 0] + data['y'] = df.points[:, 1] + data['z'] = df.points[:, 2] + + # Get the velocity of the particles + data['u'] = df['velocity'][:, 0] + data['v'] = df['velocity'][:, 1] + data['w'] = df['velocity'][:, 2] + + dataframe.append(data) + +############################# +# Post-processing +############################# +# We specify the volume of the triangulation since the mesh is not a perfect cylinder +# This value is at the beginning of the output of the simulation +volume_triangulation = 0.00540043 +L = 1.0 + +# Create the post-processing and log object +postprocessing = PneumaticConveyingUtilities(dataframe, prm_dict, particles.time_list, L, volume_triangulation) +log = LogUtilities(f"{simulation_path}/{log_filename}") + +# Get the slug length, the solid mass flow rate, the average particle velocity, and the slug velocity +postprocessing.calculate_slug_length(void_fraction_threshold=0.55) +postprocessing.calculate_solid_mass_flow_rate() +postprocessing.calculate_average_particle_velocity() +postprocessing.calculate_slug_velocity(sample_step=3) +postprocessing_dataframe = postprocessing.get_data() + +# Get the fluid velocity and the correctional volumetric force (beta) +log.flow_monitoring() +log_dataframe = log.get_log_data() + +############################# +# Print results +############################# +# Calculate the time-averaged values +start = 4.0 # ~quasi-steady state +quasisteasy_postprocessing_dataframe = postprocessing_dataframe[postprocessing_dataframe['time'] > start] +quasisteasy_log_dataframe = log_dataframe[log_dataframe['time'] > start] + +print('\nTime-averaged in quasi-steady state values:') +print(f"Fluid velocity: {quasisteasy_log_dataframe['fluid_velocity'].mean():2.3f} ± " + f"{quasisteasy_log_dataframe['fluid_velocity'].std():2.3f} m/s") +print(f"Beta force: {quasisteasy_log_dataframe['beta'].mean():2.0f} ± " + f"{quasisteasy_log_dataframe['beta'].std():2.0f} m/s²") +print(f"Slug velocity: {quasisteasy_postprocessing_dataframe['slug_velocity'].mean():2.3f} ± " + f"{quasisteasy_postprocessing_dataframe['slug_velocity'].std():2.3f} m/s") +print(f"Particles in slug velocity: {quasisteasy_postprocessing_dataframe['average_velocity'].mean():2.3f} ± " + f"{quasisteasy_postprocessing_dataframe['average_velocity'].std():2.3f} m/s") +print(f"Solid mass flow rate: {quasisteasy_postprocessing_dataframe['mass_flow_rate'].mean():2.2f} kg/s") +print(f"Slug length: {quasisteasy_postprocessing_dataframe['distance'].mean():2.2f} ± " + f"{quasisteasy_postprocessing_dataframe['distance'].std():2.2f} m") + +print('\nResult from u_s = 0.967 u_p + 0.5(gD)**0.5:') +u_p = quasisteasy_postprocessing_dataframe["average_velocity"].mean() +u_s = quasisteasy_postprocessing_dataframe["slug_velocity"].mean() +calc_u_s = 0.967*u_p+ 0.5 * (9.81 * 0.084) ** 0.5 +print(f'u_s = {calc_u_s:2.3} m/s') +print(f'Difference: {abs(calc_u_s - u_s)/u_s:.3f} %') + +############################# +# Plot results +############################# +# All plots in one figure +fig = plt.figure(figsize=(10, 9)) + +# Average fluid velocity and beta force +flow_plot = fig.add_subplot(311) +beta_plot = flow_plot.twinx() + +flow_color = 'tab:orange' +flow_plot.plot(log_dataframe['time'], log_dataframe['fluid_velocity'], color=flow_color) +flow_plot.plot(log_dataframe['time'], 3 * np.ones(len(log_dataframe)), + color=flow_color, linestyle='--', label='Target: 3 m/s') + +beta_color = 'tab:purple' +beta_plot.plot(log_dataframe['time'], log_dataframe['beta'], color=beta_color) + +# Slug velocity and particles in slug +slug_plot = fig.add_subplot(312) +particles_plot = slug_plot.twinx() + +slug_color = 'k' +slug_plot.plot(postprocessing_dataframe['time'], postprocessing_dataframe['slug_velocity'], color=slug_color) + +particle_color = 'tab:blue' +particles_plot.plot(postprocessing_dataframe['time'], postprocessing_dataframe['average_velocity'], + color=particle_color) + +# Solid mass flow rate and average particle velocity +mass_plot = fig.add_subplot(313) +length_plot = mass_plot.twinx() + +mass_color = 'tab:red' +mass_plot.plot(postprocessing_dataframe['time'], postprocessing_dataframe['mass_flow_rate'], color=mass_color) + +length_color = 'tab:green' +length_plot.plot(postprocessing_dataframe['time'], postprocessing_dataframe['distance'], color=length_color) + +# Formatting shenanigans +flow_plot.set(ylim=[1.5, 4.0], xlim=[0, 5]) +flow_plot.set_ylabel('Average fluid velocity (m/s)', color=flow_color) +flow_plot.tick_params(axis='y', labelcolor=flow_color) +flow_plot.grid(color='k', linestyle='-', linewidth=0.4) +flow_plot.xaxis.set_major_locator(plt.MaxNLocator(11)) +flow_plot.axvspan(0, start, color='gray', alpha=0.15, lw=0) +flow_plot.get_legend() + +beta_plot.set(ylim=[0, 5000]) +beta_plot.set_ylabel('Beta force (m/s²)', color=beta_color) +beta_plot.tick_params(axis='y', labelcolor=beta_color) +beta_plot.axes.xaxis.set_ticklabels([]) + +slug_plot.set(ylim=[0, 2.5], xlim=[0, 5]) +slug_plot.set_ylabel('Slug velocity (m/s)', color=slug_color) +slug_plot.tick_params(axis='y', labelcolor=slug_color) +slug_plot.grid(color='k', linestyle='-', linewidth=0.4) +slug_plot.xaxis.set_major_locator(plt.MaxNLocator(11)) +slug_plot.axvspan(0, start, color='gray', alpha=0.15, lw=0) + +particles_plot.set(ylim=[0, 2.5], xlim=[0, 5]) +particles_plot.set_ylabel('Particle velocity (m/s)', color=particle_color) +particles_plot.tick_params(axis='y', labelcolor=particle_color) +particles_plot.axes.xaxis.set_ticklabels([]) + +mass_plot.set(ylim=[0, 2.5], xlim=[0, 5]) +mass_plot.set_xlabel('Time (s)') +mass_plot.set_ylabel('Solid mass flow rate (kg/s)', color=mass_color) +mass_plot.tick_params(axis='y', labelcolor=mass_color) +mass_plot.grid(color='k', linestyle='-', linewidth=0.4) +mass_plot.xaxis.set_major_locator(plt.MaxNLocator(11)) +mass_plot.axvspan(0, start, color='gray', alpha=0.15, lw=0) + +length_plot.set(ylim=[0.1, 0.6], xlim=[0, 5]) +length_plot.set_ylabel('Slug length (m)', color=length_color) +length_plot.tick_params(axis='y', labelcolor=length_color) +length_plot.xaxis.set_major_locator(plt.MaxNLocator(11)) +length_plot.set_xlabel('Time (s)') + +fig.savefig(f'./pneumatic-conveying-data.png', bbox_inches='tight', dpi=300) +plt.tight_layout() +plt.show() \ No newline at end of file diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pyvista_utilities.py b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pyvista_utilities.py new file mode 100644 index 0000000000..4a1eb0d2b8 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/pyvista_utilities.py @@ -0,0 +1,213 @@ +import numpy as np +import pandas as pd + +def position_int_to_string(coord_int): + int_to_string = {0: 'x', 1: 'y', 2: 'z'} + return int_to_string[coord_int] +def velocity_int_to_string(coord_int): + int_to_string = {0: 'u', 1: 'v', 2: 'w'} + return int_to_string[coord_int] + +class PneumaticConveyingUtilities: + def __init__(self, dataframe, prm_dict, time_list, L, vol_triangulation): + self.dataframe = dataframe + self.prm_dict = prm_dict + self.time_list = time_list + self.L = L + self.vol_triangulation = vol_triangulation + + # Storing post-processing data + postprocessing_data_type = ['time', 'front_position', 'rear_position', 'distance', 'number_of_particles', + 'mass', 'mass_flow_rate', 'average_velocity', 'slug_velocity'] + self.postprocessing_dataframe = pd.DataFrame(columns=postprocessing_data_type) + self.postprocessing_dataframe['time'] = time_list + + # Useful variables for parameter file + self.compute_info() + + def compute_info(self): + self.dp = self.prm_dict['diameter'] + self.rhop = self.prm_dict['density particles'] + self.vp = 4. / 3. * np.pi * (self.dp / 2.) ** 3 + self.direction = position_int_to_string(self.prm_dict['periodic direction']) + + + def get_data(self): + return self.postprocessing_dataframe + + def calculate_slug_length(self, void_fraction_threshold=0.55): + # Area of the cross-section of the pipe + A = self.vol_triangulation/self.L + + # Get the number of slices and their length + n_L = int(self.L / self.dp) + dL = self.L / n_L + + for i, df in enumerate(self.dataframe): + # Create a list to store the number of particles and the position limits of slices + number_of_particles = np.zeros(n_L) + position_limits = np.linspace(-self.L/2.0, self.L/2.0, n_L+1) + + # Get the number of particles in each slice of dL + x_positions = df[self.direction] + for j in range(0, n_L): + # Get the number of particles per slice + number_of_particles[j] = np.array([(x_positions >= position_limits[j]) & + (x_positions < position_limits[j+1])], dtype=bool).sum() + + # Get the void fraction of the slice + void_fractions = 1 - number_of_particles * self.vp / (dL * A) + + # Smoothing the void fraction with a convolution operator (moving average) + period = 5 + void_fractions_smoothed = np.convolve(np.ones(period)/period, void_fractions, mode='same') + + # Since the convolution operator do not take the periodic boundary into account, we add the contribution of + # the slide at boundaries + void_fractions_smoothed[0] += 1/period * void_fractions[-2:].sum() + void_fractions_smoothed[1] += 1/period * void_fractions[-1] + void_fractions_smoothed[-2] += 1/period * void_fractions[0] + void_fractions_smoothed[-1] += 1/period * void_fractions[0:2].sum() + + # Find the state of the slide with the void fraction threshold (no slug = 0, slug = 1) + slug_state = np.where(void_fractions_smoothed <= void_fraction_threshold, 1, 0) + + correction_term = 0.0 + + # If the first and last slug state are 1, it means slug in the periodic boundaries + if slug_state[0] == 1 and slug_state[-1] == 1: + # Slug in PBC: ‾‾‾‾\_________/‾‾‾‾ + # Discretized: ‾|‾|\|_|_|_|_|/|‾|‾ + # 1 1 0 0 0 0 0 0 1 1 + + # Find the indices where the slug is not and get the front and rear indices + no_slug_index = np.where(slug_state == 0)[0] + front_index = no_slug_index[0] - 1 + rear_index = no_slug_index[-1] + 1 + + # Since the slug is in the periodic boundaries, the distance is corrected by the length of the pipe + correction_term = self.L + else: + # Slug in middle: ____/‾‾‾‾‾‾‾‾‾\____ + # Discretized: _|_|/|‾|‾|‾|‾|\|_|_ + # 0 0 0 1 1 1 1 0 0 0 + + # Find the indices where the slug is and get the front and rear indices + slug_index = np.where(slug_state == 1)[0] + front_index = slug_index[-1] + rear_index = slug_index[0] + + # Get the front and rear position of the slug + # Note: the length tends to be overestimated, so we take the position limits towards the center + front_position = position_limits[front_index] + rear_position = position_limits[rear_index+1] + + # Compute the distance between the front and rear of the slug at middle of slice + distance = front_position - rear_position + correction_term + + # Store information in the post-processing dataframe + self.postprocessing_dataframe.loc[i, 'front_position'] = front_position + self.postprocessing_dataframe.loc[i, 'rear_position'] = rear_position + self.postprocessing_dataframe.loc[i, 'distance'] = distance + + print("Slug length computing done.") + + + def calculate_solid_mass_flow_rate(self): + # Virtual wall to limit the domain in the pipe for evaluation + dL = 25 * self.dp + wall = self.L / 2. - dL + + # Create a list to store the number of particles + last_list = np.array([]) + + for i, df in enumerate(self.dataframe): + # Get the IDs and the positions of the particles + ids = df['ID'].values + positions = df[self.direction].values + + # Find the particles that crossed the wall + particle_list = ids[positions > wall] + + # Remove the particles that already crossed the wall at last time step from the list + gone_particles = np.setdiff1d(particle_list, last_list) + last_list = particle_list + + # Number of particles below and mass discharge + number_of_particles = len(gone_particles) + mass = number_of_particles * self.vp * self.rhop + + self.postprocessing_dataframe.loc[i, 'number_of_particles'] = number_of_particles + self.postprocessing_dataframe.loc[i, 'mass'] = mass + + if i == 0: + self.postprocessing_dataframe.loc[i, 'mass_flow_rate'] = 0 + else: + mass_list = self.postprocessing_dataframe['mass'].values + self.postprocessing_dataframe.loc[i, 'mass_flow_rate'] = (mass_list[0:i].sum() / + (self.time_list[i] - self.time_list[0])) + + print("Solid mass flow rate computing done.") + + def calculate_average_particle_velocity(self): + for i, df in enumerate(self.dataframe): + # ids = current_df['ID'].astype(int) + # particle_id = np.where(ids == int(id))[0][0] + velocities = df[['u', 'v', 'w']].values + positions = df[self.direction] + front_position = self.postprocessing_dataframe['front_position'] + rear_position = self.postprocessing_dataframe['rear_position'] + + avg_velocities = np.zeros(3) + + # Get the particles index in the slug + if front_position[i] < rear_position[i]: + in_slug_index = np.where((positions >= rear_position[i]) | (positions < front_position[i]))[0] + else: + in_slug_index = np.where((positions >= rear_position[i]) & (positions < front_position[i]))[0] + + # Compute the average velocity of the particles in the slug + for j in in_slug_index: + avg_velocities += velocities[j, :] + + average_velocity = avg_velocities / len(in_slug_index) + average_velocity = np.sqrt(average_velocity[0]**2 + average_velocity[1]**2 + average_velocity[2]**2) + #print("Slug's particle velocity computing done.") + + self.postprocessing_dataframe.loc[i, 'average_velocity'] = average_velocity + + print("Particle velocity in slug computing done.") + + def calculate_slug_velocity(self, sample_step=1): + # Periodic position handling + front_positions = self.postprocessing_dataframe['front_position'].values + continuous_front_positions = front_positions.copy() + dt = self.time_list[1] - self.time_list[0] + + # Transform the slug front position as if the pipe was continuous, it helps for the numerical differentiation + i_pass = 0 + for i in range(1, len(front_positions)): + if front_positions[i] < front_positions[i-1]: + i_pass += 1 + + continuous_front_positions[i] += i_pass * self.L + + # First value is computed with forward difference + velocity = (continuous_front_positions[1] - continuous_front_positions[0]) / dt + self.postprocessing_dataframe.loc[0, 'slug_velocity'] = velocity + + # Central difference for the rest of the values + for i in list(range(1, sample_step)) + list(range(len(continuous_front_positions)-sample_step, len(continuous_front_positions) - 1)): + velocity = (continuous_front_positions[i+1] - continuous_front_positions[i-1]) / (2 * dt) + self.postprocessing_dataframe.loc[i, 'slug_velocity'] = velocity + + # Central difference with skipping data in the sample step because there's a lot of fluctuation + for i in range(sample_step, len(continuous_front_positions) - sample_step): + velocity = (continuous_front_positions[i+sample_step] - continuous_front_positions[i-sample_step]) / (2 * sample_step * dt) + self.postprocessing_dataframe.loc[i, 'slug_velocity'] = velocity + + # Backward difference for the last values + velocity = (continuous_front_positions[-1] - continuous_front_positions[-2]) / dt + self.postprocessing_dataframe.loc[-1, 'slug_velocity'] = velocity + + print("Slug velocity computing done.") \ No newline at end of file diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/settling-particles.prm b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/settling-particles.prm new file mode 100644 index 0000000000..f58059055d --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/settling-particles.prm @@ -0,0 +1,123 @@ +# Listing of Parameters +# --------------------- + +set dimension = 3 + +#--------------------------------------------------- +# Simulation and IO Control +#--------------------------------------------------- + +subsection simulation control + set time step = 5e-5 + set time end = 32.5 + set log frequency = 500 + set output frequency = 1200 + set output path = ./output_dem/ +end + +#--------------------------------------------------- +# Timer +#--------------------------------------------------- + +subsection timer + set type = iteration +end + +#--------------------------------------------------- +# Restart +#--------------------------------------------------- + +subsection restart + set checkpoint = true + set frequency = 10000 + set restart = true + set filename = dem +end + +#--------------------------------------------------- +# Mesh +#--------------------------------------------------- + +subsection mesh + set type = cylinder + set grid type = balanced + set grid arguments = 45 : 0.042 : 0.5 + set initial refinement = 1 + set expand particle-wall contact search = true +end + +# -------------------------------------------------- +# Model parameters +#--------------------------------------------------- + +subsection model parameters + subsection contact detection + set contact detection method = dynamic + set neighborhood threshold = 1.3 + end + subsection load balancing + set load balance method = dynamic_with_sparse_contacts + set threshold = 0.5 + set dynamic check frequency = 8000 + set active weight factor = 0.8 + set inactive weight factor = 0.6 + end + set particle particle contact force method = hertz_mindlin_limit_overlap + set particle wall contact force method = nonlinear + set integration method = velocity_verlet + set rolling resistance torque method = constant_resistance + subsection adaptive sparse contacts + set enable adaptive sparse contacts = true + set enable particle advection = false + set granular temperature threshold = 1e-4 + set solid fraction threshold = 0.4 + end +end + +#--------------------------------------------------- +# Physical Properties +#--------------------------------------------------- + +subsection lagrangian physical properties + set g = 0, -9.81, 0 + set number of particle types = 1 + subsection particle type 0 + set size distribution type = uniform + set diameter = 0.005 + set number of particles = 32194 + set density particles = 890 + set young modulus particles = 1e6 + set poisson ratio particles = 0.33 + set restitution coefficient particles = 0.3 + set friction coefficient particles = 0.3 + set rolling friction particles = 0.2 + end + set young modulus wall = 1e6 + set poisson ratio wall = 0.33 + set restitution coefficient wall = 0.3 + set friction coefficient wall = 0.4 + set rolling friction wall = 0.2 +end + +#--------------------------------------------------- +# Boundary conditions DEM +#--------------------------------------------------- + +subsection DEM boundary conditions + set number of boundary conditions = 1 + + subsection boundary condition 0 + set type = periodic + set periodic id 0 = 1 + set periodic id 1 = 2 + set periodic direction = 0 + end +end + +#--------------------------------------------------- +# DEM Post-Processing +#--------------------------------------------------- + +subsection post-processing + set Lagrangian post-processing = true +end diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.geo b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.geo new file mode 100644 index 0000000000..640b91f5c3 --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.geo @@ -0,0 +1,90 @@ +//+ +SetFactory("OpenCASCADE"); +lc = 1; +r = 0.042; +L = 1; +Ls = 0.5; +layer = 0.021; +buffer = 0.01; + + +// Before slug +Point(0) = {-L/2, -r+layer, r, lc}; +Point(1) = {-L/2, -r+layer, -r, lc}; +Point(2) = {-(Ls/2+2*r-layer), -r+layer, -r, lc}; +Point(3) = {-(Ls/2+2*r-layer), -r+layer, r, lc}; + +Line(0)={0,1}; +Line(1)={1,2}; +Line(2)={2,3}; +Line(3)={3,0}; + +Line(100)={2,0}; + +Line Loop(1) = {1,0,100}; +Line Loop(100) = {3,2,100}; + +// Rear slope of slug +Point(4) = {-(Ls/2), r, -r, lc}; +Point(5) = {-(Ls/2), r, r, lc}; + +Line(4)={2,4}; +Line(5)={4,5}; +Line(6)={5,3}; + +Line(200)={3,4}; + +Line Loop(2) = {6,5,200}; +Line Loop(200) = {2,4,200}; + +// Top slug +Point(6) = {(Ls/2), r, -r, lc}; +Point(7) = {(Ls/2), r, r, lc}; + +Line(7)={4,6}; +Line(8)={6,7}; +Line(9)={7,5}; + +Line(300)={5,6}; + +Line Loop(3) = {8,9,300}; +Line Loop(300) = {5,7,300}; + +// Front slope of slug +Point(8) = {(Ls/2+2*r-layer), -r+layer, -r, lc}; +Point(9) = {(Ls/2+2*r-layer), -r+layer, r, lc}; + +Line(10)={7,9}; +Line(11)={9,8}; +Line(12)={8,6}; + +Line(400)={8,7}; + +Line Loop(4) = {10,11,400}; +Line Loop(400) = {8,12,400}; + +// Front stationnary layer +Point(10) = {L/2, -r+layer, r, lc}; +Point(11) = {L/2, -r+layer, -r, lc}; + +Line(13)={9,10}; +Line(14)={10,11}; +Line(15)={11,8}; + +Line(500)={11,9}; + +Line Loop(5) = {13,14,500}; +Line Loop(500) = {11,15,500}; + +Plane Surface(1) = {1}; +Plane Surface(100) = {100}; +Plane Surface(2) = {2}; +Plane Surface(200) = {200}; +Plane Surface(3) = {3}; +Plane Surface(300) = {300}; +Plane Surface(4) = {4}; +Plane Surface(400) = {400}; +Plane Surface(5) = {5}; +Plane Surface(500) = {500}; +Physical Surface(0) = {1,100,2,200,3,300,4,400,5,500}; + diff --git a/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.msh b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.msh new file mode 100644 index 0000000000..1f5b1389ea --- /dev/null +++ b/examples/unresolved-cfd-dem/dense-pneumatic-conveying/slug-shape.msh @@ -0,0 +1,121 @@ +$MeshFormat +4.1 0 8 +$EndMeshFormat +$Entities +12 21 10 0 +0 -0.5 -0.021 0.042 0 +1 -0.5 -0.021 -0.042 0 +2 -0.313 -0.021 -0.042 0 +3 -0.313 -0.021 0.042 0 +4 -0.25 0.042 -0.042 0 +5 -0.25 0.042 0.042 0 +6 0.25 0.042 -0.042 0 +7 0.25 0.042 0.042 0 +8 0.313 -0.021 -0.042 0 +9 0.313 -0.021 0.042 0 +10 0.5 -0.021 0.042 0 +11 0.5 -0.021 -0.042 0 +0 -0.5000000999999999 -0.0210001 -0.04200010000000001 -0.4999999 -0.0209999 0.04200010000000001 0 2 0 -1 +1 -0.5000000999999999 -0.0210001 -0.04200010000000001 -0.3129999 -0.0209999 -0.0419999 0 2 1 -2 +2 -0.3130001 -0.0210001 -0.04200010000000001 -0.3129999 -0.0209999 0.04200010000000001 0 2 2 -3 +3 -0.5000000999999999 -0.0210001 0.0419999 -0.3129999 -0.0209999 0.04200010000000001 0 2 3 0 +4 -0.3130001 -0.0210001 -0.04200010000000001 -0.2499999 0.0420001 -0.0419999 0 2 2 -4 +5 -0.2500001 0.0419999 -0.04200010000000001 -0.2499999 0.04200010000000001 0.04200010000000001 0 2 4 -5 +6 -0.3130001 -0.0210001 0.0419999 -0.2499999 0.04200010000000001 0.04200010000000001 0 2 5 -3 +7 -0.2500001 0.0419999 -0.04200010000000001 0.2500001 0.04200010000000001 -0.0419999 0 2 4 -6 +8 0.2499999 0.0419999 -0.04200010000000001 0.2500001 0.04200010000000001 0.04200010000000001 0 2 6 -7 +9 -0.2500001 0.0419999 0.0419999 0.2500001 0.04200010000000001 0.04200010000000001 0 2 7 -5 +10 0.2499999 -0.0210001 0.0419999 0.3130001 0.04200010000000001 0.04200010000000001 0 2 7 -9 +11 0.3129999 -0.0210001 -0.04200010000000001 0.3130001 -0.0209999 0.04200010000000001 0 2 9 -8 +12 0.2499999 -0.0210001 -0.04200010000000001 0.3130001 0.0420001 -0.0419999 0 2 8 -6 +13 0.3129999 -0.0210001 0.0419999 0.5000000999999999 -0.0209999 0.04200010000000001 0 2 9 -10 +14 0.4999999 -0.0210001 -0.04200010000000001 0.5000000999999999 -0.0209999 0.04200010000000001 0 2 10 -11 +15 0.3129999 -0.0210001 -0.04200010000000001 0.5000000999999999 -0.0209999 -0.0419999 0 2 11 -8 +100 -0.5000000999999999 -0.0210001 -0.04200010000000001 -0.3129999 -0.0209999 0.04200010000000001 0 2 2 0 +200 -0.3130001 -0.0210001 -0.04200010000000001 -0.2499999 0.0420001 0.04200010000000001 0 2 3 -4 +300 -0.2500001 0.0419999 -0.04200010000000001 0.2500001 0.04200010000000001 0.04200010000000001 0 2 5 -6 +400 0.2499999 -0.0210001 -0.04200010000000001 0.3130001 0.0420001 0.04200010000000001 0 2 8 -7 +500 0.3129999 -0.0210001 -0.04200010000000001 0.5000000999999999 -0.0209999 0.04200010000000001 0 2 11 -9 +1 -0.5000000999999999 -0.0210001 -0.04200010000000001 -0.3129999 -0.0209999 0.04200010000000001 1 0 3 1 100 0 +2 -0.3130001 -0.0210001 -0.04200010000000001 -0.2499999 0.04200010000000001 0.04200010000000001 1 0 3 6 200 5 +3 -0.2500001 0.0419999 -0.04200010000000001 0.2500001 0.04200010000000001 0.04200010000000001 1 0 3 8 9 300 +4 0.2499999 -0.0210001 -0.04200010000000001 0.3130001 0.04200010000000001 0.04200010000000001 1 0 3 10 11 400 +5 0.3129999 -0.0210001 -0.04200010000000001 0.5000000999999999 -0.0209999 0.04200010000000001 1 0 3 13 14 500 +100 -0.5000000999999999 -0.0210001 -0.04200010000000001 -0.3129999 -0.0209999 0.04200010000000001 1 0 3 3 -100 2 +200 -0.3130001 -0.0210001 -0.04200010000000001 -0.2499999 0.0420001 0.04200010000000001 1 0 3 2 200 -4 +300 -0.2500001 0.0419999 -0.04200010000000001 0.2500001 0.04200010000000001 0.04200010000000001 1 0 3 5 300 -7 +400 0.2499999 -0.0210001 -0.04200010000000001 0.3130001 0.04200010000000001 0.04200010000000001 1 0 3 8 -400 12 +500 0.3129999 -0.0210001 -0.04200010000000001 0.5000000999999999 -0.0209999 0.04200010000000001 1 0 3 11 -15 500 +$EndEntities +$Nodes +22 12 1 12 +0 0 0 1 +1 +-0.5 -0.021 0.042 +0 1 0 1 +2 +-0.5 -0.021 -0.042 +0 2 0 1 +3 +-0.313 -0.021 -0.042 +0 3 0 1 +4 +-0.313 -0.021 0.042 +0 4 0 1 +5 +-0.25 0.042 -0.042 +0 5 0 1 +6 +-0.25 0.042 0.042 +0 6 0 1 +7 +0.25 0.042 -0.042 +0 7 0 1 +8 +0.25 0.042 0.042 +0 8 0 1 +9 +0.313 -0.021 -0.042 +0 9 0 1 +10 +0.313 -0.021 0.042 +0 10 0 1 +11 +0.5 -0.021 0.042 +0 11 0 1 +12 +0.5 -0.021 -0.042 +2 1 0 0 +2 2 0 0 +2 3 0 0 +2 4 0 0 +2 5 0 0 +2 100 0 0 +2 200 0 0 +2 300 0 0 +2 400 0 0 +2 500 0 0 +$EndNodes +$Elements +10 10 1 10 +2 1 2 1 +1 1 2 3 +2 2 2 1 +2 4 5 6 +2 3 2 1 +3 6 7 8 +2 4 2 1 +4 8 10 9 +2 5 2 1 +5 10 11 12 +2 100 2 1 +6 1 3 4 +2 200 2 1 +7 3 4 5 +2 300 2 1 +8 5 6 7 +2 400 2 1 +9 7 8 9 +2 500 2 1 +10 9 12 10 +$EndElements diff --git a/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/dem-packing-in-fluidized-bed-generator.prm b/examples/unresolved-cfd-dem/gas-solid-fluidized-bed/packing-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/gas-solid-fluidized-bed/dem-packing-in-fluidized-bed-generator.prm rename to examples/unresolved-cfd-dem/gas-solid-fluidized-bed/packing-particles.prm diff --git a/examples/unresolved-cfd-dem/gas-solid-spouted-bed/dem-packing-in-spouted-bed-generator.prm b/examples/unresolved-cfd-dem/gas-solid-spouted-bed/packing-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/gas-solid-spouted-bed/dem-packing-in-spouted-bed-generator.prm rename to examples/unresolved-cfd-dem/gas-solid-spouted-bed/packing-particles.prm diff --git a/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/dem-packing-in-spouted-cylinder-bed-generator.prm b/examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/packing-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/dem-packing-in-spouted-cylinder-bed-generator.prm rename to examples/unresolved-cfd-dem/gas-solid-spouted-cylinder-bed/packing-particles.prm diff --git a/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/dem-packing-in-lsfb-generator.prm b/examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/packing-particles.prm similarity index 100% rename from examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/dem-packing-in-lsfb-generator.prm rename to examples/unresolved-cfd-dem/liquid-solid-fluidized-bed/packing-particles.prm