commit f99ed0c1563094ca59a039ab144b9da3e76c1fed
parent b9af1feee431c70f1b40417dbf171db440188c50
Author: Anders Damsgaard <andersd@riseup.net>
Date: Tue, 14 Nov 2017 11:01:45 -0500
add dynamic walls in simulation object, dynamics still not implemented
Diffstat:
5 files changed, 195 insertions(+), 11 deletions(-)
diff --git a/src/datatypes.jl b/src/datatypes.jl
@@ -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
@@ -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
@@ -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",
@@ -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
@@ -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 simulation.
+ 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 to
+ 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 of
+`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
@@ -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
@@ -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
+