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()