tadd annotated example of two-grain collision - Granular.jl - Julia package for… | |
git clone git://src.adamsgaard.dk/Granular.jl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 5ccbb37be2b185a53876ef9dda6717b742ac6065 | |
parent 7efdade719720b948e6bbe625cdad7fd53566be5 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Tue, 7 Nov 2017 16:23:00 -0500 | |
add annotated example of two-grain collision | |
Diffstat: | |
M docs/src/man/getting_started.md | 89 +++++++++++++++++++++++++++++… | |
A examples/two-grains.jl | 41 +++++++++++++++++++++++++++++… | |
M src/simulation.jl | 9 ++++++--- | |
3 files changed, 131 insertions(+), 8 deletions(-) | |
--- | |
diff --git a/docs/src/man/getting_started.md b/docs/src/man/getting_started.md | |
t@@ -43,6 +43,7 @@ As the first command, we import all the Granular.jl function… | |
julia> import Granular | |
``` | |
+### Simulation setup | |
Next, we create our simulation object which holds all information on the | |
simulated grains. This object can be called whatever is appropriate. In this | |
documentation, we will use the name `sim`: | |
t@@ -64,6 +65,7 @@ During the above `createSimulation` call, the `id` argument … | |
used to name simulation output files that are written to the disk. It is good | |
practice to use the same name as used for the simulation script file. | |
+### Adding grains one by one | |
We have now created a simulation object, which will be used during all of the | |
following. Next, we add grains to this object. The first grain is cylinder | |
shaped, placed at the x-y position (0,0) m, has a radius of 0.1 m, and a | |
t@@ -111,6 +113,7 @@ julia> sim.grains[1].lin_vel = [1.0, 0.0] | |
The first grain (index 1 in `sim.grains`) now has a positive velocity along `x… | |
with the value of 1.0 meter per second. | |
+### Setting temporal parameters for the simulation | |
Before we can start the simulation, we need to tell the code vital information… | |
like what time step to use, how often to write output files to the disk, and | |
for how long to run the simulation. To set the computational time step, we | |
t@@ -137,11 +140,24 @@ julia> Granular.setOutputFileInterval!(sim, 0.05) | |
julia> Granular.setTotalTime!(sim, 1.0) | |
``` | |
-We are now ready to run the simulation. We have two choices; we can either | |
-run the entire simulation length with a single call, which steps time until th… | |
-total time is reached and generates output files along the way. Alternatively… | |
-we can run the simulation for a single time step a time, and inspect the | |
-progress or do other modifications along the way. | |
+### Running the simulation | |
+We are now ready to run the simulation. For illustrative purposes, let us | |
+compare the kinetic energy in the granular system before and after the | |
+collision. For now, we save the initial value using the following call: | |
+ | |
+```julia-repl | |
+julia> Granular.totalGrainKineticTranslationalEnergy(sim) | |
+0.7335618846132168 | |
+``` | |
+ | |
+The above value is the total translational (not angular) kinetic energy in | |
+Joules before the simulation is started. | |
+ | |
+For running the simulation, we have two choices; we can either run the entire | |
+simulation length with a single call, which steps time until the total time is | |
+reached and generates output files along the way. Alternatively, we can run | |
+the simulation for a single time step a time, and inspect the progress or do | |
+other modifications along the way. | |
Here, we will run the entire simulation in one go, and afterwards visualize th… | |
grains from their output files using ParaView. | |
t@@ -170,6 +186,69 @@ files are generated (this can be disabled by passing `ver… | |
`run!()` command). Finally, it tells us that it has generated a ParaView | |
python file for visualization. | |
+Before going further, we are interested in getting an immediate idea of how th… | |
+collision went. We print the new velocities with the following commands: | |
+```julia-repl | |
+julia> sim.grains[1].lin_vel | |
+2-element Array{Float64, 1}: | |
+ 7.58343e-5 | |
+ 0.0 | |
+ | |
+julia> sim.grains[2].lin_vel | |
+2-element Array{Float64, 1}: | |
+ 0.999924 | |
+ 0.0 | |
+``` | |
+ | |
+The first grain has transferred effectively all of its kinetic energy to the | |
+second grain during the cause of the simulation. The total kinetic energy now | |
+is the following: | |
+ | |
+```julia-repl | |
+julia> Granular.totalGrainKineticTranslationalEnergy(sim) | |
+0.7334506347624973 | |
+``` | |
+The before and after values are reasonably close (to less than 0.1 percent), | |
+which is what can be expected given the computation accuracy in the algorithm. | |
+ | |
+### Visualizing the output | |
+To visualize the output we open [ParaView](https://www.paraview.org). The | |
+output files of the simulation are written using the VTK (visualization | |
+toolkit) format, which is natively supported by ParaView. | |
+ | |
+While the `.vtu` files produced during the simulation can be opened with | |
+ParaView and visualized manually using *Glyph* filters, the simplest and | |
+fastest way to visualize the data is to use the Python script generated for th… | |
+simulation by Granular.jl. | |
+ | |
+Open ParaView and open the *Python Shell*, found under the menu *Tools > Pytho… | |
+Shell*. In the pop-up dialog we select *Run Script*, which opens yet another | |
+dialog prompting us to locate the visualization script (`two-grains.py`, in ou… | |
+example). We locate this file, which is placed under the directory from where | |
+we launched the `julia` session with the commands above. | |
+ | |
+After selecting the `two-grains/two-grains.py` script, we can close the *Pytho… | |
+Shell* window to inspect our simulation. Press the *Play* symbol in the top | |
+toolbar, and see what happens! | |
+ | |
+Alternatively, you can color the grains using different parameters, such as | |
+velocity, number of contacts, etc. These can be selected by changing the | |
+chosen parameter under the *Glyph1* object in the *Pipeline Browser* on the | |
+left, and selecting a different field for *Coloring*. Press the *Apply* butto… | |
+to see the changes in effect. | |
+ | |
+### Exercises | |
+To gain more familiarity with the simulation procedure, I suggest experimentin… | |
+with the following: | |
+ | |
+- What effect does the grain size have on the time step? | |
+- Try to make an oblique collision by placing one of the grains at a different | |
+ `y` position. | |
+- What happens if the second grains is set to be fixed in space | |
+ (`sim.grains[2].fixed = true`)? | |
+- How is the relationship between total kinetic energy before and after | |
+ affected by the choice of time step length? Try setting different time | |
+ step values, e.g. with `sim.time_step = 0.1234` and rerun the simulation. | |
diff --git a/examples/two-grains.jl b/examples/two-grains.jl | |
t@@ -0,0 +1,41 @@ | |
+#!/usr/bin/env julia | |
+import Granular | |
+ | |
+# Create the simulation object which, among other things, will hold all | |
+# imformation on the simulated grains. You can call this object whatever you | |
+# want, but in this documentation we will use the name `sim`. | |
+sim = Granular.createSimulation(id="two-grains") | |
+ | |
+ | |
+# Add a grain to the simulation object, having the position (0,0) in x-y space, | |
+# a radius of 0.1 m, and a thickness of 0.05 m. | |
+Granular.addGrainCylindrical!(sim, [0.0, 0.0], 0.1, 0.05) | |
+ | |
+# Add a second grain, placed further down +x. | |
+Granular.addGrainCylindrical!(sim, [0.5, 0.0], 0.1, 0.05) | |
+ | |
+# Set a velocity of 0.5 m/s along +x for the first grain, to make it bump into | |
+# the second grain. | |
+sim.grains[1].lin_vel = [1.0, 0.0] | |
+ | |
+# Before we can run the simulation, we need to specify the computational time | |
+# step, how often to produce output files for visualization, and for how long … | |
+# run the simulation in model time [s]: | |
+Granular.setTimeStep!(sim) | |
+Granular.setOutputFileInterval!(sim, 0.05) | |
+Granular.setTotalTime!(sim, 1.0) | |
+ | |
+# Let's save the total kinetic energy before the simulation: | |
+E_kin_before = Granular.totalGrainKineticTranslationalEnergy(sim) | |
+ | |
+# We can now run the simulation in a single call: | |
+Granular.run!(sim) | |
+ | |
+# The kinetic energy after: | |
+E_kin_after = Granular.totalGrainKineticTranslationalEnergy(sim) | |
+ | |
+# Report these values to console | |
+info("Kinetic energy before: $E_kin_before J") | |
+info("Kinetic energy after: $E_kin_after J") | |
+ | |
+ | |
diff --git a/src/simulation.jl b/src/simulation.jl | |
t@@ -14,10 +14,13 @@ export createSimulation | |
atmosphere::Atmosphere) | |
Create a simulation object containing all relevant variables such as temporal | |
-parameters, and lists of grains and contacts. | |
+parameters, and lists of grains and contacts. The parameter `id` is used to | |
+uniquely identify the simulation when it is written to disk. | |
+ | |
+# Arguments | |
+* `id::String="unnamed"`: | |
+ | |
-The parameter `id` is used to uniquely identify the simulation when it is | |
-written to disk. | |
""" | |
function createSimulation(;id::String="unnamed", | |
time_iteration::Int=0, |