1 | import numpy as np
|
---|
2 |
|
---|
3 | from averaging import averaging
|
---|
4 | from thomasparams import thomasparams
|
---|
5 |
|
---|
6 |
|
---|
7 | def analyticaldamage(md, **kwargs):
|
---|
8 | '''
|
---|
9 | ANALYTICALDAMAGE - compute damage for an ice shelf
|
---|
10 |
|
---|
11 | This routine computes damage as a function of water / ice
|
---|
12 | material properties, ice thickness, strain rate, and ice
|
---|
13 | rigidity. The model must contain computed strain rates,
|
---|
14 | either from observed or modeled ice velocities.
|
---|
15 |
|
---|
16 | Available options:
|
---|
17 | - eq : analytical equation to use in the calculation. Must be one of:
|
---|
18 | 'Weertman1D' for a confined ice shelf free to flow in one direction
|
---|
19 | 'Weertman2D' for an unconfined ice shelf free to spread in any direction
|
---|
20 | 'Thomas' for a 2D ice shelf, taking into account full strain rate tensor (default)
|
---|
21 | - smoothing : the amount of smoothing to be applied to the strain rate data.
|
---|
22 | Type 'help averaging' for more information on its usage.
|
---|
23 | - coordsys : coordinate system for calculating the strain rate
|
---|
24 | components. Must be one of:
|
---|
25 | - sigmab : a compressive backstress term to be subtracted from the driving stress
|
---|
26 | in the damage calculation
|
---|
27 |
|
---|
28 | Return values:
|
---|
29 | 'damage' which is truncated in the range [0, 1 - 1e-9]
|
---|
30 |
|
---|
31 | 'B' is the rigidity, which is equal to md.materials.rheology_B in areas outside
|
---|
32 | those defined by 'mask.' Within areas defined by 'mask, ' where negative damage
|
---|
33 | is inferred, 'B' is updated to make damage equal to zero.
|
---|
34 |
|
---|
35 | 'backstress' is the inferred backstress necessary to balance the analytical solution
|
---|
36 | (keeping damage within its appropriate limits, e.g. D in [0, 1]).
|
---|
37 |
|
---|
38 | Usage:
|
---|
39 | damage, B, backstress = analyticaldamage(md, kwargs)
|
---|
40 |
|
---|
41 | Example:
|
---|
42 | damage, B, backstress = analyticaldamage(md, eq = 'Weertman2D', smoothing = 2, sigmab = 1.0e3)
|
---|
43 | '''
|
---|
44 |
|
---|
45 | #unpack kwargs
|
---|
46 | eq = kwargs.pop('eq', 'Thomas')
|
---|
47 | if 'eq' in kwargs:
|
---|
48 | del kwargs['eq']
|
---|
49 | smoothing = kwargs.pop('smoothing', 0)
|
---|
50 | if 'smoothing' in kwargs:
|
---|
51 | del kwargs['smoothing']
|
---|
52 | coordsys = kwargs.pop('coordsys', 'longitudinal')
|
---|
53 | if 'coordsys' in kwargs:
|
---|
54 | del kwargs['coordsys']
|
---|
55 | sigmab = kwargs.pop('sigmab', 0)
|
---|
56 | if 'sigmab' in kwargs:
|
---|
57 | del kwargs['sigmab']
|
---|
58 | assert len(kwargs) == 0, 'error, unexpected or misspelled kwargs'
|
---|
59 |
|
---|
60 | if isinstance(sigmab, (int, float)):
|
---|
61 | sigmab = sigmab * np.ones((md.mesh.numberofvertices, ))
|
---|
62 |
|
---|
63 | # check inputs
|
---|
64 | if 'strainrate' not in md.results.__dict__:
|
---|
65 | raise Exception('md.results.strainrate not present. Calculate using md = mechanicalproperties(md, vx, vy)')
|
---|
66 | if '2d' not in md.mesh.__doc__:
|
---|
67 | raise Exception('only 2d (planview) model supported currently')
|
---|
68 | if np.any(md.flowequation.element_equation != 2):
|
---|
69 | print('Warning: the model has some non SSA elements. These will be treated like SSA elements')
|
---|
70 |
|
---|
71 | a, b, theta, ex = thomasparams(md, eq=eq, smoothing=smoothing, coordsys=coordsys)
|
---|
72 |
|
---|
73 | # spreading stress
|
---|
74 | rhoi = md.materials.rho_ice
|
---|
75 | rhow = md.materials.rho_water
|
---|
76 | C = 0.5 * rhoi * md.constants.g * (1. - rhoi / rhow)
|
---|
77 | T = C * md.geometry.thickness
|
---|
78 |
|
---|
79 | # rheology
|
---|
80 | B = md.materials.rheology_B
|
---|
81 | n = averaging(md, md.materials.rheology_n, 0)
|
---|
82 |
|
---|
83 | D = 1. - (1. + a + a**2 + b**2)**((n - 1.) / (2. * n)) / np.abs(ex)**(1. / n) * (T - sigmab) / B / (2. + a) / np.sign(ex)
|
---|
84 |
|
---|
85 | # D > 1 where (2 + a). * sign(ex) < 0, compressive regions where high backstress needed
|
---|
86 | pos = np.nonzero(D > 1)
|
---|
87 | D[pos] = 0
|
---|
88 |
|
---|
89 | backstress = np.zeros((md.mesh.numberofvertices, ))
|
---|
90 |
|
---|
91 | # backstress to bring D down to one
|
---|
92 | backstress[pos] = T[pos] - (1. - D[pos]) * B[pos] * np.sign(ex[pos]) * (2. + a[pos]) * np.abs(ex[pos])**(1. / n[pos]) / (1. + a[pos] + a[pos]**2)**((n[pos] - 1.) / 2. / n[pos])
|
---|
93 |
|
---|
94 | pos = np.nonzero(D < 0)
|
---|
95 | #mask = ismember(1:md.mesh.numberofvertices, pos)
|
---|
96 | D[pos] = 0
|
---|
97 |
|
---|
98 | # backstress to bring negative damage to zero
|
---|
99 | backstress[pos] = T[pos] - (1. - D[pos]) * B[pos] * np.sign(ex[pos]) * (2. + a[pos]) * np.abs(ex[pos])**(1. / n[pos]) / (1. + a[pos] + a[pos]**2)**((n[pos] - 1.) / 2. / n[pos])
|
---|
100 |
|
---|
101 | pos = np.nonzero(backstress < 0)
|
---|
102 | backstress[pos] = 0
|
---|
103 |
|
---|
104 | # rigidity from Thomas relation for D = 0 and backstress = 0
|
---|
105 | B = np.sign(ex) / (2. + a) * (1. + a + a**2)**((n - 1.) / 2. / n) * T / (np.abs(ex)**(1. / n))
|
---|
106 | pos = np.nonzero(B < 0)
|
---|
107 | B[pos] = md.materials.rheology_B[pos]
|
---|
108 |
|
---|
109 | damage = D
|
---|
110 |
|
---|
111 | return damage, B, backstress
|
---|