tsimulation.jl - seaice-experiments - sea ice experiments using Granular.jl
 (HTM) git clone git://src.adamsgaard.dk/seaice-experiments
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tsimulation.jl (14531B)
       ---
            1 #!/usr/bin/env julia
            2 import Granular
            3 import ArgParse
            4 
            5 verbose = false
            6 
            7 function parse_command_line()
            8     s = ArgParse.ArgParseSettings()
            9     ArgParse.@add_arg_table s begin
           10         "--width"
           11             help = "strait width [m]"
           12             arg_type = Float64
           13             default = 6e3
           14         "--E"
           15             help = "Young's modulus [Pa]"
           16             arg_type = Float64
           17             default = 2e7
           18         "--nu"
           19             help = "Poisson's ratio [-]"
           20             arg_type = Float64
           21             default = 0.285
           22         "--k_n"
           23             help = "normal stiffness [N/m]"
           24             arg_type = Float64
           25             default = 1e7
           26         "--k_t"
           27             help = "tangential stiffness [N/m]"
           28             arg_type = Float64
           29             default = 1e7
           30         "--gamma_n"
           31             help = "normal viscosity [N/(m/s)]"
           32             arg_type = Float64
           33             default = 0.
           34         "--gamma_t"
           35             help = "tangential viscosity [N/(m/s)]"
           36             arg_type = Float64
           37             default = 0.
           38         "--mu_s"
           39             help = "static friction coefficient [-]"
           40             arg_type = Float64
           41             default = 0.3
           42         "--mu_d"
           43             help = "dynamic friction coefficient [-]"
           44             arg_type = Float64
           45             default = 0.3
           46         "--mu_s_wall"
           47             help = "static friction coefficient for wall particles [-]"
           48             arg_type = Float64
           49             default = 0.3
           50         "--mu_d_wall"
           51             help = "dynamic friction coefficient for wall particles [-]"
           52             arg_type = Float64
           53             default = 0.3
           54         "--tensile_strength"
           55             help = "the maximum tensile strength [Pa]"
           56             arg_type = Float64
           57             default = 0.
           58         "--r_min"
           59             help = "minimum grain radius [m]"
           60             arg_type = Float64
           61             default = 6e2
           62         "--r_max"
           63             help = "maximum grain radius [m]"
           64             arg_type = Float64
           65             default = 1.35e3
           66         "--thickness"
           67             help = "grain thickness [m]"
           68             arg_type = Float64
           69             default = 1.
           70         "--rotating"
           71             help = "allow the grains to rotate"
           72             arg_type = Bool
           73             default = true
           74         "--ocean_vel_fac"
           75             help = "ocean velocity factor [-]"
           76             arg_type = Float64
           77             default = 0.0
           78         "--atmosphere_vel_fac"
           79             help = "atmosphere velocity [m/s]"
           80             arg_type = Float64
           81             default = 30.0
           82         "--total_hours"
           83             help = "hours of simulation time [h]"
           84             arg_type = Float64
           85             default = 12.
           86         "--seed"
           87             help = "seed for the pseudo RNG"
           88             arg_type = Int
           89             default = 1
           90         "id"
           91             help = "simulation id"
           92             required = true
           93     end
           94     return ArgParse.parse_args(s)
           95 end
           96 
           97 function report_args(parsed_args)
           98     println("Parsed args:")
           99     for (arg,val) in parsed_args
          100         println("  $arg  =>  $val")
          101     end
          102 end
          103 
          104 function run_simulation(id::String,
          105                         width::Float64,
          106                         E::Float64,
          107                         nu::Float64,
          108                         k_n::Float64,
          109                         k_t::Float64,
          110                         gamma_n::Float64,
          111                         gamma_t::Float64,
          112                         mu_s::Float64,
          113                         mu_d::Float64,
          114                         mu_s_wall::Float64,
          115                         mu_d_wall::Float64,
          116                         tensile_strength::Float64,
          117                         r_min::Float64,
          118                         r_max::Float64,
          119                         thickness::Float64,
          120                         rotating::Bool,
          121                         ocean_vel_fac::Float64,
          122                         atmosphere_vel_fac::Float64,
          123                         total_hours::Float64,
          124                         seed::Int)
          125 
          126     info("## EXPERIMENT: " * id * " ##")
          127     sim = Granular.createSimulation(id=id)
          128 
          129     const Lx = 50.e3
          130     const Lx_constriction = width
          131     const Ly_constriction = 10e3
          132     const L = [Lx, Lx*3./4., 1e3]
          133     const dx = r_max*2.
          134 
          135     #n = [Int(ceil(L[1]/dx/2.)), Int(ceil(L[2]/dx/2.)), 2]
          136     n = [Int(ceil(L[1]/dx)), Int(ceil(L[2]/dx)), 2]
          137 
          138     # Initialize confining walls, which are grains that are fixed in space
          139     r = r_max
          140     h = thickness
          141     r_walls = r_min/2.
          142 
          143     ## N-S segments
          144     for y in linspace(r_walls,
          145                       Ly_constriction - 2.0*r_walls, 
          146                       Int(ceil((Ly_constriction - 2.*r_walls)/(r_walls*2.))))
          147 
          148         Granular.addGrainCylindrical!(sim,
          149                                       [Lx/2. - Lx_constriction/2. - r_walls, y], 
          150                                       r_walls, h, fixed=true, verbose=false)
          151 
          152         Granular.addGrainCylindrical!(sim,
          153                                       [Lx/2. + Lx_constriction/2. + r_walls, y], 
          154                                       r_walls, h, fixed=true, verbose=false)
          155 
          156     end
          157 
          158     dx = 2.*r_walls
          159 
          160     ## Left island upper edge
          161     x = r_walls:dx:(Lx/2. - Lx_constriction/2. - r_walls)
          162     y = ones(length(x))*Ly_constriction
          163     for i in 1:length(x)
          164         Granular.addGrainCylindrical!(sim, [x[i], y[i]], r_walls, h, fixed=true, 
          165                                       verbose=false)
          166     end
          167 
          168     ## Right island upper edge
          169     x = (Lx/2. + Lx_constriction/2. + r_walls):dx:(Lx - r_walls)
          170     y = ones(length(x))*Ly_constriction
          171     for i in 1:length(x)
          172         Granular.addGrainCylindrical!(sim, [x[i], y[i]], r_walls, h, fixed=true, 
          173                                       verbose=false)
          174     end
          175 
          176     n_walls = length(sim.grains)
          177     info("added $(n_walls) fixed grains as walls")
          178 
          179     # Initialize ocean and atmosphere
          180     sim.ocean = Granular.createRegularOceanGrid(n, L, name="no_flow")
          181     sim.atmosphere = Granular.createRegularAtmosphereGrid(n, L, 
          182                                                           name="uniform_flow")
          183     sim.atmosphere.v[:, :, 1, 1] = -atmosphere_vel_fac
          184 
          185     Granular.setGridBoundaryConditions!(sim.ocean, "inactive", "-y +y")
          186     Granular.setGridBoundaryConditions!(sim.ocean, "impermeable", "-x +x")
          187 
          188     # Initialize grains in wedge north of the constriction
          189     Granular.sortGrainsInGrid!(sim, sim.ocean)
          190     iy = 1
          191     spacing_to_boundaries = r_walls
          192     floe_padding = .5*r
          193     noise_amplitude = floe_padding
          194     Base.Random.srand(seed)
          195     for iy=1:size(sim.ocean.xh, 2)
          196         for ix=1:size(sim.ocean.xh, 1)
          197 
          198             for it=1:25  # number of grains to try adding per cell
          199 
          200                 r_rand = r_min + Base.Random.rand()*(r - r_min)
          201                 pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean,
          202                                                            ix, iy,
          203                                                            r_rand, n_iter=100,
          204                                                            seed=seed)
          205                 if !(typeof(pos) == Array{Float64, 1})
          206                     continue
          207                 end
          208 
          209                 @inbounds if pos[2] < Ly_constriction +
          210                     spacing_to_boundaries + r_rand
          211                     continue
          212                 end
          213                    
          214                 Granular.addGrainCylindrical!(sim, pos, r_rand, h, 
          215                                               verbose=false)
          216                 Granular.sortGrainsInGrid!(sim, sim.ocean)
          217             end
          218         end
          219     end
          220     n = length(sim.grains) - n_walls
          221     info("added $(n) grains")
          222 
          223     # Remove old simulation files
          224     Granular.removeSimulationFiles(sim)
          225 
          226     for i=1:length(sim.grains)
          227         sim.grains[i].youngs_modulus = E
          228         sim.grains[i].poissons_ratio = nu
          229         sim.grains[i].contact_stiffness_normal = k_n
          230         sim.grains[i].contact_stiffness_tangential = k_t
          231         sim.grains[i].contact_viscosity_normal = gamma_n
          232         sim.grains[i].contact_viscosity_tangential = gamma_t
          233         sim.grains[i].contact_static_friction = mu_s
          234         sim.grains[i].contact_dynamic_friction = mu_d
          235         sim.grains[i].tensile_strength = tensile_strength
          236         sim.grains[i].rotating = rotating
          237         if sim.grains[i].fixed == true
          238             sim.grains[i].contact_static_friction = mu_s_wall
          239             sim.grains[i].contact_dynamic_friction = mu_d_wall
          240         end
          241     end
          242 
          243     # Set temporal parameters
          244     Granular.setTotalTime!(sim, total_hours*60.*60.)
          245     #Granular.setOutputFileInterval!(sim, 60.*5.)  # output every 5 mins
          246     Granular.setOutputFileInterval!(sim, 60.)  # output every 1 mins
          247     Granular.setTimeStep!(sim, verbose=verbose)
          248     Granular.writeVTK(sim, verbose=verbose)
          249 
          250     println("$(sim.id) size before run")
          251     Granular.printMemoryUsage(sim)
          252 
          253     profile = false
          254 
          255     ice_flux = Float64[]
          256     avg_coordination_no = Float64[]
          257     #ice_flux_sample_points = 100
          258     #ice_flux = zeros(ice_flux_sample_points)
          259     #dt_ice_flux = sim.time_total/ice_flux_sample_points
          260     #time_since_ice_flux = 1e9
          261 
          262     jammed = false
          263     it_before_eval = 100
          264     time_jammed = 0.
          265     time_jammed_criterion = 60.*60.  # define as jammed after this duration
          266 
          267     # preallocate variables
          268     ice_mass_outside_domain = x = y = x_ = y_ = r_rand = 0.
          269 
          270     while sim.time < sim.time_total
          271 
          272         # run simulation for it_before_eval time steps
          273         for it=1:it_before_eval
          274             if sim.time >= sim.time_total*.75 && profile
          275                 @profile Granular.run!(sim, status_interval=1, single_step=true,
          276                                     verbose=verbose, show_file_output=verbose)
          277                 Profile.print()
          278                 profile = false
          279             else
          280                 Granular.run!(sim, status_interval=1, single_step=true,
          281                             verbose=verbose, show_file_output=verbose)
          282             end
          283         end
          284 
          285         if sim.time_iteration % 1_000 == 0
          286             @printf("\n%s size t=%5f h\n", sim.id, sim.time/3600.)
          287             Granular.printMemoryUsage(sim)
          288         end
          289 
          290         # assert if the system is jammed by looking at ice-floe mass change in 
          291         # the number of jammed grains
          292         if jammed
          293             time_jammed += sim.time_dt*float(it_before_eval)
          294             if time_jammed >= 60.*60.  # 1 h
          295                 info("$t s: system jammed for more than " * 
          296                 "$time_jammed_criterion s, stopping simulation")
          297                 exit()
          298             end
          299         end
          300 
          301         if sim.time_iteration % 1_000 == 0
          302             ice_mass_outside_domain = 0.
          303             for icefloe in sim.grains
          304                 if !icefloe.enabled
          305                     ice_mass_outside_domain += icefloe.mass
          306                 end
          307             end
          308             append!(ice_flux, ice_mass_outside_domain)
          309 
          310             # get average coordination number around channel entrance
          311             n_contacts_sum = 0
          312             n_particles = 0
          313             for i=1:length(sim.grains)
          314                 if !sim.grains[i].fixed && sim.grains[i].enabled
          315                     n_contacts_sum += sim.grains[i].n_contacts
          316                     n_particles += 1
          317                 end
          318             end
          319             append!(avg_coordination_no, float(n_contacts_sum/n_particles))
          320         end
          321 
          322         # add new grains from the top
          323         @inbounds for ix=2:(size(sim.ocean.xh, 1) - 1)
          324             if length(sim.ocean.grain_list[ix, end]) == 0
          325                 for it=1:17  # number of grains to try adding per cell
          326                     # Uniform distribution
          327                     #r_rand = r_min + Base.Random.rand()*(r_max - r_min)
          328 
          329                     # Exponential distribution with scale=1
          330                     #r_rand = r_min + Base.Random.randexp()*(r_max - r_min)/4.
          331 
          332                     # Power-law distribution (sea ice power ≈ -1.8)
          333                     r_rand = Granular.randpower(1, -1.8, r_min, r_max)
          334 
          335                     pos = Granular.findEmptyPositionInGridCell(sim, sim.ocean,
          336                                                              ix, iy,
          337                                                              r_rand, n_iter=100)
          338                     if !(typeof(pos) == Array{Float64, 1})
          339                         continue
          340                     end
          341 
          342                     Granular.addGrainCylindrical!(sim, pos, r_rand, h, 
          343                                                   verbose=false,
          344                                                   youngs_modulus=E,
          345                                                   poissons_ratio=nu,
          346                                                   contact_stiffness_normal=k_n,
          347                                                   contact_stiffness_tangential=
          348                                                   k_t,
          349                                                   contact_viscosity_normal=
          350                                                   gamma_n,
          351                                                   contact_viscosity_tangential=
          352                                                   gamma_t,
          353                                                   contact_static_friction=mu_s,
          354                                                   contact_dynamic_friction=
          355                                                   mu_d,
          356                                                   tensile_strength=
          357                                                   tensile_strength,
          358                                                   rotating=rotating)
          359                     Granular.sortGrainsInGrid!(sim, sim.ocean)
          360                 end
          361             end
          362         end
          363 
          364     end
          365 
          366     Granular.writeParaviewPythonScript(sim)
          367     t = linspace(0., sim.time_total, length(ice_flux))
          368     writedlm(sim.id * "-ice-flux.txt", [t, ice_flux, avg_coordination_no])
          369     sim = 0
          370     gc()
          371 end
          372 
          373 function main()
          374     parsed_args = parse_command_line()
          375     report_args(parsed_args)
          376 
          377     seed = parsed_args["seed"]
          378 
          379     run_simulation(parsed_args["id"] * "-seed" * string(seed),
          380                    parsed_args["width"],
          381                    parsed_args["E"],
          382                    parsed_args["nu"],
          383                    parsed_args["k_n"],
          384                    parsed_args["k_t"],
          385                    parsed_args["gamma_n"],
          386                    parsed_args["gamma_t"],
          387                    parsed_args["mu_s"],
          388                    parsed_args["mu_d"],
          389                    parsed_args["mu_s_wall"],
          390                    parsed_args["mu_d_wall"],
          391                    parsed_args["tensile_strength"],
          392                    parsed_args["r_min"],
          393                    parsed_args["r_max"],
          394                    parsed_args["thickness"],
          395                    parsed_args["rotating"],
          396                    parsed_args["ocean_vel_fac"],
          397                    parsed_args["atmosphere_vel_fac"],
          398                    parsed_args["total_hours"],
          399                    seed)
          400 end
          401 
          402 main()