tadd dynamic walls in simulation object, dynamics still not implemented - Granu… | |
git clone git://src.adamsgaard.dk/Granular.jl | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit f99ed0c1563094ca59a039ab144b9da3e76c1fed | |
parent b9af1feee431c70f1b40417dbf171db440188c50 | |
Author: Anders Damsgaard <[email protected]> | |
Date: Tue, 14 Nov 2017 11:01:45 -0500 | |
add dynamic walls in simulation object, dynamics still not implemented | |
Diffstat: | |
M src/datatypes.jl | 14 ++++++++++++++ | |
M src/simulation.jl | 43 +++++++++++++++++++++++------… | |
A src/wall.jl | 122 +++++++++++++++++++++++++++++… | |
M test/runtests.jl | 1 + | |
A test/wall.jl | 26 ++++++++++++++++++++++++++ | |
5 files changed, 195 insertions(+), 11 deletions(-) | |
--- | |
diff --git a/src/datatypes.jl b/src/datatypes.jl | |
t@@ -70,6 +70,18 @@ mutable struct GrainCylindrical | |
atmosphere_stress::Vector{Float64} | |
end | |
+# Type for linear (flat) and frictionless dynamic walls | |
+mutable struct WallLinearFrictionless | |
+ normal::Vector{Float64} # Wall-face normal vector | |
+ pos::Float64 # Position along axis parallel to normal vector | |
+ bc::String # Boundary condition | |
+ mass::Float64 # Mass, used when bc != "fixed" | |
+ thickness::Float64 # Wall thickness | |
+ normal_stress::Float64 # Normal stress when bc == "normal stress" | |
+ vel::Float64 # Velocity (constant when bc == "normal stress") | |
+ force::Float64 # Sum of normal forces on wall | |
+end | |
+ | |
# Type for gathering data from grain objects into single arrays | |
mutable struct GrainArrays | |
t@@ -310,6 +322,8 @@ mutable struct Simulation | |
atmosphere::Atmosphere | |
Nc_max::Int | |
+ | |
+ walls::Vector{WallLinearFrictionless} | |
end | |
# Mappings between boundary condition keys (Integers) and strings | |
diff --git a/src/simulation.jl b/src/simulation.jl | |
t@@ -11,15 +11,16 @@ export createSimulation | |
file_number::Int=0, | |
grains=Array{GrainCylindrical, 1}[], | |
ocean::Ocean, | |
- atmosphere::Atmosphere) | |
+ atmosphere::Atmosphere, | |
+ Nc_max::Int=16]) | |
Create a simulation object containing all relevant variables such as temporal | |
-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"`: | |
+parameters, fluid grids, grains, and contacts. All arguments are optional. The | |
+most important parameter is `id`, which is used to uniquely identify the | |
+simulation when it is written to disk. | |
+# Optional arguments | |
+* `id::String="unnamed"`: simulation identifying string. | |
""" | |
function createSimulation(;id::String="unnamed", | |
t@@ -201,19 +202,39 @@ end | |
export addGrain! | |
""" | |
addGrain!(simulation::Simulation, | |
- grain::GrainCylindrical, | |
- verbose::Bool = False) | |
+ grain::GrainCylindrical, | |
+ verbose::Bool = false) | |
Add an `grain` to the `simulation` object. If `verbose` is true, a short | |
confirmation message will be printed to stdout. | |
""" | |
function addGrain!(simulation::Simulation, | |
- grain::GrainCylindrical, | |
- verbose::Bool = False) | |
+ grain::GrainCylindrical, | |
+ verbose::Bool = false) | |
push!(simulation.grains, grain) | |
if verbose | |
- info("Added Grain $(length(simulation.grains))") | |
+ info("Added grain $(length(simulation.grains))") | |
+ end | |
+ nothing | |
+end | |
+ | |
+export addWall! | |
+""" | |
+ addWall!(simulation::Simulation, | |
+ wall::WallLinearFrictionless, | |
+ verbose::Bool = false) | |
+ | |
+Add an `wall` to the `simulation` object. If `verbose` is true, a short | |
+confirmation message will be printed to stdout. | |
+""" | |
+function addWall!(simulation::Simulation, | |
+ grain::WallLinearFrictionless, | |
+ verbose::Bool = false) | |
+ push!(simulation.walls, wall) | |
+ | |
+ if verbose | |
+ info("Added wall $(length(simulation.walls))") | |
end | |
nothing | |
end | |
diff --git a/src/wall.jl b/src/wall.jl | |
t@@ -0,0 +1,122 @@ | |
+## Manage dynamic walls in the model | |
+ | |
+export addWallLinearFrictionless! | |
+""" | |
+ function addWallLinear!(simulation, normal, pos[, bc, mass, thickness, | |
+ normal_stress, vel, force, verbose]) | |
+ | |
+Creates and adds a linear (flat) and frictionless dynamic wall to a grain to a | |
+simulation. Most of the arguments are optional, and come with default values. | |
+The only required arguments are | |
+`simulation`, `normal`, `pos`, and `bc`. | |
+ | |
+# Arguments | |
+* `simulation::Simulation`: the simulation object where the wall should be | |
+ added to. | |
+* `normal::Vector{Float64}`: 2d vector denoting the normal to the wall [m]. | |
+* `pos::Float64`: position along axis parallel to the normal vector [m]. | |
+* `bc::String="fixed"`: boundary condition, possible values are `"fixed"` | |
+ (default), `"normal stress"`, or `"velocity"`. | |
+* `mass::Float64=NaN`: wall mass, which is used if wall boundary conditions | |
+ differs from `bc="fixed"`. If the parameter is left to its default value, | |
+ the wall mass is set to be equal the total mass of grains in the simulatio… | |
+ Units: [kg] | |
+* `thickness::Float64=NaN`: wall thickness, which is used for determining wall | |
+ surface area. If the parameter is left to its default value, the wall | |
+ thickness is set to be equal to the thickest grain in the simulation. | |
+ Units: [m]. | |
+* `normal_stress::Float64=0.`: the wall normal stress when `bc == "normal | |
+ stress"` [Pa]. | |
+* `vel::Float64=0.`: the wall velocity along the `normal` vector. If the | |
+ wall boundary condition is `bc = "velocity"` the wall will move according … | |
+ this constant value. If `bc = "normal stress"` the velocity will be a free | |
+ parameter. Units: [m/s] | |
+* `force::Float64=0.`: sum of normal forces on the wall from interaction with | |
+ grains [N]. | |
+* `verbose::Bool=true`: show verbose information during function call. | |
+ | |
+# Examples | |
+The most basic example adds a new fixed wall to the simulation `sim`, with a | |
+wall-face normal of `[1., 0.]` (wall along *y* and normal to *x*), a position … | |
+`1.5` meter: | |
+ | |
+```julia | |
+Granular.addWallLinearFrictionless!(sim, [1., 0.], 1.5) | |
+``` | |
+ | |
+The following example creates a wall with a velocity of 0.5 m/s towards *-y*: | |
+ | |
+```julia | |
+Granular.addWallLinearFrictionless!(sim, [0., 1.], 1.5, | |
+ bc="velocity", | |
+ vel=-0.5) | |
+``` | |
+ | |
+To create a wall parallel to the *x* axis with a constant normal stress of 100 | |
+kPa: | |
+ | |
+```julia | |
+Granular.addWallLinearFrictionless!(sim, [1., 0.], 3.5, | |
+ bc="normal stress", | |
+ normal_stress=100e3) | |
+``` | |
+""" | |
+function addWallLinearFrictionless!(simulation::Simulation, | |
+ normal::Vector{Float64}, | |
+ pos::Float64; | |
+ bc::String = "fixed", | |
+ mass::Float64 = NaN, | |
+ thickness::Float64 = NaN, | |
+ normal_stress::Float64 = 0., | |
+ vel::Float64 = 0., | |
+ force::Float64 = 0., | |
+ verbose::Boolw=true) | |
+ | |
+ # Check input values | |
+ if length(normal) != 2 | |
+ error("Wall normal must be a two-element array (normal = ", | |
+ "$normal)") | |
+ end | |
+ | |
+ if !(normal ≈ [1., 0.]) || !(normal ≈ [0., 1.]) | |
+ error("Currently only walls with normals orthogonal to the " * | |
+ "coordinate system are allowed, i.e. normals parallel to the " * | |
+ "x or y axes. Accepted values for `normal` " * | |
+ "are [1., 0.] and [0., 1.]") | |
+ end | |
+ | |
+ # if not set, set wall mass to equal the mass of all grains. | |
+ if isnan(mass) | |
+ mass = 0. | |
+ for grain in sim.grains | |
+ mass += grain.mass | |
+ end | |
+ info("Setting wall mass to total grain mass: $mass kg") | |
+ end | |
+ | |
+ # if not set, set wall thickness to equal largest grain thickness | |
+ if isnan(thickness) | |
+ thickness = -Inf | |
+ for grain in sim.grains | |
+ if grain.thickess > thickness | |
+ thickness = grain.thickness | |
+ end | |
+ end | |
+ info("Setting wall thickness to largest grain thickness: $thickness m") | |
+ end | |
+ | |
+ # Create wall object | |
+ wall = WallLinearFrictionless(normal, | |
+ pos, | |
+ bc, | |
+ mass, | |
+ thickness, | |
+ normal_stress, | |
+ vel, | |
+ force) | |
+ | |
+ # Add to simulation object | |
+ addWall!(simulation, wall, verbose) | |
+ nothing | |
+end | |
+ | |
diff --git a/test/runtests.jl b/test/runtests.jl | |
t@@ -2,6 +2,7 @@ using Compat.Test | |
import Granular | |
include("grain.jl") | |
+include("wall.jl") | |
include("packing.jl") | |
include("util.jl") | |
include("temporal.jl") | |
diff --git a/test/wall.jl b/test/wall.jl | |
t@@ -0,0 +1,26 @@ | |
+#!/usr/bin/env julia | |
+ | |
+# Check the basic dynamic wall functionality | |
+ | |
+info("#### $(basename(@__FILE__)) ####") | |
+ | |
+sim = Granular.createSimulation(id="test") | |
+info("Testing grain value checks ") | |
+@test_throws ErrorException Granular.addWallLinearFrictionless!(sim, | |
+ [.1, .1, .1], | |
+ 1.) | |
+@test_throws ErrorException Granular.addWallLinearFrictionless!(sim, | |
+ [1., 1.], | |
+ 1.) | |
+ | |
+ | |
+info("Check that wall mass equals total grain mass and max. thickness") | |
+sim = Granular.createSimulation(id="test") | |
+@test length(sim.walls) == 0 | |
+Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 2., verbose=false) | |
+sim.grains[1].mass = 1.0 | |
+Granular.addWallLinearFrictionless!(sim, [1., 0.], 1., verbose=true) | |
+@test length(sim.walls) == 1 | |
+@test sim.walls.mass ≈ 1.0 | |
+@test sim.walls.mass ≈ 2.0 | |
+ |