Introduction
Introduction Statistics Contact Development Disclaimer Help
tridging_simulation.jl - seaice-experiments - sea ice experiments using Granula…
git clone git://src.adamsgaard.dk/seaice-experiments
Log
Files
Refs
README
LICENSE
---
tridging_simulation.jl (17625B)
---
1 #/usr/bin/env julia
2 ENV["MPLBACKEND"] = "Agg"
3 import Granular
4 import PyPlot
5 import ArgParse
6 import DelimitedFiles
7 using Random
8
9 let
10 render = false
11
12 function parse_command_line()
13 s = ArgParse.ArgParseSettings()
14 ArgParse.@add_arg_table s begin
15 "--E"
16 help = "Young's modulus [Pa]"
17 arg_type = Float64
18 default = 2e7
19 "--nu"
20 help = "Poisson's ratio [-]"
21 arg_type = Float64
22 default = 0.285
23 "--mu_d"
24 help = "dynamic friction coefficient [-]"
25 arg_type = Float64
26 default = 0.3
27 "--tensile_strength"
28 help = "the maximum tensile strength [Pa]"
29 arg_type = Float64
30 default = 400e3
31 "--tensile_strength_std_dev"
32 help = "standard deviation of the maximum tensile strength […
33 arg_type = Float64
34 default = 0.0
35 "--shear_strength"
36 help = "the maximum shear strength [Pa]"
37 arg_type = Float64
38 default = 200e3
39 "--r"
40 help = "grain radius [m]"
41 arg_type = Float64
42 default = 0.01
43 "--size_scaling"
44 help = "scale factor for r,nx1,nx2,ny1,ny2 [-]"
45 arg_type = Float64
46 default = 1.0
47 "--heal_rate"
48 help = "healing rate for new bonds [Pa/s]"
49 arg_type = Float64
50 default = 1.0
51 "--thickness"
52 help = "grain thickness [m]"
53 arg_type = Float64
54 default = 1.
55 "--rotating"
56 help = "allow the grains to rotate"
57 arg_type = Bool
58 default = true
59 "--compressive_velocity"
60 help = "compressive velocity [m/s]"
61 arg_type = Float64
62 default = 0.1
63 "--ny1"
64 help = "thickness in number of grains for left ice floe"
65 arg_type = Int
66 default = 10
67 "--ny2"
68 help = "thickness in number of grains for right ice floe"
69 arg_type = Int
70 default = 11
71 "--nx1"
72 help = "width in number of grains for left ice floe"
73 arg_type = Int
74 default = 100
75 "--nx2"
76 help = "width in number of grains for right ice floe"
77 arg_type = Int
78 default = 100
79 "--seed"
80 help = "seed for the pseudo RNG"
81 arg_type = Int
82 default = 1
83 "--one_floe"
84 help = "generate a single floe instead of two separate ones"
85 arg_type = Bool
86 default = false
87 "--many_floes"
88 help = "generate many floes instead of two separate ones"
89 arg_type = Bool
90 default = false
91 "--continuous_ice"
92 help = "add ice continuously and compress from both sides"
93 arg_type = Bool
94 default = false
95 "id"
96 help = "simulation id"
97 required = true
98 end
99 return ArgParse.parse_args(s)
100 end
101
102 function report_args(parsed_args)
103 println("Parsed args:")
104 for (arg,val) in parsed_args
105 println(" $arg => $val")
106 end
107 end
108
109 function run_simulation(id::String,
110 E::Float64,
111 nu::Float64,
112 mu_d::Float64,
113 tensile_strength::Float64,
114 tensile_strength_std_dev::Float64,
115 shear_strength::Float64,
116 r::Float64,
117 size_scaling::Float64,
118 heal_rate::Float64,
119 thickness::Float64,
120 rotating::Bool,
121 compressive_velocity::Float64,
122 ny1::Int,
123 ny2::Int,
124 nx1::Int,
125 nx2::Int,
126 seed::Int,
127 one_floe::Bool=false,
128 many_floes::Bool=false,
129 continuous_ice::Bool=false)
130
131 ####################################################################…
132 #### SIMULATION PARAMETERS
133 ####################################################################…
134
135 # Common simulation identifier
136 id_prefix = id
137
138 # Grain mechanical properties
139 youngs_modulus = E # Elastic modulus [Pa]
140 poissons_ratio = nu # Shear-stiffness ratio [-]
141 contact_dynamic_friction = mu_d # Coulomb-frictional coefficient [-]
142
143 # Simulation duration [s]
144 t_total = (nx1 + nx2)/2*r*2/compressive_velocity
145
146 # Temporal interval between output files
147 file_dt = t_total/200
148
149 # Misc parameters
150 water_density = 1000.
151 g = 9.8
152 #g = 0.0
153 y_water_surface = 0.0
154
155 r = r/size_scaling
156 nx1 = Int(round(nx1*size_scaling))
157 nx2 = Int(round(nx2*size_scaling))
158 ny1 = Int(round(ny1*size_scaling))
159 ny2 = Int(round(ny2*size_scaling))
160
161 Random.seed!(seed)
162
163 ####################################################################…
164 #### Create ice floes
165 ####################################################################…
166 sim = Granular.createSimulation("$(id_prefix)")
167 Granular.removeSimulationFiles(sim)
168
169 if one_floe
170 ny2 = ny1
171 Granular.regularPacking!(sim, [nx1+nx2, ny1], r, r, padding_fact…
172 tiling="triangular",
173 origo=[0.0, -0.66*ny1*r*2]
174 )
175 # Add linear gradient in compressive velocity
176 max_x = (nx1+nx2)*r*2
177 for grain in sim.grains
178 grain.lin_vel[1] = (1.0 - grain.lin_pos[1]/max_x) * compress…
179 end
180
181 elseif many_floes
182
183 N_floes = 6
184 x = 0.0
185 for i=1:N_floes
186
187 t_total = nx1*N_floes*r/compressive_velocity
188
189 nx = nx1 + Int(round(nx1*0.5*rand()))
190 ny = ny1 + Int(round(ny1*0.5*rand()))
191
192 N0 = length(sim.grains)
193 # Left ice floe
194 Granular.regularPacking!(sim, [nx, ny], r, r, padding_factor…
195 tiling="triangular",
196 origo=[x, -0.66*ny1*r*2]
197 )
198 if i == 1
199 for grain in sim.grains
200 grain.lin_vel[1] = 0.5*compressive_velocity
201 end
202 end
203
204 N1 = length(sim.grains)
205
206 for in=(N0 + 1):N1
207 sim.grains[in].color = i
208 end
209
210 if i == N_floes
211 for in=(N0 + 1):N1
212 sim.grains[in].lin_vel[1] = -0.5*compressive_velocity
213 end
214 end
215
216 x += nx * 2.0*r + 4.0*r
217 end
218
219 elseif continuous_ice
220
221 # Left ice floe
222 Granular.regularPacking!(sim, [nx1, ny1], r, r, padding_factor=0…
223 tiling="triangular",
224 origo=[0.0, -0.66*ny1*r*2]
225 )
226 for grain in sim.grains
227 grain.lin_vel[1] = 0.5*compressive_velocity
228 end
229
230 # Right ice floe
231 Granular.regularPacking!(sim, [nx2, ny2], r, r, padding_factor=0…
232 tiling="triangular",
233 origo=[nx1*2*r + 10*r*size_scaling,
234 -0.66*ny2*r*2]
235 )
236 for grain in sim.grains
237 if grain.lin_vel[1] == 0.0
238 grain.lin_vel[1] = -0.5*compressive_velocity
239 end
240 end
241
242 else # two ice floes
243
244 # Left ice floe
245 Granular.regularPacking!(sim, [nx1, ny1], r, r, padding_factor=0…
246 tiling="triangular",
247 origo=[0.0, -0.66*ny1*r*2]
248 )
249 grainArrays = Granular.convertGrainDataToArrays(sim)
250 x_min = minimum(grainArrays.lin_pos[1,:])
251 for grain in sim.grains
252 grain.lin_vel[1] = compressive_velocity
253 grain.lin_pos[1] -= x_min
254 end
255
256 # Right ice floe
257 Granular.regularPacking!(sim, [nx2, ny2], r, r, padding_factor=0…
258 tiling="triangular",
259 origo=[nx1*2*r + 10*r*size_scaling,
260 -0.66*ny2*r*2]
261 )
262 end
263
264 for grain in sim.grains
265 grain.contact_radius *= 1.0 + 1e-6
266 grain.areal_radius *= 1.0 + 1e-6
267 end
268
269 if many_floes
270 Granular.fitGridToGrains!(sim, sim.ocean, padding=r*100, verbose…
271
272 else
273 # Create a grid for contact searching spanning the extent of the…
274 #sim.ocean = Granular.createRegularOceanGrid([(nx1+nx2) - 10,
275 # max(ny1,ny2)*10 - …
276 # [(nx1+nx2)*r*2 + 11…
277 # max(ny1,ny2)*2*r*1…
278 # 2*r],
279 # origo=[0., -max(ny1…
280 Granular.fitGridToGrains!(sim, sim.ocean, padding=r*100, verbose…
281 end
282
283 # Make the top and bottom boundaries impermeable, and the side bound…
284 # periodic, which will come in handy during shear
285 Granular.setGridBoundaryConditions!(sim.ocean, "impermeable")
286
287 # Set grain mechanical properties
288 for grain in sim.grains
289 grain.youngs_modulus = youngs_modulus
290 grain.poissons_ratio = poissons_ratio
291 grain.tensile_strength = abs(tensile_strength + randn()*tensile_…
292 grain.shear_strength = abs(shear_strength + randn()*tensile_stre…
293 grain.contact_static_friction = contact_dynamic_friction # mu_s…
294 grain.contact_dynamic_friction = contact_dynamic_friction
295 grain.rotating = rotating
296 grain.ocean_drag_coeff_horiz = 0.0 # don't include drag on ends
297 end
298
299 Granular.setTimeStep!(sim)
300 Granular.setTotalTime!(sim, t_total)
301 Granular.setOutputFileInterval!(sim, file_dt)
302 if render
303 Granular.plotGrains(sim, verbose=true)
304 end
305
306 grainArrays = Granular.convertGrainDataToArrays(sim)
307 x_max = maximum(grainArrays.lin_pos[1,:])
308 x_min = minimum(grainArrays.lin_pos[1,:])
309
310 # fix velocities of outermost parts of the ice floes
311 if many_floes
312 fix_dist = nx1*r*2
313 else
314 fix_dist = r*10
315 end
316
317 for grain in sim.grains
318 if abs(grain.lin_vel[1]) > 0.0
319 grain.fixed = true
320 grain.allow_y_acc = true
321 end
322 end
323
324 ####################################################################…
325 #### RUN THE SIMULATION
326 ####################################################################…
327 theta = 0.0; submerged_volume = 0.0
328 time = Float64[]
329 N = Float64[] # normal stress on leftmost fixed particles
330 τ = Float64[] # shear stress on leftmost fixed particles
331 A = sim.grains[1].thickness * ny1*r*2
332 while sim.time < sim.time_total
333
334 append!(time, sim.time)
335
336 # Record cumulative force on leftmost fixed particles
337 normal_force = 0.0
338 tangential_force = 0.0
339 for grain in sim.grains
340 if grain.fixed && grain.lin_pos[1] < 0.7*x_max
341 normal_force += grain.force[1]
342 tangential_force += grain.force[2]
343 end
344 end
345 append!(N, -normal_force/A) # compressive = positive
346 append!(τ, tangential_force/A)
347
348 # Run for 100 time steps before measuring bulk forces
349 for i=1:100
350
351 if sim.time_iteration < 3
352 # Age (and strengthen) all existing bonds
353 for grain in sim.grains
354 for ic=1:length(grain.contact_age)
355 grain.contact_age[ic] = 1e16
356 end
357 end
358 elseif sim.time_iteration == 3
359 # weaken any new bonding
360 for grain in sim.grains
361 grain.strength_heal_rate = heal_rate # new bond sten…
362 end
363 end
364
365 # remove velocity constraint on grains that have left the fi…
366 if continuous_ice
367 for grain in sim.grains
368 if grain.lin_pos[1] < fix_dist
369 grain.fixed = true
370 grain.allow_y_acc = true
371 elseif grain.lin_pos[1] > x_max …
372 grain.fixed = true
373 grain.allow_y_acc = true
374 else
375 if grain.fixed == true
376 newgrain = deepc…
377 grain.fixed = fa…
378 # keep shifting …
379 if grain.lin_vel…
380 while !G…
381 …
382 …
383 …
384 end
385 else
386 while !G…
387 …
388 …
389 …
390 end
391 end
392 newgrain.lin_dis…
393 newgrain.n_conta…
394 newgrain.contact…
395 Granular.addGrai…
396 i_newgrain = len…
397 println("freeing…
398 println("adding …
399 Granular.sortGra…
400 Granular.findCon…
401 println("new gra…
402 # max out contac…
403 for g2 in sim.gr…
404 if i_new…
405 …
406 …
407 …
408 …
409 …
410 …
411 …
412 end
413 end
414 end
415 end
416 end
417 end
418
419 # Adjust body forces, assuming water surface at y=0
420 for grain in sim.grains
421
422 # Gravitational force
423 Granular.setBodyForce!(grain, [0.0, -grain.mass*g])
424
425
426 if grain.lin_pos[2] + grain.areal_radius < y_water_surfa…
427 # Add buoyant force, fully submerged
428 Granular.addBodyForce!(grain, [0.0,
429 water_density*grain.v…
430 # set ocean drag coefficient
431 grain.ocean_drag_coeff_vert = 0.85
432
433
434 elseif grain.lin_pos[2] - grain.areal_radius < y_water_s…
435 # Add buoyant force, partially submerged
436
437 theta = 2*acos(abs(grain.lin_pos[2])/grain.areal_rad…
438 if grain.lin_pos[2] < y_water_surface
439 submerged_volume = grain.volume -
440 (grain.areal_radius^2/2*
441 (theta - sin(theta))*grain.thickness)
442 else
443 theta = 2*acos(abs(grain.lin_pos[2])/grain.areal…
444 submerged_volume = grain.areal_radius^2/2*
445 (theta - sin(theta))*grain.thickness
446 end
447
448 Granular.addBodyForce!(grain,
449 [0.0, water_density*submerged…
450 grain.ocean_drag_coeff_vert = 0.85
451 else
452 # above water
453 grain.ocean_drag_coeff_vert = 0.0
454 end
455 end
456 Granular.run!(sim, single_step=true)
457 end
458
459 end
460
461 # Plot normal stress and shear stress vs time
462 DelimitedFiles.writedlm(id_prefix * "-data.txt", [time, N, τ])
463 PyPlot.subplot(211)
464 PyPlot.subplots_adjust(hspace=0.0)
465 ax1 = PyPlot.gca()
466 PyPlot.setp(ax1[:get_xticklabels](),visible=false) # Disable x labels
467 PyPlot.plot(time, N/1e3)
468 PyPlot.ylabel("Compressive stress [kPa]")
469 PyPlot.subplot(212, sharex=ax1)
470 PyPlot.plot(time, τ/1e3)
471 PyPlot.xlabel("Time [s]")
472 PyPlot.ylabel("Shear stress [kPa]")
473 PyPlot.tight_layout()
474 PyPlot.savefig(sim.id * "-time_vs_stress.pdf")
475 PyPlot.clf()
476
477 # Create GSD plot to signify that simulation is complete
478 #Granular.writeSimulation(sim)
479 #if render
480 # Granular.plotGrainSizeDistribution(sim)
481 #end
482 end
483
484 function main()
485 parsed_args = parse_command_line()
486 report_args(parsed_args)
487
488 seed = parsed_args["seed"]
489 run_simulation(parsed_args["id"] * "-seed" * string(seed),
490 parsed_args["E"],
491 parsed_args["nu"],
492 parsed_args["mu_d"],
493 parsed_args["tensile_strength"],
494 parsed_args["tensile_strength_std_dev"],
495 parsed_args["shear_strength"],
496 parsed_args["r"],
497 parsed_args["size_scaling"],
498 parsed_args["heal_rate"],
499 parsed_args["thickness"],
500 parsed_args["rotating"],
501 parsed_args["compressive_velocity"],
502 parsed_args["ny1"],
503 parsed_args["ny2"],
504 parsed_args["nx1"],
505 parsed_args["nx2"],
506 seed,
507 parsed_args["one_floe"],
508 parsed_args["many_floes"],
509 parsed_args["continuous_ice"])
510 end
511
512 main()
513 end
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.