Granular.jl

Julia package for granular dynamics simulation
git clone git://src.adamsgaard.dk/Granular.jl
Log | Files | Refs | README | LICENSE

commit 92fd072d14948ea81f129829e3558af53834e22c
parent 77288c0e7ced17146a3ad9c393a06eb4ebd5f501
Author: Anders Damsgaard <andersd@riseup.net>
Date:   Wed,  1 Nov 2017 13:48:52 -0400

rename repository and package to Granular.jl

The motivation is to uphold the general applicability of this package,
and open the possibility of prospective inclusion in the Julia package
repository.  Ice floes are in the code and documentation now referred to
as grains.  As Github still mirrors anders-dc/Granular.jl to
anders-dc/SeaIce.jl, I keep the previous urls for travis-CI, appveyor,
and codecov.

Diffstat:
M.travis.yml | 4++--
MREADME.md | 22+++++++++++-----------
Mdocs/make.jl | 8++++----
Mdocs/src/lib/internals.md | 6+++---
Mdocs/src/lib/public.md | 4++--
Mdocs/src/man/installation.md | 10+++++-----
Mexamples/image.jl | 26+++++++++++++-------------
Mexamples/logo.jl | 76++++++++++++++++++++++++++++++++++++++--------------------------------------
Agranular-status.sh | 14++++++++++++++
Aparaview_filters/GrainFilter.cpd | 200+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aparaview_filters/GranularInteractionFilter.cpd | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dparaview_filters/SeaIceGranularInteractionParaviewFilter.cpd | 82-------------------------------------------------------------------------------
Dparaview_filters/SeaIceParaviewFilter.cpd | 200-------------------------------------------------------------------------------
Dseaice-status.sh | 14--------------
Asrc/Granular.jl | 23+++++++++++++++++++++++
Dsrc/SeaIce.jl | 23-----------------------
Msrc/atmosphere.jl | 58+++++++++++++++++++++++++++++-----------------------------
Msrc/contact_search.jl | 94++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/datatypes.jl | 16++++++++--------
Asrc/grain.jl | 729+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/grid.jl | 76++++++++++++++++++++++++++++++++++++++--------------------------------------
Dsrc/icefloe.jl | 729-------------------------------------------------------------------------------
Msrc/interaction.jl | 124++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/io.jl | 148++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/ocean.jl | 60++++++++++++++++++++++++++++++------------------------------
Msrc/packing.jl | 24++++++++++++------------
Msrc/simulation.jl | 64++++++++++++++++++++++++++++++++--------------------------------
Msrc/temporal.jl | 42+++++++++++++++++++++---------------------
Msrc/temporal_integration.jl | 104++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/atmosphere.jl | 146++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/cohesion.jl | 46+++++++++++++++++++++++-----------------------
Mtest/collision-2floes-normal.jl | 150++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/collision-2floes-oblique.jl | 578+++++++++++++++++++++++++++++++++++++++---------------------------------------
Mtest/collision-5floes-normal.jl | 234++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/contact-search-and-geometry.jl | 284++++++++++++++++++++++++++++++++++++++++----------------------------------------
Atest/grain.jl | 44++++++++++++++++++++++++++++++++++++++++++++
Mtest/grid.jl | 370++++++++++++++++++++++++++++++++++++++++----------------------------------------
Dtest/icefloe.jl | 44--------------------------------------------
Mtest/jld.jl | 18+++++++++---------
Mtest/memory-management.jl | 162++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/netcdf.jl | 18+++++++++---------
Mtest/ocean.jl | 136++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mtest/profiling.jl | 46+++++++++++++++++++++++-----------------------
Mtest/runtests.jl | 4++--
Mtest/temporal.jl | 32++++++++++++++++----------------
Mtest/util.jl | 32++++++++++++++++----------------
Mtest/vtk.jl | 62+++++++++++++++++++++++++++++++-------------------------------
47 files changed, 2734 insertions(+), 2734 deletions(-)

diff --git a/.travis.yml b/.travis.yml @@ -25,10 +25,10 @@ before_script: after_success: - julia -e 'Pkg.add("Documenter")' - - julia -e 'cd(Pkg.dir("SeaIce")); include(joinpath("docs", "make.jl"))' + - julia -e 'cd(Pkg.dir("Granular")); include(joinpath("docs", "make.jl"))' deploy: - provider: script - script: julia -e 'cd(Pkg.dir("SeaIce")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' + script: julia -e 'cd(Pkg.dir("Granular")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' on: os: linux diff --git a/README.md b/README.md @@ -1,39 +1,39 @@ -# SeaIce +# Granular -![SeaIce.jl -logo](https://github.com/anders-dc/SeaIce.jl/raw/master/docs/src/assets/logo.gif) +![Granular.jl +logo](https://github.com/anders-dc/Granular.jl/raw/master/docs/src/assets/logo.gif) -A [Julia](https://julialang.org) package for sea-ice granular mechanics. +A [Julia](https://julialang.org) package for granular mechanics. | Documentation | Build Status (Linux/Mac) | Build Status (Win) | Test Coverage | |:-------------:|:------------------------:|:------------------:|:-------------:| -|[![Seaice.jl Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://anders-dc.github.io/SeaIce.jl/latest) | [![Build Status](https://travis-ci.org/anders-dc/SeaIce.jl.svg?branch=master)](https://travis-ci.org/anders-dc/SeaIce.jl) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/anders-dc/SeaIce.jl?svg=true)](https://ci.appveyor.com/project/anders-dc/seaice-jl/) | [![codecov.io](http://codecov.io/github/anders-dc/SeaIce.jl/coverage.svg?branch=master)](http://codecov.io/github/anders-dc/SeaIce.jl?branch=master) | +|[![Granular.jl Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://anders-dc.github.io/Granular.jl/latest) | [![Build Status](https://travis-ci.org/anders-dc/SeaIce.jl.svg?branch=master)](https://travis-ci.org/anders-dc/SeaIce.jl) | [![Build Status](https://ci.appveyor.com/api/projects/status/github/anders-dc/SeaIce.jl?svg=true)](https://ci.appveyor.com/project/anders-dc/seaice-jl/) | [![codecov.io](http://codecov.io/github/anders-dc/SeaIce.jl/coverage.svg?branch=master)](http://codecov.io/github/anders-dc/SeaIce.jl?branch=master) | ## Installation -[SeaIce.jl](https://github.com/anders-dc/SeaIce.jl) is in heavy development and +[Granular.jl](https://github.com/anders-dc/Granular.jl) is in heavy development and not yet ready for third-party use. If you know better install it directly from the Julia shell by: ```julia -julia> Pkg.clone("git://github.com/anders-dc/SeaIce.jl.git") +julia> Pkg.clone("git://github.com/anders-dc/Granular.jl") ``` This will install the contents of this repository in the folder -`~/.julia/v$(JULIA_VERSION)/SeaIce`, and install the packages specified as +`~/.julia/v$(JULIA_VERSION)/Granular`, and install the packages specified as [requirements](REQUIRE). You can run the package tests, which are contained in the [test/ directory](test/), with the following command: ```julia -julia> Pkg.test("SeaIce") +julia> Pkg.test("Granular") ``` The package can be updated from this repository using: ```julia -julia> Pkg.update("SeaIce") +julia> Pkg.update("Granular") ``` -For more information on installation and usage, please refer to the [documentation](https://anders-dc.github.io/SeaIce.jl/latest). +For more information on installation and usage, please refer to the [documentation](https://anders-dc.github.io/Granular.jl/latest). ## Author [Anders Damsgaard](https://adamsgaard.dk), Geophysical Fluid Dynamics Laboratory, Princeton University. diff --git a/docs/make.jl b/docs/make.jl @@ -1,10 +1,10 @@ -using Documenter, SeaIce +using Documenter, Granular makedocs( - modules = [SeaIce], + modules = [Granular], clean = false, format = :html, - sitename = "SeaIce.jl", + sitename = "Granular.jl", authors = "Anders Damsgaard", pages = Any[ # Compat: `Any` for 0.4 compat "Home" => "index.md", @@ -22,7 +22,7 @@ makedocs( ) deploydocs( - repo = "github.com/anders-dc/SeaIce.jl.git", + repo = "github.com/anders-dc/Granular.jl.git", julia = "0.6", deps = nothing, make = nothing, diff --git a/docs/src/lib/internals.md b/docs/src/lib/internals.md @@ -1,6 +1,6 @@ # Package-internal documentation -This page lists all the documented internals of the `SeaIce` module. +This page lists all the documented internals of the `Granular` module. ## Index A list of all internal documentation sorted by module. @@ -11,7 +11,7 @@ Pages = ["internals.md"] ## Internal Interface ```@autodocs -Modules = [SeaIce] +Modules = [Granular] Public = false Private = true -``` +a`` diff --git a/docs/src/lib/public.md b/docs/src/lib/public.md @@ -1,6 +1,6 @@ # Public API documentation -Documentation for `SeaIce.jl`'s public interface. +Documentation for `Granular.jl`'s public interface. See [Package-internal documentation](@ref) for internal package docs. @@ -11,7 +11,7 @@ Pages = ["public.md"] ## Public Interface ```@autodocs -Modules = [SeaIce] +Modules = [Granular] Public = true Private = false ``` diff --git a/docs/src/man/installation.md b/docs/src/man/installation.md @@ -1,12 +1,12 @@ # Installation -SeaIce.jl can be installed directly from the Julia shell by: +Granular.jl can be installed directly from the Julia shell by: ```julia-repl -julia> Pkg.clone("git://github.com/anders-dc/SeaIce.jl.git") +julia> Pkg.clone("git://github.com/anders-dc/Granular.jl.git") ``` This will install the contents of this repository in the folder -`~/.julia/v$(JULIA_VERSION)/SeaIce` and install its requirements. The package [JLD](https://github.com/JuliaIO/JLD.jl) +`~/.julia/v$(JULIA_VERSION)/Granular` and install its requirements. The package [JLD](https://github.com/JuliaIO/JLD.jl) is used for model restarts and is recommended but not required, and is thus not automatically installed. @@ -14,11 +14,11 @@ You can run the package tests, which are contained in the `test/` directory, wit the following command: ```julia-repl -julia> Pkg.test("SeaIce") +julia> Pkg.test("Granular") ``` The package can be updated from this repository using: ```julia-repl -julia> Pkg.update("SeaIce") +julia> Pkg.update("Granular") ``` diff --git a/examples/image.jl b/examples/image.jl @@ -1,6 +1,6 @@ #!/usr/bin/env julia -import SeaIce +import Granular import FileIO import Colors @@ -41,7 +41,7 @@ const youngs_modulus = 2e7 const tensile_strength = 0e3 const h = .5 -sim = SeaIce.createSimulation(id="image") +sim = Granular.createSimulation(id="image") info("nx = $nx, ny = $ny") @@ -56,7 +56,7 @@ for iy=1:size(img_bw, 1) r = .5*dx*((1. - Float64(img_bw[iy, ix]))) if r > .1*dx - SeaIce.addIceFloeCylindrical!(sim, [x + dx, y - dy], r, h, + Granular.addGrainCylindrical!(sim, [x + dx, y - dy], r, h, tensile_strength=tensile_strength, youngs_modulus=youngs_modulus, verbose=verbose) @@ -65,7 +65,7 @@ for iy=1:size(img_bw, 1) end # set ocean forcing -sim.ocean = SeaIce.createRegularOceanGrid([nx, ny, 1], [Lx, Ly, 1.], +sim.ocean = Granular.createRegularOceanGrid([nx, ny, 1], [Lx, Ly, 1.], name="image_ocean") if forcing == "gyres" @@ -108,30 +108,30 @@ r = dx/4. ## N-S wall segments for y in linspace(r, Ly-r, Int(round((Ly - 2.*r)/(r*2)))) - SeaIce.addIceFloeCylindrical!(sim, [r, y], r, h, fixed=true, + Granular.addGrainCylindrical!(sim, [r, y], r, h, fixed=true, youngs_modulus=youngs_modulus, verbose=false) - SeaIce.addIceFloeCylindrical!(sim, [Lx-r, y], r, h, fixed=true, + Granular.addGrainCylindrical!(sim, [Lx-r, y], r, h, fixed=true, youngs_modulus=youngs_modulus, verbose=false) end ## E-W wall segments for x in linspace(3.*r, Lx-3.*r, Int(round((Lx - 6.*r)/(r*2)))) - SeaIce.addIceFloeCylindrical!(sim, [x, r], r, h, fixed=true, + Granular.addGrainCylindrical!(sim, [x, r], r, h, fixed=true, youngs_modulus=youngs_modulus, verbose=false) - SeaIce.addIceFloeCylindrical!(sim, [x, Ly-r], r, h, fixed=true, + Granular.addGrainCylindrical!(sim, [x, Ly-r], r, h, fixed=true, youngs_modulus=youngs_modulus, verbose=false) end # Finalize setup and start simulation -SeaIce.setTimeStep!(sim, verbose=verbose) +Granular.setTimeStep!(sim, verbose=verbose) -SeaIce.setTotalTime!(sim, 5.) -SeaIce.setOutputFileInterval!(sim, .1) +Granular.setTotalTime!(sim, 5.) +Granular.setOutputFileInterval!(sim, .1) -SeaIce.removeSimulationFiles(sim) -SeaIce.run!(sim, verbose=verbose) +Granular.removeSimulationFiles(sim) +Granular.run!(sim, verbose=verbose) diff --git a/examples/logo.jl b/examples/logo.jl @@ -1,10 +1,10 @@ #!/usr/bin/env julia -import SeaIce +import Granular const verbose = true -const text = "SeaIce.jl" +const text = "Granular.jl" const forcing = "gyres" #const forcing = "down" @@ -12,17 +12,17 @@ const forcing = "gyres" # Font created with `figlet` and the font 'pebbles'. If figlet is not installed # on your system, use the string below: -#logo_string = -#""".oOOOo. ooOoOOo o -#o o O O O -#O. o o -# `OOoo. O O -# `O .oOo. .oOoO' o .oOo .oOo. 'o o -# o OooO' O o O O OooO' O O -#O. .O O o O O o O oO o o -# `oooO' `OoO' `OoO'o ooOOoOo `OoO' `OoO' Oo O Oo -# o -# oO' """ +#logo_string = +#""" .oOOOo. o o +#.O o O O O +#o o o +#O O O +#O .oOOo `OoOo. .oOoO' 'OoOo. O o o .oOoO' `OoOo. 'o o +#o. O o O o o O o O O O o o O O +# O. oO O o O O o O o o o O O oO o o +# `OooO' o `OoO'o o O `OoO'o Oo `OoO'o o Oo O Oo +# o +# oO' """ logo_string = readstring(`figlet -f pebbles "$text"`) @@ -50,7 +50,7 @@ c = ' ' h = .5 const youngs_modulus = 2e6 -sim = SeaIce.createSimulation(id="logo") +sim = Granular.createSimulation(id="logo") print(logo_string) info("nx = $nx, ny = $ny") @@ -85,18 +85,18 @@ for iy=1:length(logo_string_split) end if r > 0. - SeaIce.addIceFloeCylindrical!(sim, [x + dx, y - dy], r, h, - tensile_strength=200e3, - youngs_modulus=youngs_modulus, - verbose=verbose) + Granular.addGrainCylindrical!(sim, [x + dx, y - dy], r, h, + tensile_strength=200e3, + youngs_modulus=youngs_modulus, + verbose=verbose) end r = -1. end end # set ocean forcing -sim.ocean = SeaIce.createRegularOceanGrid([nx, ny, 1], [Lx, Ly, 1.], - name="logo_ocean") +sim.ocean = Granular.createRegularOceanGrid([nx, ny, 1], [Lx, Ly, 1.], +name="logo_ocean") if forcing == "gyres" epsilon = 0.25 # amplitude of periodic oscillations @@ -138,32 +138,32 @@ r = dx/4. ## N-S wall segments for y in linspace(r, Ly-r, Int(round((Ly - 2.*r)/(r*2)))) - SeaIce.addIceFloeCylindrical!(sim, [r, y], r, h, fixed=true, - youngs_modulus=youngs_modulus, - verbose=false) - SeaIce.addIceFloeCylindrical!(sim, [Lx-r, y], r, h, fixed=true, - youngs_modulus=youngs_modulus, - verbose=false) + Granular.addGrainCylindrical!(sim, [r, y], r, h, fixed=true, + youngs_modulus=youngs_modulus, + verbose=false) + Granular.addGrainCylindrical!(sim, [Lx-r, y], r, h, fixed=true, + youngs_modulus=youngs_modulus, + verbose=false) end ## E-W wall segments for x in linspace(3.*r, Lx-3.*r, Int(round((Lx - 6.*r)/(r*2)))) - SeaIce.addIceFloeCylindrical!(sim, [x, r], r, h, fixed=true, - youngs_modulus=youngs_modulus, - verbose=false) - SeaIce.addIceFloeCylindrical!(sim, [x, Ly-r], r, h, fixed=true, - youngs_modulus=youngs_modulus, - verbose=false) + Granular.addGrainCylindrical!(sim, [x, r], r, h, fixed=true, + youngs_modulus=youngs_modulus, + verbose=false) + Granular.addGrainCylindrical!(sim, [x, Ly-r], r, h, fixed=true, + youngs_modulus=youngs_modulus, + verbose=false) end # Finalize setup and start simulation -SeaIce.setTimeStep!(sim, verbose=verbose) +Granular.setTimeStep!(sim, verbose=verbose) -SeaIce.setTotalTime!(sim, 5.) -SeaIce.setOutputFileInterval!(sim, .1) +Granular.setTotalTime!(sim, 5.) +Granular.setOutputFileInterval!(sim, .1) -SeaIce.removeSimulationFiles(sim) -SeaIce.run!(sim, verbose=verbose) +Granular.removeSimulationFiles(sim) +Granular.run!(sim, verbose=verbose) -SeaIce.render(sim, images=true, animation=false) +Granular.render(sim, images=true, animation=false) diff --git a/granular-status.sh b/granular-status.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Status script which traverses the subdirectories of the current folder for +# simulations. You may want to add this to your shell's PATH variable. + +set -e +cmd_sing='julia --color=yes -e "import Granular; Granular.status()"' +cmd_loop='julia --color=yes -e "import Granular; Granular.status(loop=true, t_int=10)"' + +if [[ "$1" == "loop" ]]; then + eval $cmd_loop +else + eval $cmd_sing +fi diff --git a/paraview_filters/GrainFilter.cpd b/paraview_filters/GrainFilter.cpd @@ -0,0 +1,200 @@ +<CustomFilterDefinitions> + <CustomProxyDefinition name="Granular" group="filters"> + <CompoundSourceProxy id="6702" servers="1"> + <Proxy group="filters" type="Glyph" id="6613" servers="1" compound_name="Glyph1"> + <Property name="GlyphMode" id="6613.GlyphMode" number_of_elements="1"> + <Element index="0" value="0"/> + <Domain name="enum" id="6613.GlyphMode.enum"> + <Entry value="0" text="All Points"/> + <Entry value="1" text="Every Nth Point"/> + <Entry value="2" text="Uniform Spatial Distribution"/> + </Domain> + </Property> + <Property name="GlyphTransform" id="6613.GlyphTransform" number_of_elements="1"> + <Proxy value="6535"/> + <Domain name="proxy_list" id="6613.GlyphTransform.proxy_list"> + <Proxy value="6535"/> + </Domain> + </Property> + <Property name="Input" id="6613.Input" number_of_elements="1"> + <Domain name="groups" id="6613.Input.groups"/> + <Domain name="input_array1" id="6613.Input.input_array1"/> + <Domain name="input_array2" id="6613.Input.input_array2"/> + <Domain name="input_type" id="6613.Input.input_type"/> + </Property> + <Property name="MaximumNumberOfSamplePoints" id="6613.MaximumNumberOfSamplePoints" number_of_elements="1"> + <Element index="0" value="5000"/> + <Domain name="range" id="6613.MaximumNumberOfSamplePoints.range"/> + </Property> + <Property name="Orient" id="6613.Orient" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="bool" id="6613.Orient.bool"/> + </Property> + <Property name="Scalars" id="6613.Scalars" number_of_elements="5"> + <Element index="0" value=""/> + <Element index="1" value=""/> + <Element index="2" value=""/> + <Element index="3" value="0"/> + <Element index="4" value="Diameter (areal) [m]"/> + <Domain name="array_list" id="6613.Scalars.array_list"> + <String text="Contact friction (dynamic) [-]"/> + <String text="Contact friction (static) [-]"/> + <String text="Contact stiffness (normal) [N m^-1]"/> + <String text="Contact stiffness (tangential) [N m^-1]"/> + <String text="Contact viscosity (normal) [N m^-1 s]"/> + <String text="Contact viscosity (tangential) [N m^-1 s]"/> + <String text="Density [kg m^-3]"/> + <String text="Diameter (areal) [m]"/> + <String text="Diameter (contact) [m]"/> + <String text="Fixed in space [-]"/> + <String text="Free to rotate [-]"/> + <String text="Mass [kg]"/> + <String text="Moment of inertia [kg m^2]"/> + <String text="Surface area [m^2]"/> + <String text="Thickness [m]"/> + <String text="Volume [m^3]"/> + </Domain> + </Property> + <Property name="ScaleFactor" id="6613.ScaleFactor" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="bounds" id="6613.ScaleFactor.bounds"/> + <Domain name="scalar_range" id="6613.ScaleFactor.scalar_range"/> + <Domain name="vector_range" id="6613.ScaleFactor.vector_range"/> + </Property> + <Property name="ScaleMode" id="6613.ScaleMode" number_of_elements="1"> + <Element index="0" value="0"/> + <Domain name="enum" id="6613.ScaleMode.enum"> + <Entry value="0" text="scalar"/> + <Entry value="1" text="vector"/> + <Entry value="2" text="vector_components"/> + <Entry value="3" text="off"/> + </Domain> + </Property> + <Property name="Seed" id="6613.Seed" number_of_elements="1"> + <Element index="0" value="10339"/> + <Domain name="range" id="6613.Seed.range"/> + </Property> + <Property name="Source" id="6613.Source" number_of_elements="1"> + <Proxy value="6591" output_port="0"/> + <Domain name="groups" id="6613.Source.groups"/> + <Domain name="input_type" id="6613.Source.input_type"/> + <Domain name="proxy_list" id="6613.Source.proxy_list"> + <Proxy value="6536"/> + <Proxy value="6547"/> + <Proxy value="6558"/> + <Proxy value="6569"/> + <Proxy value="6580"/> + <Proxy value="6591"/> + <Proxy value="6602"/> + </Domain> + </Property> + <Property name="Stride" id="6613.Stride" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="range" id="6613.Stride.range"/> + </Property> + <Property name="Vectors" id="6613.Vectors" number_of_elements="5"> + <Element index="0" value="1"/> + <Element index="1" value=""/> + <Element index="2" value=""/> + <Element index="3" value="0"/> + <Element index="4" value="Angular position [rad]"/> + <Domain name="array_list" id="6613.Vectors.array_list"> + <String text="Angular acceleration [rad s^-2]"/> + <String text="Angular position [rad]"/> + <String text="Angular velocity [rad s^-1]"/> + <String text="Linear acceleration [m s^-2]"/> + <String text="Linear velocity [m s^-1]"/> + <String text="Sum of forces [N]"/> + <String text="Sum of torques [N*m]"/> + </Domain> + </Property> + </Proxy> + <Proxy group="extended_sources" type="Transform2" id="6535" servers="1" compound_name="auto_6535"> + <Property name="Position" id="6535.Position" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="0"/> + <Domain name="range" id="6535.Position.range"/> + </Property> + <Property name="PositionInfo" id="6535.PositionInfo" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="0"/> + </Property> + <Property name="Rotation" id="6535.Rotation" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="0"/> + <Domain name="range" id="6535.Rotation.range"/> + </Property> + <Property name="RotationInfo" id="6535.RotationInfo" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="0"/> + </Property> + <Property name="Scale" id="6535.Scale" number_of_elements="3"> + <Element index="0" value="1"/> + <Element index="1" value="1"/> + <Element index="2" value="1"/> + <Domain name="range" id="6535.Scale.range"/> + </Property> + <Property name="ScaleInfo" id="6535.ScaleInfo" number_of_elements="3"> + <Element index="0" value="1"/> + <Element index="1" value="1"/> + <Element index="2" value="1"/> + </Property> + </Proxy> + <Proxy group="sources" type="SphereSource" id="6591" servers="1" compound_name="auto_6591"> + <Property name="Center" id="6591.Center" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="0"/> + <Domain name="range" id="6591.Center.range"/> + </Property> + <Property name="EndPhi" id="6591.EndPhi" number_of_elements="1"> + <Element index="0" value="180"/> + <Domain name="range" id="6591.EndPhi.range"/> + </Property> + <Property name="EndTheta" id="6591.EndTheta" number_of_elements="1"> + <Element index="0" value="360"/> + <Domain name="range" id="6591.EndTheta.range"/> + </Property> + <Property name="PhiResolution" id="6591.PhiResolution" number_of_elements="1"> + <Element index="0" value="8"/> + <Domain name="range" id="6591.PhiResolution.range"/> + </Property> + <Property name="Radius" id="6591.Radius" number_of_elements="1"> + <Element index="0" value="0.5"/> + <Domain name="range" id="6591.Radius.range"/> + </Property> + <Property name="StartPhi" id="6591.StartPhi" number_of_elements="1"> + <Element index="0" value="0"/> + <Domain name="range" id="6591.StartPhi.range"/> + </Property> + <Property name="StartTheta" id="6591.StartTheta" number_of_elements="1"> + <Element index="0" value="0"/> + <Domain name="range" id="6591.StartTheta.range"/> + </Property> + <Property name="ThetaResolution" id="6591.ThetaResolution" number_of_elements="1"> + <Element index="0" value="8"/> + <Domain name="range" id="6591.ThetaResolution.range"/> + </Property> + </Proxy> + <ExposedProperties> + <Property name="GlyphMode" proxy_name="Glyph1" exposed_name="Glyph Mode"/> + <Property name="GlyphTransform" proxy_name="Glyph1" exposed_name="Glyph Transform"/> + <Property name="Input" proxy_name="Glyph1" exposed_name="Input"/> + <Property name="MaximumNumberOfSamplePoints" proxy_name="Glyph1" exposed_name="Maximum Number Of Sample Points"/> + <Property name="Orient" proxy_name="Glyph1" exposed_name="Orient"/> + <Property name="Scalars" proxy_name="Glyph1" exposed_name="Scalars"/> + <Property name="ScaleFactor" proxy_name="Glyph1" exposed_name="Scale Factor"/> + <Property name="ScaleMode" proxy_name="Glyph1" exposed_name="Scale Mode"/> + <Property name="Vectors" proxy_name="Glyph1" exposed_name="Vectors"/> + </ExposedProperties> + <OutputPort name="Output" proxy="Glyph1" port_index="0"/> + <Hints> + <ShowInMenu/> + </Hints> + </CompoundSourceProxy> + </CustomProxyDefinition> +</CustomFilterDefinitions> diff --git a/paraview_filters/GranularInteractionFilter.cpd b/paraview_filters/GranularInteractionFilter.cpd @@ -0,0 +1,82 @@ +<CustomFilterDefinitions> + <CustomProxyDefinition name="GranularInteraction" group="filters"> + <CompoundSourceProxy id="6731" servers="1"> + <Proxy group="filters" type="TubeFilter" id="6634" servers="1" compound_name="Tube1"> + <Property name="Capping" id="6634.Capping" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="bool" id="6634.Capping.bool"/> + </Property> + <Property name="DefaultNormal" id="6634.DefaultNormal" number_of_elements="3"> + <Element index="0" value="0"/> + <Element index="1" value="0"/> + <Element index="2" value="1"/> + <Domain name="range" id="6634.DefaultNormal.range"/> + </Property> + <Property name="Input" id="6634.Input" number_of_elements="1"> + <Domain name="groups" id="6634.Input.groups"/> + <Domain name="input_array1" id="6634.Input.input_array1"/> + <Domain name="input_array2" id="6634.Input.input_array2"/> + <Domain name="input_type" id="6634.Input.input_type"/> + </Property> + <Property name="NumberOfSides" id="6634.NumberOfSides" number_of_elements="1"> + <Element index="0" value="6"/> + <Domain name="range" id="6634.NumberOfSides.range"/> + </Property> + <Property name="Radius" id="6634.Radius" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="bounds" id="6634.Radius.bounds"/> + </Property> + <Property name="RadiusFactor" id="6634.RadiusFactor" number_of_elements="1"> + <Element index="0" value="250"/> + <Domain name="range" id="6634.RadiusFactor.range"/> + </Property> + <Property name="SelectInputScalars" id="6634.SelectInputScalars" number_of_elements="5"> + <Element index="0" value=""/> + <Element index="1" value=""/> + <Element index="2" value=""/> + <Element index="3" value="0"/> + <Element index="4" value="Tensile stress [Pa]"/> + <Domain name="array_list" id="6634.SelectInputScalars.array_list"> + <String text="Contact age [s]"/> + <String text="Contact area [m^2]"/> + <String text="Contact stiffness [N/m]"/> + <String text="Effective radius [m]"/> + <String text="Force [N]"/> + <String text="Tensile stress [Pa]"/> + </Domain> + </Property> + <Property name="SelectInputVectors" id="6634.SelectInputVectors" number_of_elements="5"> + <Element index="0" value="1"/> + <Element index="1" value=""/> + <Element index="2" value=""/> + <Element index="3" value="0"/> + <Element index="4" value="Inter-particle vector [m]"/> + <Domain name="array_list" id="6634.SelectInputVectors.array_list"> + <String text="Inter-particle vector [m]"/> + <String text="Shear displacement [m]"/> + </Domain> + </Property> + <Property name="UseDefaultNormal" id="6634.UseDefaultNormal" number_of_elements="1"> + <Element index="0" value="0"/> + <Domain name="bool" id="6634.UseDefaultNormal.bool"/> + </Property> + <Property name="VaryRadius" id="6634.VaryRadius" number_of_elements="1"> + <Element index="0" value="1"/> + <Domain name="enum" id="6634.VaryRadius.enum"> + <Entry value="0" text="Off"/> + <Entry value="1" text="By Scalar"/> + <Entry value="2" text="By Vector"/> + <Entry value="3" text="By Absolute Scalar"/> + </Domain> + </Property> + </Proxy> + <ExposedProperties> + <Property name="Input" proxy_name="Tube1" exposed_name="Input"/> + </ExposedProperties> + <OutputPort name="Output" proxy="Tube1" port_index="0"/> + <Hints> + <ShowInMenu/> + </Hints> + </CompoundSourceProxy> + </CustomProxyDefinition> +</CustomFilterDefinitions> diff --git a/paraview_filters/SeaIceGranularInteractionParaviewFilter.cpd b/paraview_filters/SeaIceGranularInteractionParaviewFilter.cpd @@ -1,82 +0,0 @@ -<CustomFilterDefinitions> - <CustomProxyDefinition name="SeaIceGranularInteraction" group="filters"> - <CompoundSourceProxy id="6731" servers="1"> - <Proxy group="filters" type="TubeFilter" id="6634" servers="1" compound_name="Tube1"> - <Property name="Capping" id="6634.Capping" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="bool" id="6634.Capping.bool"/> - </Property> - <Property name="DefaultNormal" id="6634.DefaultNormal" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="1"/> - <Domain name="range" id="6634.DefaultNormal.range"/> - </Property> - <Property name="Input" id="6634.Input" number_of_elements="1"> - <Domain name="groups" id="6634.Input.groups"/> - <Domain name="input_array1" id="6634.Input.input_array1"/> - <Domain name="input_array2" id="6634.Input.input_array2"/> - <Domain name="input_type" id="6634.Input.input_type"/> - </Property> - <Property name="NumberOfSides" id="6634.NumberOfSides" number_of_elements="1"> - <Element index="0" value="6"/> - <Domain name="range" id="6634.NumberOfSides.range"/> - </Property> - <Property name="Radius" id="6634.Radius" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="bounds" id="6634.Radius.bounds"/> - </Property> - <Property name="RadiusFactor" id="6634.RadiusFactor" number_of_elements="1"> - <Element index="0" value="250"/> - <Domain name="range" id="6634.RadiusFactor.range"/> - </Property> - <Property name="SelectInputScalars" id="6634.SelectInputScalars" number_of_elements="5"> - <Element index="0" value=""/> - <Element index="1" value=""/> - <Element index="2" value=""/> - <Element index="3" value="0"/> - <Element index="4" value="Tensile stress [Pa]"/> - <Domain name="array_list" id="6634.SelectInputScalars.array_list"> - <String text="Contact age [s]"/> - <String text="Contact area [m^2]"/> - <String text="Contact stiffness [N/m]"/> - <String text="Effective radius [m]"/> - <String text="Force [N]"/> - <String text="Tensile stress [Pa]"/> - </Domain> - </Property> - <Property name="SelectInputVectors" id="6634.SelectInputVectors" number_of_elements="5"> - <Element index="0" value="1"/> - <Element index="1" value=""/> - <Element index="2" value=""/> - <Element index="3" value="0"/> - <Element index="4" value="Inter-particle vector [m]"/> - <Domain name="array_list" id="6634.SelectInputVectors.array_list"> - <String text="Inter-particle vector [m]"/> - <String text="Shear displacement [m]"/> - </Domain> - </Property> - <Property name="UseDefaultNormal" id="6634.UseDefaultNormal" number_of_elements="1"> - <Element index="0" value="0"/> - <Domain name="bool" id="6634.UseDefaultNormal.bool"/> - </Property> - <Property name="VaryRadius" id="6634.VaryRadius" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="enum" id="6634.VaryRadius.enum"> - <Entry value="0" text="Off"/> - <Entry value="1" text="By Scalar"/> - <Entry value="2" text="By Vector"/> - <Entry value="3" text="By Absolute Scalar"/> - </Domain> - </Property> - </Proxy> - <ExposedProperties> - <Property name="Input" proxy_name="Tube1" exposed_name="Input"/> - </ExposedProperties> - <OutputPort name="Output" proxy="Tube1" port_index="0"/> - <Hints> - <ShowInMenu/> - </Hints> - </CompoundSourceProxy> - </CustomProxyDefinition> -</CustomFilterDefinitions> diff --git a/paraview_filters/SeaIceParaviewFilter.cpd b/paraview_filters/SeaIceParaviewFilter.cpd @@ -1,200 +0,0 @@ -<CustomFilterDefinitions> - <CustomProxyDefinition name="SeaIce" group="filters"> - <CompoundSourceProxy id="6702" servers="1"> - <Proxy group="filters" type="Glyph" id="6613" servers="1" compound_name="Glyph1"> - <Property name="GlyphMode" id="6613.GlyphMode" number_of_elements="1"> - <Element index="0" value="0"/> - <Domain name="enum" id="6613.GlyphMode.enum"> - <Entry value="0" text="All Points"/> - <Entry value="1" text="Every Nth Point"/> - <Entry value="2" text="Uniform Spatial Distribution"/> - </Domain> - </Property> - <Property name="GlyphTransform" id="6613.GlyphTransform" number_of_elements="1"> - <Proxy value="6535"/> - <Domain name="proxy_list" id="6613.GlyphTransform.proxy_list"> - <Proxy value="6535"/> - </Domain> - </Property> - <Property name="Input" id="6613.Input" number_of_elements="1"> - <Domain name="groups" id="6613.Input.groups"/> - <Domain name="input_array1" id="6613.Input.input_array1"/> - <Domain name="input_array2" id="6613.Input.input_array2"/> - <Domain name="input_type" id="6613.Input.input_type"/> - </Property> - <Property name="MaximumNumberOfSamplePoints" id="6613.MaximumNumberOfSamplePoints" number_of_elements="1"> - <Element index="0" value="5000"/> - <Domain name="range" id="6613.MaximumNumberOfSamplePoints.range"/> - </Property> - <Property name="Orient" id="6613.Orient" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="bool" id="6613.Orient.bool"/> - </Property> - <Property name="Scalars" id="6613.Scalars" number_of_elements="5"> - <Element index="0" value=""/> - <Element index="1" value=""/> - <Element index="2" value=""/> - <Element index="3" value="0"/> - <Element index="4" value="Diameter (areal) [m]"/> - <Domain name="array_list" id="6613.Scalars.array_list"> - <String text="Contact friction (dynamic) [-]"/> - <String text="Contact friction (static) [-]"/> - <String text="Contact stiffness (normal) [N m^-1]"/> - <String text="Contact stiffness (tangential) [N m^-1]"/> - <String text="Contact viscosity (normal) [N m^-1 s]"/> - <String text="Contact viscosity (tangential) [N m^-1 s]"/> - <String text="Density [kg m^-3]"/> - <String text="Diameter (areal) [m]"/> - <String text="Diameter (contact) [m]"/> - <String text="Fixed in space [-]"/> - <String text="Free to rotate [-]"/> - <String text="Mass [kg]"/> - <String text="Moment of inertia [kg m^2]"/> - <String text="Surface area [m^2]"/> - <String text="Thickness [m]"/> - <String text="Volume [m^3]"/> - </Domain> - </Property> - <Property name="ScaleFactor" id="6613.ScaleFactor" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="bounds" id="6613.ScaleFactor.bounds"/> - <Domain name="scalar_range" id="6613.ScaleFactor.scalar_range"/> - <Domain name="vector_range" id="6613.ScaleFactor.vector_range"/> - </Property> - <Property name="ScaleMode" id="6613.ScaleMode" number_of_elements="1"> - <Element index="0" value="0"/> - <Domain name="enum" id="6613.ScaleMode.enum"> - <Entry value="0" text="scalar"/> - <Entry value="1" text="vector"/> - <Entry value="2" text="vector_components"/> - <Entry value="3" text="off"/> - </Domain> - </Property> - <Property name="Seed" id="6613.Seed" number_of_elements="1"> - <Element index="0" value="10339"/> - <Domain name="range" id="6613.Seed.range"/> - </Property> - <Property name="Source" id="6613.Source" number_of_elements="1"> - <Proxy value="6591" output_port="0"/> - <Domain name="groups" id="6613.Source.groups"/> - <Domain name="input_type" id="6613.Source.input_type"/> - <Domain name="proxy_list" id="6613.Source.proxy_list"> - <Proxy value="6536"/> - <Proxy value="6547"/> - <Proxy value="6558"/> - <Proxy value="6569"/> - <Proxy value="6580"/> - <Proxy value="6591"/> - <Proxy value="6602"/> - </Domain> - </Property> - <Property name="Stride" id="6613.Stride" number_of_elements="1"> - <Element index="0" value="1"/> - <Domain name="range" id="6613.Stride.range"/> - </Property> - <Property name="Vectors" id="6613.Vectors" number_of_elements="5"> - <Element index="0" value="1"/> - <Element index="1" value=""/> - <Element index="2" value=""/> - <Element index="3" value="0"/> - <Element index="4" value="Angular position [rad]"/> - <Domain name="array_list" id="6613.Vectors.array_list"> - <String text="Angular acceleration [rad s^-2]"/> - <String text="Angular position [rad]"/> - <String text="Angular velocity [rad s^-1]"/> - <String text="Linear acceleration [m s^-2]"/> - <String text="Linear velocity [m s^-1]"/> - <String text="Sum of forces [N]"/> - <String text="Sum of torques [N*m]"/> - </Domain> - </Property> - </Proxy> - <Proxy group="extended_sources" type="Transform2" id="6535" servers="1" compound_name="auto_6535"> - <Property name="Position" id="6535.Position" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="0"/> - <Domain name="range" id="6535.Position.range"/> - </Property> - <Property name="PositionInfo" id="6535.PositionInfo" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="0"/> - </Property> - <Property name="Rotation" id="6535.Rotation" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="0"/> - <Domain name="range" id="6535.Rotation.range"/> - </Property> - <Property name="RotationInfo" id="6535.RotationInfo" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="0"/> - </Property> - <Property name="Scale" id="6535.Scale" number_of_elements="3"> - <Element index="0" value="1"/> - <Element index="1" value="1"/> - <Element index="2" value="1"/> - <Domain name="range" id="6535.Scale.range"/> - </Property> - <Property name="ScaleInfo" id="6535.ScaleInfo" number_of_elements="3"> - <Element index="0" value="1"/> - <Element index="1" value="1"/> - <Element index="2" value="1"/> - </Property> - </Proxy> - <Proxy group="sources" type="SphereSource" id="6591" servers="1" compound_name="auto_6591"> - <Property name="Center" id="6591.Center" number_of_elements="3"> - <Element index="0" value="0"/> - <Element index="1" value="0"/> - <Element index="2" value="0"/> - <Domain name="range" id="6591.Center.range"/> - </Property> - <Property name="EndPhi" id="6591.EndPhi" number_of_elements="1"> - <Element index="0" value="180"/> - <Domain name="range" id="6591.EndPhi.range"/> - </Property> - <Property name="EndTheta" id="6591.EndTheta" number_of_elements="1"> - <Element index="0" value="360"/> - <Domain name="range" id="6591.EndTheta.range"/> - </Property> - <Property name="PhiResolution" id="6591.PhiResolution" number_of_elements="1"> - <Element index="0" value="8"/> - <Domain name="range" id="6591.PhiResolution.range"/> - </Property> - <Property name="Radius" id="6591.Radius" number_of_elements="1"> - <Element index="0" value="0.5"/> - <Domain name="range" id="6591.Radius.range"/> - </Property> - <Property name="StartPhi" id="6591.StartPhi" number_of_elements="1"> - <Element index="0" value="0"/> - <Domain name="range" id="6591.StartPhi.range"/> - </Property> - <Property name="StartTheta" id="6591.StartTheta" number_of_elements="1"> - <Element index="0" value="0"/> - <Domain name="range" id="6591.StartTheta.range"/> - </Property> - <Property name="ThetaResolution" id="6591.ThetaResolution" number_of_elements="1"> - <Element index="0" value="8"/> - <Domain name="range" id="6591.ThetaResolution.range"/> - </Property> - </Proxy> - <ExposedProperties> - <Property name="GlyphMode" proxy_name="Glyph1" exposed_name="Glyph Mode"/> - <Property name="GlyphTransform" proxy_name="Glyph1" exposed_name="Glyph Transform"/> - <Property name="Input" proxy_name="Glyph1" exposed_name="Input"/> - <Property name="MaximumNumberOfSamplePoints" proxy_name="Glyph1" exposed_name="Maximum Number Of Sample Points"/> - <Property name="Orient" proxy_name="Glyph1" exposed_name="Orient"/> - <Property name="Scalars" proxy_name="Glyph1" exposed_name="Scalars"/> - <Property name="ScaleFactor" proxy_name="Glyph1" exposed_name="Scale Factor"/> - <Property name="ScaleMode" proxy_name="Glyph1" exposed_name="Scale Mode"/> - <Property name="Vectors" proxy_name="Glyph1" exposed_name="Vectors"/> - </ExposedProperties> - <OutputPort name="Output" proxy="Glyph1" port_index="0"/> - <Hints> - <ShowInMenu/> - </Hints> - </CompoundSourceProxy> - </CustomProxyDefinition> -</CustomFilterDefinitions> diff --git a/seaice-status.sh b/seaice-status.sh @@ -1,14 +0,0 @@ -#!/bin/bash - -# Status script which traverses the subdirectories of the current folder for -# simulations. You may want to add this to your shell's PATH variable. - -set -e -cmd_sing='julia --color=yes -e "import SeaIce; SeaIce.status()"' -cmd_loop='julia --color=yes -e "import SeaIce; SeaIce.status(loop=true, t_int=10)"' - -if [[ "$1" == "loop" ]]; then - eval $cmd_loop -else - eval $cmd_sing -fi diff --git a/src/Granular.jl b/src/Granular.jl @@ -0,0 +1,23 @@ +#!/usr/bin/env julia + +""" +# Granular.jl +Offline granular dynamics simulator module. +""" +module Granular + +include("datatypes.jl") +include("grain.jl") +include("simulation.jl") +include("grid.jl") +include("packing.jl") +include("contact_search.jl") +include("interaction.jl") +include("temporal.jl") +include("temporal_integration.jl") +include("io.jl") +include("ocean.jl") +include("atmosphere.jl") +include("util.jl") + +end # module end diff --git a/src/SeaIce.jl b/src/SeaIce.jl @@ -1,23 +0,0 @@ -#!/usr/bin/env julia - -""" -# SeaIce.jl -Offline sea-ice dynamics simulator module. -""" -module SeaIce - -include("datatypes.jl") -include("icefloe.jl") -include("simulation.jl") -include("grid.jl") -include("packing.jl") -include("contact_search.jl") -include("interaction.jl") -include("temporal.jl") -include("temporal_integration.jl") -include("io.jl") -include("ocean.jl") -include("atmosphere.jl") -include("util.jl") - -end # module end diff --git a/src/atmosphere.jl b/src/atmosphere.jl @@ -133,7 +133,7 @@ end export addAtmosphereDrag! """ Add drag from linear and angular velocity difference between atmosphere and all -ice floes. +grains. """ function addAtmosphereDrag!(simulation::Simulation) if typeof(simulation.atmosphere.input_file) == Bool @@ -147,73 +147,73 @@ function addAtmosphereDrag!(simulation::Simulation) ne = Vector{Float64}(2) nw = Vector{Float64}(2) - for ice_floe in simulation.ice_floes + for grain in simulation.grains - if !ice_floe.enabled + if !grain.enabled continue end - i, j = ice_floe.atmosphere_grid_pos + i, j = grain.atmosphere_grid_pos k = 1 x_tilde, y_tilde = getNonDimensionalCellCoordinates(simulation. atmosphere, i, j, - ice_floe.lin_pos) + grain.lin_pos) if x_tilde < 0. || x_tilde > 1. || y_tilde < 0. || y_tilde > 1. warn(""" relative coordinates outside bounds ($(x_tilde), $(y_tilde)), - pos = $(ice_floe.lin_pos) at i,j = $(i), $(j). + pos = $(grain.lin_pos) at i,j = $(i), $(j). """) end bilinearInterpolation!(uv_interp, u, v, x_tilde, y_tilde, i, j, k, 1) - applyAtmosphereDragToIceFloe!(ice_floe, uv_interp[1], uv_interp[2]) - applyAtmosphereVorticityToIceFloe!(ice_floe, + applyAtmosphereDragToGrain!(grain, uv_interp[1], uv_interp[2]) + applyAtmosphereVorticityToGrain!(grain, curl(simulation.atmosphere, x_tilde, y_tilde, i, j, k, 1, sw, se, ne, nw)) end nothing end -export applyAtmosphereDragToIceFloe! +export applyAtmosphereDragToGrain! """ Add Stokes-type drag from velocity difference between atmosphere and a single -ice floe. +grain. """ -function applyAtmosphereDragToIceFloe!(ice_floe::IceFloeCylindrical, +function applyAtmosphereDragToGrain!(grain::GrainCylindrical, u::Float64, v::Float64) rho_a = 1.2754 # atmosphere density - length = ice_floe.areal_radius*2. - width = ice_floe.areal_radius*2. + length = grain.areal_radius*2. + width = grain.areal_radius*2. drag_force = rho_a * - (.5*ice_floe.ocean_drag_coeff_vert*width*.1*ice_floe.thickness + - ice_floe.atmosphere_drag_coeff_horiz*length*width) * - ([u, v] - ice_floe.lin_vel)*norm([u, v] - ice_floe.lin_vel) + (.5*grain.ocean_drag_coeff_vert*width*.1*grain.thickness + + grain.atmosphere_drag_coeff_horiz*length*width) * + ([u, v] - grain.lin_vel)*norm([u, v] - grain.lin_vel) - ice_floe.force += drag_force - ice_floe.atmosphere_stress = drag_force/ice_floe.horizontal_surface_area + grain.force += drag_force + grain.atmosphere_stress = drag_force/grain.horizontal_surface_area nothing end -export applyAtmosphereVorticityToIceFloe! +export applyAtmosphereVorticityToGrain! """ Add Stokes-type torque from angular velocity difference between atmosphere and a -single ice floe. See Eq. 9.28 in "Introduction to Fluid Mechanics" by Nakayama +single grain. See Eq. 9.28 in "Introduction to Fluid Mechanics" by Nakayama and Boucher, 1999. """ -function applyAtmosphereVorticityToIceFloe!(ice_floe::IceFloeCylindrical, +function applyAtmosphereVorticityToGrain!(grain::GrainCylindrical, atmosphere_curl::Float64) rho_a = 1.2754 # atmosphere density - ice_floe.torque += - pi*ice_floe.areal_radius^4.*rho_a* - (ice_floe.areal_radius/5.*ice_floe.atmosphere_drag_coeff_horiz + - .1*ice_floe.thickness*ice_floe.atmosphere_drag_coeff_vert)* - abs(.5*atmosphere_curl - ice_floe.ang_vel)* - (.5*atmosphere_curl - ice_floe.ang_vel) + grain.torque += + pi*grain.areal_radius^4.*rho_a* + (grain.areal_radius/5.*grain.atmosphere_drag_coeff_horiz + + .1*grain.thickness*grain.atmosphere_drag_coeff_vert)* + abs(.5*atmosphere_curl - grain.ang_vel)* + (.5*atmosphere_curl - grain.ang_vel) nothing end @@ -239,8 +239,8 @@ function compareAtmospheres(atmosphere1::Atmosphere, atmosphere2::Atmosphere) Base.Test.@test atmosphere1.u ≈ atmosphere2.u Base.Test.@test atmosphere1.v ≈ atmosphere2.v - if isassigned(atmosphere1.ice_floe_list, 1) - Base.Test.@test atmosphere1.ice_floe_list == atmosphere2.ice_floe_list + if isassigned(atmosphere1.grain_list, 1) + Base.Test.@test atmosphere1.grain_list == atmosphere2.grain_list end nothing end diff --git a/src/contact_search.jl b/src/contact_search.jl @@ -3,17 +3,17 @@ export findContacts! """ findContacts!(simulation[, method]) -Top-level function to perform an inter-ice floe contact search, based on ice +Top-level function to perform an inter-grain contact search, based on ice floe linear positions and contact radii. The simplest contact search algorithm (`method="all to all"`) is the most -computationally expensive (O(n^2)). The method "ocean grid" bins the ice floes +computationally expensive (O(n^2)). The method "ocean grid" bins the grains into their corresponding cells on the ocean grid and searches for contacts only within the vicinity. When this method is applied, it is assumed that the -`contact_radius` values of the ice floes are *smaller than half the cell size*. +`contact_radius` values of the grains are *smaller than half the cell size*. # Arguments -* `simulation::Simulation`: the simulation object containing the ice floes. +* `simulation::Simulation`: the simulation object containing the grains. * `method::String`: the contact-search method to apply. Valid options are "all to all" and "ocean grid". """ @@ -35,47 +35,47 @@ function findContacts!(simulation::Simulation; nothing end -export interIceFloePositionVector +export interGrainPositionVector """ - interIceFloePositionVector(simulation, i, j) + interGrainPositionVector(simulation, i, j) -Returns a `vector` pointing from ice floe `i` to ice floe `j` in the +Returns a `vector` pointing from grain `i` to grain `j` in the `simulation`. # Arguments -* `simulation::Simulation`: the simulation object containing the ice floes. -* `i::Int`: index of the first ice floe. -* `j::Int`: index of the second ice floe. +* `simulation::Simulation`: the simulation object containing the grains. +* `i::Int`: index of the first grain. +* `j::Int`: index of the second grain. """ -function interIceFloePositionVector(simulation::Simulation, +function interGrainPositionVector(simulation::Simulation, i::Int, j::Int) - @inbounds return simulation.ice_floes[i].lin_pos - - simulation.ice_floes[j].lin_pos + @inbounds return simulation.grains[i].lin_pos - + simulation.grains[j].lin_pos end """ position_ij is the inter-grain position vector, and can be found with -interIceFloePositionVector(). +interGrainPositionVector(). """ function findOverlap(simulation::Simulation, i::Int, j::Int, position_ij::Vector{Float64}) - @inbounds return norm(position_ij) - (simulation.ice_floes[i].contact_radius - + simulation.ice_floes[j].contact_radius) + @inbounds return norm(position_ij) - (simulation.grains[i].contact_radius + + simulation.grains[j].contact_radius) end export findContactsAllToAll! """ findContactsAllToAll!(simulation) -Perform an O(n^2) all-to-all contact search between all ice floes in the -`simulation` object. Contacts between fixed ice floes are ignored. +Perform an O(n^2) all-to-all contact search between all grains in the +`simulation` object. Contacts between fixed grains are ignored. """ function findContactsAllToAll!(simulation::Simulation) - @inbounds for i = 1:length(simulation.ice_floes) + @inbounds for i = 1:length(simulation.grains) # Check contacts with other grains - for j = 1:length(simulation.ice_floes) + for j = 1:length(simulation.grains) checkAndAddContact!(simulation, i, j) end end @@ -86,17 +86,17 @@ export findContactsInGrid! """ findContactsInGrid!(simulation) -Perform an O(n*log(n)) cell-based contact search between all ice floes in the -`simulation` object. Contacts between fixed or disabled ice floes are ignored. +Perform an O(n*log(n)) cell-based contact search between all grains in the +`simulation` object. Contacts between fixed or disabled grains are ignored. """ function findContactsInGrid!(simulation::Simulation, grid::Any) - for idx_i = 1:length(simulation.ice_floes) + for idx_i = 1:length(simulation.grains) if typeof(grid) == Ocean - grid_pos = simulation.ice_floes[idx_i].ocean_grid_pos + grid_pos = simulation.grains[idx_i].ocean_grid_pos elseif typeof(grid) == Atmosphere - grid_pos = simulation.ice_floes[idx_i].atmosphere_grid_pos + grid_pos = simulation.grains[idx_i].atmosphere_grid_pos else error("grid type not understood") end @@ -110,7 +110,7 @@ function findContactsInGrid!(simulation::Simulation, grid::Any) continue end - @inbounds for idx_j in grid.ice_floe_list[i, j] + @inbounds for idx_j in grid.grain_list[i, j] checkAndAddContact!(simulation, idx_i, idx_j) end end @@ -123,28 +123,28 @@ export checkAndAddContact! """ checkAndAddContact!(simulation, i, j) -Check for contact between two ice floes and register the interaction in the -`simulation` object. The indexes of the two ice floes is stored in +Check for contact between two grains and register the interaction in the +`simulation` object. The indexes of the two grains is stored in `simulation.contact_pairs` as `[i, j]`. The overlap vector is parallel to a -straight line connecting the ice floe centers, points away from ice floe `i` and +straight line connecting the grain centers, points away from grain `i` and towards `j`, and is stored in `simulation.overlaps`. A zero-length vector is written to `simulation.contact_parallel_displacement`. # Arguments -* `simulation::Simulation`: the simulation object containing the ice floes. -* `i::Int`: index of the first ice floe. -* `j::Int`: index of the second ice floe. +* `simulation::Simulation`: the simulation object containing the grains. +* `i::Int`: index of the first grain. +* `j::Int`: index of the second grain. """ function checkAndAddContact!(sim::Simulation, i::Int, j::Int) if i < j - @inbounds if (sim.ice_floes[i].fixed && sim.ice_floes[j].fixed) || - !sim.ice_floes[i].enabled || !sim.ice_floes[j].enabled + @inbounds if (sim.grains[i].fixed && sim.grains[j].fixed) || + !sim.grains[i].enabled || !sim.grains[j].enabled return end # Inter-grain position vector and grain overlap - position_ij = interIceFloePositionVector(sim, i, j) + position_ij = interGrainPositionVector(sim, i, j) overlap_ij = findOverlap(sim, i, j, position_ij) contact_found = false @@ -154,7 +154,7 @@ function checkAndAddContact!(sim::Simulation, i::Int, j::Int) # Check if contact is already registered for ic=1:sim.Nc_max - @inbounds if sim.ice_floes[i].contacts[ic] == j + @inbounds if sim.grains[i].contacts[ic] == j contact_found = true break # contact already registered end @@ -168,23 +168,23 @@ function checkAndAddContact!(sim::Simulation, i::Int, j::Int) # Test if this contact exceeds the number of contacts if ic == (sim.Nc_max + 1) for ic=1:sim.Nc_max - warn("ice_floes[$i].contacts[$ic] = " * - "$(sim.ice_floes[i].contacts[ic])") - warn("ice_floes[$i].contact_age[$ic] = " * - "$(sim.ice_floes[i].contact_age[ic])") + warn("grains[$i].contacts[$ic] = " * + "$(sim.grains[i].contacts[ic])") + warn("grains[$i].contact_age[$ic] = " * + "$(sim.grains[i].contact_age[ic])") end error("contact $i-$j exceeds max. number of contacts " * - "(sim.Nc_max = $(sim.Nc_max)) for ice floe $i") + "(sim.Nc_max = $(sim.Nc_max)) for grain $i") end # Register as new contact - @inbounds if sim.ice_floes[i].contacts[ic] == 0 # empty - @inbounds sim.ice_floes[i].n_contacts += 1 - @inbounds sim.ice_floes[j].n_contacts += 1 - @inbounds sim.ice_floes[i].contacts[ic] = j - @inbounds fill!(sim.ice_floes[i]. + @inbounds if sim.grains[i].contacts[ic] == 0 # empty + @inbounds sim.grains[i].n_contacts += 1 + @inbounds sim.grains[j].n_contacts += 1 + @inbounds sim.grains[i].contacts[ic] = j + @inbounds fill!(sim.grains[i]. contact_parallel_displacement[ic] , 0.) - @inbounds sim.ice_floes[i].contact_age[ic] = 0. + @inbounds sim.grains[i].contact_age[ic] = 0. break end end diff --git a/src/datatypes.jl b/src/datatypes.jl @@ -1,5 +1,5 @@ ## Particle composite types -mutable struct IceFloeCylindrical +mutable struct GrainCylindrical # Material properties density::Float64 @@ -66,8 +66,8 @@ mutable struct IceFloeCylindrical atmosphere_stress::Vector{Float64} end -# Type for gathering data from ice floe objects into single arrays -mutable struct IceFloeArrays +# Type for gathering data from grain objects into single arrays +mutable struct GrainArrays # Material properties density::Vector{Float64} @@ -162,7 +162,7 @@ h-points. During read, the velocities are interpolated to the cell corners placement in `[xh, yh, zl, time]`. * `e::Array{Float64, Int}`: interface height relative to mean sea level [m], dimensions correspond to placement in `[xh, yh, zi, time]`. -* `ice_floe_list::Array{Float64, Int}`: indexes of ice floes contained in the +* `grain_list::Array{Float64, Int}`: indexes of grains contained in the ocean grid cells. =# mutable struct Ocean @@ -188,7 +188,7 @@ mutable struct Ocean h::Array{Float64, 4} e::Array{Float64, 4} - ice_floe_list::Array{Vector{Int}, 2} + grain_list::Array{Vector{Int}, 2} end #= @@ -220,7 +220,7 @@ cell corners (q-points). dimensions correspond to placement in `[xq, yq, zl, time]`. * `v::Array{Float64, Int}`: meridional velocity (positive towards north) [m/s], dimensions correspond to placement in `[xq, yq, zl, time]`. -* `ice_floe_list::Array{Float64, Int}`: interface height relative to mean sea +* `grain_list::Array{Float64, Int}`: interface height relative to mean sea level [m], dimensions correspond to placement in `[xh, yh, zi, time]`. =# mutable struct Atmosphere @@ -243,7 +243,7 @@ mutable struct Atmosphere u::Array{Float64, 4} v::Array{Float64, 4} - ice_floe_list::Array{Vector{Int}, 2} + grain_list::Array{Vector{Int}, 2} # If true the grid positions are identical to the ocean grid collocated_with_ocean_grid::Bool @@ -261,7 +261,7 @@ mutable struct Simulation file_number::Int file_time_since_output_file::Float64 - ice_floes::Vector{IceFloeCylindrical} + grains::Vector{GrainCylindrical} ocean::Ocean atmosphere::Atmosphere diff --git a/src/grain.jl b/src/grain.jl @@ -0,0 +1,729 @@ +## Manage grains in the model +hasPyPlot = false +if typeof(Pkg.installed("PyPlot")) == VersionNumber + import PyPlot + hasPyPlot = true +end + +export addGrainCylindrical! +""" + function addGrainCylindrical!(simulation, lin_pos, contact_radius, + thickness[, areal_radius, lin_vel, lin_acc, + force, ang_pos, ang_vel, ang_acc, torque, + density, contact_stiffness_normal, + contact_stiffness_tangential, + contact_viscosity_normal, + contact_viscosity_tangential, + contact_static_friction, + contact_dynamic_friction, + youngs_modulus, poissons_ratio, + tensile_strength, tensile_heal_rate, + compressive_strength_prefactor, + ocean_drag_coeff_vert, + ocean_drag_coeff_horiz, + atmosphere_drag_coeff_vert, + atmosphere_drag_coeff_horiz, + pressure, fixed, rotating, enabled, verbose, + ocean_grid_pos, atmosphere_grid_pos, + n_contact, granular_stress, ocean_stress, + atmosphere_stress]) + +Creates and adds a cylindrical grain to a simulation. Most of the arguments +are optional, and come with default values. The only required arguments are +`simulation`, `lin_pos`, `contact_radius`, and `thickness`. + +# Arguments +* `simulation::Simulation`: the simulation object where the grain should be + added to. +* `lin_pos::Vector{Float64}`: linear position of grain center [m]. +* `contact_radius::Float64`: grain radius for granular interaction [m]. +* `thickness::Float64`: grain thickness [m]. +* `areal_radius = false`: grain radius for determining sea-ice concentration + [m]. +* `lin_vel::Vector{Float64} = [0., 0.]`: linear velocity [m/s]. +* `lin_acc::Vector{Float64} = [0., 0.]`: linear acceleration [m/s^2]. +* `force::Vector{Float64} = [0., 0.]`: linear force balance [N]. +* `ang_pos::Float64 = 0.`: angular position around its center vertical axis + [rad]. +* `ang_vel::Float64 = 0.`: angular velocity around its center vertical axis + [rad/s]. +* `ang_acc::Float64 = 0.`: angular acceleration around its center vertical axis + [rad/s^2]. +* `torque::Float64 = 0.`: torque around its center vertical axis [N*m] +* `density::Float64 = 934.`: grain mean density [kg/m^3]. +* `contact_stiffness_normal::Float64 = 1e7`: contact-normal stiffness [N/m]; + overridden if `youngs_modulus` is set to a positive value. +* `contact_stiffness_tangential::Float64 = 0.`: contact-tangential stiffness + [N/m]; overridden if `youngs_modulus` is set to a positive value. +* `contact_viscosity_normal::Float64 = 0.`: contact-normal viscosity [N/m/s]. +* `contact_viscosity_tangential::Float64 = 0.`: contact-tangential viscosity + [N/m/s]. +* `contact_static_friction::Float64 = 0.4`: contact static Coulomb frictional + coefficient [-]. +* `contact_dynamic_friction::Float64 = 0.4`: contact dynamic Coulomb frictional + coefficient [-]. +* `youngs_modulus::Float64 = 2e7`: elastic modulus [Pa]; overrides any value + set for `contact_stiffness_normal`. +* `poissons_ratio::Float64 = 0.185`: Poisson's ratio, used to determine the + contact-tangential stiffness from `youngs_modulus` [-]. +* `tensile_strength::Float64 = 0.`: contact-tensile (cohesive) bond strength + [Pa]. +* `tensile_heal_rate::Float64 = 0.`: rate at which contact-tensile bond strength + is obtained [1/s]. +* `compressive_strength_prefactor::Float64 = 1285e3`: maximum compressive + strength on granular contact (not currently enforced) [m*Pa]. +* `ocean_drag_coeff_vert::Float64 = 0.85`: vertical drag coefficient for ocean + against grain sides [-]. +* `ocean_drag_coeff_horiz::Float64 = 5e-4`: horizontal drag coefficient for + ocean against grain bottom [-]. +* `atmosphere_drag_coeff_vert::Float64 = 0.4`: vertical drag coefficient for + atmosphere against grain sides [-]. +* `atmosphere_drag_coeff_horiz::Float64 = 2.5e-4`: horizontal drag coefficient + for atmosphere against grain bottom [-]. +* `pressure::Float64 = 0.`: current compressive stress on grain [Pa]. +* `fixed::Bool = false`: grain is fixed in space. +* `rotating::Bool = true`: grain is allowed to rotate. +* `enabled::Bool = true`: grain interacts with other grains. +* `verbose::Bool = true`: display diagnostic information during the function + call. +* `ocean_grid_pos::Array{Int, 1} = [0, 0]`: position of grain in the ocean + grid. +* `atmosphere_grid_pos::Array{Int, 1} = [0, 0]`: position of grain in the + atmosphere grid. +* `n_contacts::Int = 0`: number of contacts with other grains. +* `granular_stress::Vector{Float64} = [0., 0.]`: resultant stress on grain + from granular interactions [Pa]. +* `ocean_stress::Vector{Float64} = [0., 0.]`: resultant stress on grain from + ocean drag [Pa]. +* `atmosphere_stress::Vector{Float64} = [0., 0.]`: resultant stress on grain + from atmosphere drag [Pa]. + +# Examples +The most basic example adds a new grain to the simulation `sim`, with a +center at `[1., 2.]`, a radius of `1.` meter, and a thickness of `0.5` +meter: + +```julia +Granular.addGrainCylindrical!(sim, [1., 2.], 1., .5) +``` + +The following example will create a grain with tensile strength (cohesion), +and a velocity of 0.5 m/s towards -x: + +```julia +Granular.addGrainCylindrical!(sim, [4., 2.], 1., .5, + tensile_strength = 200e3, + lin_vel = [-.5, 0.]) +``` + +Fixed grains are useful for creating walls or coasts, and loops are useful +for creating regular arrangements: + +```julia +for i=1:5 + Granular.addGrainCylindrical!(sim, [i*2., 0., 3.], 1., .5, fixed=true) +end +``` +""" +function addGrainCylindrical!(simulation::Simulation, + lin_pos::Vector{Float64}, + contact_radius::Float64, + thickness::Float64; + areal_radius = false, + lin_vel::Vector{Float64} = [0., 0.], + lin_acc::Vector{Float64} = [0., 0.], + force::Vector{Float64} = [0., 0.], + ang_pos::Float64 = 0., + ang_vel::Float64 = 0., + ang_acc::Float64 = 0., + torque::Float64 = 0., + density::Float64 = 934., + contact_stiffness_normal::Float64 = 1e7, + contact_stiffness_tangential::Float64 = 0., + contact_viscosity_normal::Float64 = 0., + contact_viscosity_tangential::Float64 = 0., + contact_static_friction::Float64 = 0.4, + contact_dynamic_friction::Float64 = 0.4, + youngs_modulus::Float64 = 2e7, + #youngs_modulus::Float64 = 2e9, # Hopkins 2004 + poissons_ratio::Float64 = 0.185, # Hopkins 2004 + #tensile_strength::Float64 = 500e3, # Hopkins2004 + tensile_strength::Float64 = 0., + tensile_heal_rate::Float64 = 0., + compressive_strength_prefactor::Float64 = 1285e3, + # Hopkins 2004 + ocean_drag_coeff_vert::Float64 = 0.85, # H&C 2011 + ocean_drag_coeff_horiz::Float64 = 5e-4, # H&C 2011 + atmosphere_drag_coeff_vert::Float64 = 0.4, + # H&C 2011 + atmosphere_drag_coeff_horiz::Float64 = 2.5e-4, + # H&C2011 + pressure::Float64 = 0., + fixed::Bool = false, + rotating::Bool = true, + enabled::Bool = true, + verbose::Bool = true, + ocean_grid_pos::Array{Int, 1} = [0, 0], + atmosphere_grid_pos::Array{Int, 1} = [0, 0], + n_contacts::Int = 0, + granular_stress::Vector{Float64} = [0., 0.], + ocean_stress::Vector{Float64} = [0., 0.], + atmosphere_stress::Vector{Float64} = [0., 0.]) + + # Check input values + if length(lin_pos) != 2 + error("Linear position must be a two-element array (lin_pos = ", + "$lin_pos)") + end + if length(lin_vel) != 2 + error("Linear velocity must be a two-element array (lin_vel = ", + "$lin_vel)") + end + if length(lin_acc) != 2 + error("Linear acceleration must be a two-element array (lin_acc = ", + "$lin_acc)") + end + if contact_radius <= 0.0 + error("Radius must be greater than 0.0 (radius = $contact_radius m)") + end + if density <= 0.0 + error("Density must be greater than 0.0 (density = $density kg/m^3)") + end + + if !areal_radius + areal_radius = contact_radius + end + + contacts::Array{Int, 1} = zeros(Int, simulation.Nc_max) + contact_parallel_displacement = + Vector{Vector{Float64}}(simulation.Nc_max) + contact_age::Vector{Float64} = zeros(Float64, simulation.Nc_max) + for i=1:simulation.Nc_max + contact_parallel_displacement[i] = zeros(2) + end + + # Create grain object with placeholder values for surface area, volume, + # mass, and moment of inertia. + grain = GrainCylindrical(density, + + thickness, + contact_radius, + areal_radius, + 1.0, # circumreference + 1.0, # horizontal_surface_area + 1.0, # side_surface_area + 1.0, # volume + 1.0, # mass + 1.0, # moment_of_inertia + lin_pos, + lin_vel, + lin_acc, + force, + + ang_pos, + ang_vel, + ang_acc, + torque, + + fixed, + rotating, + enabled, + + contact_stiffness_normal, + contact_stiffness_tangential, + contact_viscosity_normal, + contact_viscosity_tangential, + contact_static_friction, + contact_dynamic_friction, + + youngs_modulus, + poissons_ratio, + tensile_strength, + tensile_heal_rate, + compressive_strength_prefactor, + + ocean_drag_coeff_vert, + ocean_drag_coeff_horiz, + atmosphere_drag_coeff_vert, + atmosphere_drag_coeff_horiz, + + pressure, + n_contacts, + ocean_grid_pos, + atmosphere_grid_pos, + contacts, + contact_parallel_displacement, + contact_age, + + granular_stress, + ocean_stress, + atmosphere_stress + ) + + # Overwrite previous placeholder values + grain.circumreference = grainCircumreference(grain) + grain.horizontal_surface_area = grainHorizontalSurfaceArea(grain) + grain.side_surface_area = grainSideSurfaceArea(grain) + grain.volume = grainVolume(grain) + grain.mass = grainMass(grain) + grain.moment_of_inertia = grainMomentOfInertia(grain) + + # Add to simulation object + addGrain!(simulation, grain, verbose) + nothing +end + +export grainCircumreference +"Returns the circumreference of the grain" +function grainCircumreference(grain::GrainCylindrical) + return pi*grain.areal_radius*2. +end + +export grainHorizontalSurfaceArea +"Returns the top or bottom (horizontal) surface area of the grain" +function grainHorizontalSurfaceArea(grain::GrainCylindrical) + return pi*grain.areal_radius^2. +end + +export grainSideSurfaceArea +"Returns the surface area of the grain sides" +function grainSideSurfaceArea(grain::GrainCylindrical) + return grainCircumreference(grain)*grain.thickness +end + +export grainVolume +"Returns the volume of the grain" +function grainVolume(grain::GrainCylindrical) + return grainHorizontalSurfaceArea(grain)*grain.thickness +end + +export grainMass +"Returns the mass of the grain" +function grainMass(grain::GrainCylindrical) + return grainVolume(grain)*grain.density +end + +export grainMomentOfInertia +"Returns the moment of inertia of the grain" +function grainMomentOfInertia(grain::GrainCylindrical) + return 0.5*grainMass(grain)*grain.areal_radius^2. +end + +export convertGrainDataToArrays +""" +Gathers all grain parameters from the `GrainCylindrical` type in continuous +arrays in an `GrainArrays` structure. +""" +function convertGrainDataToArrays(simulation::Simulation) + + ifarr = GrainArrays( + Array{Float64}(length(simulation.grains)), + + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + + Array{Int}(length(simulation.grains)), + Array{Int}(length(simulation.grains)), + Array{Int}(length(simulation.grains)), + + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + Array{Float64}(length(simulation.grains)), + + Array{Float64}(length(simulation.grains)), + Array{Int}(length(simulation.grains)), + + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + zeros(Float64, 3, length(simulation.grains)), + ) + + # fill arrays + for i=1:length(simulation.grains) + ifarr.density[i] = simulation.grains[i].density + + ifarr.thickness[i] = simulation.grains[i].thickness + ifarr.contact_radius[i] = simulation.grains[i].contact_radius + ifarr.areal_radius[i] = simulation.grains[i].areal_radius + ifarr.circumreference[i] = simulation.grains[i].circumreference + ifarr.horizontal_surface_area[i] = + simulation.grains[i].horizontal_surface_area + ifarr.side_surface_area[i] = simulation.grains[i].side_surface_area + ifarr.volume[i] = simulation.grains[i].volume + ifarr.mass[i] = simulation.grains[i].mass + ifarr.moment_of_inertia[i] = simulation.grains[i].moment_of_inertia + + ifarr.lin_pos[1:2, i] = simulation.grains[i].lin_pos + ifarr.lin_vel[1:2, i] = simulation.grains[i].lin_vel + ifarr.lin_acc[1:2, i] = simulation.grains[i].lin_acc + ifarr.force[1:2, i] = simulation.grains[i].force + + ifarr.ang_pos[3, i] = simulation.grains[i].ang_pos + ifarr.ang_vel[3, i] = simulation.grains[i].ang_vel + ifarr.ang_acc[3, i] = simulation.grains[i].ang_acc + ifarr.torque[3, i] = simulation.grains[i].torque + + ifarr.fixed[i] = Int(simulation.grains[i].fixed) + ifarr.rotating[i] = Int(simulation.grains[i].rotating) + ifarr.enabled[i] = Int(simulation.grains[i].enabled) + + ifarr.contact_stiffness_normal[i] = + simulation.grains[i].contact_stiffness_normal + ifarr.contact_stiffness_tangential[i] = + simulation.grains[i].contact_stiffness_tangential + ifarr.contact_viscosity_normal[i] = + simulation.grains[i].contact_viscosity_normal + ifarr.contact_viscosity_tangential[i] = + simulation.grains[i].contact_viscosity_tangential + ifarr.contact_static_friction[i] = + simulation.grains[i].contact_static_friction + ifarr.contact_dynamic_friction[i] = + simulation.grains[i].contact_dynamic_friction + + ifarr.youngs_modulus[i] = simulation.grains[i].youngs_modulus + ifarr.poissons_ratio[i] = simulation.grains[i].poissons_ratio + ifarr.tensile_strength[i] = simulation.grains[i].tensile_strength + ifarr.compressive_strength_prefactor[i] = + simulation.grains[i].compressive_strength_prefactor + + ifarr.ocean_drag_coeff_vert[i] = + simulation.grains[i].ocean_drag_coeff_vert + ifarr.ocean_drag_coeff_horiz[i] = + simulation.grains[i].ocean_drag_coeff_horiz + ifarr.atmosphere_drag_coeff_vert[i] = + simulation.grains[i].atmosphere_drag_coeff_vert + ifarr.atmosphere_drag_coeff_horiz[i] = + simulation.grains[i].atmosphere_drag_coeff_horiz + + ifarr.pressure[i] = simulation.grains[i].pressure + ifarr.n_contacts[i] = simulation.grains[i].n_contacts + + ifarr.granular_stress[1:2, i] = simulation.grains[i].granular_stress + ifarr.ocean_stress[1:2, i] = simulation.grains[i].ocean_stress + ifarr.atmosphere_stress[1:2, i] = + simulation.grains[i].atmosphere_stress + end + + return ifarr +end + +function deleteGrainArrays!(ifarr::GrainArrays) + f1 = zeros(1) + f2 = zeros(1,1) + i1 = zeros(Int, 1) + + ifarr.density = f1 + + ifarr.thickness = f1 + ifarr.contact_radius = f1 + ifarr.areal_radius = f1 + ifarr.circumreference = f1 + ifarr.horizontal_surface_area = f1 + ifarr.side_surface_area = f1 + ifarr.volume = f1 + ifarr.mass = f1 + ifarr.moment_of_inertia = f1 + + ifarr.lin_pos = f2 + ifarr.lin_vel = f2 + ifarr.lin_acc = f2 + ifarr.force = f2 + + ifarr.ang_pos = f2 + ifarr.ang_vel = f2 + ifarr.ang_acc = f2 + ifarr.torque = f2 + + ifarr.fixed = i1 + ifarr.rotating = i1 + ifarr.enabled = i1 + + ifarr.contact_stiffness_normal = f1 + ifarr.contact_stiffness_tangential = f1 + ifarr.contact_viscosity_normal = f1 + ifarr.contact_viscosity_tangential = f1 + ifarr.contact_static_friction = f1 + ifarr.contact_dynamic_friction = f1 + + ifarr.youngs_modulus = f1 + ifarr.poissons_ratio = f1 + ifarr.tensile_strength = f1 + ifarr.compressive_strength_prefactor = f1 + + ifarr.ocean_drag_coeff_vert = f1 + ifarr.ocean_drag_coeff_horiz = f1 + ifarr.atmosphere_drag_coeff_vert = f1 + ifarr.atmosphere_drag_coeff_horiz = f1 + + ifarr.pressure = f1 + ifarr.n_contacts = i1 + + ifarr.granular_stress = f2 + ifarr.ocean_stress = f2 + ifarr.atmosphere_stress = f2 + + gc() + nothing +end + +export printGrainInfo +""" + printGrainInfo(grain::GrainCylindrical) + +Prints the contents of an grain to stdout in a formatted style. +""" +function printGrainInfo(f::GrainCylindrical) + println(" density: $(f.density) kg/m^3") + println(" thickness: $(f.thickness) m") + println(" contact_radius: $(f.contact_radius) m") + println(" areal_radius: $(f.areal_radius) m") + println(" circumreference: $(f.circumreference) m") + println(" horizontal_surface_area: $(f.horizontal_surface_area) m^2") + println(" side_surface_area: $(f.side_surface_area) m^2") + println(" volume: $(f.volume) m^3") + println(" mass: $(f.mass) kg") + println(" moment_of_inertia: $(f.moment_of_inertia) kg*m^2\n") + + println(" lin_pos: $(f.lin_pos) m") + println(" lin_vel: $(f.lin_vel) m/s") + println(" lin_acc: $(f.lin_acc) m/s^2") + println(" force: $(f.force) N\n") + + println(" ang_pos: $(f.ang_pos) rad") + println(" ang_vel: $(f.ang_vel) rad/s") + println(" ang_acc: $(f.ang_acc) rad/s^2") + println(" torque: $(f.torque) N*m\n") + + println(" fixed: $(f.fixed)") + println(" rotating: $(f.rotating)") + println(" enabled: $(f.enabled)\n") + + println(" k_n: $(f.contact_stiffness_normal) N/m") + println(" k_t: $(f.contact_stiffness_tangential) N/m") + println(" γ_n: $(f.contact_viscosity_normal) N/(m/s)") + println(" γ_t: $(f.contact_viscosity_tangential) N/(m/s)") + println(" μ_s: $(f.contact_static_friction)") + println(" μ_d: $(f.contact_dynamic_friction)\n") + + println(" E: $(f.youngs_modulus) Pa") + println(" ν: $(f.poissons_ratio)") + println(" σ_t: $(f.tensile_strength) Pa") + println(" c(σ_c): $(f.compressive_strength_prefactor) m^0.5 Pa\n") + + println(" c_o_v: $(f.ocean_drag_coeff_vert)") + println(" c_o_h: $(f.ocean_drag_coeff_horiz)") + println(" c_a_v: $(f.atmosphere_drag_coeff_vert)") + println(" c_a_h: $(f.atmosphere_drag_coeff_horiz)\n") + + println(" pressure: $(f.pressure) Pa") + println(" n_contacts: $(f.n_contacts)") + println(" contacts: $(f.contacts)") + println(" delta_t: $(f.contact_parallel_displacement)\n") + + println(" granular_stress: $(f.granular_stress) Pa") + println(" ocean_stress: $(f.ocean_stress) Pa") + println(" atmosphere_stress: $(f.atmosphere_stress) Pa") + nothing +end + +export grainKineticTranslationalEnergy +"Returns the translational kinetic energy of the grain" +function grainKineticTranslationalEnergy(grain::GrainCylindrical) + return 0.5*grain.mass*norm(grain.lin_vel)^2. +end + +export totalGrainKineticTranslationalEnergy +""" +Returns the sum of translational kinetic energies of all grains in a +simulation +""" +function totalGrainKineticTranslationalEnergy(simulation::Simulation) + E_sum = 0. + for grain in simulation.grains + E_sum += grainKineticTranslationalEnergy(grain) + end + return E_sum +end + +export grainKineticRotationalEnergy +"Returns the rotational kinetic energy of the grain" +function grainKineticRotationalEnergy(grain::GrainCylindrical) + return 0.5*grain.moment_of_inertia*norm(grain.ang_vel)^2. +end + +export totalGrainKineticRotationalEnergy +""" +Returns the sum of rotational kinetic energies of all grains in a simulation +""" +function totalGrainKineticRotationalEnergy(simulation::Simulation) + E_sum = 0. + for grain in simulation.grains + E_sum += grainKineticRotationalEnergy(grain) + end + return E_sum +end + +export compareGrains +""" + compareGrains(if1::GrainCylindrical, if2::GrainCylindrical) + +Compare values of two grain objects using the `Base.Test` framework. +""" +function compareGrains(if1::GrainCylindrical, if2::GrainCylindrical) + + Base.Test.@test if1.density ≈ if2.density + Base.Test.@test if1.thickness ≈ if2.thickness + Base.Test.@test if1.contact_radius ≈ + if2.contact_radius + Base.Test.@test if1.areal_radius ≈ if2.areal_radius + Base.Test.@test if1.circumreference ≈ + if2.circumreference + Base.Test.@test if1.horizontal_surface_area ≈ if2.horizontal_surface_area + Base.Test.@test if1.side_surface_area ≈ if2.side_surface_area + Base.Test.@test if1.volume ≈ if2.volume + Base.Test.@test if1.mass ≈ if2.mass + Base.Test.@test if1.moment_of_inertia ≈ if2.moment_of_inertia + + Base.Test.@test if1.lin_pos ≈ if2.lin_pos + Base.Test.@test if1.lin_vel ≈ if2.lin_vel + Base.Test.@test if1.lin_acc ≈ if2.lin_acc + Base.Test.@test if1.force ≈ if2.force + + Base.Test.@test if1.ang_pos ≈ if2.ang_pos + Base.Test.@test if1.ang_vel ≈ if2.ang_vel + Base.Test.@test if1.ang_acc ≈ if2.ang_acc + Base.Test.@test if1.torque ≈ if2.torque + + Base.Test.@test if1.fixed == if2.fixed + Base.Test.@test if1.rotating == if2.rotating + Base.Test.@test if1.enabled == if2.enabled + + Base.Test.@test if1.contact_stiffness_normal ≈ if2.contact_stiffness_normal + Base.Test.@test if1.contact_stiffness_tangential ≈ + if2.contact_stiffness_tangential + Base.Test.@test if1.contact_viscosity_normal ≈ if2.contact_viscosity_normal + Base.Test.@test if1.contact_viscosity_tangential ≈ + if2.contact_viscosity_tangential + Base.Test.@test if1.contact_static_friction ≈ if2.contact_static_friction + Base.Test.@test if1.contact_dynamic_friction ≈ if2.contact_dynamic_friction + + Base.Test.@test if1.youngs_modulus ≈ if2.youngs_modulus + Base.Test.@test if1.poissons_ratio ≈ if2.poissons_ratio + Base.Test.@test if1.tensile_strength ≈ if2.tensile_strength + Base.Test.@test if1.tensile_heal_rate ≈ if2.tensile_heal_rate + Base.Test.@test if1.compressive_strength_prefactor ≈ + if2.compressive_strength_prefactor + + Base.Test.@test if1.ocean_drag_coeff_vert ≈ if2.ocean_drag_coeff_vert + Base.Test.@test if1.ocean_drag_coeff_horiz ≈ if2.ocean_drag_coeff_horiz + Base.Test.@test if1.atmosphere_drag_coeff_vert ≈ + if2.atmosphere_drag_coeff_vert + Base.Test.@test if1.atmosphere_drag_coeff_horiz ≈ + if2.atmosphere_drag_coeff_horiz + + Base.Test.@test if1.pressure ≈ if2.pressure + Base.Test.@test if1.n_contacts == if2.n_contacts + Base.Test.@test if1.ocean_grid_pos == if2.ocean_grid_pos + Base.Test.@test if1.contacts == if2.contacts + Base.Test.@test if1.contact_parallel_displacement == + if2.contact_parallel_displacement + Base.Test.@test if1.contact_age ≈ if2.contact_age + + Base.Test.@test if1.granular_stress ≈ if2.granular_stress + Base.Test.@test if1.ocean_stress ≈ if2.ocean_stress + Base.Test.@test if1.atmosphere_stress ≈ if2.atmosphere_stress + nothing +end + +export plotGrainSizeDistribution +""" + plotGrainSizeDistribution(simulation, [filename_postfix], [nbins], + [size_type], [figsize], [filetype]) + +Plot the grain size distribution as a histogram and save it to the disk. The +plot is saved accoring to the simulation id, the optional `filename_postfix` +string, and the `filetype`, and is written to the current folder. + +# Arguments +* `simulation::Simulation`: the simulation object containing the grains. +* `filename_postfix::String`: optional string for the output filename. +* `nbins::Int`: number of bins in the histogram (default = 12). +* `size_type::String`: specify whether to use the `contact` or `areal` radius + for the grain size. The default is `contact`. +* `figsize::Tuple`: the output figure size in inches (default = (6,4). +* `filetype::String`: the output file type (default = "png"). +* `verbose::String`: show output file as info message in stdout (default = + true). +* `skip_fixed::Bool`: ommit grains that are fixed in space from the size + distribution (default = true). +* `logy::Bool`: plot y-axis in log scale. +""" +function plotGrainSizeDistribution(simulation::Simulation; + filename_postfix::String = "", + nbins::Int=12, + size_type::String = "contact", + figsize::Tuple = (6,4), + filetype::String = "png", + verbose::Bool = true, + skip_fixed::Bool = true, + log_y::Bool = true) + + if !hasPyPlot + error("Function not available because PyPlot is not installed") + return + end + diameters = Float64[] + for i=1:length(simulation.grains) + if simulation.grains[i].fixed && skip_fixed + continue + end + if size_type == "contact" + push!(diameters, simulation.grains[i].contact_radius*2.) + elseif size_type == "areal" + push!(diameters, simulation.grains[i].areal_radius*2.) + else + error("size_type '$size_type' not understood") + end + end + PyPlot.pygui(false) + PyPlot.figure(figsize=figsize) + PyPlot.plt[:hist](diameters, nbins, log=log_y) + PyPlot.xlabel("Diameter [m]") + PyPlot.ylabel("Count [-]") + filename = string(simulation.id * filename_postfix * + "-grain-size-distribution." * filetype) + PyPlot.savefig(filename) + if verbose + info(filename) + end +end diff --git a/src/grid.jl b/src/grid.jl @@ -108,25 +108,25 @@ function curl(grid::Any, ((grid.u[i+1, j+1, k,it] - grid.u[i+1, j , k,it])/se_ne)*x_tilde)) end -export sortIceFloesInGrid! +export sortGrainsInGrid! """ -Find ice-floe positions in grid, based on their center positions. +Find grain positions in grid, based on their center positions. """ -function sortIceFloesInGrid!(simulation::Simulation, grid::Any; verbose=true) +function sortGrainsInGrid!(simulation::Simulation, grid::Any; verbose=true) if simulation.time_iteration == 0 - grid.ice_floe_list = + grid.grain_list = Array{Array{Int, 1}}(size(grid.xh, 1), size(grid.xh, 2)) for i=1:size(grid.xh, 1) for j=1:size(grid.xh, 2) - @inbounds grid.ice_floe_list[i, j] = Int[] + @inbounds grid.grain_list[i, j] = Int[] end end else for i=1:size(grid.xh, 1) for j=1:size(grid.xh, 2) - @inbounds empty!(grid.ice_floe_list[i, j]) + @inbounds empty!(grid.grain_list[i, j]) end end end @@ -136,26 +136,26 @@ function sortIceFloesInGrid!(simulation::Simulation, grid::Any; verbose=true) ne = Vector{Float64}(2) nw = Vector{Float64}(2) - for idx=1:length(simulation.ice_floes) + for idx=1:length(simulation.grains) - @inbounds if !simulation.ice_floes[idx].enabled + @inbounds if !simulation.grains[idx].enabled continue end - # After first iteration, check if ice floe is in same cell before + # After first iteration, check if grain is in same cell before # traversing entire grid if typeof(grid) == Ocean - @inbounds i_old, j_old = simulation.ice_floes[idx].ocean_grid_pos + @inbounds i_old, j_old = simulation.grains[idx].ocean_grid_pos elseif typeof(grid) == Atmosphere @inbounds i_old, j_old = - simulation.ice_floes[idx].atmosphere_grid_pos + simulation.grains[idx].atmosphere_grid_pos else error("grid type not understood.") end if simulation.time > 0. && i_old > 0 && j_old > 0 && isPointInCell(grid, i_old, j_old, - simulation.ice_floes[idx].lin_pos, sw, se, ne, nw) + simulation.grains[idx].lin_pos, sw, se, ne, nw) i = i_old j = j_old @@ -174,7 +174,7 @@ function sortIceFloesInGrid!(simulation::Simulation, grid::Any; verbose=true) j_t = max(min(j_old + j_rel, ny), 1) @inbounds if isPointInCell(grid, i_t, j_t, - simulation.ice_floes[idx].lin_pos, + simulation.grains[idx].lin_pos, sw, se, ne, nw) i = i_t j = j_t @@ -189,33 +189,33 @@ function sortIceFloesInGrid!(simulation::Simulation, grid::Any; verbose=true) if !found i, j = findCellContainingPoint(grid, - simulation.ice_floes[idx]. + simulation.grains[idx]. lin_pos, sw, se, ne, nw) end - # remove ice floe if it is outside of the grid + # remove grain if it is outside of the grid if i == 0 && j == 0 if verbose - info("Disabling ice floe $idx at pos (" * - "$(simulation.ice_floes[idx].lin_pos))") + info("Disabling grain $idx at pos (" * + "$(simulation.grains[idx].lin_pos))") end - disableIceFloe!(simulation, idx) + disableGrain!(simulation, idx) continue end - # add cell to ice floe + # add cell to grain if typeof(grid) == Ocean - @inbounds simulation.ice_floes[idx].ocean_grid_pos .= i, j + @inbounds simulation.grains[idx].ocean_grid_pos .= i, j elseif typeof(grid) == Atmosphere - @inbounds simulation.ice_floes[idx].atmosphere_grid_pos .= i, j + @inbounds simulation.grains[idx].atmosphere_grid_pos .= i, j else error("grid type not understood.") end end - # add ice floe to cell - @inbounds push!(grid.ice_floe_list[i, j], idx) + # add grain to cell + @inbounds push!(grid.grain_list[i, j], idx) end nothing end @@ -512,13 +512,13 @@ end export findEmptyPositionInGridCell """ -Attempt locate an empty spot for an ice floe with radius `r` with center +Attempt locate an empty spot for an grain with radius `r` with center coordinates in a specified grid cell (`i`, `j`) without overlapping any other -ice floes in that cell or the neighboring cells. This function will stop +grains in that cell or the neighboring cells. This function will stop attempting after `n_iter` iterations, each with randomly generated positions. -This function assumes that existing ice floes have been binned according to the -grid (e.g., using `sortIceFloesInGrid()`). +This function assumes that existing grains have been binned according to the +grid (e.g., using `sortGrainsInGrid()`). """ function findEmptyPositionInGridCell(simulation::Simulation, grid::Any, @@ -559,16 +559,16 @@ function findEmptyPositionInGridCell(simulation::Simulation, continue end - # traverse list of ice floes in the target cell and check + # traverse list of grains in the target cell and check # for overlaps - for icefloe_idx in grid.ice_floe_list[it, jt] - overlap = norm(simulation.ice_floes[icefloe_idx].lin_pos - + for grain_idx in grid.grain_list[it, jt] + overlap = norm(simulation.grains[grain_idx].lin_pos - pos) - - (simulation.ice_floes[icefloe_idx].contact_radius + r) + (simulation.grains[grain_idx].contact_radius + r) if overlap < 0. if verbose - info("overlap with $icefloe_idx in cell $i,$j") + info("overlap with $grain_idx in cell $i,$j") end overlap_found = true break @@ -596,7 +596,7 @@ function findEmptyPositionInGridCell(simulation::Simulation, return pos else if verbose - warn("could not insert an ice floe into " * + warn("could not insert an grain into " * "$(typeof(grid)) grid cell ($i, $j)") end return false @@ -604,16 +604,16 @@ function findEmptyPositionInGridCell(simulation::Simulation, end """ -Copy ice floe related information from ocean to atmosphere grid. This is useful +Copy grain related information from ocean to atmosphere grid. This is useful when the two grids are of identical geometry, meaning only only one sorting phase is necessary. """ function copyGridSortingInfo!(ocean::Ocean, atmosphere::Atmosphere, - icefloes::Array{IceFloeCylindrical, 1}) + grains::Array{GrainCylindrical, 1}) - for icefloe in icefloes - icefloe.atmosphere_grid_pos = deepcopy(icefloe.ocean_grid_pos) + for grain in grains + grain.atmosphere_grid_pos = deepcopy(grain.ocean_grid_pos) end - atmosphere.ice_floe_list = deepcopy(ocean.ice_floe_list) + atmosphere.grain_list = deepcopy(ocean.grain_list) nothing end diff --git a/src/icefloe.jl b/src/icefloe.jl @@ -1,729 +0,0 @@ -## Manage icefloes in the model -hasPyPlot = false -if typeof(Pkg.installed("PyPlot")) == VersionNumber - import PyPlot - hasPyPlot = true -end - -export addIceFloeCylindrical! -""" - function addIceFloeCylindrical!(simulation, lin_pos, contact_radius, - thickness[, areal_radius, lin_vel, lin_acc, - force, ang_pos, ang_vel, ang_acc, torque, - density, contact_stiffness_normal, - contact_stiffness_tangential, - contact_viscosity_normal, - contact_viscosity_tangential, - contact_static_friction, - contact_dynamic_friction, - youngs_modulus, poissons_ratio, - tensile_strength, tensile_heal_rate, - compressive_strength_prefactor, - ocean_drag_coeff_vert, - ocean_drag_coeff_horiz, - atmosphere_drag_coeff_vert, - atmosphere_drag_coeff_horiz, - pressure, fixed, rotating, enabled, verbose, - ocean_grid_pos, atmosphere_grid_pos, - n_contact, granular_stress, ocean_stress, - atmosphere_stress]) - -Creates and adds a cylindrical icefloe to a simulation. Most of the arguments -are optional, and come with default values. The only required arguments are -`simulation`, `lin_pos`, `contact_radius`, and `thickness`. - -# Arguments -* `simulation::Simulation`: the simulation object where the ice floe should be - added to. -* `lin_pos::Vector{Float64}`: linear position of ice-floe center [m]. -* `contact_radius::Float64`: ice-floe radius for granular interaction [m]. -* `thickness::Float64`: ice-floe thickness [m]. -* `areal_radius = false`: ice-floe radius for determining sea-ice concentration - [m]. -* `lin_vel::Vector{Float64} = [0., 0.]`: linear velocity [m/s]. -* `lin_acc::Vector{Float64} = [0., 0.]`: linear acceleration [m/s^2]. -* `force::Vector{Float64} = [0., 0.]`: linear force balance [N]. -* `ang_pos::Float64 = 0.`: angular position around its center vertical axis - [rad]. -* `ang_vel::Float64 = 0.`: angular velocity around its center vertical axis - [rad/s]. -* `ang_acc::Float64 = 0.`: angular acceleration around its center vertical axis - [rad/s^2]. -* `torque::Float64 = 0.`: torque around its center vertical axis [N*m] -* `density::Float64 = 934.`: ice-floe mean density [kg/m^3]. -* `contact_stiffness_normal::Float64 = 1e7`: contact-normal stiffness [N/m]; - overridden if `youngs_modulus` is set to a positive value. -* `contact_stiffness_tangential::Float64 = 0.`: contact-tangential stiffness - [N/m]; overridden if `youngs_modulus` is set to a positive value. -* `contact_viscosity_normal::Float64 = 0.`: contact-normal viscosity [N/m/s]. -* `contact_viscosity_tangential::Float64 = 0.`: contact-tangential viscosity - [N/m/s]. -* `contact_static_friction::Float64 = 0.4`: contact static Coulomb frictional - coefficient [-]. -* `contact_dynamic_friction::Float64 = 0.4`: contact dynamic Coulomb frictional - coefficient [-]. -* `youngs_modulus::Float64 = 2e7`: elastic modulus [Pa]; overrides any value - set for `contact_stiffness_normal`. -* `poissons_ratio::Float64 = 0.185`: Poisson's ratio, used to determine the - contact-tangential stiffness from `youngs_modulus` [-]. -* `tensile_strength::Float64 = 0.`: contact-tensile (cohesive) bond strength - [Pa]. -* `tensile_heal_rate::Float64 = 0.`: rate at which contact-tensile bond strength - is obtained [1/s]. -* `compressive_strength_prefactor::Float64 = 1285e3`: maximum compressive - strength on granular contact (not currently enforced) [m*Pa]. -* `ocean_drag_coeff_vert::Float64 = 0.85`: vertical drag coefficient for ocean - against ice-floe sides [-]. -* `ocean_drag_coeff_horiz::Float64 = 5e-4`: horizontal drag coefficient for - ocean against ice-floe bottom [-]. -* `atmosphere_drag_coeff_vert::Float64 = 0.4`: vertical drag coefficient for - atmosphere against ice-floe sides [-]. -* `atmosphere_drag_coeff_horiz::Float64 = 2.5e-4`: horizontal drag coefficient - for atmosphere against ice-floe bottom [-]. -* `pressure::Float64 = 0.`: current compressive stress on ice floe [Pa]. -* `fixed::Bool = false`: ice floe is fixed in space. -* `rotating::Bool = true`: ice floe is allowed to rotate. -* `enabled::Bool = true`: ice floe interacts with other ice floes. -* `verbose::Bool = true`: display diagnostic information during the function - call. -* `ocean_grid_pos::Array{Int, 1} = [0, 0]`: position of ice floe in the ocean - grid. -* `atmosphere_grid_pos::Array{Int, 1} = [0, 0]`: position of ice floe in the - atmosphere grid. -* `n_contacts::Int = 0`: number of contacts with other ice floes. -* `granular_stress::Vector{Float64} = [0., 0.]`: resultant stress on ice floe - from granular interactions [Pa]. -* `ocean_stress::Vector{Float64} = [0., 0.]`: resultant stress on ice floe from - ocean drag [Pa]. -* `atmosphere_stress::Vector{Float64} = [0., 0.]`: resultant stress on ice floe - from atmosphere drag [Pa]. - -# Examples -The most basic example adds a new ice floe to the simulation `sim`, with a -center at `[1., 2.]`, a radius of `1.` meter, and a thickness of `0.5` -meter: - -```julia -SeaIce.addIceFloeCylindrical!(sim, [1., 2.], 1., .5) -``` - -The following example will create a ice floe with tensile strength (cohesion), -and a velocity of 0.5 m/s towards -x: - -```julia -SeaIce.addIceFloeCylindrical!(sim, [4., 2.], 1., .5, - tensile_strength = 200e3, - lin_vel = [-.5, 0.]) -``` - -Fixed ice floes are useful for creating walls or coasts, and loops are useful -for creating regular arrangements: - -```julia -for i=1:5 - SeaIce.addIceFloeCylindrical!(sim, [i*2., 0., 3.], 1., .5, fixed=true) -end -``` -""" -function addIceFloeCylindrical!(simulation::Simulation, - lin_pos::Vector{Float64}, - contact_radius::Float64, - thickness::Float64; - areal_radius = false, - lin_vel::Vector{Float64} = [0., 0.], - lin_acc::Vector{Float64} = [0., 0.], - force::Vector{Float64} = [0., 0.], - ang_pos::Float64 = 0., - ang_vel::Float64 = 0., - ang_acc::Float64 = 0., - torque::Float64 = 0., - density::Float64 = 934., - contact_stiffness_normal::Float64 = 1e7, - contact_stiffness_tangential::Float64 = 0., - contact_viscosity_normal::Float64 = 0., - contact_viscosity_tangential::Float64 = 0., - contact_static_friction::Float64 = 0.4, - contact_dynamic_friction::Float64 = 0.4, - youngs_modulus::Float64 = 2e7, - #youngs_modulus::Float64 = 2e9, # Hopkins 2004 - poissons_ratio::Float64 = 0.185, # Hopkins 2004 - #tensile_strength::Float64 = 500e3, # Hopkins2004 - tensile_strength::Float64 = 0., - tensile_heal_rate::Float64 = 0., - compressive_strength_prefactor::Float64 = 1285e3, - # Hopkins 2004 - ocean_drag_coeff_vert::Float64 = 0.85, # H&C 2011 - ocean_drag_coeff_horiz::Float64 = 5e-4, # H&C 2011 - atmosphere_drag_coeff_vert::Float64 = 0.4, - # H&C 2011 - atmosphere_drag_coeff_horiz::Float64 = 2.5e-4, - # H&C2011 - pressure::Float64 = 0., - fixed::Bool = false, - rotating::Bool = true, - enabled::Bool = true, - verbose::Bool = true, - ocean_grid_pos::Array{Int, 1} = [0, 0], - atmosphere_grid_pos::Array{Int, 1} = [0, 0], - n_contacts::Int = 0, - granular_stress::Vector{Float64} = [0., 0.], - ocean_stress::Vector{Float64} = [0., 0.], - atmosphere_stress::Vector{Float64} = [0., 0.]) - - # Check input values - if length(lin_pos) != 2 - error("Linear position must be a two-element array (lin_pos = ", - "$lin_pos)") - end - if length(lin_vel) != 2 - error("Linear velocity must be a two-element array (lin_vel = ", - "$lin_vel)") - end - if length(lin_acc) != 2 - error("Linear acceleration must be a two-element array (lin_acc = ", - "$lin_acc)") - end - if contact_radius <= 0.0 - error("Radius must be greater than 0.0 (radius = $contact_radius m)") - end - if density <= 0.0 - error("Density must be greater than 0.0 (density = $density kg/m^3)") - end - - if !areal_radius - areal_radius = contact_radius - end - - contacts::Array{Int, 1} = zeros(Int, simulation.Nc_max) - contact_parallel_displacement = - Vector{Vector{Float64}}(simulation.Nc_max) - contact_age::Vector{Float64} = zeros(Float64, simulation.Nc_max) - for i=1:simulation.Nc_max - contact_parallel_displacement[i] = zeros(2) - end - - # Create icefloe object with placeholder values for surface area, volume, - # mass, and moment of inertia. - icefloe = IceFloeCylindrical(density, - - thickness, - contact_radius, - areal_radius, - 1.0, # circumreference - 1.0, # horizontal_surface_area - 1.0, # side_surface_area - 1.0, # volume - 1.0, # mass - 1.0, # moment_of_inertia - lin_pos, - lin_vel, - lin_acc, - force, - - ang_pos, - ang_vel, - ang_acc, - torque, - - fixed, - rotating, - enabled, - - contact_stiffness_normal, - contact_stiffness_tangential, - contact_viscosity_normal, - contact_viscosity_tangential, - contact_static_friction, - contact_dynamic_friction, - - youngs_modulus, - poissons_ratio, - tensile_strength, - tensile_heal_rate, - compressive_strength_prefactor, - - ocean_drag_coeff_vert, - ocean_drag_coeff_horiz, - atmosphere_drag_coeff_vert, - atmosphere_drag_coeff_horiz, - - pressure, - n_contacts, - ocean_grid_pos, - atmosphere_grid_pos, - contacts, - contact_parallel_displacement, - contact_age, - - granular_stress, - ocean_stress, - atmosphere_stress - ) - - # Overwrite previous placeholder values - icefloe.circumreference = iceFloeCircumreference(icefloe) - icefloe.horizontal_surface_area = iceFloeHorizontalSurfaceArea(icefloe) - icefloe.side_surface_area = iceFloeSideSurfaceArea(icefloe) - icefloe.volume = iceFloeVolume(icefloe) - icefloe.mass = iceFloeMass(icefloe) - icefloe.moment_of_inertia = iceFloeMomentOfInertia(icefloe) - - # Add to simulation object - addIceFloe!(simulation, icefloe, verbose) - nothing -end - -export iceFloeCircumreference -"Returns the circumreference of the ice floe" -function iceFloeCircumreference(icefloe::IceFloeCylindrical) - return pi*icefloe.areal_radius*2. -end - -export iceFloeHorizontalSurfaceArea -"Returns the top or bottom (horizontal) surface area of the ice floe" -function iceFloeHorizontalSurfaceArea(icefloe::IceFloeCylindrical) - return pi*icefloe.areal_radius^2. -end - -export iceFloeSideSurfaceArea -"Returns the surface area of the ice-floe sides" -function iceFloeSideSurfaceArea(icefloe::IceFloeCylindrical) - return iceFloeCircumreference(icefloe)*icefloe.thickness -end - -export iceFloeVolume -"Returns the volume of the ice floe" -function iceFloeVolume(icefloe::IceFloeCylindrical) - return iceFloeHorizontalSurfaceArea(icefloe)*icefloe.thickness -end - -export iceFloeMass -"Returns the mass of the ice floe" -function iceFloeMass(icefloe::IceFloeCylindrical) - return iceFloeVolume(icefloe)*icefloe.density -end - -export iceFloeMomentOfInertia -"Returns the moment of inertia of the ice floe" -function iceFloeMomentOfInertia(icefloe::IceFloeCylindrical) - return 0.5*iceFloeMass(icefloe)*icefloe.areal_radius^2. -end - -export convertIceFloeDataToArrays -""" -Gathers all ice-floe parameters from the `IceFloeCylindrical` type in continuous -arrays in an `IceFloeArrays` structure. -""" -function convertIceFloeDataToArrays(simulation::Simulation) - - ifarr = IceFloeArrays( - Array{Float64}(length(simulation.ice_floes)), - - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - - Array{Int}(length(simulation.ice_floes)), - Array{Int}(length(simulation.ice_floes)), - Array{Int}(length(simulation.ice_floes)), - - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - Array{Float64}(length(simulation.ice_floes)), - - Array{Float64}(length(simulation.ice_floes)), - Array{Int}(length(simulation.ice_floes)), - - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - zeros(Float64, 3, length(simulation.ice_floes)), - ) - - # fill arrays - for i=1:length(simulation.ice_floes) - ifarr.density[i] = simulation.ice_floes[i].density - - ifarr.thickness[i] = simulation.ice_floes[i].thickness - ifarr.contact_radius[i] = simulation.ice_floes[i].contact_radius - ifarr.areal_radius[i] = simulation.ice_floes[i].areal_radius - ifarr.circumreference[i] = simulation.ice_floes[i].circumreference - ifarr.horizontal_surface_area[i] = - simulation.ice_floes[i].horizontal_surface_area - ifarr.side_surface_area[i] = simulation.ice_floes[i].side_surface_area - ifarr.volume[i] = simulation.ice_floes[i].volume - ifarr.mass[i] = simulation.ice_floes[i].mass - ifarr.moment_of_inertia[i] = simulation.ice_floes[i].moment_of_inertia - - ifarr.lin_pos[1:2, i] = simulation.ice_floes[i].lin_pos - ifarr.lin_vel[1:2, i] = simulation.ice_floes[i].lin_vel - ifarr.lin_acc[1:2, i] = simulation.ice_floes[i].lin_acc - ifarr.force[1:2, i] = simulation.ice_floes[i].force - - ifarr.ang_pos[3, i] = simulation.ice_floes[i].ang_pos - ifarr.ang_vel[3, i] = simulation.ice_floes[i].ang_vel - ifarr.ang_acc[3, i] = simulation.ice_floes[i].ang_acc - ifarr.torque[3, i] = simulation.ice_floes[i].torque - - ifarr.fixed[i] = Int(simulation.ice_floes[i].fixed) - ifarr.rotating[i] = Int(simulation.ice_floes[i].rotating) - ifarr.enabled[i] = Int(simulation.ice_floes[i].enabled) - - ifarr.contact_stiffness_normal[i] = - simulation.ice_floes[i].contact_stiffness_normal - ifarr.contact_stiffness_tangential[i] = - simulation.ice_floes[i].contact_stiffness_tangential - ifarr.contact_viscosity_normal[i] = - simulation.ice_floes[i].contact_viscosity_normal - ifarr.contact_viscosity_tangential[i] = - simulation.ice_floes[i].contact_viscosity_tangential - ifarr.contact_static_friction[i] = - simulation.ice_floes[i].contact_static_friction - ifarr.contact_dynamic_friction[i] = - simulation.ice_floes[i].contact_dynamic_friction - - ifarr.youngs_modulus[i] = simulation.ice_floes[i].youngs_modulus - ifarr.poissons_ratio[i] = simulation.ice_floes[i].poissons_ratio - ifarr.tensile_strength[i] = simulation.ice_floes[i].tensile_strength - ifarr.compressive_strength_prefactor[i] = - simulation.ice_floes[i].compressive_strength_prefactor - - ifarr.ocean_drag_coeff_vert[i] = - simulation.ice_floes[i].ocean_drag_coeff_vert - ifarr.ocean_drag_coeff_horiz[i] = - simulation.ice_floes[i].ocean_drag_coeff_horiz - ifarr.atmosphere_drag_coeff_vert[i] = - simulation.ice_floes[i].atmosphere_drag_coeff_vert - ifarr.atmosphere_drag_coeff_horiz[i] = - simulation.ice_floes[i].atmosphere_drag_coeff_horiz - - ifarr.pressure[i] = simulation.ice_floes[i].pressure - ifarr.n_contacts[i] = simulation.ice_floes[i].n_contacts - - ifarr.granular_stress[1:2, i] = simulation.ice_floes[i].granular_stress - ifarr.ocean_stress[1:2, i] = simulation.ice_floes[i].ocean_stress - ifarr.atmosphere_stress[1:2, i] = - simulation.ice_floes[i].atmosphere_stress - end - - return ifarr -end - -function deleteIceFloeArrays!(ifarr::IceFloeArrays) - f1 = zeros(1) - f2 = zeros(1,1) - i1 = zeros(Int, 1) - - ifarr.density = f1 - - ifarr.thickness = f1 - ifarr.contact_radius = f1 - ifarr.areal_radius = f1 - ifarr.circumreference = f1 - ifarr.horizontal_surface_area = f1 - ifarr.side_surface_area = f1 - ifarr.volume = f1 - ifarr.mass = f1 - ifarr.moment_of_inertia = f1 - - ifarr.lin_pos = f2 - ifarr.lin_vel = f2 - ifarr.lin_acc = f2 - ifarr.force = f2 - - ifarr.ang_pos = f2 - ifarr.ang_vel = f2 - ifarr.ang_acc = f2 - ifarr.torque = f2 - - ifarr.fixed = i1 - ifarr.rotating = i1 - ifarr.enabled = i1 - - ifarr.contact_stiffness_normal = f1 - ifarr.contact_stiffness_tangential = f1 - ifarr.contact_viscosity_normal = f1 - ifarr.contact_viscosity_tangential = f1 - ifarr.contact_static_friction = f1 - ifarr.contact_dynamic_friction = f1 - - ifarr.youngs_modulus = f1 - ifarr.poissons_ratio = f1 - ifarr.tensile_strength = f1 - ifarr.compressive_strength_prefactor = f1 - - ifarr.ocean_drag_coeff_vert = f1 - ifarr.ocean_drag_coeff_horiz = f1 - ifarr.atmosphere_drag_coeff_vert = f1 - ifarr.atmosphere_drag_coeff_horiz = f1 - - ifarr.pressure = f1 - ifarr.n_contacts = i1 - - ifarr.granular_stress = f2 - ifarr.ocean_stress = f2 - ifarr.atmosphere_stress = f2 - - gc() - nothing -end - -export printIceFloeInfo -""" - printIceFloeInfo(icefloe::IceFloeCylindrical) - -Prints the contents of an ice floe to stdout in a formatted style. -""" -function printIceFloeInfo(f::IceFloeCylindrical) - println(" density: $(f.density) kg/m^3") - println(" thickness: $(f.thickness) m") - println(" contact_radius: $(f.contact_radius) m") - println(" areal_radius: $(f.areal_radius) m") - println(" circumreference: $(f.circumreference) m") - println(" horizontal_surface_area: $(f.horizontal_surface_area) m^2") - println(" side_surface_area: $(f.side_surface_area) m^2") - println(" volume: $(f.volume) m^3") - println(" mass: $(f.mass) kg") - println(" moment_of_inertia: $(f.moment_of_inertia) kg*m^2\n") - - println(" lin_pos: $(f.lin_pos) m") - println(" lin_vel: $(f.lin_vel) m/s") - println(" lin_acc: $(f.lin_acc) m/s^2") - println(" force: $(f.force) N\n") - - println(" ang_pos: $(f.ang_pos) rad") - println(" ang_vel: $(f.ang_vel) rad/s") - println(" ang_acc: $(f.ang_acc) rad/s^2") - println(" torque: $(f.torque) N*m\n") - - println(" fixed: $(f.fixed)") - println(" rotating: $(f.rotating)") - println(" enabled: $(f.enabled)\n") - - println(" k_n: $(f.contact_stiffness_normal) N/m") - println(" k_t: $(f.contact_stiffness_tangential) N/m") - println(" γ_n: $(f.contact_viscosity_normal) N/(m/s)") - println(" γ_t: $(f.contact_viscosity_tangential) N/(m/s)") - println(" μ_s: $(f.contact_static_friction)") - println(" μ_d: $(f.contact_dynamic_friction)\n") - - println(" E: $(f.youngs_modulus) Pa") - println(" ν: $(f.poissons_ratio)") - println(" σ_t: $(f.tensile_strength) Pa") - println(" c(σ_c): $(f.compressive_strength_prefactor) m^0.5 Pa\n") - - println(" c_o_v: $(f.ocean_drag_coeff_vert)") - println(" c_o_h: $(f.ocean_drag_coeff_horiz)") - println(" c_a_v: $(f.atmosphere_drag_coeff_vert)") - println(" c_a_h: $(f.atmosphere_drag_coeff_horiz)\n") - - println(" pressure: $(f.pressure) Pa") - println(" n_contacts: $(f.n_contacts)") - println(" contacts: $(f.contacts)") - println(" delta_t: $(f.contact_parallel_displacement)\n") - - println(" granular_stress: $(f.granular_stress) Pa") - println(" ocean_stress: $(f.ocean_stress) Pa") - println(" atmosphere_stress: $(f.atmosphere_stress) Pa") - nothing -end - -export iceFloeKineticTranslationalEnergy -"Returns the translational kinetic energy of the ice floe" -function iceFloeKineticTranslationalEnergy(icefloe::IceFloeCylindrical) - return 0.5*icefloe.mass*norm(icefloe.lin_vel)^2. -end - -export totalIceFloeKineticTranslationalEnergy -""" -Returns the sum of translational kinetic energies of all ice floes in a -simulation -""" -function totalIceFloeKineticTranslationalEnergy(simulation::Simulation) - E_sum = 0. - for icefloe in simulation.ice_floes - E_sum += iceFloeKineticTranslationalEnergy(icefloe) - end - return E_sum -end - -export iceFloeKineticRotationalEnergy -"Returns the rotational kinetic energy of the ice floe" -function iceFloeKineticRotationalEnergy(icefloe::IceFloeCylindrical) - return 0.5*icefloe.moment_of_inertia*norm(icefloe.ang_vel)^2. -end - -export totalIceFloeKineticRotationalEnergy -""" -Returns the sum of rotational kinetic energies of all ice floes in a simulation -""" -function totalIceFloeKineticRotationalEnergy(simulation::Simulation) - E_sum = 0. - for icefloe in simulation.ice_floes - E_sum += iceFloeKineticRotationalEnergy(icefloe) - end - return E_sum -end - -export compareIceFloes -""" - compareIceFloes(if1::IceFloeCylindrical, if2::IceFloeCylindrical) - -Compare values of two ice floe objects using the `Base.Test` framework. -""" -function compareIceFloes(if1::IceFloeCylindrical, if2::IceFloeCylindrical) - - Base.Test.@test if1.density ≈ if2.density - Base.Test.@test if1.thickness ≈ if2.thickness - Base.Test.@test if1.contact_radius ≈ - if2.contact_radius - Base.Test.@test if1.areal_radius ≈ if2.areal_radius - Base.Test.@test if1.circumreference ≈ - if2.circumreference - Base.Test.@test if1.horizontal_surface_area ≈ if2.horizontal_surface_area - Base.Test.@test if1.side_surface_area ≈ if2.side_surface_area - Base.Test.@test if1.volume ≈ if2.volume - Base.Test.@test if1.mass ≈ if2.mass - Base.Test.@test if1.moment_of_inertia ≈ if2.moment_of_inertia - - Base.Test.@test if1.lin_pos ≈ if2.lin_pos - Base.Test.@test if1.lin_vel ≈ if2.lin_vel - Base.Test.@test if1.lin_acc ≈ if2.lin_acc - Base.Test.@test if1.force ≈ if2.force - - Base.Test.@test if1.ang_pos ≈ if2.ang_pos - Base.Test.@test if1.ang_vel ≈ if2.ang_vel - Base.Test.@test if1.ang_acc ≈ if2.ang_acc - Base.Test.@test if1.torque ≈ if2.torque - - Base.Test.@test if1.fixed == if2.fixed - Base.Test.@test if1.rotating == if2.rotating - Base.Test.@test if1.enabled == if2.enabled - - Base.Test.@test if1.contact_stiffness_normal ≈ if2.contact_stiffness_normal - Base.Test.@test if1.contact_stiffness_tangential ≈ - if2.contact_stiffness_tangential - Base.Test.@test if1.contact_viscosity_normal ≈ if2.contact_viscosity_normal - Base.Test.@test if1.contact_viscosity_tangential ≈ - if2.contact_viscosity_tangential - Base.Test.@test if1.contact_static_friction ≈ if2.contact_static_friction - Base.Test.@test if1.contact_dynamic_friction ≈ if2.contact_dynamic_friction - - Base.Test.@test if1.youngs_modulus ≈ if2.youngs_modulus - Base.Test.@test if1.poissons_ratio ≈ if2.poissons_ratio - Base.Test.@test if1.tensile_strength ≈ if2.tensile_strength - Base.Test.@test if1.tensile_heal_rate ≈ if2.tensile_heal_rate - Base.Test.@test if1.compressive_strength_prefactor ≈ - if2.compressive_strength_prefactor - - Base.Test.@test if1.ocean_drag_coeff_vert ≈ if2.ocean_drag_coeff_vert - Base.Test.@test if1.ocean_drag_coeff_horiz ≈ if2.ocean_drag_coeff_horiz - Base.Test.@test if1.atmosphere_drag_coeff_vert ≈ - if2.atmosphere_drag_coeff_vert - Base.Test.@test if1.atmosphere_drag_coeff_horiz ≈ - if2.atmosphere_drag_coeff_horiz - - Base.Test.@test if1.pressure ≈ if2.pressure - Base.Test.@test if1.n_contacts == if2.n_contacts - Base.Test.@test if1.ocean_grid_pos == if2.ocean_grid_pos - Base.Test.@test if1.contacts == if2.contacts - Base.Test.@test if1.contact_parallel_displacement == - if2.contact_parallel_displacement - Base.Test.@test if1.contact_age ≈ if2.contact_age - - Base.Test.@test if1.granular_stress ≈ if2.granular_stress - Base.Test.@test if1.ocean_stress ≈ if2.ocean_stress - Base.Test.@test if1.atmosphere_stress ≈ if2.atmosphere_stress - nothing -end - -export plotIceFloeSizeDistribution -""" - plotIceFloeSizeDistribution(simulation, [filename_postfix], [nbins], - [size_type], [figsize], [filetype]) - -Plot the ice-floe size distribution as a histogram and save it to the disk. The -plot is saved accoring to the simulation id, the optional `filename_postfix` -string, and the `filetype`, and is written to the current folder. - -# Arguments -* `simulation::Simulation`: the simulation object containing the ice floes. -* `filename_postfix::String`: optional string for the output filename. -* `nbins::Int`: number of bins in the histogram (default = 12). -* `size_type::String`: specify whether to use the `contact` or `areal` radius - for the ice-floe size. The default is `contact`. -* `figsize::Tuple`: the output figure size in inches (default = (6,4). -* `filetype::String`: the output file type (default = "png"). -* `verbose::String`: show output file as info message in stdout (default = - true). -* `skip_fixed::Bool`: ommit ice floes that are fixed in space from the size - distribution (default = true). -* `logy::Bool`: plot y-axis in log scale. -""" -function plotIceFloeSizeDistribution(simulation::Simulation; - filename_postfix::String = "", - nbins::Int=12, - size_type::String = "contact", - figsize::Tuple = (6,4), - filetype::String = "png", - verbose::Bool = true, - skip_fixed::Bool = true, - log_y::Bool = true) - - if !hasPyPlot - error("Function not available because PyPlot is not installed") - return - end - diameters = Float64[] - for i=1:length(simulation.ice_floes) - if simulation.ice_floes[i].fixed && skip_fixed - continue - end - if size_type == "contact" - push!(diameters, simulation.ice_floes[i].contact_radius*2.) - elseif size_type == "areal" - push!(diameters, simulation.ice_floes[i].areal_radius*2.) - else - error("size_type '$size_type' not understood") - end - end - PyPlot.pygui(false) - PyPlot.figure(figsize=figsize) - PyPlot.plt[:hist](diameters, nbins, log=log_y) - PyPlot.xlabel("Diameter [m]") - PyPlot.ylabel("Count [-]") - filename = string(simulation.id * filename_postfix * - "-ice-floe-size-distribution." * filetype) - PyPlot.savefig(filename) - if verbose - info(filename) - end -end diff --git a/src/interaction.jl b/src/interaction.jl @@ -7,51 +7,51 @@ export interact! Resolve mechanical interaction between all particle pairs. """ function interact!(simulation::Simulation) - for i=1:length(simulation.ice_floes) + for i=1:length(simulation.grains) for ic=1:simulation.Nc_max - j = simulation.ice_floes[i].contacts[ic] + j = simulation.grains[i].contacts[ic] if i > j # skip i > j and j == 0 continue end - #=if norm(simulation.ice_floes[i].lin_pos - - simulation.ice_floes[j].lin_pos) - - (simulation.ice_floes[i].contact_radius + - simulation.ice_floes[j].contact_radius) > 0. + #=if norm(simulation.grains[i].lin_pos - + simulation.grains[j].lin_pos) - + (simulation.grains[i].contact_radius + + simulation.grains[j].contact_radius) > 0. - simulation.ice_floes[i].contacts[ic] = 0 # remove contact - simulation.ice_floes[i].n_contacts -= 1 - simulation.ice_floes[j].n_contacts -= 1 + simulation.grains[i].contacts[ic] = 0 # remove contact + simulation.grains[i].n_contacts -= 1 + simulation.grains[j].n_contacts -= 1 else=# - interactIceFloes!(simulation, i, j, ic) + interactGrains!(simulation, i, j, ic) #end end end - for i=1:length(simulation.ice_floes) - @inbounds simulation.ice_floes[i].granular_stress = - simulation.ice_floes[i].force/ - simulation.ice_floes[i].horizontal_surface_area + for i=1:length(simulation.grains) + @inbounds simulation.grains[i].granular_stress = + simulation.grains[i].force/ + simulation.grains[i].horizontal_surface_area end nothing end -export interactIceFloes! +export interactGrains! """ - interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) + interactGrains!(simulation::Simulation, i::Int, j::Int, ic::Int) Resolve an grain-to-grain interaction using a prescibed contact law. This -function adds the compressive force of the interaction to the ice floe -`pressure` field of mean compressive stress on the ice floe sides. +function adds the compressive force of the interaction to the grain +`pressure` field of mean compressive stress on the grain sides. The function uses the macroscopic contact-stiffness parameterization based on Young's modulus and Poisson's ratio if Young's modulus is a positive value. """ -function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) +function interactGrains!(simulation::Simulation, i::Int, j::Int, ic::Int) - if !simulation.ice_floes[i].enabled || !simulation.ice_floes[j].enabled + if !simulation.grains[i].enabled || !simulation.grains[j].enabled return end @@ -59,11 +59,11 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) force_t = 0. # Contact-parallel (tangential) force # Inter-position vector - p = simulation.ice_floes[i].lin_pos - simulation.ice_floes[j].lin_pos + p = simulation.grains[i].lin_pos - simulation.grains[j].lin_pos dist = norm(p) - r_i = simulation.ice_floes[i].contact_radius - r_j = simulation.ice_floes[j].contact_radius + r_i = simulation.grains[i].contact_radius + r_j = simulation.grains[j].contact_radius # Floe distance; <0: compression, >0: tension δ_n = dist - (r_i + r_j) @@ -73,32 +73,32 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) t = [-n[2], n[1]] # Contact kinematics - vel_lin = simulation.ice_floes[i].lin_vel - - simulation.ice_floes[j].lin_vel + vel_lin = simulation.grains[i].lin_vel - + simulation.grains[j].lin_vel vel_n = dot(vel_lin, n) vel_t = dot(vel_lin, t) - - harmonicMean(r_i, r_j)*(simulation.ice_floes[i].ang_vel + - simulation.ice_floes[j].ang_vel) + harmonicMean(r_i, r_j)*(simulation.grains[i].ang_vel + + simulation.grains[j].ang_vel) # Correct old tangential displacement for contact rotation and add new - δ_t0 =simulation.ice_floes[i].contact_parallel_displacement[ic] + δ_t0 =simulation.grains[i].contact_parallel_displacement[ic] δ_t = dot(t, δ_t0 - (n*dot(n, δ_t0))) + vel_t*simulation.time_step # Effective radius R_ij = harmonicMean(r_i, r_j) # Contact area - A_ij = R_ij*min(simulation.ice_floes[i].thickness, - simulation.ice_floes[j].thickness) + A_ij = R_ij*min(simulation.grains[i].thickness, + simulation.grains[j].thickness) # Contact mechanical parameters - if simulation.ice_floes[i].youngs_modulus > 0. && - simulation.ice_floes[j].youngs_modulus > 0. + if simulation.grains[i].youngs_modulus > 0. && + simulation.grains[j].youngs_modulus > 0. - E = harmonicMean(simulation.ice_floes[i].youngs_modulus, - simulation.ice_floes[j].youngs_modulus) - ν = harmonicMean(simulation.ice_floes[i].poissons_ratio, - simulation.ice_floes[j].poissons_ratio) + E = harmonicMean(simulation.grains[i].youngs_modulus, + simulation.grains[j].youngs_modulus) + ν = harmonicMean(simulation.grains[i].poissons_ratio, + simulation.grains[j].poissons_ratio) # Effective normal and tangential stiffness k_n = E*A_ij/R_ij @@ -106,21 +106,21 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) k_t = k_n*2.*(1. - ν^2.)/((2. - ν)*(1. + ν)) # Obermayr et al 2011 else # Micromechanical parameterization: k_n and k_t set explicitly - k_n = harmonicMean(simulation.ice_floes[i].contact_stiffness_normal, - simulation.ice_floes[j].contact_stiffness_normal) + k_n = harmonicMean(simulation.grains[i].contact_stiffness_normal, + simulation.grains[j].contact_stiffness_normal) - k_t = harmonicMean(simulation.ice_floes[i].contact_stiffness_tangential, - simulation.ice_floes[j].contact_stiffness_tangential) + k_t = harmonicMean(simulation.grains[i].contact_stiffness_tangential, + simulation.grains[j].contact_stiffness_tangential) end - γ_n = harmonicMean(simulation.ice_floes[i].contact_viscosity_normal, - simulation.ice_floes[j].contact_viscosity_normal) + γ_n = harmonicMean(simulation.grains[i].contact_viscosity_normal, + simulation.grains[j].contact_viscosity_normal) - γ_t = harmonicMean(simulation.ice_floes[i].contact_viscosity_tangential, - simulation.ice_floes[j].contact_viscosity_tangential) + γ_t = harmonicMean(simulation.grains[i].contact_viscosity_tangential, + simulation.grains[j].contact_viscosity_tangential) - μ_d_minimum = min(simulation.ice_floes[i].contact_dynamic_friction, - simulation.ice_floes[j].contact_dynamic_friction) + μ_d_minimum = min(simulation.grains[i].contact_dynamic_friction, + simulation.grains[j].contact_dynamic_friction) # Determine contact forces if k_n ≈ 0. && γ_n ≈ 0. @@ -144,19 +144,19 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) if δ_n > 0. # linearly increase tensile strength with time until max. value - tensile_strength = min(simulation.ice_floes[i].contact_age[ic]/ - max(simulation.ice_floes[i].tensile_heal_rate, + tensile_strength = min(simulation.grains[i].contact_age[ic]/ + max(simulation.grains[i].tensile_heal_rate, 1e-12), 1.)* - simulation.ice_floes[i].tensile_strength + simulation.grains[i].tensile_strength # break bond if abs(force_n) >= tensile_strength*A_ij force_n = 0. force_t = 0. - simulation.ice_floes[i].contacts[ic] = 0 # remove contact - simulation.ice_floes[i].n_contacts -= 1 - simulation.ice_floes[j].n_contacts -= 1 + simulation.grains[i].contacts[ic] = 0 # remove contact + simulation.grains[i].n_contacts -= 1 + simulation.grains[j].n_contacts -= 1 end end @@ -185,18 +185,18 @@ function interactIceFloes!(simulation::Simulation, i::Int, j::Int, ic::Int) error("unknown contact_tangential_rheology (k_t = $k_t, γ_t = $γ_t") end - simulation.ice_floes[i].contact_parallel_displacement[ic] = δ_t*t - simulation.ice_floes[i].contact_age[ic] += simulation.time_step + simulation.grains[i].contact_parallel_displacement[ic] = δ_t*t + simulation.grains[i].contact_age[ic] += simulation.time_step - simulation.ice_floes[i].force += force_n*n + force_t*t; - simulation.ice_floes[j].force -= force_n*n + force_t*t; + simulation.grains[i].force += force_n*n + force_t*t; + simulation.grains[j].force -= force_n*n + force_t*t; - simulation.ice_floes[i].torque += -force_t*R_ij - simulation.ice_floes[j].torque += -force_t*R_ij + simulation.grains[i].torque += -force_t*R_ij + simulation.grains[j].torque += -force_t*R_ij - simulation.ice_floes[i].pressure += - force_n/simulation.ice_floes[i].side_surface_area; - simulation.ice_floes[j].pressure += - force_n/simulation.ice_floes[j].side_surface_area; + simulation.grains[i].pressure += + force_n/simulation.grains[i].side_surface_area; + simulation.grains[j].pressure += + force_n/simulation.grains[j].side_surface_area; nothing end diff --git a/src/io.jl b/src/io.jl @@ -205,7 +205,7 @@ end export writeVTK """ -Write a VTK file to disk containing all ice floes in the `simulation` in an +Write a VTK file to disk containing all grains in the `simulation` in an unstructured mesh (file type `.vtu`). These files can be read by ParaView and can be visualized by applying a *Glyph* filter. @@ -225,13 +225,13 @@ function writeVTK(simulation::Simulation; folder = folder * "/" * simulation.id mkpath(folder) - filename = string(folder, "/", simulation.id, ".icefloes.", + filename = string(folder, "/", simulation.id, ".grains.", simulation.file_number) - writeIceFloeVTK(simulation, filename, verbose=verbose) + writeGrainVTK(simulation, filename, verbose=verbose) - filename = string(folder, "/", simulation.id, ".icefloe-interaction.", + filename = string(folder, "/", simulation.id, ".grain-interaction.", simulation.file_number) - writeIceFloeInteractionVTK(simulation, filename, verbose=verbose) + writeGrainInteractionVTK(simulation, filename, verbose=verbose) if typeof(simulation.ocean.input_file) != Bool && ocean filename = string(folder, "/", simulation.id, ".ocean.", @@ -247,18 +247,18 @@ function writeVTK(simulation::Simulation; nothing end -export writeIceFloeVTK +export writeGrainVTK """ -Write a VTK file to disk containing all ice floes in the `simulation` in an +Write a VTK file to disk containing all grains in the `simulation` in an unstructured mesh (file type `.vtu`). These files can be read by ParaView and can be visualized by applying a *Glyph* filter. This function is called by `writeVTK()`. """ -function writeIceFloeVTK(simulation::Simulation, +function writeGrainVTK(simulation::Simulation, filename::String; verbose::Bool=false) - ifarr = convertIceFloeDataToArrays(simulation) + ifarr = convertGrainDataToArrays(simulation) # add arrays to VTK file vtkfile = WriteVTK.vtk_grid(filename, ifarr.lin_pos, WriteVTK.MeshCell[]) @@ -341,7 +341,7 @@ function writeIceFloeVTK(simulation::Simulation, WriteVTK.vtk_point_data(vtkfile, ifarr.atmosphere_stress, "Atmosphere stress [Pa]") - deleteIceFloeArrays!(ifarr) + deleteGrainArrays!(ifarr) ifarr = 0 gc() @@ -352,16 +352,16 @@ function writeIceFloeVTK(simulation::Simulation, nothing end -export writeIceFloeInteractionVTK +export writeGrainInteractionVTK """ - writeIceFloeInteractionVTK(simulation::Simulation, + writeGrainInteractionVTK(simulation::Simulation, filename::String; verbose::Bool=false) -Saves ice-floe interactions to `.vtp` files for visualization with VTK, for +Saves grain interactions to `.vtp` files for visualization with VTK, for example in Paraview. Convert Cell Data to Point Data and use with Tube filter. """ -function writeIceFloeInteractionVTK(simulation::Simulation, +function writeGrainInteractionVTK(simulation::Simulation, filename::String; verbose::Bool=false) @@ -375,38 +375,38 @@ function writeIceFloeInteractionVTK(simulation::Simulation, tensile_stress = Float64[] shear_displacement = Vector{Float64}[] contact_age = Float64[] - for i=1:length(simulation.ice_floes) + for i=1:length(simulation.grains) for ic=1:simulation.Nc_max - if simulation.ice_floes[i].contacts[ic] > 0 - j = simulation.ice_floes[i].contacts[ic] + if simulation.grains[i].contacts[ic] > 0 + j = simulation.grains[i].contacts[ic] - if !simulation.ice_floes[i].enabled || - !simulation.ice_floes[j].enabled + if !simulation.grains[i].enabled || + !simulation.grains[j].enabled continue end - p = simulation.ice_floes[i].lin_pos - - simulation.ice_floes[j].lin_pos + p = simulation.grains[i].lin_pos - + simulation.grains[j].lin_pos dist = norm(p) - r_i = simulation.ice_floes[i].contact_radius - r_j = simulation.ice_floes[j].contact_radius + r_i = simulation.grains[i].contact_radius + r_j = simulation.grains[j].contact_radius δ_n = dist - (r_i + r_j) R_ij = harmonicMean(r_i, r_j) - if simulation.ice_floes[i].youngs_modulus > 0. && - simulation.ice_floes[j].youngs_modulus > 0. - E_ij = harmonicMean(simulation.ice_floes[i]. + if simulation.grains[i].youngs_modulus > 0. && + simulation.grains[j].youngs_modulus > 0. + E_ij = harmonicMean(simulation.grains[i]. youngs_modulus, - simulation.ice_floes[j]. + simulation.grains[j]. youngs_modulus) - A_ij = R_ij*min(simulation.ice_floes[i].thickness, - simulation.ice_floes[j].thickness) + A_ij = R_ij*min(simulation.grains[i].thickness, + simulation.grains[j].thickness) k_n = E_ij*A_ij/R_ij else - k_n = harmonicMean(simulation.ice_floes[i]. + k_n = harmonicMean(simulation.grains[i]. contact_stiffness_normal, - simulation.ice_floes[j]. + simulation.grains[j]. contact_stiffness_normal) end @@ -421,15 +421,15 @@ function writeIceFloeInteractionVTK(simulation::Simulation, push!(contact_stiffness, k_n) push!(tensile_stress, k_n*δ_n/A_ij) - push!(shear_displacement, simulation.ice_floes[i]. + push!(shear_displacement, simulation.grains[i]. contact_parallel_displacement[ic]) - push!(contact_age, simulation.ice_floes[i].contact_age[ic]) + push!(contact_age, simulation.grains[i].contact_age[ic]) end end end - # Insert a piece for each ice floe interaction using ice floe positions as + # Insert a piece for each grain interaction using grain positions as # coordinates and connect them with lines by referencing their indexes. open(filename * ".vtp", "w") do f write(f, "<?xml version=\"1.0\"?>\n") @@ -437,7 +437,7 @@ function writeIceFloeInteractionVTK(simulation::Simulation, "byte_order=\"LittleEndian\">\n") write(f, " <PolyData>\n") write(f, " <Piece " * - "NumberOfPoints=\"$(length(simulation.ice_floes))\" " * + "NumberOfPoints=\"$(length(simulation.grains))\" " * "NumberOfVerts=\"0\" " * "NumberOfLines=\"$(length(i1))\" " * "NumberOfStrips=\"0\" " * @@ -524,11 +524,11 @@ function writeIceFloeInteractionVTK(simulation::Simulation, write(f, " </CellData>\n") write(f, " <Points>\n") - # Write line endpoints (ice floe centers) + # Write line endpoints (grain centers) #write(f, " <DataArray Name=\"Position [m]\" type=\"Float32\" " * write(f, " <DataArray type=\"Float32\" Name=\"Points\" " * "NumberOfComponents=\"3\" format=\"ascii\">\n") - for i in simulation.ice_floes + for i in simulation.grains @inbounds write(f, "$(i.lin_pos[1]) $(i.lin_pos[2]) 0.0 ") end write(f, "\n") @@ -678,7 +678,7 @@ function writeParaviewPythonScript(simulation::Simulation; width::Integer=1920, height::Integer=1080, framerate::Integer=10, - ice_floes_color_scheme::String="X Ray", + grains_color_scheme::String="X Ray", verbose::Bool=true) if filename == "" folder = string(folder, "/", simulation.id) @@ -694,12 +694,12 @@ function writeParaviewPythonScript(simulation::Simulation; paraview.simple._DisableFirstRenderCameraReset() FileName=[""") for i=1:simulation.file_number - write(f, "'$(vtk_folder)/$(simulation.id).icefloes.$(i).vtu', ") + write(f, "'$(vtk_folder)/$(simulation.id).grains.$(i).vtu', ") end write(f, """] -imageicefloes = XMLUnstructuredGridReader(FileName=FileName) +imagegrains = XMLUnstructuredGridReader(FileName=FileName) -imageicefloes.PointArrayStatus = [ +imagegrains.PointArrayStatus = [ 'Density [kg m^-3]', 'Thickness [m]', 'Diameter (contact) [m]', @@ -751,41 +751,41 @@ renderView1 = GetActiveViewOrCreate('RenderView') # renderView1.ViewSize = [2478, 1570] # show data in view -imageicefloesDisplay = Show(imageicefloes, renderView1) +imagegrainsDisplay = Show(imagegrains, renderView1) # trace defaults for the display properties. -imageicefloesDisplay.Representation = 'Surface' -imageicefloesDisplay.AmbientColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.ColorArrayName = [None, ''] -imageicefloesDisplay.OSPRayScaleArray = 'Angular acceleration [rad s^-2]' -imageicefloesDisplay.OSPRayScaleFunction = 'PiecewiseFunction' -imageicefloesDisplay.SelectOrientationVectors = 'Angular acceleration [rad s^-2]' -imageicefloesDisplay.ScaleFactor = 6.050000000000001 -imageicefloesDisplay.SelectScaleArray = 'Angular acceleration [rad s^-2]' -imageicefloesDisplay.GlyphType = 'Arrow' -imageicefloesDisplay.GlyphTableIndexArray = 'Angular acceleration [rad s^-2]' -imageicefloesDisplay.DataAxesGrid = 'GridAxesRepresentation' -imageicefloesDisplay.PolarAxes = 'PolarAxesRepresentation' -imageicefloesDisplay.ScalarOpacityUnitDistance = 64.20669746996803 -imageicefloesDisplay.GaussianRadius = 3.0250000000000004 -imageicefloesDisplay.SetScaleArray = ['POINTS', 'Atmosphere drag coefficient (horizontal) [-]'] -imageicefloesDisplay.ScaleTransferFunction = 'PiecewiseFunction' -imageicefloesDisplay.OpacityArray = ['POINTS', 'Atmosphere drag coefficient (horizontal) [-]'] -imageicefloesDisplay.OpacityTransferFunction = 'PiecewiseFunction' +imagegrainsDisplay.Representation = 'Surface' +imagegrainsDisplay.AmbientColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.ColorArrayName = [None, ''] +imagegrainsDisplay.OSPRayScaleArray = 'Angular acceleration [rad s^-2]' +imagegrainsDisplay.OSPRayScaleFunction = 'PiecewiseFunction' +imagegrainsDisplay.SelectOrientationVectors = 'Angular acceleration [rad s^-2]' +imagegrainsDisplay.ScaleFactor = 6.050000000000001 +imagegrainsDisplay.SelectScaleArray = 'Angular acceleration [rad s^-2]' +imagegrainsDisplay.GlyphType = 'Arrow' +imagegrainsDisplay.GlyphTableIndexArray = 'Angular acceleration [rad s^-2]' +imagegrainsDisplay.DataAxesGrid = 'GridAxesRepresentation' +imagegrainsDisplay.PolarAxes = 'PolarAxesRepresentation' +imagegrainsDisplay.ScalarOpacityUnitDistance = 64.20669746996803 +imagegrainsDisplay.GaussianRadius = 3.0250000000000004 +imagegrainsDisplay.SetScaleArray = ['POINTS', 'Atmosphere drag coefficient (horizontal) [-]'] +imagegrainsDisplay.ScaleTransferFunction = 'PiecewiseFunction' +imagegrainsDisplay.OpacityArray = ['POINTS', 'Atmosphere drag coefficient (horizontal) [-]'] +imagegrainsDisplay.OpacityTransferFunction = 'PiecewiseFunction' # init the 'GridAxesRepresentation' selected for 'DataAxesGrid' -imageicefloesDisplay.DataAxesGrid.XTitleColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.YTitleColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.ZTitleColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.GridColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.XLabelColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.YLabelColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.DataAxesGrid.ZLabelColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.XTitleColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.YTitleColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.ZTitleColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.GridColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.XLabelColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.YLabelColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.DataAxesGrid.ZLabelColor = [0.0, 0.0, 0.0] # init the 'PolarAxesRepresentation' selected for 'PolarAxes' -imageicefloesDisplay.PolarAxes.PolarAxisTitleColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.PolarAxes.PolarAxisLabelColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.PolarAxes.LastRadialAxisTextColor = [0.0, 0.0, 0.0] -imageicefloesDisplay.PolarAxes.SecondaryRadialAxesTextColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.PolarAxes.PolarAxisTitleColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.PolarAxes.PolarAxisLabelColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.PolarAxes.LastRadialAxisTextColor = [0.0, 0.0, 0.0] +imagegrainsDisplay.PolarAxes.SecondaryRadialAxesTextColor = [0.0, 0.0, 0.0] # reset view to fit data renderView1.ResetCamera() @@ -797,7 +797,7 @@ renderView1.InteractionMode = '2D' renderView1.Update() # create a new 'Glyph' -glyph1 = Glyph(Input=imageicefloes, +glyph1 = Glyph(Input=imagegrains, GlyphType='Arrow') glyph1.Scalars = ['POINTS', 'Atmosphere drag coefficient (horizontal) [-]'] glyph1.Vectors = ['POINTS', 'Angular acceleration [rad s^-2]'] @@ -876,7 +876,7 @@ glyph1Display.RescaleTransferFunctionToDataRange(False, True) diameterarealmPWF = GetOpacityTransferFunction('Diameterarealm') # Apply a preset using its name. Note this may not work as expected when presets have duplicate names. -diameterarealmLUT.ApplyPreset('$(ice_floes_color_scheme)', True) +diameterarealmLUT.ApplyPreset('$(grains_color_scheme)', True) # Hide orientation axes renderView1.OrientationAxesVisibility = 0 @@ -916,7 +916,7 @@ Wrapper function which calls `writeParaviewPythonScript(...)` and executes it from the shell using the supplied `pvpython` argument. # Arguments -* `simulation::Simulation`: simulation object containing the ice-floe data. +* `simulation::Simulation`: simulation object containing the grain data. * `pvpython::String`: path to the `pvpython` executable to use. By default, the script uses the pvpython in the system PATH. * `images::Bool`: render images to disk (default: true) diff --git a/src/ocean.jl b/src/ocean.jl @@ -259,74 +259,74 @@ function addOceanDrag!(simulation::Simulation) ne = Vector{Float64}(2) nw = Vector{Float64}(2) - for ice_floe in simulation.ice_floes + for grain in simulation.grains - if !ice_floe.enabled + if !grain.enabled continue end - i, j = ice_floe.ocean_grid_pos + i, j = grain.ocean_grid_pos k = 1 x_tilde, y_tilde = getNonDimensionalCellCoordinates(simulation.ocean, i, j, - ice_floe.lin_pos) + grain.lin_pos) if x_tilde < 0. || x_tilde > 1. || y_tilde < 0. || y_tilde > 1. warn(""" relative coordinates outside bounds ($(x_tilde), $(y_tilde)), - pos = $(ice_floe.lin_pos) at i,j = $(i), $(j). + pos = $(grain.lin_pos) at i,j = $(i), $(j). """) end bilinearInterpolation!(uv_interp, u, v, x_tilde, y_tilde, i, j, k, 1) - applyOceanDragToIceFloe!(ice_floe, uv_interp[1], uv_interp[2]) - applyOceanVorticityToIceFloe!(ice_floe, + applyOceanDragToGrain!(grain, uv_interp[1], uv_interp[2]) + applyOceanVorticityToGrain!(grain, curl(simulation.ocean, x_tilde, y_tilde, i, j, k, 1, sw, se, ne, nw)) end nothing end -export applyOceanDragToIceFloe! +export applyOceanDragToGrain! """ Add Stokes-type drag from velocity difference between ocean and a single ice floe. """ -function applyOceanDragToIceFloe!(ice_floe::IceFloeCylindrical, +function applyOceanDragToGrain!(grain::GrainCylindrical, u::Float64, v::Float64) - freeboard = .1*ice_floe.thickness # height above water + freeboard = .1*grain.thickness # height above water rho_o = 1000. # ocean density - draft = ice_floe.thickness - freeboard # height of submerged thickness - length = ice_floe.areal_radius*2. - width = ice_floe.areal_radius*2. + draft = grain.thickness - freeboard # height of submerged thickness + length = grain.areal_radius*2. + width = grain.areal_radius*2. - drag_force = rho_o * (.5*ice_floe.ocean_drag_coeff_vert*width*draft + - ice_floe.ocean_drag_coeff_horiz*length*width) * - ([u, v] - ice_floe.lin_vel)*norm([u, v] - ice_floe.lin_vel) + drag_force = rho_o * (.5*grain.ocean_drag_coeff_vert*width*draft + + grain.ocean_drag_coeff_horiz*length*width) * + ([u, v] - grain.lin_vel)*norm([u, v] - grain.lin_vel) - ice_floe.force += drag_force - ice_floe.ocean_stress = drag_force/ice_floe.horizontal_surface_area + grain.force += drag_force + grain.ocean_stress = drag_force/grain.horizontal_surface_area nothing end -export applyOceanVorticityToIceFloe! +export applyOceanVorticityToGrain! """ Add Stokes-type torque from angular velocity difference between ocean and a -single ice floe. See Eq. 9.28 in "Introduction to Fluid Mechanics" by Nakayama +single grain. See Eq. 9.28 in "Introduction to Fluid Mechanics" by Nakayama and Boucher, 1999. """ -function applyOceanVorticityToIceFloe!(ice_floe::IceFloeCylindrical, +function applyOceanVorticityToGrain!(grain::GrainCylindrical, ocean_curl::Float64) - freeboard = .1*ice_floe.thickness # height above water + freeboard = .1*grain.thickness # height above water rho_o = 1000. # ocean density - draft = ice_floe.thickness - freeboard # height of submerged thickness + draft = grain.thickness - freeboard # height of submerged thickness - ice_floe.torque += - pi*ice_floe.areal_radius^4.*rho_o* - (ice_floe.areal_radius/5.*ice_floe.ocean_drag_coeff_horiz + - draft*ice_floe.ocean_drag_coeff_vert)* - abs(.5*ocean_curl - ice_floe.ang_vel)*(.5*ocean_curl - ice_floe.ang_vel) + grain.torque += + pi*grain.areal_radius^4.*rho_o* + (grain.areal_radius/5.*grain.ocean_drag_coeff_horiz + + draft*grain.ocean_drag_coeff_vert)* + abs(.5*ocean_curl - grain.ang_vel)*(.5*ocean_curl - grain.ang_vel) nothing end @@ -355,8 +355,8 @@ function compareOceans(ocean1::Ocean, ocean2::Ocean) Base.Test.@test ocean1.h ≈ ocean2.h Base.Test.@test ocean1.e ≈ ocean2.e - if isassigned(ocean1.ice_floe_list, 1) - Base.Test.@test ocean1.ice_floe_list == ocean2.ice_floe_list + if isassigned(ocean1.grain_list, 1) + Base.Test.@test ocean1.grain_list == ocean2.grain_list end nothing end diff --git a/src/packing.jl b/src/packing.jl @@ -1,4 +1,4 @@ -## Functions for creating ice-floe packings +## Functions for creating grain packings """ Return random point in spherical annulus between `(r_i + r_j)` and `2.*(r_i + r_j)` around `x_i`. Note: there is slightly higher point density towards (r_i + @@ -18,10 +18,10 @@ Generate disc packing in 2D using Poisson disc sampling with O(N) complexity, as described by [Robert Bridson (2007)](http://www.cs.ubc.ca/~rbridson/docs/bridson-siggraph07-poissondisk.pdf). # Arguments -* `simulation::Simulation`: simulation object where ice floes are inserted. -* `radius_max::Real`: largest ice-floe radius to use. -* `radius_min::Real`: smallest ice-floe radius to use. -* `sample_limit::Integer=30`: number of points to sample around each ice floe +* `simulation::Simulation`: simulation object where grains are inserted. +* `radius_max::Real`: largest grain radius to use. +* `radius_min::Real`: smallest grain radius to use. +* `sample_limit::Integer=30`: number of points to sample around each grain before giving up. * `max_padding_factor::Real=2.`: this factor scales the padding to use during ice floe generation in numbers of grain diameters. @@ -52,15 +52,15 @@ function poissonDiscSampling(simulation::Simulation; width_y = nw[2] - sw[2] # assume regular grid # Step 1: If grid is empty: select random initial sample and save its index - # to the background grid. Else: Make all ice floes active for search - if isempty(simulation.ice_floes) + # to the background grid. Else: Make all grains active for search + if isempty(simulation.grains) r = rand()*(radius_max - radius_min) + radius_min x0 = rand(2).*[width_x, width_y] + sw - addIceFloeCylindrical!(simulation, x0, r, thickness) - sortIceFloesInGrid!(simulation, grid) + addGrainCylindrical!(simulation, x0, r, thickness) + sortGrainsInGrid!(simulation, grid) push!(active_list, 1) else - for i=1:length(simulation.ice_floes) + for i=1:length(simulation.grains) push!(active_list, i) end end @@ -75,8 +75,8 @@ function poissonDiscSampling(simulation::Simulation; i = rand(1:length(active_list)) deleteat!(active_list, i) - x_i = simulation.ice_floes[i].lin_pos - r_i = simulation.ice_floes[i].contact_radius + x_i = simulation.grains[i].lin_pos + r_i = simulation.grains[i].contact_radius r_j = rand()*(radius_max - radius_min) + radius_min for j=1:sample_limit diff --git a/src/simulation.jl b/src/simulation.jl @@ -9,12 +9,12 @@ export createSimulation time_step::Float64=-1., file_time_step::Float64=-1., file_number::Int=0, - ice_floes=Array{IceFloeCylindrical, 1}[], + grains=Array{GrainCylindrical, 1}[], ocean::Ocean, atmosphere::Atmosphere) Create a simulation object containing all relevant variables such as temporal -parameters, and lists of ice floes 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. @@ -27,7 +27,7 @@ function createSimulation(;id::String="unnamed", file_time_step::Float64=-1., file_number::Int=0, file_time_since_output_file::Float64=0., - ice_floes=Array{IceFloeCylindrical, 1}[], + grains=Array{GrainCylindrical, 1}[], ocean::Ocean=createEmptyOcean(), atmosphere::Atmosphere=createEmptyAtmosphere(), Nc_max::Int=16) @@ -40,7 +40,7 @@ function createSimulation(;id::String="unnamed", file_time_step, file_number, file_time_since_output_file, - ice_floes, + grains, ocean, atmosphere, Nc_max) @@ -57,7 +57,7 @@ export run! write_jld = false) Run the `simulation` through time until `simulation.time` equals or exceeds -`simulatim.time_total`. This function requires that all ice floes are added to +`simulatim.time_total`. This function requires that all grains are added to the simulation and that the length of the computational time step is adjusted accordingly. @@ -77,9 +77,9 @@ to disk. this causes `simulation.time` to exceed `simulation.time_total`, the latter is increased accordingly. * `temporal_integration_method::String="Three-term Taylor"`: type of integration - method to use. See `updateIceFloeKinematics` for details. + method to use. See `updateGrainKinematics` for details. * `write_jld::Bool=false`: write simulation state to disk as JLD files (see - `SeaIce.writeSimulation(...)` whenever saving VTK output. + `Granular.writeSimulation(...)` whenever saving VTK output. """ function run!(simulation::Simulation; verbose::Bool=true, @@ -139,16 +139,16 @@ function run!(simulation::Simulation; if typeof(simulation.atmosphere.input_file) != Bool && !simulation.atmosphere.collocated_with_ocean_grid - sortIceFloesInGrid!(simulation, simulation.atmosphere) + sortGrainsInGrid!(simulation, simulation.atmosphere) end if typeof(simulation.ocean.input_file) != Bool - sortIceFloesInGrid!(simulation, simulation.ocean) + sortGrainsInGrid!(simulation, simulation.ocean) findContacts!(simulation, method="ocean grid") if simulation.atmosphere.collocated_with_ocean_grid copyGridSortingInfo!(simulation.ocean, simulation.atmosphere, - simulation.ice_floes) + simulation.grains) end elseif typeof(simulation.atmosphere.input_file) != Bool @@ -168,7 +168,7 @@ function run!(simulation::Simulation; addAtmosphereDrag!(simulation) end - updateIceFloeKinematics!(simulation, method=temporal_integration_method) + updateGrainKinematics!(simulation, method=temporal_integration_method) # Update time variables simulation.time_iteration += 1 @@ -195,43 +195,43 @@ function run!(simulation::Simulation; nothing end -export addIceFloe! +export addGrain! """ - addIceFloe!(simulation::Simulation, - icefloe::IceFloeCylindrical, + addGrain!(simulation::Simulation, + grain::GrainCylindrical, verbose::Bool = False) -Add an `icefloe` to the `simulation` object. If `verbose` is true, a short +Add an `grain` to the `simulation` object. If `verbose` is true, a short confirmation message will be printed to stdout. """ -function addIceFloe!(simulation::Simulation, - icefloe::IceFloeCylindrical, +function addGrain!(simulation::Simulation, + grain::GrainCylindrical, verbose::Bool = False) - push!(simulation.ice_floes, icefloe) + push!(simulation.grains, grain) if verbose - info("Added IceFloe $(length(simulation.ice_floes))") + info("Added Grain $(length(simulation.grains))") end nothing end -export disableIceFloe! -"Disable ice floe with index `i` in the `simulation` object." -function disableIceFloe!(simulation::Simulation, i::Int) +export disableGrain! +"Disable grain with index `i` in the `simulation` object." +function disableGrain!(simulation::Simulation, i::Int) if i < 1 error("Index must be greater than 0 (i = $i)") end - simulation.ice_floes[i].enabled = false + simulation.grains[i].enabled = false nothing end export zeroForcesAndTorques! -"Sets the `force` and `torque` values of all ice floes to zero." +"Sets the `force` and `torque` values of all grains to zero." function zeroForcesAndTorques!(simulation::Simulation) - for icefloe in simulation.ice_floes - fill!(icefloe.force, 0.) - icefloe.torque = 0. - icefloe.pressure = 0. + for grain in simulation.grains + fill!(grain.force, 0.) + grain.torque = 0. + grain.pressure = 0. end nothing end @@ -263,8 +263,8 @@ function compareSimulations(sim1::Simulation, sim2::Simulation) Base.Test.@test sim1.file_time_since_output_file ≈ sim2.file_time_since_output_file - for i=1:length(sim1.ice_floes) - compareIceFloes(sim1.ice_floes[i], sim2.ice_floes[i]) + for i=1:length(sim1.grains) + compareGrains(sim1.grains[i], sim2.grains[i]) end compareOceans(sim1.ocean, sim2.ocean) compareAtmospheres(sim1.atmosphere, sim2.atmosphere) @@ -284,8 +284,8 @@ function printMemoryUsage(sim::Simulation) reportMemory(sim, "sim") println(" where:") - reportMemory(sim.ice_floes, " sim.ice_floes", - "(N=$(length(sim.ice_floes)))") + reportMemory(sim.grains, " sim.grains", + "(N=$(length(sim.grains)))") reportMemory(sim.ocean, " sim.ocean", "($(size(sim.ocean.xh, 1))x" * diff --git a/src/temporal.jl b/src/temporal.jl @@ -82,41 +82,41 @@ function checkTimeParameters(simulation::Simulation; single_step::Bool=false) nothing end -export findSmallestIceFloeMass -"Finds the smallest mass of all ice floes in a simulation. Used to determine +export findSmallestGrainMass +"Finds the smallest mass of all grains in a simulation. Used to determine the optimal time step length." -function findSmallestIceFloeMass(simulation::Simulation) +function findSmallestGrainMass(simulation::Simulation) m_min = 1e20 i_min = -1 - for i=1:length(simulation.ice_floes) - @inbounds icefloe = simulation.ice_floes[i] - if icefloe.mass < m_min - m_min = icefloe.mass + for i=1:length(simulation.grains) + @inbounds grain = simulation.grains[i] + if grain.mass < m_min + m_min = grain.mass i_min = i end end return m_min, i_min end -export findLargestIceFloeStiffness -"Finds the largest elastic stiffness of all ice floes in a simulation. Used to +export findLargestGrainStiffness +"Finds the largest elastic stiffness of all grains in a simulation. Used to determine the optimal time step length." -function findLargestIceFloeStiffness(simulation::Simulation) +function findLargestGrainStiffness(simulation::Simulation) k_n_max = 0. k_t_max = 0. i_n_max = -1 i_t_max = -1 - for i=1:length(simulation.ice_floes) + for i=1:length(simulation.grains) - @inbounds icefloe = simulation.ice_floes[i] + @inbounds grain = simulation.grains[i] - if icefloe.youngs_modulus > 0. - k_n = icefloe.youngs_modulus*icefloe.thickness # A = h*r - k_t = k_n*2.*(1. - icefloe.poissons_ratio^2.)/ - ((2. - icefloe.poissons_ratio)*(1. + icefloe.poissons_ratio)) + if grain.youngs_modulus > 0. + k_n = grain.youngs_modulus*grain.thickness # A = h*r + k_t = k_n*2.*(1. - grain.poissons_ratio^2.)/ + ((2. - grain.poissons_ratio)*(1. + grain.poissons_ratio)) else - k_n = icefloe.contact_stiffness_normal - k_t = icefloe.contact_stiffness_tangential + k_n = grain.contact_stiffness_normal + k_t = grain.contact_stiffness_tangential end if k_n > k_n_max @@ -139,12 +139,12 @@ stiffnesses, and grain density. Uses the scheme by Radjaii et al. 2011. function setTimeStep!(simulation::Simulation; epsilon::Float64=0.07, verbose::Bool=true) - if length(simulation.ice_floes) < 1 + if length(simulation.grains) < 1 error("At least 1 grain is needed to find the computational time step.") end - k_n_max, k_t_max, _, _ = findLargestIceFloeStiffness(simulation) - m_min, _ = findSmallestIceFloeMass(simulation) + k_n_max, k_t_max, _, _ = findLargestGrainStiffness(simulation) + m_min, _ = findSmallestGrainMass(simulation) simulation.time_step = epsilon/(sqrt(maximum([k_n_max, k_t_max])/m_min)) diff --git a/src/temporal_integration.jl b/src/temporal_integration.jl @@ -1,37 +1,37 @@ -export updateIceFloeKinematics! +export updateGrainKinematics! """ - updateIceFloeKinematics!(simulation::Simulation[, + updateGrainKinematics!(simulation::Simulation[, method::String = "Three-term Taylor"]) -Update the ice floe kinematic parameters using a temporal integration scheme, +Update the grain kinematic parameters using a temporal integration scheme, the current force and torque balance, and gravitational acceleration. # Arguments -* `simulation::Simulation`: update the ice floe positions in this object +* `simulation::Simulation`: update the grain positions in this object according to temporal integration of length `simulation.time_step`. * `method::String = "Three-term Taylor"`: the integration method to use. Available methods are "Two-term Taylor" and "Three-term Taylor". The three-term Taylor expansion is slightly more computationally expensive than the two-term Taylor expansion, but offers an order-of-magnitude increase in - precision of ice floe positions. The two-term expansion can obtain similar + precision of grain positions. The two-term expansion can obtain similar precision if the time step is 1/10 the length. """ -function updateIceFloeKinematics!(simulation::Simulation; +function updateGrainKinematics!(simulation::Simulation; method::String = "Three-term Taylor") if method == "Two-term Taylor" - for ice_floe in simulation.ice_floes - if !ice_floe.enabled + for grain in simulation.grains + if !grain.enabled continue end - updateIceFloeKinematicsTwoTermTaylor!(ice_floe, simulation) + updateGrainKinematicsTwoTermTaylor!(grain, simulation) end elseif method == "Three-term Taylor" - for ice_floe in simulation.ice_floes - if !ice_floe.enabled + for grain in simulation.grains + if !grain.enabled continue end - updateIceFloeKinematicsThreeTermTaylor!(ice_floe, simulation) + updateGrainKinematicsThreeTermTaylor!(grain, simulation) end else error("Unknown integration method '$method'") @@ -39,77 +39,77 @@ function updateIceFloeKinematics!(simulation::Simulation; nothing end -export updateIceFloeKinematicsTwoTermTaylor! +export updateGrainKinematicsTwoTermTaylor! """ Use a two-term Taylor expansion for integrating the kinematic degrees of freedom -for an `icefloe`. +for an `grain`. """ -function updateIceFloeKinematicsTwoTermTaylor!(icefloe::IceFloeCylindrical, +function updateGrainKinematicsTwoTermTaylor!(grain::GrainCylindrical, simulation::Simulation) - icefloe.lin_acc = icefloe.force/icefloe.mass - icefloe.ang_acc = icefloe.torque/icefloe.moment_of_inertia + grain.lin_acc = grain.force/grain.mass + grain.ang_acc = grain.torque/grain.moment_of_inertia - if icefloe.fixed - fill!(icefloe.lin_acc, 0.) - icefloe.ang_acc = 0. - elseif !icefloe.rotating - icefloe.ang_acc = 0. + if grain.fixed + fill!(grain.lin_acc, 0.) + grain.ang_acc = 0. + elseif !grain.rotating + grain.ang_acc = 0. end - icefloe.lin_pos += - icefloe.lin_vel * simulation.time_step + - 0.5*icefloe.lin_acc * simulation.time_step^2.0 - icefloe.ang_pos += - icefloe.ang_vel * simulation.time_step + - 0.5*icefloe.ang_acc * simulation.time_step^2.0 + grain.lin_pos += + grain.lin_vel * simulation.time_step + + 0.5*grain.lin_acc * simulation.time_step^2.0 + grain.ang_pos += + grain.ang_vel * simulation.time_step + + 0.5*grain.ang_acc * simulation.time_step^2.0 - icefloe.lin_vel += icefloe.lin_acc * simulation.time_step - icefloe.ang_vel += icefloe.ang_acc * simulation.time_step + grain.lin_vel += grain.lin_acc * simulation.time_step + grain.ang_vel += grain.ang_acc * simulation.time_step nothing end -export updateIceFloeKinematicsThreeTermTaylor! +export updateGrainKinematicsThreeTermTaylor! """ Use a three-term Taylor expansion for integrating the kinematic degrees of -freedom for an `icefloe`. +freedom for an `grain`. """ -function updateIceFloeKinematicsThreeTermTaylor!(icefloe::IceFloeCylindrical, +function updateGrainKinematicsThreeTermTaylor!(grain::GrainCylindrical, simulation::Simulation) if simulation.time_iteration == 0 lin_acc_0 = zeros(2) ang_acc_0 = 0. else - lin_acc_0 = icefloe.lin_acc - ang_acc_0 = icefloe.ang_acc + lin_acc_0 = grain.lin_acc + ang_acc_0 = grain.ang_acc end - icefloe.lin_acc = icefloe.force/icefloe.mass - icefloe.ang_acc = icefloe.torque/icefloe.moment_of_inertia + grain.lin_acc = grain.force/grain.mass + grain.ang_acc = grain.torque/grain.moment_of_inertia - if icefloe.fixed - fill!(icefloe.lin_acc, 0.) - icefloe.ang_acc = 0. - elseif !icefloe.rotating - icefloe.ang_acc = 0. + if grain.fixed + fill!(grain.lin_acc, 0.) + grain.ang_acc = 0. + elseif !grain.rotating + grain.ang_acc = 0. end # Temporal gradient in acceleration using backwards differences - d_lin_acc_dt = (icefloe.lin_acc - lin_acc_0)/simulation.time_step - d_ang_acc_dt = (icefloe.ang_acc - ang_acc_0)/simulation.time_step + d_lin_acc_dt = (grain.lin_acc - lin_acc_0)/simulation.time_step + d_ang_acc_dt = (grain.ang_acc - ang_acc_0)/simulation.time_step - icefloe.lin_pos += - icefloe.lin_vel * simulation.time_step + - 0.5 * icefloe.lin_acc * simulation.time_step^2. + + grain.lin_pos += + grain.lin_vel * simulation.time_step + + 0.5 * grain.lin_acc * simulation.time_step^2. + 1./6. * d_lin_acc_dt * simulation.time_step^3. - icefloe.ang_pos += - icefloe.ang_vel * simulation.time_step + - 0.5 * icefloe.ang_acc * simulation.time_step^2. + + grain.ang_pos += + grain.ang_vel * simulation.time_step + + 0.5 * grain.ang_acc * simulation.time_step^2. + 1./6. * d_ang_acc_dt * simulation.time_step^3. - icefloe.lin_vel += icefloe.lin_acc * simulation.time_step + + grain.lin_vel += grain.lin_acc * simulation.time_step + 0.5 * d_lin_acc_dt * simulation.time_step^2. - icefloe.ang_vel += icefloe.ang_acc * simulation.time_step + + grain.ang_vel += grain.ang_acc * simulation.time_step + 0.5 * d_ang_acc_dt * simulation.time_step^2. nothing end diff --git a/test/atmosphere.jl b/test/atmosphere.jl @@ -6,8 +6,8 @@ info("#### $(basename(@__FILE__)) ####") info("Testing regular grid generation") -sim = SeaIce.createSimulation() -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) +sim = Granular.createSimulation() +sim.atmosphere = Granular.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) @test size(sim.atmosphere.xq) == (7, 7) @test size(sim.atmosphere.yq) == (7, 7) @test size(sim.atmosphere.xh) == (6, 6) @@ -24,114 +24,114 @@ sim.atmosphere = SeaIce.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) @test sim.atmosphere.v ≈ zeros(7, 7, 6, 1) info("Testing velocity drag interaction (static atmosphere)") -SeaIce.addIceFloeCylindrical!(sim, [.5, .5], .25, .1) -SeaIce.setTotalTime!(sim, 5.) -SeaIce.setTimeStep!(sim) +Granular.addGrainCylindrical!(sim, [.5, .5], .25, .1) +Granular.setTotalTime!(sim, 5.) +Granular.setTimeStep!(sim) sim_init = deepcopy(sim) -sim.ice_floes[1].lin_vel[1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim.grains[1].lin_vel[1] = 0.1 +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init ≈ E_kin_rot_final # no rotation before or after @test E_kin_lin_init > E_kin_lin_final # linear velocity lost due to atmos drag -@test sim.ice_floes[1].atmosphere_stress[1] < 0. -@test sim.ice_floes[1].atmosphere_stress[2] ≈ 0. +@test sim.grains[1].atmosphere_stress[1] < 0. +@test sim.grains[1].atmosphere_stress[2] ≈ 0. info("Testing velocity drag interaction (static ice floe)") sim = deepcopy(sim_init) sim.atmosphere.v[:, :, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init ≈ E_kin_rot_final # no rotation before or after @test E_kin_lin_init < E_kin_lin_final # linear vel. gained due to atmos drag -@test sim.ice_floes[1].atmosphere_stress[1] ≈ 0. -@test sim.ice_floes[1].atmosphere_stress[2] > 0. +@test sim.grains[1].atmosphere_stress[1] ≈ 0. +@test sim.grains[1].atmosphere_stress[2] > 0. info("Testing vortex interaction (static atmosphere)") sim = deepcopy(sim_init) -sim.ice_floes[1].ang_vel = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim.grains[1].ang_vel = 0.1 +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init > E_kin_rot_final # energy lost to atmosphere -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained info("Testing vortex interaction (static ice floe)") sim = deepcopy(sim_init) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.atmosphere = Granular.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.atmosphere.v[1, :, 1, 1] = -0.1 sim.atmosphere.v[2, :, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to atm vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.atmosphere = Granular.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.atmosphere.v[1, :, 1, 1] = 0.1 sim.atmosphere.v[2, :, 1, 1] = -0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel < 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos < 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel < 0. # check angular velocity orientation +@test sim.grains[1].ang_pos < 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to atm vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.atmosphere = Granular.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.atmosphere.u[:, 1, 1, 1] = -0.1 sim.atmosphere.u[:, 2, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel < 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos < 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel < 0. # check angular velocity orientation +@test sim.grains[1].ang_pos < 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to atm vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.atmosphere = Granular.createRegularAtmosphereGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.atmosphere.u[:, 1, 1, 1] = 0.1 sim.atmosphere.u[:, 2, 1, 1] = -0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to atm vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained -sim = SeaIce.createSimulation() -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) -sim2 = SeaIce.createSimulation() -sim2.atmosphere = SeaIce.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) -SeaIce.compareAtmospheres(sim.atmosphere, sim2.atmosphere) +sim = Granular.createSimulation() +sim.atmosphere = Granular.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) +sim2 = Granular.createSimulation() +sim2.atmosphere = Granular.createRegularAtmosphereGrid([6, 6, 6], [1., 1., 1.]) +Granular.compareAtmospheres(sim.atmosphere, sim2.atmosphere) diff --git a/test/cohesion.jl b/test/cohesion.jl @@ -1,37 +1,37 @@ #!/usr/bin/env julia # Check for conservation of kinetic energy (=momentum) during a normal collision -# between two ice cylindrical ice floes +# between two ice cylindrical grains info("#### $(basename(@__FILE__)) ####") verbose=false -sim_init = SeaIce.createSimulation() -SeaIce.addIceFloeCylindrical!(sim_init, [0., 0.], 10., 1.) -SeaIce.addIceFloeCylindrical!(sim_init, [18., 0.], 10., 1.) -sim_init.ice_floes[1].youngs_modulus = 1e-5 # repulsion is negligible -sim_init.ice_floes[2].youngs_modulus = 1e-5 # repulsion is negligible -SeaIce.setTimeStep!(sim_init, verbose=verbose) +sim_init = Granular.createSimulation() +Granular.addGrainCylindrical!(sim_init, [0., 0.], 10., 1.) +Granular.addGrainCylindrical!(sim_init, [18., 0.], 10., 1.) +sim_init.grains[1].youngs_modulus = 1e-5 # repulsion is negligible +sim_init.grains[2].youngs_modulus = 1e-5 # repulsion is negligible +Granular.setTimeStep!(sim_init, verbose=verbose) info("# Check contact age scheme") sim = deepcopy(sim_init) -SeaIce.setTotalTime!(sim, 10.) +Granular.setTotalTime!(sim, 10.) sim.time_step = 1. -SeaIce.run!(sim, verbose=verbose) -@test sim.ice_floes[1].contact_age[1] ≈ sim.time +Granular.run!(sim, verbose=verbose) +@test sim.grains[1].contact_age[1] ≈ sim.time info("# Check if bonds add tensile strength") -sim = SeaIce.createSimulation(id="cohesion") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., tensile_strength=500e3) -SeaIce.addIceFloeCylindrical!(sim, [20.1, 0.], 10., 1., tensile_strength=500e3) -sim.ice_floes[1].lin_vel[1] = 0.1 -SeaIce.setTimeStep!(sim) -SeaIce.setTotalTime!(sim, 10.) -SeaIce.run!(sim, verbose=verbose) -@test sim.ice_floes[1].lin_vel[1] > 0. -@test sim.ice_floes[1].lin_vel[2] ≈ 0. -@test sim.ice_floes[2].lin_vel[1] > 0. -@test sim.ice_floes[2].lin_vel[2] ≈ 0. -@test sim.ice_floes[1].ang_vel ≈ 0. -@test sim.ice_floes[2].ang_vel ≈ 0. +sim = Granular.createSimulation(id="cohesion") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., tensile_strength=500e3) +Granular.addGrainCylindrical!(sim, [20.1, 0.], 10., 1., tensile_strength=500e3) +sim.grains[1].lin_vel[1] = 0.1 +Granular.setTimeStep!(sim) +Granular.setTotalTime!(sim, 10.) +Granular.run!(sim, verbose=verbose) +@test sim.grains[1].lin_vel[1] > 0. +@test sim.grains[1].lin_vel[2] ≈ 0. +@test sim.grains[2].lin_vel[1] > 0. +@test sim.grains[2].lin_vel[2] ≈ 0. +@test sim.grains[1].ang_vel ≈ 0. +@test sim.grains[2].ang_vel ≈ 0. diff --git a/test/collision-2floes-normal.jl b/test/collision-2floes-normal.jl @@ -1,209 +1,209 @@ #!/usr/bin/env julia # Check for conservation of kinetic energy (=momentum) during a normal collision -# between two ice cylindrical ice floes +# between two ice cylindrical grains info("#### $(basename(@__FILE__)) ####") verbose=false info("# One ice floe fixed") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[2].fixed = true +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[2].fixed = true -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.2 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.2 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("# Adding contact-normal viscosity") info("# One ice floe fixed") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_viscosity_normal = 1e4 -sim.ice_floes[2].contact_viscosity_normal = 1e4 -sim.ice_floes[2].fixed = true +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_viscosity_normal = 1e4 +sim.grains[2].contact_viscosity_normal = 1e4 +sim.grains[2].fixed = true -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_viscosity_normal = 1e4 -sim.ice_floes[2].contact_viscosity_normal = 1e4 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_viscosity_normal = 1e4 +sim.grains[2].contact_viscosity_normal = 1e4 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final diff --git a/test/collision-2floes-oblique.jl b/test/collision-2floes-oblique.jl @@ -1,7 +1,7 @@ #!/usr/bin/env julia # Check for conservation of kinetic energy (=momentum) during a normal collision -# between two ice cylindrical ice floes +# between two ice cylindrical grains info("#### $(basename(@__FILE__)) ####") @@ -9,604 +9,604 @@ verbose=false info("## Contact-normal elasticity only") info("# One ice floe fixed") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19., 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_dynamic_friction = 0. -sim.ice_floes[2].contact_dynamic_friction = 0. -sim.ice_floes[2].fixed = true +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19., 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_dynamic_friction = 0. +sim.grains[2].contact_dynamic_friction = 0. +sim.grains[2].fixed = true -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) #sim.file_time_step = 1. sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.01 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_dynamic_friction = 0. -sim.ice_floes[2].contact_dynamic_friction = 0. +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_dynamic_friction = 0. +sim.grains[2].contact_dynamic_friction = 0. -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.01 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("## Contact-normal elasticity and tangential viscosity and friction") -SeaIce.setTotalTime!(sim, 30.0) -sim_init.ice_floes[1].contact_viscosity_tangential = 1e6 -sim_init.ice_floes[2].contact_viscosity_tangential = 1e6 -sim_init.ice_floes[1].contact_dynamic_friction = 1e2 # no Coulomb sliding -sim_init.ice_floes[2].contact_dynamic_friction = 1e2 # no Coulomb sliding -sim_init.ice_floes[2].fixed = true +Granular.setTotalTime!(sim, 30.0) +sim_init.grains[1].contact_viscosity_tangential = 1e6 +sim_init.grains[2].contact_viscosity_tangential = 1e6 +sim_init.grains[1].contact_dynamic_friction = 1e2 # no Coulomb sliding +sim_init.grains[2].contact_dynamic_friction = 1e2 # no Coulomb sliding +sim_init.grains[2].fixed = true sim = deepcopy(sim_init) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos ≈ 0. -@test sim.ice_floes[2].ang_vel ≈ 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos ≈ 0. +@test sim.grains[2].ang_vel ≈ 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("mu_d = 0.") sim = deepcopy(sim_init) -sim.ice_floes[1].contact_dynamic_friction = 0. -SeaIce.setTimeStep!(sim, epsilon=0.07) +sim.grains[1].contact_dynamic_friction = 0. +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos ≈ 0. -@test sim.ice_floes[1].ang_vel ≈ 0. -@test sim.ice_floes[2].ang_pos ≈ 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos ≈ 0. +@test sim.grains[1].ang_vel ≈ 0. +@test sim.grains[2].ang_pos ≈ 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.1 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos ≈ 0. -@test sim.ice_floes[2].ang_vel ≈ 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos ≈ 0. +@test sim.grains[2].ang_vel ≈ 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.09 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos ≈ 0. -@test sim.ice_floes[2].ang_vel ≈ 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos ≈ 0. +@test sim.grains[2].ang_vel ≈ 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_viscosity_tangential = 1e4 -sim.ice_floes[2].contact_viscosity_tangential = 1e4 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 10.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_viscosity_tangential = 1e4 +sim.grains[2].contact_viscosity_tangential = 1e4 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.04 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.04 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("# Ice floes free to move, mirrored") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, 10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 -sim.ice_floes[1].contact_viscosity_tangential = 1e4 -sim.ice_floes[2].contact_viscosity_tangential = 1e4 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, 10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 +sim.grains[1].contact_viscosity_tangential = 1e4 +sim.grains[2].contact_viscosity_tangential = 1e4 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos > 0. -@test sim.ice_floes[1].ang_vel > 0. -@test sim.ice_floes[2].ang_pos > 0. -@test sim.ice_floes[2].ang_vel > 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos > 0. +@test sim.grains[1].ang_vel > 0. +@test sim.grains[2].ang_pos > 0. +@test sim.grains[2].ang_vel > 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.04 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.04 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos > 0. -@test sim.ice_floes[1].ang_vel > 0. -@test sim.ice_floes[2].ang_pos > 0. -@test sim.ice_floes[2].ang_vel > 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos > 0. +@test sim.grains[1].ang_vel > 0. +@test sim.grains[2].ang_pos > 0. +@test sim.grains[2].ang_vel > 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("# Ice floes free to move, mirrored #2") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.04 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.04 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("# Tangential elasticity, no tangential viscosity, no Coulomb slip") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 -sim.ice_floes[1].contact_dynamic_friction = 1e3 # disable Coulomb slip -sim.ice_floes[2].contact_dynamic_friction = 1e3 # disable Coulomb slip -sim.ice_floes[1].contact_viscosity_tangential = 0. # disable tan. viscosity -sim.ice_floes[2].contact_viscosity_tangential = 0. # disable tan. viscosity -sim.ice_floes[1].contact_stiffness_tangential = - sim.ice_floes[1].contact_stiffness_normal # enable tangential elasticity -sim.ice_floes[2].contact_stiffness_tangential = - sim.ice_floes[2].contact_stiffness_normal # enable tangential elasticity - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 +sim.grains[1].contact_dynamic_friction = 1e3 # disable Coulomb slip +sim.grains[2].contact_dynamic_friction = 1e3 # disable Coulomb slip +sim.grains[1].contact_viscosity_tangential = 0. # disable tan. viscosity +sim.grains[2].contact_viscosity_tangential = 0. # disable tan. viscosity +sim.grains[1].contact_stiffness_tangential = + sim.grains[1].contact_stiffness_normal # enable tangential elasticity +sim.grains[2].contact_stiffness_tangential = + sim.grains[2].contact_stiffness_normal # enable tangential elasticity + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.1 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.04 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.04 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init ≈ E_kin_lin_final+E_kin_rot_final atol=E_kin_lin_init*tol info("# Tangential elasticity, no tangential viscosity, Coulomb slip") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 -sim.ice_floes[1].contact_dynamic_friction = 0.1 # enable Coulomb slip -sim.ice_floes[2].contact_dynamic_friction = 0.1 # enable Coulomb slip -sim.ice_floes[1].contact_viscosity_tangential = 0. # disable tan. viscosity -sim.ice_floes[2].contact_viscosity_tangential = 0. # disable tan. viscosity -sim.ice_floes[1].contact_stiffness_tangential = - sim.ice_floes[1].contact_stiffness_normal # enable tangential elasticity -sim.ice_floes[2].contact_stiffness_tangential = - sim.ice_floes[2].contact_stiffness_normal # enable tangential elasticity - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 +sim.grains[1].contact_dynamic_friction = 0.1 # enable Coulomb slip +sim.grains[2].contact_dynamic_friction = 0.1 # enable Coulomb slip +sim.grains[1].contact_viscosity_tangential = 0. # disable tan. viscosity +sim.grains[2].contact_viscosity_tangential = 0. # disable tan. viscosity +sim.grains[1].contact_stiffness_tangential = + sim.grains[1].contact_stiffness_normal # enable tangential elasticity +sim.grains[2].contact_stiffness_tangential = + sim.grains[2].contact_stiffness_normal # enable tangential elasticity + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.03 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final info("# Tangential elasticity, tangential viscosity, no Coulomb slip") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 -sim.ice_floes[1].contact_dynamic_friction = 1e3 # disable Coulomb slip -sim.ice_floes[2].contact_dynamic_friction = 1e3 # disable Coulomb slip -sim.ice_floes[1].contact_viscosity_tangential = 1e4 # enable tan. viscosity -sim.ice_floes[2].contact_viscosity_tangential = 1e4 # enable tan. viscosity -sim.ice_floes[1].contact_stiffness_tangential = - sim.ice_floes[1].contact_stiffness_normal # enable tangential elasticity -sim.ice_floes[2].contact_stiffness_tangential = - sim.ice_floes[2].contact_stiffness_normal # enable tangential elasticity - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 +sim.grains[1].contact_dynamic_friction = 1e3 # disable Coulomb slip +sim.grains[2].contact_dynamic_friction = 1e3 # disable Coulomb slip +sim.grains[1].contact_viscosity_tangential = 1e4 # enable tan. viscosity +sim.grains[2].contact_viscosity_tangential = 1e4 # enable tan. viscosity +sim.grains[1].contact_stiffness_tangential = + sim.grains[1].contact_stiffness_normal # enable tangential elasticity +sim.grains[2].contact_stiffness_tangential = + sim.grains[2].contact_stiffness_normal # enable tangential elasticity + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.03 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final info("# Tangential elasticity, tangential viscosity, Coulomb slip") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) -sim.ice_floes[2].lin_vel[1] = -0.1 -sim.ice_floes[1].contact_dynamic_friction = 0.1 # enable Coulomb slip -sim.ice_floes[2].contact_dynamic_friction = 0.1 # enable Coulomb slip -sim.ice_floes[1].contact_viscosity_tangential = 1e4 # enable tan. viscosity -sim.ice_floes[2].contact_viscosity_tangential = 1e4 # enable tan. viscosity -sim.ice_floes[1].contact_stiffness_tangential = - sim.ice_floes[1].contact_stiffness_normal # enable tangential elasticity -sim.ice_floes[2].contact_stiffness_tangential = - sim.ice_floes[2].contact_stiffness_normal # enable tangential elasticity - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [19.0, -10.], 10., 1., verbose=verbose) +sim.grains[2].lin_vel[1] = -0.1 +sim.grains[1].contact_dynamic_friction = 0.1 # enable Coulomb slip +sim.grains[2].contact_dynamic_friction = 0.1 # enable Coulomb slip +sim.grains[1].contact_viscosity_tangential = 1e4 # enable tan. viscosity +sim.grains[2].contact_viscosity_tangential = 1e4 # enable tan. viscosity +sim.grains[1].contact_stiffness_tangential = + sim.grains[1].contact_stiffness_normal # enable tangential elasticity +sim.grains[2].contact_stiffness_tangential = + sim.grains[2].contact_stiffness_normal # enable tangential elasticity + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 30.0) +Granular.setTotalTime!(sim, 30.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.03 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -@test sim.ice_floes[1].ang_pos < 0. -@test sim.ice_floes[1].ang_vel < 0. -@test sim.ice_floes[2].ang_pos < 0. -@test sim.ice_floes[2].ang_vel < 0. -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +@test sim.grains[1].ang_pos < 0. +@test sim.grains[1].ang_vel < 0. +@test sim.grains[2].ang_pos < 0. +@test sim.grains[2].ang_vel < 0. +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init+E_kin_rot_init > E_kin_lin_final+E_kin_rot_final diff --git a/test/collision-5floes-normal.jl b/test/collision-5floes-normal.jl @@ -1,278 +1,278 @@ #!/usr/bin/env julia # Check for conservation of kinetic energy (=momentum) during a normal collision -# between two ice cylindrical ice floes +# between two ice cylindrical grains info("#### $(basename(@__FILE__)) ####") verbose=false info("# One ice floe fixed") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[2].fixed = true -sim.ice_floes[3].fixed = true -sim.ice_floes[4].fixed = true -sim.ice_floes[5].fixed = true - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[2].fixed = true +sim.grains[3].fixed = true +sim.grains[4].fixed = true +sim.grains[5].fixed = true + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.2 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final -@test 0. < norm(sim.ice_floes[1].lin_vel) +@test 0. < norm(sim.grains[1].lin_vel) for i=2:5 info("testing ice floe $i") - @test 0. ≈ norm(sim.ice_floes[i].lin_vel) + @test 0. ≈ norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final -@test 0. < norm(sim.ice_floes[1].lin_vel) +@test 0. < norm(sim.grains[1].lin_vel) for i=2:5 info("testing ice floe $i") - @test 0. ≈ norm(sim.ice_floes[i].lin_vel) + @test 0. ≈ norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final -@test 0. < norm(sim.ice_floes[1].lin_vel) +@test 0. < norm(sim.grains[1].lin_vel) for i=2:5 info("testing ice floe $i") - @test 0. ≈ norm(sim.ice_floes[i].lin_vel) + @test 0. ≈ norm(sim.grains[i].lin_vel) end info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 40.0) +Granular.setTotalTime!(sim, 40.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.2 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final for i=1:5 info("testing ice floe $i") - @test 0. < norm(sim.ice_floes[i].lin_vel) + @test 0. < norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final for i=1:5 info("testing ice floe $i") - @test 0. < norm(sim.ice_floes[i].lin_vel) + @test 0. < norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init ≈ E_kin_lin_final atol=E_kin_lin_init*tol @test E_kin_rot_init ≈ E_kin_rot_final for i=1:5 info("testing ice floe $i") - @test 0. < norm(sim.ice_floes[i].lin_vel) + @test 0. < norm(sim.grains[i].lin_vel) end info("# Adding contact-normal viscosity") info("# One ice floe fixed") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_viscosity_normal = 1e4 -sim.ice_floes[2].contact_viscosity_normal = 1e4 -sim.ice_floes[3].contact_viscosity_normal = 1e4 -sim.ice_floes[4].contact_viscosity_normal = 1e4 -sim.ice_floes[5].contact_viscosity_normal = 1e4 -sim.ice_floes[2].fixed = true -sim.ice_floes[3].fixed = true -sim.ice_floes[4].fixed = true -sim.ice_floes[5].fixed = true - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_viscosity_normal = 1e4 +sim.grains[2].contact_viscosity_normal = 1e4 +sim.grains[3].contact_viscosity_normal = 1e4 +sim.grains[4].contact_viscosity_normal = 1e4 +sim.grains[5].contact_viscosity_normal = 1e4 +sim.grains[2].fixed = true +sim.grains[3].fixed = true +sim.grains[4].fixed = true +sim.grains[5].fixed = true + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final -@test 0. < norm(sim.ice_floes[1].lin_vel) +@test 0. < norm(sim.grains[1].lin_vel) for i=2:5 info("testing ice floe $i") - @test 0. ≈ norm(sim.ice_floes[i].lin_vel) + @test 0. ≈ norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final -@test 0. < norm(sim.ice_floes[1].lin_vel) +@test 0. < norm(sim.grains[1].lin_vel) for i=2:5 info("testing ice floe $i") - @test 0. ≈ norm(sim.ice_floes[i].lin_vel) + @test 0. ≈ norm(sim.grains[i].lin_vel) end info("# Ice floes free to move") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) -sim.ice_floes[1].lin_vel[1] = 0.1 -sim.ice_floes[1].contact_viscosity_normal = 1e4 -sim.ice_floes[2].contact_viscosity_normal = 1e4 -sim.ice_floes[3].contact_viscosity_normal = 1e4 -sim.ice_floes[4].contact_viscosity_normal = 1e4 -sim.ice_floes[5].contact_viscosity_normal = 1e4 - -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [40.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [60.05, 0.], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [80.05, 0.], 10., 1., verbose=verbose) +sim.grains[1].lin_vel[1] = 0.1 +sim.grains[1].contact_viscosity_normal = 1e4 +sim.grains[2].contact_viscosity_normal = 1e4 +sim.grains[3].contact_viscosity_normal = 1e4 +sim.grains[4].contact_viscosity_normal = 1e4 +sim.grains[5].contact_viscosity_normal = 1e4 + +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) # With decreasing timestep (epsilon towards 0), the explicit integration scheme # should become more correct -SeaIce.setTotalTime!(sim, 10.0) +Granular.setTotalTime!(sim, 10.0) sim_init = deepcopy(sim) info("Testing kinetic energy conservation with Two-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.007) +Granular.setTimeStep!(sim, epsilon=0.007) tol = 0.02 info("Relative tolerance: $(tol*100.)%") -SeaIce.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) +Granular.run!(sim, temporal_integration_method="Two-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final for i=1:5 info("testing ice floe $i") - @test 0. < norm(sim.ice_floes[i].lin_vel) + @test 0. < norm(sim.grains[i].lin_vel) end info("Testing kinetic energy conservation with Three-term Taylor scheme") sim = deepcopy(sim_init) -SeaIce.setTimeStep!(sim, epsilon=0.07) +Granular.setTimeStep!(sim, epsilon=0.07) tol = 0.01 info("Relative tolerance: $(tol*100.)% with time step: $(sim.time_step)") -SeaIce.run!(sim, temporal_integration_method="Three-term Taylor", +Granular.run!(sim, temporal_integration_method="Three-term Taylor", verbose=verbose) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_lin_init > E_kin_lin_final @test E_kin_rot_init ≈ E_kin_rot_final for i=1:5 info("testing ice floe $i") - @test 0. < norm(sim.ice_floes[i].lin_vel) + @test 0. < norm(sim.grains[i].lin_vel) end diff --git a/test/contact-search-and-geometry.jl b/test/contact-search-and-geometry.jl @@ -4,13 +4,13 @@ info("#### $(basename(@__FILE__)) ####") -info("Testing interIceFloePositionVector(...) and findOverlap(...)") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [18., 0.], 10., 1., verbose=false) +info("Testing interGrainPositionVector(...) and findOverlap(...)") +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [18., 0.], 10., 1., verbose=false) -position_ij = SeaIce.interIceFloePositionVector(sim, 1, 2) -overlap_ij = SeaIce.findOverlap(sim, 1, 2, position_ij) +position_ij = Granular.interGrainPositionVector(sim, 1, 2) +overlap_ij = Granular.findOverlap(sim, 1, 2, position_ij) @test [-18., 0.] ≈ position_ij @test -2. ≈ overlap_ij @@ -18,226 +18,226 @@ overlap_ij = SeaIce.findOverlap(sim, 1, 2, position_ij) info("Testing findContactsAllToAll(...)") sim_copy = deepcopy(sim) -SeaIce.findContactsAllToAll!(sim) +Granular.findContactsAllToAll!(sim) info("Testing findContacts(...)") sim = deepcopy(sim_copy) -SeaIce.findContacts!(sim) +Granular.findContacts!(sim) -sim.ice_floes[1].fixed = true +sim.grains[1].fixed = true # The contact should be registered in ice floe 1, but not ice floe 2 -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts info("Testing findContacts(...)") sim = deepcopy(sim_copy) -SeaIce.findContacts!(sim) +Granular.findContacts!(sim) -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts -@test_throws ErrorException SeaIce.findContacts!(sim, method="") +@test_throws ErrorException Granular.findContacts!(sim, method="") sim = deepcopy(sim_copy) -sim.ice_floes[1].fixed = true -sim.ice_floes[2].fixed = true -SeaIce.findContacts!(sim) +sim.grains[1].fixed = true +sim.grains[2].fixed = true +Granular.findContacts!(sim) for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 0 == sim.ice_floes[1].n_contacts -@test 0 == sim.ice_floes[2].n_contacts +@test 0 == sim.grains[1].n_contacts +@test 0 == sim.grains[2].n_contacts sim = deepcopy(sim_copy) -SeaIce.disableIceFloe!(sim, 1) -SeaIce.findContacts!(sim) +Granular.disableGrain!(sim, 1) +Granular.findContacts!(sim) for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 0 == sim.ice_floes[1].n_contacts -@test 0 == sim.ice_floes[2].n_contacts +@test 0 == sim.grains[1].n_contacts +@test 0 == sim.grains[2].n_contacts sim = deepcopy(sim_copy) -SeaIce.disableIceFloe!(sim, 1) -SeaIce.disableIceFloe!(sim, 2) -SeaIce.findContacts!(sim) +Granular.disableGrain!(sim, 1) +Granular.disableGrain!(sim, 2) +Granular.findContacts!(sim) for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 0 == sim.ice_floes[1].n_contacts -@test 0 == sim.ice_floes[2].n_contacts +@test 0 == sim.grains[1].n_contacts +@test 0 == sim.grains[2].n_contacts info("Testing if interact(...) removes contacts correctly") sim = deepcopy(sim_copy) -SeaIce.findContacts!(sim) -SeaIce.interact!(sim) -SeaIce.findContacts!(sim) +Granular.findContacts!(sim) +Granular.interact!(sim) +Granular.findContacts!(sim) -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts info("Testing findContactsGrid(...)") sim = deepcopy(sim_copy) -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean) -SeaIce.findContactsInGrid!(sim, sim.ocean) +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) +Granular.sortGrainsInGrid!(sim, sim.ocean) +Granular.findContactsInGrid!(sim, sim.ocean) -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts sim = deepcopy(sim_copy) -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) -sim.ice_floes[1].fixed = true -SeaIce.sortIceFloesInGrid!(sim, sim.ocean) -SeaIce.findContactsInGrid!(sim, sim.ocean) +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) +sim.grains[1].fixed = true +Granular.sortGrainsInGrid!(sim, sim.ocean) +Granular.findContactsInGrid!(sim, sim.ocean) -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts sim = deepcopy(sim_copy) -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) -sim.ice_floes[1].fixed = true -sim.ice_floes[2].fixed = true -SeaIce.sortIceFloesInGrid!(sim, sim.ocean) -SeaIce.findContactsInGrid!(sim, sim.ocean) +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) +sim.grains[1].fixed = true +sim.grains[2].fixed = true +Granular.sortGrainsInGrid!(sim, sim.ocean) +Granular.findContactsInGrid!(sim, sim.ocean) for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 0 == sim.ice_floes[1].n_contacts -@test 0 == sim.ice_floes[2].n_contacts +@test 0 == sim.grains[1].n_contacts +@test 0 == sim.grains[2].n_contacts info("Testing findContacts(...)") sim = deepcopy(sim_copy) -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean) -SeaIce.findContacts!(sim) +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [80., 80., 2.]) +Granular.sortGrainsInGrid!(sim, sim.ocean) +Granular.findContacts!(sim) -@test 2 == sim.ice_floes[1].contacts[1] +@test 2 == sim.grains[1].contacts[1] for ic=2:sim.Nc_max - @test 0 == sim.ice_floes[1].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[1].contact_parallel_displacement[ic] + @test 0 == sim.grains[1].contacts[ic] + @test [0., 0.] ≈ sim.grains[1].contact_parallel_displacement[ic] end for ic=1:sim.Nc_max - @test 0 == sim.ice_floes[2].contacts[ic] - @test [0., 0.] ≈ sim.ice_floes[2].contact_parallel_displacement[ic] + @test 0 == sim.grains[2].contacts[ic] + @test [0., 0.] ≈ sim.grains[2].contact_parallel_displacement[ic] end -@test 1 == sim.ice_floes[1].n_contacts -@test 1 == sim.ice_floes[2].n_contacts +@test 1 == sim.grains[1].n_contacts +@test 1 == sim.grains[2].n_contacts -@test_throws ErrorException SeaIce.findContacts!(sim, method="") +@test_throws ErrorException Granular.findContacts!(sim, method="") info("Testing contact registration with multiple contacts") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [2., 2.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [4., 2.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [6., 2.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [2., 4.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [4., 4.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [6., 4.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [2., 6.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [4., 6.], 1.01, 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [6., 6.], 1.01, 1., verbose=false) -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [8., 8., 2.]) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean) -SeaIce.findContacts!(sim) -@test 2 == sim.ice_floes[1].n_contacts -@test 3 == sim.ice_floes[2].n_contacts -@test 2 == sim.ice_floes[3].n_contacts -@test 3 == sim.ice_floes[4].n_contacts -@test 4 == sim.ice_floes[5].n_contacts -@test 3 == sim.ice_floes[6].n_contacts -@test 2 == sim.ice_floes[7].n_contacts -@test 3 == sim.ice_floes[8].n_contacts -@test 2 == sim.ice_floes[9].n_contacts -SeaIce.interact!(sim) -SeaIce.interact!(sim) -SeaIce.interact!(sim) -SeaIce.interact!(sim) -@test 2 == sim.ice_floes[1].n_contacts -@test 3 == sim.ice_floes[2].n_contacts -@test 2 == sim.ice_floes[3].n_contacts -@test 3 == sim.ice_floes[4].n_contacts -@test 4 == sim.ice_floes[5].n_contacts -@test 3 == sim.ice_floes[6].n_contacts -@test 2 == sim.ice_floes[7].n_contacts -@test 3 == sim.ice_floes[8].n_contacts -@test 2 == sim.ice_floes[9].n_contacts +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [2., 2.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [4., 2.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [6., 2.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [2., 4.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [4., 4.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [6., 4.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [2., 6.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [4., 6.], 1.01, 1., verbose=false) +Granular.addGrainCylindrical!(sim, [6., 6.], 1.01, 1., verbose=false) +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [8., 8., 2.]) +Granular.sortGrainsInGrid!(sim, sim.ocean) +Granular.findContacts!(sim) +@test 2 == sim.grains[1].n_contacts +@test 3 == sim.grains[2].n_contacts +@test 2 == sim.grains[3].n_contacts +@test 3 == sim.grains[4].n_contacts +@test 4 == sim.grains[5].n_contacts +@test 3 == sim.grains[6].n_contacts +@test 2 == sim.grains[7].n_contacts +@test 3 == sim.grains[8].n_contacts +@test 2 == sim.grains[9].n_contacts +Granular.interact!(sim) +Granular.interact!(sim) +Granular.interact!(sim) +Granular.interact!(sim) +@test 2 == sim.grains[1].n_contacts +@test 3 == sim.grains[2].n_contacts +@test 2 == sim.grains[3].n_contacts +@test 3 == sim.grains[4].n_contacts +@test 4 == sim.grains[5].n_contacts +@test 3 == sim.grains[6].n_contacts +@test 2 == sim.grains[7].n_contacts +@test 3 == sim.grains[8].n_contacts +@test 2 == sim.grains[9].n_contacts for i=1:9 - sim.ice_floes[i].contact_radius = 0.99 + sim.grains[i].contact_radius = 0.99 end -SeaIce.interact!(sim) +Granular.interact!(sim) for i=1:9 - @test sim.ice_floes[i].n_contacts == 0 + @test sim.grains[i].n_contacts == 0 end diff --git a/test/grain.jl b/test/grain.jl @@ -0,0 +1,44 @@ +#!/usr/bin/env julia + +# Check the basic icefloe functionality + +info("#### $(basename(@__FILE__)) ####") + +info("Writing simple simulation to VTK file") +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) +Granular.printGrainInfo(sim.grains[1]) + + +@test_throws ErrorException Granular.addGrainCylindrical!(sim, [.1, .1, .1], + 10., 1.) +@test_throws ErrorException Granular.addGrainCylindrical!(sim, [.1, .1], + 10., 1., + lin_vel=[.2,.2,.2]) +@test_throws ErrorException Granular.addGrainCylindrical!(sim, [.1, .1], + 10., 1., + lin_acc=[.2,.2,.2]) +@test_throws ErrorException Granular.addGrainCylindrical!(sim, [.1, .1], + 0., 1.) +@test_throws ErrorException Granular.addGrainCylindrical!(sim, [.1, .1], + 10., 1., density=-2.) +@test_throws ErrorException Granular.disableGrain!(sim, 0) + +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) +Granular.compareGrains(sim.grains[1], sim.grains[2]) + +if typeof(Pkg.installed("PyPlot")) == VersionNumber + Granular.plotGrainSizeDistribution(sim) + rm("test-grain-size-distribution.png") + Granular.plotGrainSizeDistribution(sim, skip_fixed=false) + rm("test-grain-size-distribution.png") + Granular.plotGrainSizeDistribution(sim, log_y=false) + rm("test-grain-size-distribution.png") + Granular.plotGrainSizeDistribution(sim, size_type="areal") + rm("test-grain-size-distribution.png") + @test_throws ErrorException Granular.plotGrainSizeDistribution(sim, size_type="asdf") +else + @test_throws ErrorException Granular.plotGrainSizeDistribution(sim) +end diff --git a/test/grid.jl b/test/grid.jl @@ -5,81 +5,81 @@ verbose = true info("#### $(basename(@__FILE__)) ####") -ocean = SeaIce.readOceanNetCDF("Baltic/00010101.ocean_month.nc", +ocean = Granular.readOceanNetCDF("Baltic/00010101.ocean_month.nc", "Baltic/ocean_hgrid.nc") info("Testing coordinate retrieval functions") -sw, se, ne, nw = SeaIce.getCellCornerCoordinates(ocean.xq, ocean.yq, 1, 1) +sw, se, ne, nw = Granular.getCellCornerCoordinates(ocean.xq, ocean.yq, 1, 1) @test sw ≈ [6., 53.] @test se ≈ [7., 53.] @test ne ≈ [7., 54.] @test nw ≈ [6., 54.] -@test SeaIce.getCellCenterCoordinates(ocean.xh, ocean.yh, 1, 1) ≈ [6.5, 53.5] +@test Granular.getCellCenterCoordinates(ocean.xh, ocean.yh, 1, 1) ≈ [6.5, 53.5] info("Testing area-determination methods") -@test SeaIce.areaOfTriangle([0., 0.], [1., 0.], [0., 1.]) ≈ .5 -@test SeaIce.areaOfTriangle([1., 0.], [0., 1.], [0., 0.]) ≈ .5 -@test SeaIce.areaOfQuadrilateral([1., 0.], [0., 1.], [0., 0.], [1., 1.]) ≈ 1. +@test Granular.areaOfTriangle([0., 0.], [1., 0.], [0., 1.]) ≈ .5 +@test Granular.areaOfTriangle([1., 0.], [0., 1.], [0., 0.]) ≈ .5 +@test Granular.areaOfQuadrilateral([1., 0.], [0., 1.], [0., 0.], [1., 1.]) ≈ 1. info("Testing area-based cell content determination") -@test SeaIce.isPointInCell(ocean, 1, 1, [6.5, 53.5], sw, se, ne, nw) == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.5, 53.5]) == true -@test SeaIce.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.5, 53.5]) ≈ +@test Granular.isPointInCell(ocean, 1, 1, [6.5, 53.5], sw, se, ne, nw) == true +@test Granular.isPointInCell(ocean, 1, 1, [6.5, 53.5]) == true +@test Granular.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.5, 53.5]) ≈ [.5, .5] -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.5], sw, se, ne, nw) == true -@test SeaIce.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.1, 53.5]) ≈ +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.5], sw, se, ne, nw) == true +@test Granular.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.1, 53.5]) ≈ [.1, .5] -@test SeaIce.isPointInCell(ocean, 1, 1, [6.0, 53.5], sw, se, ne, nw) == true -@test SeaIce.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.0, 53.5]) ≈ +@test Granular.isPointInCell(ocean, 1, 1, [6.0, 53.5], sw, se, ne, nw) == true +@test Granular.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.0, 53.5]) ≈ [.0, .5] -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.7], sw, se, ne, nw) == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.9], sw, se, ne, nw) == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.99999], sw, se, ne, nw) == true -@test SeaIce.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.1, 53.99999]) ≈ +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.7], sw, se, ne, nw) == true +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.9], sw, se, ne, nw) == true +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.99999], sw, se, ne, nw) == true +@test Granular.getNonDimensionalCellCoordinates(ocean, 1, 1, [6.1, 53.99999]) ≈ [.1, .99999] -@test SeaIce.isPointInCell(ocean, 1, 1, [7.5, 53.5], sw, se, ne, nw) == false -@test SeaIce.isPointInCell(ocean, 1, 1, [0.0, 53.5], sw, se, ne, nw) == false -x_tilde, _ = SeaIce.getNonDimensionalCellCoordinates(ocean, 1, 1, [0., 53.5]) +@test Granular.isPointInCell(ocean, 1, 1, [7.5, 53.5], sw, se, ne, nw) == false +@test Granular.isPointInCell(ocean, 1, 1, [0.0, 53.5], sw, se, ne, nw) == false +x_tilde, _ = Granular.getNonDimensionalCellCoordinates(ocean, 1, 1, [0., 53.5]) @test x_tilde < 0. info("Testing conformal mapping methods") -@test SeaIce.conformalQuadrilateralCoordinates([0., 0.], +@test Granular.conformalQuadrilateralCoordinates([0., 0.], [5., 0.], [5., 3.], [0., 3.], [2.5, 1.5]) ≈ [0.5, 0.5] -@test SeaIce.conformalQuadrilateralCoordinates([0., 0.], +@test Granular.conformalQuadrilateralCoordinates([0., 0.], [5., 0.], [5., 3.], [0., 3.], [7.5, 1.5]) ≈ [1.5, 0.5] -@test SeaIce.conformalQuadrilateralCoordinates([0., 0.], +@test Granular.conformalQuadrilateralCoordinates([0., 0.], [5., 0.], [5., 3.], [0., 3.], [7.5,-1.5]) ≈ [1.5,-0.5] -@test_throws ErrorException SeaIce.conformalQuadrilateralCoordinates([0., 0.], +@test_throws ErrorException Granular.conformalQuadrilateralCoordinates([0., 0.], [5., 3.], [0., 3.], [5., 0.], [7.5,-1.5]) info("Checking cell content using conformal mapping methods") -@test SeaIce.isPointInCell(ocean, 1, 1, [6.4, 53.4], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.4, 53.4], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.5], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.5], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.0, 53.5], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.0, 53.5], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.7], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.7], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.9], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.9], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [6.1, 53.99999], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [6.1, 53.99999], sw, se, ne, nw, method="Conformal") == true -@test SeaIce.isPointInCell(ocean, 1, 1, [7.5, 53.5], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [7.5, 53.5], sw, se, ne, nw, method="Conformal") == false -@test SeaIce.isPointInCell(ocean, 1, 1, [0.0, 53.5], sw, se, ne, nw, +@test Granular.isPointInCell(ocean, 1, 1, [0.0, 53.5], sw, se, ne, nw, method="Conformal") == false info("Testing bilinear interpolation scheme on conformal mapping") @@ -88,79 +88,79 @@ ocean.u[2, 1, 1, 1] = 1.0 ocean.u[2, 2, 1, 1] = 0.0 ocean.u[1, 2, 1, 1] = 0.0 val = [NaN, NaN] -SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], +Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .5, .5, 1, 1) -@time SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .5, +@time Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .5, .5, 1, 1) @test val[1] ≈ .5 @test val[2] ≈ .5 -SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], 1., 1., +Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], 1., 1., 1, 1) @test val[1] ≈ .0 @test val[2] ≈ .0 -SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], 0., 0., +Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], 0., 0., 1, 1) @test val[1] ≈ 1. @test val[2] ≈ 1. -SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .25, .25, +Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .25, .25, 1, 1) @test val[1] ≈ .75 @test val[2] ≈ .75 -SeaIce.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .75, .75, +Granular.bilinearInterpolation!(val, ocean.u[:,:,1,1], ocean.u[:,:,1,1], .75, .75, 1, 1) @test val[1] ≈ .25 @test val[2] ≈ .25 info("Testing cell binning - Area-based approach") -@test SeaIce.findCellContainingPoint(ocean, [6.2,53.4], method="Area") == (1, 1) -@test SeaIce.findCellContainingPoint(ocean, [7.2,53.4], method="Area") == (2, 1) -@test SeaIce.findCellContainingPoint(ocean, [0.2,53.4], method="Area") == (0, 0) +@test Granular.findCellContainingPoint(ocean, [6.2,53.4], method="Area") == (1, 1) +@test Granular.findCellContainingPoint(ocean, [7.2,53.4], method="Area") == (2, 1) +@test Granular.findCellContainingPoint(ocean, [0.2,53.4], method="Area") == (0, 0) info("Testing cell binning - Conformal mapping") -@test SeaIce.findCellContainingPoint(ocean, [6.2,53.4], method="Conformal") == +@test Granular.findCellContainingPoint(ocean, [6.2,53.4], method="Conformal") == (1, 1) -@test SeaIce.findCellContainingPoint(ocean, [7.2,53.4], method="Conformal") == +@test Granular.findCellContainingPoint(ocean, [7.2,53.4], method="Conformal") == (2, 1) -@test SeaIce.findCellContainingPoint(ocean, [0.2, 53.4], method="Conformal") == +@test Granular.findCellContainingPoint(ocean, [0.2, 53.4], method="Conformal") == (0, 0) -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.readOceanNetCDF("Baltic/00010101.ocean_month.nc", +sim = Granular.createSimulation() +sim.ocean = Granular.readOceanNetCDF("Baltic/00010101.ocean_month.nc", "Baltic/ocean_hgrid.nc") -SeaIce.addIceFloeCylindrical!(sim, [6.5, 53.5], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [6.6, 53.5], 10., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [7.5, 53.5], 10., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -@test sim.ice_floes[1].ocean_grid_pos == [1, 1] -@test sim.ice_floes[2].ocean_grid_pos == [1, 1] -@test sim.ice_floes[3].ocean_grid_pos == [2, 1] -@test sim.ocean.ice_floe_list[1, 1] == [1, 2] -@test sim.ocean.ice_floe_list[2, 1] == [3] +Granular.addGrainCylindrical!(sim, [6.5, 53.5], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [6.6, 53.5], 10., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [7.5, 53.5], 10., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +@test sim.grains[1].ocean_grid_pos == [1, 1] +@test sim.grains[2].ocean_grid_pos == [1, 1] +@test sim.grains[3].ocean_grid_pos == [2, 1] +@test sim.ocean.grain_list[1, 1] == [1, 2] +@test sim.ocean.grain_list[2, 1] == [3] info("Testing ocean drag") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) sim.ocean.u[:,:,1,1] = 5. -SeaIce.addIceFloeCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) sim.time = ocean.time[1] -SeaIce.addOceanDrag!(sim) -@test sim.ice_floes[1].force[1] > 0. -@test sim.ice_floes[1].force[2] ≈ 0. -@test sim.ice_floes[2].force[1] > 0. -@test sim.ice_floes[2].force[2] ≈ 0. +Granular.addOceanDrag!(sim) +@test sim.grains[1].force[1] > 0. +@test sim.grains[1].force[2] ≈ 0. +@test sim.grains[2].force[1] > 0. +@test sim.grains[2].force[2] ≈ 0. sim.ocean.u[:,:,1,1] = -5. sim.ocean.v[:,:,1,1] = 5. -SeaIce.addIceFloeCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) sim.time = ocean.time[1] -SeaIce.addOceanDrag!(sim) -@test sim.ice_floes[1].force[1] < 0. -@test sim.ice_floes[1].force[2] > 0. -@test sim.ice_floes[2].force[1] < 0. -@test sim.ice_floes[2].force[2] > 0. +Granular.addOceanDrag!(sim) +@test sim.grains[1].force[1] < 0. +@test sim.grains[1].force[2] > 0. +@test sim.grains[2].force[1] < 0. +@test sim.grains[2].force[2] > 0. info("Testing curl function") ocean.u[1, 1, 1, 1] = 1.0 @@ -172,40 +172,40 @@ sw = Vector{Float64}(2) se = Vector{Float64}(2) ne = Vector{Float64}(2) nw = Vector{Float64}(2) -@test SeaIce.curl(ocean, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) > 0. +@test Granular.curl(ocean, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) > 0. ocean.u[1, 1, 1, 1] = 0.0 ocean.u[2, 1, 1, 1] = 0.0 ocean.u[2, 2, 1, 1] = 1.0 ocean.u[1, 2, 1, 1] = 1.0 ocean.v[:, :, 1, 1] = 0.0 -@test SeaIce.curl(ocean, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) < 0. +@test Granular.curl(ocean, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) < 0. info("Testing atmosphere drag") -sim = SeaIce.createSimulation() -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) -atmosphere = SeaIce.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) +sim = Granular.createSimulation() +sim.atmosphere = Granular.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) +atmosphere = Granular.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) sim.atmosphere.u[:,:,1,1] = 5. -SeaIce.addIceFloeCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.atmosphere, verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.atmosphere, verbose=verbose) sim.time = ocean.time[1] -SeaIce.addAtmosphereDrag!(sim) -@test sim.ice_floes[1].force[1] > 0. -@test sim.ice_floes[1].force[2] ≈ 0. -@test sim.ice_floes[2].force[1] > 0. -@test sim.ice_floes[2].force[2] ≈ 0. +Granular.addAtmosphereDrag!(sim) +@test sim.grains[1].force[1] > 0. +@test sim.grains[1].force[2] ≈ 0. +@test sim.grains[2].force[1] > 0. +@test sim.grains[2].force[2] ≈ 0. sim.atmosphere.u[:,:,1,1] = -5. sim.atmosphere.v[:,:,1,1] = 5. -SeaIce.addIceFloeCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.atmosphere, verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.atmosphere, verbose=verbose) sim.time = ocean.time[1] -SeaIce.addAtmosphereDrag!(sim) -@test sim.ice_floes[1].force[1] < 0. -@test sim.ice_floes[1].force[2] > 0. -@test sim.ice_floes[2].force[1] < 0. -@test sim.ice_floes[2].force[2] > 0. +Granular.addAtmosphereDrag!(sim) +@test sim.grains[1].force[1] < 0. +@test sim.grains[1].force[2] > 0. +@test sim.grains[2].force[1] < 0. +@test sim.grains[2].force[2] > 0. info("Testing curl function") atmosphere.u[1, 1, 1, 1] = 1.0 @@ -213,134 +213,134 @@ atmosphere.u[2, 1, 1, 1] = 1.0 atmosphere.u[2, 2, 1, 1] = 0.0 atmosphere.u[1, 2, 1, 1] = 0.0 atmosphere.v[:, :, 1, 1] = 0.0 -@test SeaIce.curl(atmosphere, .5, .5, 1, 1, 1, 1) > 0. -@test SeaIce.curl(atmosphere, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) > 0. +@test Granular.curl(atmosphere, .5, .5, 1, 1, 1, 1) > 0. +@test Granular.curl(atmosphere, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) > 0. atmosphere.u[1, 1, 1, 1] = 0.0 atmosphere.u[2, 1, 1, 1] = 0.0 atmosphere.u[2, 2, 1, 1] = 1.0 atmosphere.u[1, 2, 1, 1] = 1.0 atmosphere.v[:, :, 1, 1] = 0.0 -@test SeaIce.curl(atmosphere, .5, .5, 1, 1, 1, 1) < 0. -@test SeaIce.curl(atmosphere, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) < 0. +@test Granular.curl(atmosphere, .5, .5, 1, 1, 1, 1) < 0. +@test Granular.curl(atmosphere, .5, .5, 1, 1, 1, 1, sw, se, ne, nw) < 0. info("Testing findEmptyPositionInGridCell") info("# Insert into empty cell") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, 0.5, +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, 0.5, verbose=true) @test pos != false -@test SeaIce.isPointInCell(sim.ocean, 1, 1, pos) == true +@test Granular.isPointInCell(sim.ocean, 1, 1, pos) == true info("# Insert into cell with one other ice floe") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.addIceFloeCylindrical!(sim, [.25, .25], .25, 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, .25, +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.addGrainCylindrical!(sim, [.25, .25], .25, 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, .25, verbose=true) @test pos != false -@test SeaIce.isPointInCell(sim.ocean, 1, 1, pos) == true +@test Granular.isPointInCell(sim.ocean, 1, 1, pos) == true -info("# Insert into cell with two other ice floes") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.addIceFloeCylindrical!(sim, [.25, .25], .25, 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [.75, .75], .25, 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, .25, +info("# Insert into cell with two other grains") +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.addGrainCylindrical!(sim, [.25, .25], .25, 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [.75, .75], .25, 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, .25, verbose=true) @test pos != false -@test SeaIce.isPointInCell(sim.ocean, 1, 1, pos) == true +@test Granular.isPointInCell(sim.ocean, 1, 1, pos) == true info("# Insert into full cell") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.addIceFloeCylindrical!(sim, [.5, .5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [.75, .5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [.5, .75], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [.75, .75], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, 0.5, +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.addGrainCylindrical!(sim, [.5, .5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [.75, .5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [.5, .75], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [.75, .75], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 1, 1, 0.5, verbose=false) @test pos == false info("# Insert into empty cell") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 2, 2, 0.5, +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 2, 2, 0.5, verbose=true) @test pos != false -@test SeaIce.isPointInCell(sim.ocean, 2, 2, pos) == true +@test Granular.isPointInCell(sim.ocean, 2, 2, pos) == true info("# Insert into full cell") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.addIceFloeCylindrical!(sim, [1.5, 1.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [1.75, 1.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [1.5, 1.75], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [1.75, 1.75], 1., 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -pos = SeaIce.findEmptyPositionInGridCell(sim, sim.ocean, 2, 2, 0.5, +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +Granular.addGrainCylindrical!(sim, [1.5, 1.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [1.75, 1.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [1.5, 1.75], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [1.75, 1.75], 1., 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean, 2, 2, 0.5, verbose=false) @test pos == false info("Test default sorting with ocean/atmosphere grids") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([4, 4, 2], [4., 4.000001, 2.]) -SeaIce.addIceFloeCylindrical!(sim, [0.5, 0.5], .1, 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [0.7, 0.7], .1, 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], .1, 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -SeaIce.setTimeStep!(sim) -SeaIce.setTotalTime!(sim, 1.0) -SeaIce.run!(sim, single_step=true, verbose=verbose) +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +sim.atmosphere = Granular.createRegularAtmosphereGrid([4, 4, 2], [4., 4.000001, 2.]) +Granular.addGrainCylindrical!(sim, [0.5, 0.5], .1, 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [0.7, 0.7], .1, 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], .1, 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +Granular.setTimeStep!(sim) +Granular.setTotalTime!(sim, 1.0) +Granular.run!(sim, single_step=true, verbose=verbose) @test sim.atmosphere.collocated_with_ocean_grid == false -@test sim.ice_floes[1].ocean_grid_pos == [1, 1] -@test sim.ice_floes[2].ocean_grid_pos == [1, 1] -@test sim.ice_floes[3].ocean_grid_pos == [3, 3] -@test sim.ocean.ice_floe_list[1, 1] == [1, 2] -@test sim.ocean.ice_floe_list[2, 2] == [] -@test sim.ocean.ice_floe_list[3, 3] == [3] -@test sim.ice_floes[1].atmosphere_grid_pos == [1, 1] -@test sim.ice_floes[2].atmosphere_grid_pos == [1, 1] -@test sim.ice_floes[3].atmosphere_grid_pos == [3, 3] -@test sim.atmosphere.ice_floe_list[1, 1] == [1, 2] -@test sim.atmosphere.ice_floe_list[2, 2] == [] -@test sim.atmosphere.ice_floe_list[3, 3] == [3] +@test sim.grains[1].ocean_grid_pos == [1, 1] +@test sim.grains[2].ocean_grid_pos == [1, 1] +@test sim.grains[3].ocean_grid_pos == [3, 3] +@test sim.ocean.grain_list[1, 1] == [1, 2] +@test sim.ocean.grain_list[2, 2] == [] +@test sim.ocean.grain_list[3, 3] == [3] +@test sim.grains[1].atmosphere_grid_pos == [1, 1] +@test sim.grains[2].atmosphere_grid_pos == [1, 1] +@test sim.grains[3].atmosphere_grid_pos == [3, 3] +@test sim.atmosphere.grain_list[1, 1] == [1, 2] +@test sim.atmosphere.grain_list[2, 2] == [] +@test sim.atmosphere.grain_list[3, 3] == [3] info("Test optimization when ocean/atmosphere grids are collocated") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) -SeaIce.addIceFloeCylindrical!(sim, [0.5, 0.5], .1, 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [0.7, 0.7], .1, 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], .1, 1., verbose=verbose) -SeaIce.sortIceFloesInGrid!(sim, sim.ocean, verbose=verbose) -SeaIce.setTimeStep!(sim) -SeaIce.setTotalTime!(sim, 1.0) -SeaIce.run!(sim, single_step=true, verbose=verbose) +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([4, 4, 2], [4., 4., 2.]) +sim.atmosphere = Granular.createRegularAtmosphereGrid([4, 4, 2], [4., 4., 2.]) +Granular.addGrainCylindrical!(sim, [0.5, 0.5], .1, 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [0.7, 0.7], .1, 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], .1, 1., verbose=verbose) +Granular.sortGrainsInGrid!(sim, sim.ocean, verbose=verbose) +Granular.setTimeStep!(sim) +Granular.setTotalTime!(sim, 1.0) +Granular.run!(sim, single_step=true, verbose=verbose) @test sim.atmosphere.collocated_with_ocean_grid == true -@test sim.ice_floes[1].ocean_grid_pos == [1, 1] -@test sim.ice_floes[2].ocean_grid_pos == [1, 1] -@test sim.ice_floes[3].ocean_grid_pos == [3, 3] -@test sim.ocean.ice_floe_list[1, 1] == [1, 2] -@test sim.ocean.ice_floe_list[2, 2] == [] -@test sim.ocean.ice_floe_list[3, 3] == [3] -@test sim.ice_floes[1].atmosphere_grid_pos == [1, 1] -@test sim.ice_floes[2].atmosphere_grid_pos == [1, 1] -@test sim.ice_floes[3].atmosphere_grid_pos == [3, 3] -@test sim.atmosphere.ice_floe_list[1, 1] == [1, 2] -@test sim.atmosphere.ice_floe_list[2, 2] == [] -@test sim.atmosphere.ice_floe_list[3, 3] == [3] +@test sim.grains[1].ocean_grid_pos == [1, 1] +@test sim.grains[2].ocean_grid_pos == [1, 1] +@test sim.grains[3].ocean_grid_pos == [3, 3] +@test sim.ocean.grain_list[1, 1] == [1, 2] +@test sim.ocean.grain_list[2, 2] == [] +@test sim.ocean.grain_list[3, 3] == [3] +@test sim.grains[1].atmosphere_grid_pos == [1, 1] +@test sim.grains[2].atmosphere_grid_pos == [1, 1] +@test sim.grains[3].atmosphere_grid_pos == [3, 3] +@test sim.atmosphere.grain_list[1, 1] == [1, 2] +@test sim.atmosphere.grain_list[2, 2] == [] +@test sim.atmosphere.grain_list[3, 3] == [3] info("Testing ocean drag") -sim = SeaIce.createSimulation() +sim = Granular.createSimulation() sim.ocean.u[:,:,1,1] = 5. -SeaIce.addIceFloeCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) -SeaIce.addIceFloeCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.5, 3.5], 1., 1., verbose=verbose) +Granular.addGrainCylindrical!(sim, [2.6, 2.5], 1., 1., verbose=verbose) diff --git a/test/icefloe.jl b/test/icefloe.jl @@ -1,44 +0,0 @@ -#!/usr/bin/env julia - -# Check the basic icefloe functionality - -info("#### $(basename(@__FILE__)) ####") - -info("Writing simple simulation to VTK file") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) -SeaIce.printIceFloeInfo(sim.ice_floes[1]) - - -@test_throws ErrorException SeaIce.addIceFloeCylindrical!(sim, [.1, .1, .1], - 10., 1.) -@test_throws ErrorException SeaIce.addIceFloeCylindrical!(sim, [.1, .1], - 10., 1., - lin_vel=[.2,.2,.2]) -@test_throws ErrorException SeaIce.addIceFloeCylindrical!(sim, [.1, .1], - 10., 1., - lin_acc=[.2,.2,.2]) -@test_throws ErrorException SeaIce.addIceFloeCylindrical!(sim, [.1, .1], - 0., 1.) -@test_throws ErrorException SeaIce.addIceFloeCylindrical!(sim, [.1, .1], - 10., 1., density=-2.) -@test_throws ErrorException SeaIce.disableIceFloe!(sim, 0) - -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) -SeaIce.compareIceFloes(sim.ice_floes[1], sim.ice_floes[2]) - -if typeof(Pkg.installed("PyPlot")) == VersionNumber - SeaIce.plotIceFloeSizeDistribution(sim) - rm("test-ice-floe-size-distribution.png") - SeaIce.plotIceFloeSizeDistribution(sim, skip_fixed=false) - rm("test-ice-floe-size-distribution.png") - SeaIce.plotIceFloeSizeDistribution(sim, log_y=false) - rm("test-ice-floe-size-distribution.png") - SeaIce.plotIceFloeSizeDistribution(sim, size_type="areal") - rm("test-ice-floe-size-distribution.png") - @test_throws ErrorException SeaIce.plotIceFloeSizeDistribution(sim, size_type="asdf") -else - @test_throws ErrorException SeaIce.plotIceFloeSizeDistribution(sim) -end diff --git a/test/jld.jl b/test/jld.jl @@ -7,15 +7,15 @@ if typeof(Pkg.installed("JLD")) == VersionNumber info("JLD found, proceeding with JLD-specific tests") info("Writing simple simulation to JLD file") - sim = SeaIce.createSimulation(id="test") - SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) - SeaIce.addIceFloeCylindrical!(sim, [18., 0.], 10., 1., verbose=false) - sim.ocean = SeaIce.createRegularOceanGrid([10, 20, 5], [10., 25., 2.]) - SeaIce.findContacts!(sim, method="all to all") - SeaIce.writeVTK(sim, verbose=false) + sim = Granular.createSimulation(id="test") + Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) + Granular.addGrainCylindrical!(sim, [18., 0.], 10., 1., verbose=false) + sim.ocean = Granular.createRegularOceanGrid([10, 20, 5], [10., 25., 2.]) + Granular.findContacts!(sim, method="all to all") + Granular.writeVTK(sim, verbose=false) - SeaIce.writeSimulation(sim) + Granular.writeSimulation(sim) - sim2 = SeaIce.readSimulation("./test/test.1.jld") - SeaIce.compareSimulations(sim, sim2) + sim2 = Granular.readSimulation("./test/test.1.jld") + Granular.compareSimulations(sim, sim2) end diff --git a/test/memory-management.jl b/test/memory-management.jl @@ -2,9 +2,9 @@ info("#### $(basename(@__FILE__)) ####") -info("Testing memory footprint of SeaIce types") +info("Testing memory footprint of Granular types") -sim = SeaIce.createSimulation() +sim = Granular.createSimulation() empty_sim_size = 96 empty_sim_size_recursive = 472 @@ -14,160 +14,160 @@ empty_sim_size_recursive = 472 size_per_icefloe = 352 size_per_icefloe_recursive = 1136 -info("Testing memory usage when adding ice floes") +info("Testing memory usage when adding grains") for i=1:100 - SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1., 1., verbose=false) + Granular.addGrainCylindrical!(sim, [1., 1.], 1., 1., verbose=false) @test sizeof(sim) == empty_sim_size - @test sizeof(sim.ice_floes) == sizeof(Int)*i - @test sizeof(sim.ice_floes[:]) == sizeof(Int)*i - @test Base.summarysize(sim.ice_floes) == size_per_icefloe_recursive*i + + @test sizeof(sim.grains) == sizeof(Int)*i + @test sizeof(sim.grains[:]) == sizeof(Int)*i + @test Base.summarysize(sim.grains) == size_per_icefloe_recursive*i + sizeof(Int)*i @test Base.summarysize(sim) == empty_sim_size_recursive + sizeof(Int)*i + size_per_icefloe_recursive*i - @test Base.summarysize(sim.ice_floes[i]) == size_per_icefloe_recursive + @test Base.summarysize(sim.grains[i]) == size_per_icefloe_recursive for j=1:i - @test sizeof(sim.ice_floes[j]) == size_per_icefloe - @test Base.summarysize(sim.ice_floes[j]) == size_per_icefloe_recursive + @test sizeof(sim.grains[j]) == size_per_icefloe + @test Base.summarysize(sim.grains[j]) == size_per_icefloe_recursive end end info("Checking memory footprint when overwriting simulation object") -sim = SeaIce.createSimulation() +sim = Granular.createSimulation() @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive info("Check memory usage when stepping time for empty simulation object") -sim = SeaIce.createSimulation() +sim = Granular.createSimulation() sim.time_step = 1.0 for i=1:10 - SeaIce.run!(sim, single_step=true, verbose=false) + Granular.run!(sim, single_step=true, verbose=false) @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive end info("Check memory when stepping time with single ice floe") -sim = SeaIce.createSimulation() -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1., 1., verbose=false) +sim = Granular.createSimulation() +Granular.addGrainCylindrical!(sim, [1., 1.], 1., 1., verbose=false) sim.time_step = 1.0 for i=1:10 - SeaIce.run!(sim, single_step=true, verbose=false) + Granular.run!(sim, single_step=true, verbose=false) @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive + - sizeof(Int)*length(sim.ice_floes) + - size_per_icefloe_recursive*length(sim.ice_floes) + sizeof(Int)*length(sim.grains) + + size_per_icefloe_recursive*length(sim.grains) end -info("Check memory when stepping time with two separate ice floes") -sim = SeaIce.createSimulation() -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 3., 1., verbose=false) +info("Check memory when stepping time with two separate grains") +sim = Granular.createSimulation() +Granular.addGrainCylindrical!(sim, [1., 1.], 1., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [1., 1.], 3., 1., verbose=false) sim.time_step = 1.0 for i=1:10 - SeaIce.run!(sim, single_step=true, verbose=false) + Granular.run!(sim, single_step=true, verbose=false) @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive + - sizeof(Int)*length(sim.ice_floes) + - size_per_icefloe_recursive*length(sim.ice_floes) + sizeof(Int)*length(sim.grains) + + size_per_icefloe_recursive*length(sim.grains) end -info("Check memory when stepping time with two interacting ice floes (all to all)") -sim = SeaIce.createSimulation() -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1.9, 1., verbose=false) +info("Check memory when stepping time with two interacting grains (all to all)") +sim = Granular.createSimulation() +Granular.addGrainCylindrical!(sim, [1., 1.], 1., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [1., 1.], 1.9, 1., verbose=false) sim.time_step = 1.0 for i=1:10 - SeaIce.run!(sim, single_step=true, verbose=false) + Granular.run!(sim, single_step=true, verbose=false) @test sizeof(sim) == empty_sim_size @test Base.summarysize(sim) == empty_sim_size_recursive + - sizeof(Int)*length(sim.ice_floes) + - size_per_icefloe_recursive*length(sim.ice_floes) + sizeof(Int)*length(sim.grains) + + size_per_icefloe_recursive*length(sim.grains) end -info("Check memory when stepping time with two interacting ice floes (cell sorting)") -sim = SeaIce.createSimulation() -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [1., 1.], 1.9, 1., verbose=false) +info("Check memory when stepping time with two interacting grains (cell sorting)") +sim = Granular.createSimulation() +Granular.addGrainCylindrical!(sim, [1., 1.], 1., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [1., 1.], 1.9, 1., verbose=false) nx, ny, nz = 5, 5, 1 -sim.ocean = SeaIce.createRegularOceanGrid([nx, ny, nz], [10., 10., 10.]) +sim.ocean = Granular.createRegularOceanGrid([nx, ny, nz], [10., 10., 10.]) sim.time_step = 1e-6 -SeaIce.run!(sim, single_step=true, verbose=false) +Granular.run!(sim, single_step=true, verbose=false) original_size_recursive = Base.summarysize(sim) for i=1:10 - SeaIce.run!(sim, single_step=true, verbose=false) + Granular.run!(sim, single_step=true, verbose=false) @test Base.summarysize(sim) == original_size_recursive end info("Checking if memory is freed after ended collision (all to all)") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) -sim.ice_floes[1].lin_vel[1] = 0.1 -SeaIce.setTotalTime!(sim, 10.0) -SeaIce.setTimeStep!(sim, epsilon=0.07, verbose=false) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) +sim.grains[1].lin_vel[1] = 0.1 +Granular.setTotalTime!(sim, 10.0) +Granular.setTimeStep!(sim, epsilon=0.07, verbose=false) original_size_recursive = Base.summarysize(sim) -SeaIce.run!(sim, verbose=false) +Granular.run!(sim, verbose=false) @test Base.summarysize(sim) == original_size_recursive info("Checking if memory is freed after ended collision (cell sorting)") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) -sim.ocean = SeaIce.createRegularOceanGrid([2, 2, 2], [40., 40., 10.]) -sim.ice_floes[1].lin_vel[1] = 0.1 -SeaIce.setTotalTime!(sim, 10.0) -SeaIce.setTimeStep!(sim, epsilon=0.07, verbose=false) -SeaIce.run!(sim, single_step=true, verbose=false) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) +sim.ocean = Granular.createRegularOceanGrid([2, 2, 2], [40., 40., 10.]) +sim.grains[1].lin_vel[1] = 0.1 +Granular.setTotalTime!(sim, 10.0) +Granular.setTimeStep!(sim, epsilon=0.07, verbose=false) +Granular.run!(sim, single_step=true, verbose=false) original_sim_size_recursive = Base.summarysize(sim) -original_icefloes_size_recursive = Base.summarysize(sim.ice_floes) +original_icefloes_size_recursive = Base.summarysize(sim.grains) original_ocean_size_recursive = Base.summarysize(sim.ocean) original_atmosphere_size_recursive = Base.summarysize(sim.atmosphere) -SeaIce.run!(sim, verbose=false) -@test Base.summarysize(sim.ice_floes) == original_icefloes_size_recursive +Granular.run!(sim, verbose=false) +@test Base.summarysize(sim.grains) == original_icefloes_size_recursive @test Base.summarysize(sim.ocean) == original_ocean_size_recursive @test Base.summarysize(sim.atmosphere) == original_atmosphere_size_recursive @test Base.summarysize(sim) == original_sim_size_recursive -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([2, 2, 2], [40., 40., 10.]) -sim.ice_floes[1].lin_vel[1] = 0.1 -SeaIce.setTotalTime!(sim, 10.0) -SeaIce.setTimeStep!(sim, epsilon=0.07, verbose=false) -SeaIce.run!(sim, single_step=true, verbose=false) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) +sim.atmosphere = Granular.createRegularAtmosphereGrid([2, 2, 2], [40., 40., 10.]) +sim.grains[1].lin_vel[1] = 0.1 +Granular.setTotalTime!(sim, 10.0) +Granular.setTimeStep!(sim, epsilon=0.07, verbose=false) +Granular.run!(sim, single_step=true, verbose=false) original_sim_size_recursive = Base.summarysize(sim) -original_icefloes_size_recursive = Base.summarysize(sim.ice_floes) +original_icefloes_size_recursive = Base.summarysize(sim.grains) original_ocean_size_recursive = Base.summarysize(sim.ocean) original_atmosphere_size_recursive = Base.summarysize(sim.atmosphere) -SeaIce.run!(sim, verbose=false) -@test Base.summarysize(sim.ice_floes) == original_icefloes_size_recursive +Granular.run!(sim, verbose=false) +@test Base.summarysize(sim.grains) == original_icefloes_size_recursive @test Base.summarysize(sim.ocean) == original_ocean_size_recursive @test Base.summarysize(sim.atmosphere) == original_atmosphere_size_recursive @test Base.summarysize(sim) == original_sim_size_recursive -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) -sim.atmosphere = SeaIce.createRegularAtmosphereGrid([2, 2, 2], [40., 40., 10.]) -sim.ocean = SeaIce.createRegularOceanGrid([2, 2, 2], [40., 40., 10.]) -sim.ice_floes[1].lin_vel[1] = 0.1 -SeaIce.setTotalTime!(sim, 10.0) -SeaIce.setTimeStep!(sim, epsilon=0.07, verbose=false) -SeaIce.run!(sim, single_step=true, verbose=false) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [20.05, 0.], 10., 1., verbose=false) +sim.atmosphere = Granular.createRegularAtmosphereGrid([2, 2, 2], [40., 40., 10.]) +sim.ocean = Granular.createRegularOceanGrid([2, 2, 2], [40., 40., 10.]) +sim.grains[1].lin_vel[1] = 0.1 +Granular.setTotalTime!(sim, 10.0) +Granular.setTimeStep!(sim, epsilon=0.07, verbose=false) +Granular.run!(sim, single_step=true, verbose=false) original_sim_size_recursive = Base.summarysize(sim) -original_icefloes_size_recursive = Base.summarysize(sim.ice_floes) +original_icefloes_size_recursive = Base.summarysize(sim.grains) original_ocean_size_recursive = Base.summarysize(sim.ocean) original_atmosphere_size_recursive = Base.summarysize(sim.atmosphere) -SeaIce.run!(sim, verbose=false) -@test Base.summarysize(sim.ice_floes) == original_icefloes_size_recursive +Granular.run!(sim, verbose=false) +@test Base.summarysize(sim.grains) == original_icefloes_size_recursive @test Base.summarysize(sim.ocean) == original_ocean_size_recursive @test Base.summarysize(sim.atmosphere) == original_atmosphere_size_recursive @test Base.summarysize(sim) == original_sim_size_recursive -SeaIce.printMemoryUsage(sim) +Granular.printMemoryUsage(sim) diff --git a/test/netcdf.jl b/test/netcdf.jl @@ -4,11 +4,11 @@ info("#### $(basename(@__FILE__)) ####") -@test_throws ErrorException SeaIce.readOceanStateNetCDF("nonexistentfile") -@test_throws ErrorException SeaIce.readOceanGridNetCDF("nonexistentfile") +@test_throws ErrorException Granular.readOceanStateNetCDF("nonexistentfile") +@test_throws ErrorException Granular.readOceanGridNetCDF("nonexistentfile") info("Testing dimensions of content read from Baltic test case") -ocean = SeaIce.readOceanNetCDF("Baltic/00010101.ocean_month.nc", +ocean = Granular.readOceanNetCDF("Baltic/00010101.ocean_month.nc", "Baltic/ocean_hgrid.nc") @test ocean.time/(24.*60.*60.) ≈ [.5, 1.5, 2.5, 3.5, 4.5] @test size(ocean.xq) == (24, 15) @@ -21,12 +21,12 @@ ocean = SeaIce.readOceanNetCDF("Baltic/00010101.ocean_month.nc", @test size(ocean.e) == (23, 14, 64, 5) info("Testing ocean state interpolation") -@test_throws ErrorException SeaIce.interpolateOceanState(ocean, time=0.) -@test_throws ErrorException SeaIce.interpolateOceanState(ocean, time=1.e34) -u1, v1, h1, e1 = SeaIce.interpolateOceanState(ocean, ocean.time[1]) -u2, v2, h2, e2 = SeaIce.interpolateOceanState(ocean, ocean.time[2]) -@test_throws ErrorException SeaIce.interpolateOceanState(ocean, -1.) -u1_5, v1_5, h1_5, e1_5 = SeaIce.interpolateOceanState(ocean, +@test_throws ErrorException Granular.interpolateOceanState(ocean, time=0.) +@test_throws ErrorException Granular.interpolateOceanState(ocean, time=1.e34) +u1, v1, h1, e1 = Granular.interpolateOceanState(ocean, ocean.time[1]) +u2, v2, h2, e2 = Granular.interpolateOceanState(ocean, ocean.time[2]) +@test_throws ErrorException Granular.interpolateOceanState(ocean, -1.) +u1_5, v1_5, h1_5, e1_5 = Granular.interpolateOceanState(ocean, ocean.time[1] + (ocean.time[2] - ocean.time[1])/2.) @test u1 ≈ ocean.u[:, :, :, 1] @test v1 ≈ ocean.v[:, :, :, 1] diff --git a/test/ocean.jl b/test/ocean.jl @@ -6,8 +6,8 @@ info("#### $(basename(@__FILE__)) ####") info("Testing regular grid generation") -sim = SeaIce.createSimulation() -sim.ocean = SeaIce.createRegularOceanGrid([6, 6, 6], [1., 1., 1.]) +sim = Granular.createSimulation() +sim.ocean = Granular.createRegularOceanGrid([6, 6, 6], [1., 1., 1.]) @test size(sim.ocean.xq) == (7, 7) @test size(sim.ocean.yq) == (7, 7) @test size(sim.ocean.xh) == (6, 6) @@ -28,108 +28,108 @@ sim.ocean = SeaIce.createRegularOceanGrid([6, 6, 6], [1., 1., 1.]) @test sim.ocean.e ≈ zeros(7, 7, 6, 1) info("Testing velocity drag interaction (static ocean)") -SeaIce.addIceFloeCylindrical!(sim, [.5, .5], .25, .1) -SeaIce.setTotalTime!(sim, 5.) -SeaIce.setTimeStep!(sim) +Granular.addGrainCylindrical!(sim, [.5, .5], .25, .1) +Granular.setTotalTime!(sim, 5.) +Granular.setTimeStep!(sim) sim_init = deepcopy(sim) -sim.ice_floes[1].lin_vel[1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim.grains[1].lin_vel[1] = 0.1 +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init ≈ E_kin_rot_final # no rotation before or after @test E_kin_lin_init > E_kin_lin_final # linear velocity lost due to ocean drag -@test sim.ice_floes[1].ocean_stress[1] < 0. -@test sim.ice_floes[1].ocean_stress[2] ≈ 0. +@test sim.grains[1].ocean_stress[1] < 0. +@test sim.grains[1].ocean_stress[2] ≈ 0. info("Testing velocity drag interaction (static ice floe)") sim = deepcopy(sim_init) sim.ocean.v[:, :, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init ≈ E_kin_rot_final # no rotation before or after @test E_kin_lin_init < E_kin_lin_final # linear vel. gained due to ocean drag -@test sim.ice_floes[1].ocean_stress[1] ≈ 0. -@test sim.ice_floes[1].ocean_stress[2] > 0. +@test sim.grains[1].ocean_stress[1] ≈ 0. +@test sim.grains[1].ocean_stress[2] > 0. info("Testing vortex interaction (static ocean)") sim = deepcopy(sim_init) -sim.ice_floes[1].ang_vel = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) +sim.grains[1].ang_vel = 0.1 +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) @test E_kin_rot_init > E_kin_rot_final # energy lost to ocean -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained info("Testing vortex interaction (static ice floe)") sim = deepcopy(sim_init) -sim.ocean = SeaIce.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.ocean.v[1, :, 1, 1] = -0.1 sim.ocean.v[2, :, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to ocean vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.ocean = SeaIce.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.ocean.v[1, :, 1, 1] = 0.1 sim.ocean.v[2, :, 1, 1] = -0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel < 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos < 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel < 0. # check angular velocity orientation +@test sim.grains[1].ang_pos < 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to ocean vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.ocean = SeaIce.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.ocean.u[:, 1, 1, 1] = -0.1 sim.ocean.u[:, 2, 1, 1] = 0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel < 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos < 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel < 0. # check angular velocity orientation +@test sim.grains[1].ang_pos < 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to ocean vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained sim = deepcopy(sim_init) -sim.ocean = SeaIce.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) -sim.ice_floes[1].lin_pos[1] = 0.5 -sim.ice_floes[1].lin_pos[2] = 0.5 +sim.ocean = Granular.createRegularOceanGrid([1, 1, 1], [1., 1., 1.]) +sim.grains[1].lin_pos[1] = 0.5 +sim.grains[1].lin_pos[2] = 0.5 sim.ocean.u[:, 1, 1, 1] = 0.1 sim.ocean.u[:, 2, 1, 1] = -0.1 -E_kin_lin_init = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_init = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -SeaIce.run!(sim, verbose=false) -E_kin_lin_final = SeaIce.totalIceFloeKineticTranslationalEnergy(sim) -E_kin_rot_final = SeaIce.totalIceFloeKineticRotationalEnergy(sim) -@test sim.ice_floes[1].ang_vel > 0. # check angular velocity orientation -@test sim.ice_floes[1].ang_pos > 0. # check angular position orientation +E_kin_lin_init = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_init = Granular.totalGrainKineticRotationalEnergy(sim) +Granular.run!(sim, verbose=false) +E_kin_lin_final = Granular.totalGrainKineticTranslationalEnergy(sim) +E_kin_rot_final = Granular.totalGrainKineticRotationalEnergy(sim) +@test sim.grains[1].ang_vel > 0. # check angular velocity orientation +@test sim.grains[1].ang_pos > 0. # check angular position orientation @test E_kin_rot_init < E_kin_rot_final # rotation after due to ocean vortex @test E_kin_lin_init ≈ E_kin_lin_final # no linear velocity gained diff --git a/test/profiling.jl b/test/profiling.jl @@ -1,6 +1,6 @@ #!/usr/bin/env julia import Plots -import SeaIce +import Granular import CurveFit using Base.Test @@ -8,29 +8,29 @@ info("#### $(basename(@__FILE__)) ####") verbose=false -info("Testing performance with many interacting ice floes") +info("Testing performance with many interacting grains") function timeSingleStepInDenseSimulation(nx::Int; verbose::Bool=true, profile::Bool=false, grid_sorting::Bool=true, include_atmosphere::Bool=false) - sim = SeaIce.createSimulation() + sim = Granular.createSimulation() #nx, ny = 25, 25 #nx, ny = 250, 250 ny = nx dx, dy = 40., 40. - sim.ocean = SeaIce.createRegularOceanGrid([nx, ny, 2], [nx*dx, ny*dy, 10.]) + sim.ocean = Granular.createRegularOceanGrid([nx, ny, 2], [nx*dx, ny*dy, 10.]) if !grid_sorting sim.ocean.input_file = false # fallback to all-to-all contact search end r = min(dx, dy)/2. if include_atmosphere - sim.atmosphere = SeaIce.createRegularAtmosphereGrid([nx, ny, 2], + sim.atmosphere = Granular.createRegularAtmosphereGrid([nx, ny, 2], [nx*dx, ny*dy, 10.]) end - # add ice floes in regular packing + # add grains in regular packing for iy=1:ny for ix=1:nx x = r + (ix - 1)*dx @@ -39,11 +39,11 @@ function timeSingleStepInDenseSimulation(nx::Int; verbose::Bool=true, if ix == 1 || iy == 1 || ix == nx || iy == ny fixed = true end - SeaIce.addIceFloeCylindrical!(sim, [x, y], r*1.1, 1., + Granular.addGrainCylindrical!(sim, [x, y], r*1.1, 1., fixed=fixed, verbose=false) end end - print_with_color(:green, "number of ice floes: $(length(sim.ice_floes))\n") + print_with_color(:green, "number of grains: $(length(sim.grains))\n") if grid_sorting if include_atmosphere print_with_color(:green, "using cell-based spatial decomposition " * @@ -56,35 +56,35 @@ function timeSingleStepInDenseSimulation(nx::Int; verbose::Bool=true, print_with_color(:green, "using all-to-all contact search\n") end - SeaIce.setTotalTime!(sim, 1.0) - SeaIce.setTimeStep!(sim) - SeaIce.run!(sim, single_step=true, verbose=true) + Granular.setTotalTime!(sim, 1.0) + Granular.setTimeStep!(sim) + Granular.run!(sim, single_step=true, verbose=true) if profile - @profile SeaIce.run!(sim, single_step=true, verbose=true) + @profile Granular.run!(sim, single_step=true, verbose=true) if verbose Profile.print() end - SeaIce.run!(sim, single_step=true, verbose=true) + Granular.run!(sim, single_step=true, verbose=true) end n_runs = 4 t_elapsed = 1e12 for i=1:n_runs tic() - @time SeaIce.run!(sim, single_step=true, verbose=true) + @time Granular.run!(sim, single_step=true, verbose=true) t = toc() if t < t_elapsed t_elapsed = t end end - #SeaIce.writeVTK(sim) + #Granular.writeVTK(sim) - @test sim.ice_floes[1].n_contacts == 0 - @test sim.ice_floes[2].n_contacts == 1 - @test sim.ice_floes[3].n_contacts == 1 - @test sim.ice_floes[nx].n_contacts == 0 - @test sim.ice_floes[nx + 1].n_contacts == 1 - @test sim.ice_floes[nx + 2].n_contacts == 4 + @test sim.grains[1].n_contacts == 0 + @test sim.grains[2].n_contacts == 1 + @test sim.grains[3].n_contacts == 1 + @test sim.grains[nx].n_contacts == 0 + @test sim.grains[nx + 1].n_contacts == 1 + @test sim.grains[nx + 2].n_contacts == 4 return t_elapsed, Base.summarysize(sim) end @@ -149,7 +149,7 @@ Plots.plot!(elements, fit_cell_sorting2(elements), label=label_cell_sorting2) Plots.title!("Dense granular system " * "(host: $(gethostname()))") -Plots.xaxis!("Number of ice floes") +Plots.xaxis!("Number of grains") Plots.yaxis!("Wall time per time step [s]") Plots.savefig("profiling-cpu.pdf") @@ -191,6 +191,6 @@ Plots.plot!(elements, fit_cell_sorting2(elements), label=label_cell_sorting2) Plots.title!("Dense granular system " * "(host: $(gethostname()))") -Plots.xaxis!("Number of ice floes") +Plots.xaxis!("Number of grains") Plots.yaxis!("Memory usage [kb]") Plots.savefig("profiling-memory-usage.pdf") diff --git a/test/runtests.jl b/test/runtests.jl @@ -1,7 +1,7 @@ -import SeaIce +import Granular using Base.Test -include("icefloe.jl") +include("grain.jl") include("packing.jl") include("util.jl") include("temporal.jl") diff --git a/test/temporal.jl b/test/temporal.jl @@ -1,21 +1,21 @@ info("Testing temporal functionality") -sim = SeaIce.createSimulation() -@test_throws ErrorException SeaIce.setTimeStep!(sim) +sim = Granular.createSimulation() +@test_throws ErrorException Granular.setTimeStep!(sim) -SeaIce.setOutputFileInterval!(sim, 1e-9) -@test_throws ErrorException SeaIce.setTotalTime!(sim, 0.) -@test_throws ErrorException SeaIce.setCurrentTime!(sim, 0.) -SeaIce.setCurrentTime!(sim, 1.) +Granular.setOutputFileInterval!(sim, 1e-9) +@test_throws ErrorException Granular.setTotalTime!(sim, 0.) +@test_throws ErrorException Granular.setCurrentTime!(sim, 0.) +Granular.setCurrentTime!(sim, 1.) @test sim.time ≈ 1.0 -@test_throws ErrorException SeaIce.incrementCurrentTime!(sim, 0.) -SeaIce.setOutputFileInterval!(sim, 0.) -SeaIce.disableOutputFiles!(sim) -@test_throws ErrorException SeaIce.checkTimeParameters(sim) -SeaIce.addIceFloeCylindrical!(sim, [.1,.1], 2., 2.) -sim.ice_floes[1].mass = 0. -@test_throws ErrorException SeaIce.setTimeStep!(sim) +@test_throws ErrorException Granular.incrementCurrentTime!(sim, 0.) +Granular.setOutputFileInterval!(sim, 0.) +Granular.disableOutputFiles!(sim) +@test_throws ErrorException Granular.checkTimeParameters(sim) +Granular.addGrainCylindrical!(sim, [.1,.1], 2., 2.) +sim.grains[1].mass = 0. +@test_throws ErrorException Granular.setTimeStep!(sim) -sim = SeaIce.createSimulation() -sim2 = SeaIce.createSimulation() -SeaIce.compareSimulations(sim, sim2) +sim = Granular.createSimulation() +sim2 = Granular.createSimulation() +Granular.compareSimulations(sim, sim2) diff --git a/test/util.jl b/test/util.jl @@ -4,23 +4,23 @@ info("#### $(basename(@__FILE__)) ####") info("Testing power-law RNG") -@test 1 == length(SeaIce.randpower()) -@test () == size(SeaIce.randpower()) -@test 1 == length(SeaIce.randpower(1)) -@test () == size(SeaIce.randpower(1)) -@test 4 == length(SeaIce.randpower((2,2))) -@test (2,2) == size(SeaIce.randpower((2,2))) -@test 5 == length(SeaIce.randpower(5)) -@test (5,) == size(SeaIce.randpower(5)) +@test 1 == length(Granular.randpower()) +@test () == size(Granular.randpower()) +@test 1 == length(Granular.randpower(1)) +@test () == size(Granular.randpower(1)) +@test 4 == length(Granular.randpower((2,2))) +@test (2,2) == size(Granular.randpower((2,2))) +@test 5 == length(Granular.randpower(5)) +@test (5,) == size(Granular.randpower(5)) srand(1) for i=1:10^5 - @test 0. <= SeaIce.randpower() <= 1. - @test 0. <= SeaIce.randpower(1, 1., 0., 1.) <= 1. - @test 0. <= SeaIce.randpower(1, 1., 0., .1) <= .1 - @test 5. <= SeaIce.randpower(1, 1., 5., 6.) <= 6. - @test 0. <= minimum(SeaIce.randpower((2,2), 1., 0., 1.)) - @test 1. >= maximum(SeaIce.randpower((2,2), 1., 0., 1.)) - @test 0. <= minimum(SeaIce.randpower(5, 1., 0., 1.)) - @test 1. >= minimum(SeaIce.randpower(5, 1., 0., 1.)) + @test 0. <= Granular.randpower() <= 1. + @test 0. <= Granular.randpower(1, 1., 0., 1.) <= 1. + @test 0. <= Granular.randpower(1, 1., 0., .1) <= .1 + @test 5. <= Granular.randpower(1, 1., 5., 6.) <= 6. + @test 0. <= minimum(Granular.randpower((2,2), 1., 0., 1.)) + @test 1. >= maximum(Granular.randpower((2,2), 1., 0., 1.)) + @test 0. <= minimum(Granular.randpower(5, 1., 0., 1.)) + @test 1. >= minimum(Granular.randpower(5, 1., 0., 1.)) end diff --git a/test/vtk.jl b/test/vtk.jl @@ -5,12 +5,12 @@ info("#### $(basename(@__FILE__)) ####") info("Writing simple simulation to VTK file") -sim = SeaIce.createSimulation(id="test") -SeaIce.addIceFloeCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) -SeaIce.addIceFloeCylindrical!(sim, [18., 0.], 10., 1., verbose=false) -sim.ocean = SeaIce.createRegularOceanGrid([10, 20, 5], [10., 25., 2.]) -SeaIce.findContacts!(sim, method="all to all") -SeaIce.writeVTK(sim, verbose=false) +sim = Granular.createSimulation(id="test") +Granular.addGrainCylindrical!(sim, [ 0., 0.], 10., 1., verbose=false) +Granular.addGrainCylindrical!(sim, [18., 0.], 10., 1., verbose=false) +sim.ocean = Granular.createRegularOceanGrid([10, 20, 5], [10., 25., 2.]) +Granular.findContacts!(sim, method="all to all") +Granular.writeVTK(sim, verbose=false) cmd_post = "" if is_linux() @@ -26,42 +26,42 @@ else error("checksum verification of VTK file not supported on this platform") end -icefloepath = "test/test.icefloes.1.vtu" -icefloechecksum = +grainpath = "test/test.grains.1.vtu" +grainchecksum = "c75ffde29fbdd80161dafd524e690fbcbae2136d4f68c29f725d2d2454c6a162 " * -icefloepath * "\n" +grainpath * "\n" -icefloeinteractionpath = "test/test.icefloe-interaction.1.vtp" -icefloeinteractionchecksum = +graininteractionpath = "test/test.grain-interaction.1.vtp" +graininteractionchecksum = "881598f8f7279ece4301f6c94cb8f9146eb695f8c710edb446f49c1f7a061b84 " * -icefloeinteractionpath * "\n" +graininteractionpath * "\n" oceanpath = "test/test.ocean.1.vts" oceanchecksum = "d56ffb109841a803f2b2b94c74c87f7a497237204841d557d2b1043694d51f0d " * oceanpath * "\n" -@test readstring(`$(cmd) $(icefloepath)$(cmd_post)`) == icefloechecksum -@test readstring(`$(cmd) $(icefloeinteractionpath)$(cmd_post)`) == - icefloeinteractionchecksum +@test readstring(`$(cmd) $(grainpath)$(cmd_post)`) == grainchecksum +@test readstring(`$(cmd) $(graininteractionpath)$(cmd_post)`) == + graininteractionchecksum @test readstring(`$(cmd) $(oceanpath)$(cmd_post)`) == oceanchecksum -SeaIce.removeSimulationFiles(sim) +Granular.removeSimulationFiles(sim) info("Testing VTK write during run!()") -SeaIce.setOutputFileInterval!(sim, 1e-9) -SeaIce.setTotalTime!(sim, 1.5) -SeaIce.setTimeStep!(sim) +Granular.setOutputFileInterval!(sim, 1e-9) +Granular.setTotalTime!(sim, 1.5) +Granular.setTimeStep!(sim) sim.file_number = 0 -SeaIce.run!(sim, single_step=true) -@test SeaIce.readSimulationStatus(sim.id) == 1 -SeaIce.setOutputFileInterval!(sim, 0.1) -SeaIce.run!(sim) +Granular.run!(sim, single_step=true) +@test Granular.readSimulationStatus(sim.id) == 1 +Granular.setOutputFileInterval!(sim, 0.1) +Granular.run!(sim) -SeaIce.status() +Granular.status() info("Testing generation of Paraview Python script") -SeaIce.writeParaviewPythonScript(sim, +Granular.writeParaviewPythonScript(sim, save_animation=true, save_images=false) @test isfile("$(sim.id)/$(sim.id).py") && filesize("$(sim.id)/$(sim.id).py") > 0 @@ -75,7 +75,7 @@ catch return_signal end end -SeaIce.writeParaviewPythonScript(sim, +Granular.writeParaviewPythonScript(sim, save_animation=false, save_images=true) try @@ -84,14 +84,14 @@ catch return_signal if !isa(return_signal, Base.UVError) @test isfile("$(sim.id)/$(sim.id).0000.png") @test isfile("$(sim.id)/$(sim.id).0014.png") - SeaIce.render(sim) + Granular.render(sim) @test isfile("$(sim.id)/$(sim.id).0001.png") end end -@test readstring(`$(cmd) $(icefloepath)$(cmd_post)`) == icefloechecksum -@test readstring(`$(cmd) $(icefloeinteractionpath)$(cmd_post)`) == - icefloeinteractionchecksum +@test readstring(`$(cmd) $(grainpath)$(cmd_post)`) == grainchecksum +@test readstring(`$(cmd) $(graininteractionpath)$(cmd_post)`) == + graininteractionchecksum @test readstring(`$(cmd) $(oceanpath)$(cmd_post)`) == oceanchecksum -SeaIce.removeSimulationFiles(sim) +Granular.removeSimulationFiles(sim)