Skip to content

Commit a1a41a3

Browse files
committed
Deployed d6cb1fc with MkDocs version: 1.4.2
1 parent e218f59 commit a1a41a3

7 files changed

Lines changed: 163 additions & 14 deletions

File tree

gallery-Lagrangian-CPO-parcel/index.html

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,15 @@
9090
<ul class="current">
9191
<li class="toctree-l1 current"><a class="reference internal current" href="./">Lagrangian CPO parcel</a>
9292
<ul class="current">
93-
<li class="toctree-l2"><a class="reference internal" href="#constant-conditions">Constant conditions</a>
93+
<li class="toctree-l2"><a class="reference internal" href="#constant-thermomechanical-conditions">Constant thermomechanical conditions</a>
9494
</li>
9595
<li class="toctree-l2"><a class="reference internal" href="#ice-core-cpos">Ice core CPOs</a>
9696
<ul>
9797
<li class="toctree-l3"><a class="reference internal" href="#code-example">📝 Code example</a>
9898
</li>
9999
</ul>
100100
</li>
101-
<li class="toctree-l2"><a class="reference internal" href="#ssa-parcel">SSA parcel</a>
101+
<li class="toctree-l2"><a class="reference internal" href="#ssa-column">SSA column</a>
102102
</li>
103103
</ul>
104104
</li>
@@ -147,12 +147,13 @@
147147
<div class="section" itemprop="articleBody">
148148

149149
<h1 id="lagrangian-cpo-parcel">Lagrangian CPO parcel</h1>
150-
<p><img alt="" src="https://raw.githubusercontent.com/nicholasmr/specfab/main/images/modes-strain/lagrangian-parcel-trajectory-bg.png#center" style="width:400px" /> </p>
150+
<p><img alt="" src="https://raw.githubusercontent.com/nicholasmr/specfab/main/images/modes-strain/lagrangian-parcel-trajectory.png#center" style="width:380px" /> </p>
151151
<p>A Lagrangian parcel refers to a small, moving material volume that is followed through time as it flows within e.g. a glacier or ice sheet, unlike the <a href="../gallery-Eulerian-CPO-field/">Eulerian perspective</a> which focuses on fixed locations in space.
152152
A Lagrangian description is well-suited for studying CPO evolution along a flow line <span class="arithmatex">\({\bf x}(t)\)</span> if the thermomechanical background conditions are (approximately) steady; that is, the velocity, temperature, and stress fields are constant in time, <em>though not necessarily in space</em>.
153153
By treating each parcel as a discrete entity with its own microstructural state that updates with time, a Lagrangian parcel model is a particularly simply way to estimate CPO evolution and to calculate CPO-induced quantities along a flow line, such as mechanical or dielectric anisotropy. </p>
154154
<p>Below, some examples are given on how to model CPO evolution of a Lagrangian parcel relevant to glacier ice.</p>
155-
<h2 id="constant-conditions">Constant conditions</h2>
155+
<hr />
156+
<h2 id="constant-thermomechanical-conditions">Constant thermomechanical conditions</h2>
156157
<p><em>Specfab</em> includes a high-level integrator for calculating the CPO evolution of a Lagrangian parcel subject to a spatio-temporally constant strain-rate, stress and temperature.
157158
The following code illustrates how to use it, which relies on specifying the kinematic mode of deformation in terms of the <code>DK</code> object.</p>
158159
<pre><code class="language-python">import numpy as np
@@ -206,9 +207,11 @@ <h2 id="constant-conditions">Constant conditions</h2>
206207

207208
strain = np.array([sf.F_to_strain(Fi[nn]) for nn in np.arange(Nt)]) # strain tensor
208209
</code></pre>
210+
<hr />
209211
<h2 id="ice-core-cpos">Ice core CPOs</h2>
212+
<div style="float: left; width: 60%;">
210213
<p>A Lagrangian approach is well-suited for modelling the vertical CPO profile at ice sheet domes and divides.
211-
Assuming, for example, the classical Nye model of an ice divide of height <span class="arithmatex">\(H\)</span> (no basal melt, constant rate of thinning, a constant accumulation rate <span class="arithmatex">\(a\)</span>), the <a href="../deformation-kinematics/">velocity gradient</a> is constant and equal to </p>
214+
Assuming e.g. the classical Nye model of an ice divide of height <span class="arithmatex">\(H\)</span> (no basal melt, constant rate of thinning, a constant accumulation rate <span class="arithmatex">\(a\)</span>), the <a href="../deformation-kinematics/">velocity gradient</a> is constant and equal to </p>
212215
<div class="arithmatex">\[
213216
\nabla {\bf u} =
214217
-\frac{1}{\tau}
@@ -219,14 +222,22 @@ <h2 id="ice-core-cpos">Ice core CPOs</h2>
219222
\end{bmatrix}
220223
,
221224
\]</div>
222-
<p>where <span class="arithmatex">\(q=0\)</span> for a axis-symmetric dome and <span class="arithmatex">\(q=\pm 1\)</span> for a divide aligned with the <span class="arithmatex">\(x\)</span> or <span class="arithmatex">\(y\)</span> direction, and the <span class="arithmatex">\(e\)</span>-folding time <span class="arithmatex">\(\tau\)</span> is </p>
225+
<p>where <span class="arithmatex">\(q=0\)</span> for a axis-symmetric dome and <span class="arithmatex">\(q=\pm 1\)</span> for a divide aligned with the <span class="arithmatex">\(x\)</span> or <span class="arithmatex">\(y\)</span> direction.
226+
The <span class="arithmatex">\(e\)</span>-folding time <span class="arithmatex">\(\tau\)</span> is a function of the ice-equivalent accumulation rate and divide thickness: </p>
223227
<div class="arithmatex">\[
224228
\tau = \frac{a}{H}.
225229
\]</div>
230+
<p>Depending on whether temperatures are large enough to <a href="../fabdyn-DDRX/">activate DDRX</a> or not, the temperature profile must be prescribed, too. </p>
231+
</div>
232+
<div style="float: right;width: 2%;"></div>
233+
<div style="float: right;width: 38%;">
234+
<p><img alt="" src="https://raw.githubusercontent.com/nicholasmr/specfab/main/images/deformation/divide-parcel.png" style="width:250px" /> </p>
235+
</div>
236+
<div style="clear: both;"></div>
226237
<h3 id="code-example">📝 Code example</h3>
227-
<p>The example shows how to model the CPO profile of the GRIP ice core, Greenland:</p>
238+
<p>The below example shows how to model the CPO profile of the GRIP ice core, Greenland:</p>
228239
<pre><code class="language-python">&quot;&quot;&quot;
229-
Modeled CPO profile of GRIP ice core, Greenland
240+
Modeled CPO profile of the GRIP ice core, Greenland
230241
&quot;&quot;&quot;
231242

232243
import numpy as np
@@ -362,8 +373,12 @@ <h3 id="code-example">📝 Code example</h3>
362373
plt.savefig('GRIP.png', dpi=175, pad_inches=0.1, bbox_inches='tight')
363374
</code></pre>
364375
<p><img alt="" src="https://raw.githubusercontent.com/nicholasmr/specfab/main/docs/snippets/Lagrangian-CPO-parcel/GRIP.png#center" style="width:400px" /> </p>
365-
<h2 id="ssa-parcel">SSA parcel</h2>
366-
<p><strong>To be documented...</strong></p>
376+
<hr />
377+
<h2 id="ssa-column">SSA column</h2>
378+
<p>If the Shallow Shelf/Stream Approximation (SSA) is applicable, velocities can be assumed depth constant (no vertical shearing).
379+
In this case, a <a href="../gallery-Eulerian-CPO-field/">depth-average treatment of CPO evolution</a> transforms the Lagrangian parcel model into a Lagrangian <em>column</em> model.
380+
This generalizes the above parcel model, since the velocity gradient, stress and temperature fields can no longer be assumed constant but depend on the column position <span class="arithmatex">\({\bf x}(t)=[x(t),y(t)]\)</span>.</p>
381+
<p>🚧 <em>Documentation not finished.</em></p>
367382

368383
</div>
369384
</div><footer>

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,5 +195,5 @@ <h1 id="specfab-documentation">specfab documentation</h1>
195195

196196
<!--
197197
MkDocs version : 1.4.2
198-
Build Date UTC : 2025-06-24 13:58:03.131492+00:00
198+
Build Date UTC : 2025-06-24 16:09:18.784490+00:00
199199
-->

search/search_index.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

sitemap.xml.gz

0 Bytes
Binary file not shown.

snippets/Lagrangian-CPO-parcel/GRIP.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
Modeled CPO profile of GRIP ice core, Greenland
2+
Modeled CPO profile of the GRIP ice core, Greenland
33
"""
44

55
import numpy as np
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
"""
2+
Modeled CPO evolution for a SSA parcel over Pine Island Glacier, Antarctica
3+
"""
4+
5+
import numpy as np
6+
from scipy import interpolate
7+
import pandas as pd
8+
9+
import matplotlib.pyplot as plt
10+
11+
from matplotlib import rc
12+
#rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']})
13+
rc('font',**{'family':'serif','serif':['Palatino']})
14+
rc('text', usetex=True)
15+
16+
from specfabpy import specfab as sf
17+
from specfabpy import common as sfcom
18+
from specfabpy import plotting as sfplt
19+
20+
### Init
21+
22+
L = 12 # expansion series truncation
23+
lm, nlm_len = sf.init(L)
24+
25+
### Velocity gradient experienced by parcel
26+
27+
H = 3027 # ice thickness (Montagnat et al., 2014)
28+
a = 0.24 # meter ice equiv. per yr (Montagnat et al., 2014)
29+
30+
tau = H/a # e-folding time scale
31+
ugrad = -1/tau * np.diag([-0.5, -0.5, 1]) # uniaxial compression along z-axis
32+
D = (ugrad+np.transpose(ugrad))/2 # symmetric part (strain rate tensor)
33+
W = (ugrad-np.transpose(ugrad))/2 # anti-symmetric part (spin tensor)
34+
S = D # stress tensor (assume coaxiality with strain-rate tensor; magnitude does not matter for our purpose)
35+
36+
### Fabric dynamics
37+
38+
# Lattice rotation
39+
iota, zeta = 1, 0 # "deck of cards" behavior
40+
41+
# DDRX
42+
A = 1.1e7 # rate prefactor (tunable parameter)
43+
Q = 3.36e4 # activation energy (see Richards et al. (2021) and Lilien et al. (2023))
44+
R = 8.314 # gas constant
45+
Gamma0 = lambda D, T: A*np.sqrt(np.einsum('ij,ji',D,D)/2)*np.exp(-Q/(R*(T+273.15))) # DDRX rate factor
46+
47+
### Numerics
48+
49+
Nt = 500 # number of time steps
50+
dt = 100 # time step size (yr)
51+
ti = np.arange(0,Nt) * dt # time vector
52+
zi = np.exp(-ti/tau) # relative height above bed at each point in time
53+
54+
### Temperature profile
55+
56+
df = pd.read_csv('../../../data/icecores/GRIP/temperature.csv') # fetch from github
57+
f = interpolate.interp1d(df['zrel'].to_numpy(), df['T'].to_numpy(), kind='nearest', fill_value='extrapolate')
58+
Ti = f(zi) # temperature vector
59+
#Ti[:] = -60 # no DDRX if very cold
60+
61+
### Initial fabric state
62+
63+
nlm = np.zeros((Nt,nlm_len), dtype=np.complex64) # state vector
64+
lami = np.zeros((Nt,3)) # a2 eigenvalues
65+
66+
lxy = 0.25 # initial horizontal eigenvalues
67+
a2_0 = np.diag([lxy, lxy, 1-2*lxy]) # initial a2 surface state
68+
nlm[0,:sf.L2len] = sf.a2_to_nlm(a2_0) # initial state vector
69+
lami[0] = sfcom.eigenframe(nlm[0])[1] # eigenvalues of initial state
70+
71+
### Euler integration
72+
73+
for tt in np.arange(1,Nt):
74+
nlm_0 = nlm[tt-1,:] # previous solution
75+
T = Ti[tt] # temperature from borehole measurements
76+
M_LROT = sf.M_LROT(nlm_0, D, W, iota, zeta) # lattice rotation operator
77+
M_DDRX = Gamma0(D,T)*sf.M_DDRX(nlm_0, S) # DDRX operator
78+
M_REG = sf.M_REG(nlm_0, D) # regularization operator
79+
M = M_LROT + M_DDRX + M_REG
80+
nlm[tt] = nlm_0 + dt*np.matmul(M, nlm_0) # Euler step
81+
lami[tt] = sfcom.eigenframe(nlm[tt])[1]
82+
83+
### Plot modeled eigenvalues
84+
85+
fig = plt.figure(figsize=(3,4))
86+
ax = plt.subplot(111)
87+
88+
c1,c2,c3 = 'tab:green', 'tab:red', 'k'
89+
90+
ax.plot(lami[:,0], zi, '-', c=c1, label=r'$\lambda_1$')
91+
ax.plot(lami[:,1], zi, '-', c=c2, label=r'$\lambda_2$')
92+
ax.plot(lami[:,2], zi, '--', c=c3, label=r'$\lambda_3$')
93+
94+
ax.legend(loc=1, fancybox=False, frameon=False)
95+
ax.set_title(r'GRIP ice core')
96+
97+
ax.set_xlabel(r'$\lambda_i$')
98+
ax.set_xticks(np.arange(0,1+.01,0.2))
99+
ax.set_xlim([0,1])
100+
101+
ax.set_ylabel(r'$z/H$')
102+
ax.set_yticks(np.arange(0,1+.01,0.1))
103+
ax.set_ylim([0,1])
104+
105+
### Plot modeled CPOs
106+
107+
geo, prj = sfplt.getprojection(rotation=45, inclination=50)
108+
109+
def plotCPO(ax, nlm, p0, HW=0.2, cmap='Greys'):
110+
axtrans = ax.transData.transform(p0)
111+
trans = fig.transFigure.inverted().transform(axtrans)
112+
axin = plt.axes([trans[0]-HW/2, trans[1]-HW/2, HW,HW], projection=prj)
113+
axin.set_global()
114+
lvlset = [np.linspace(0.05, 0.45, 8), lambda x,p:'%.1f'%x]
115+
sfplt.plotODF(nlm, lm, axin, lvlset=lvlset, cmap=cmap, showcb=False, nchunk=None)
116+
sfplt.plotcoordaxes(axin, geo, negaxes=False, color=sfplt.c_dred, axislabels='xi')
117+
return axin
118+
119+
for _ in np.linspace(0.1, 0.9, 4):
120+
I = np.argmin(np.abs(zi-_))
121+
plotCPO(ax, nlm[I], (1.2,_))
122+
123+
### Plot observations
124+
125+
df = pd.read_csv('../../../data/icecores/GRIP/orientations.csv') # fetch from github
126+
zi = df['zrel'].to_numpy()
127+
128+
kw = dict(marker='o', facecolor='none', zorder=1)
129+
ax.scatter(df['lam1'].to_numpy(), zi, edgecolor=c1, **kw)
130+
ax.scatter(df['lam2'].to_numpy(), zi, edgecolor=c2, **kw)
131+
ax.scatter(df['lam3'].to_numpy(), zi, edgecolor=c3, **kw)
132+
133+
### Save plot
134+
135+
plt.savefig('GRIP.png', dpi=175, pad_inches=0.1, bbox_inches='tight')

waveprop-electromagnetic/index.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ <h2 id="glacier-ice">Glacier ice</h2>
180180
\]</div>
181181
<p>where <span class="arithmatex">\(\langle {\bf c}^2 \rangle\)</span> is the <a href="../cpo-structuretensors/">second-order structure tensor</a>.</p>
182182
<h3 id="code-example">📝 Code example</h3>
183-
<p>Experimental, bug reports are welcome.</p>
184183
<pre><code class="language-python">import numpy as np
185184
from specfabpy import specfab as sf
186185
lm, nlm_len = sf.init(4)

0 commit comments

Comments
 (0)