agd.ExportedCode.Notebooks_Algo.SeismicNorm

 1# Code automatically exported from notebook SeismicNorm.ipynb in directory Notebooks_Algo
 2# Do not modify
 3from agd.Metrics.Seismic import Hooke,Thomsen,TTI
 4from agd.Metrics import Riemann
 5from ... import Sphere
 6from ... import LinearParallel as lp
 7from ... import AutomaticDifferentiation as ad
 8from agd.Plotting import SetTitle3D
 9
10import numpy as np
11import copy
12from matplotlib import pyplot as plt
13
14def proj_orthorombic(c):
15    """Project onto the vector space of Hooke tensors corresponding to orthorombic materials in their frame of reference"""
16    to_orthorombic = (c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5]) # Seismologists start at 1 ...
17    return Hooke.from_orthorombic(*to_orthorombic).hooke
18
19def frame_score(c,proj,r):
20    """Score for wether c coincides with its projection in the frame defined by r"""
21    c = c.rotate(lp.transpose(r)) # Put in specified frame
22    c.hooke -= proj(c.hooke) # Substract projection 
23    return (c.to_Mandel()**2).sum(axis=(0,1)) # Return frobenius norm squared
24
25def proj_hooke2(c):
26    """Project onto the vector space of Hooke tensors with (2,1) block diagonal structure"""
27    z = np.zeros_like(c[0,0])
28    return ad.array([
29        [c[0,0],c[0,1],     z],
30        [c[1,0],c[1,1],     z],
31        [     z,     z,c[2,2]] ])
32
33def proj_tetragonal(c):
34    """Tetragonal Hooke tensors share the coefficients c11=c22, c13=c23, c44=c55"""
35    c11,c12,c13,c22,c23,c33,c44,c55,c66 = ( # Seismologists start at 1 ...
36        c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5])
37    α=(c11+c22)/2
38    γ=(c13+c23)/2
39    δ=(c44+c55)/2
40    return Hooke.from_orthorombic(α,c12,γ,α,γ,c33,δ,δ,c66).hooke
41
42def proj_hexagonal(c):
43    """Hexagonal Hooke tensors are tetragonal, with the additional property that c66=(c11-c12)/2"""
44    c11,c12,c13,c22,c23,c33,c44,c55,c66 = ( # Seismologists start at 1 ...
45        c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5])
46    α=(3*(c11+c22)+2*c12+4*c66)/8
47    β=(c11+c22+6*c12-4*c66)/8
48    γ=(c13+c23)/2
49    δ=(c44+c55)/2
50    return Hooke.from_orthorombic(α,β,γ,α,γ,c33,δ,δ,(α-β)/2).hooke
51
52def rotation_from_ball(x):
53    """
54    Produces a rotation matrix from an element of the unit ball
55    B_3 -> S_3 (lower half) -> SO_3, via quaternions
56    B_1 -> SO_2, via rotation of angle pi*x
57    """
58    if   len(x)==3: return Sphere.rotation3_from_ball3(x)[0] 
59    elif len(x)==1: return lp.rotation(np.pi*x[0])
60    else: raise ValueError("Unsupported dimension")
61
62def ball_samples(vdim,dens):
63    """
64    Produce samples of the unit ball of dimension vdim.
65    Approx c(vdim) * dens^vdim elements.
66    """
67    aB,h = np.linspace(-1,1,dens,retstep=True,endpoint=False)
68    B = np.array(np.meshgrid(*(aB,)*vdim,indexing='ij'))
69    B += h*np.random.rand(*B.shape) # Add random perturbations
70    B = B[:,np.linalg.norm(B,axis=0)<=1]
71    return B.reshape(vdim,-1)
72
73def newton_extremize(f,x,niter,max_cond=1e10):
74    """
75    Runs niter steps of Newton's method for extremizing f. 
76    (A.k.a, solve grad(f) = 0)
77    """
78    x_ad = ad.Dense2.identity(constant=x,shape_free=(len(x),))
79    for i in range(niter):
80        f_ad = f(x_ad)
81#        print(np.linalg.eigvalsh(f_ad.coef2[0]))
82        x_ad.value -= lp.solve_AV(f_ad.hessian(),f_ad.gradient())
83    return x_ad.value,f_ad.value
84
85def hooke_frame(c,proj,dens=8,niter=8):
86    """
87    Optimize the frame score, via a Newton method, with a large number of initial seeds.
88    Return the best rotation and associated score.
89    """
90    def f(x): return frame_score(c,proj,rotation_from_ball(x))
91    x = ball_samples({2:1,3:3}[c.vdim],dens) 
92    x,f_x = newton_extremize(f,x,niter)
93    argmin = np.nanargmin(f_x)
94    return lp.transpose(rotation_from_ball(x[:,argmin])),f_x[argmin]
def proj_orthorombic(c):
15def proj_orthorombic(c):
16    """Project onto the vector space of Hooke tensors corresponding to orthorombic materials in their frame of reference"""
17    to_orthorombic = (c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5]) # Seismologists start at 1 ...
18    return Hooke.from_orthorombic(*to_orthorombic).hooke

Project onto the vector space of Hooke tensors corresponding to orthorombic materials in their frame of reference

def frame_score(c, proj, r):
20def frame_score(c,proj,r):
21    """Score for wether c coincides with its projection in the frame defined by r"""
22    c = c.rotate(lp.transpose(r)) # Put in specified frame
23    c.hooke -= proj(c.hooke) # Substract projection 
24    return (c.to_Mandel()**2).sum(axis=(0,1)) # Return frobenius norm squared

Score for wether c coincides with its projection in the frame defined by r

def proj_hooke2(c):
26def proj_hooke2(c):
27    """Project onto the vector space of Hooke tensors with (2,1) block diagonal structure"""
28    z = np.zeros_like(c[0,0])
29    return ad.array([
30        [c[0,0],c[0,1],     z],
31        [c[1,0],c[1,1],     z],
32        [     z,     z,c[2,2]] ])

Project onto the vector space of Hooke tensors with (2,1) block diagonal structure

def proj_tetragonal(c):
34def proj_tetragonal(c):
35    """Tetragonal Hooke tensors share the coefficients c11=c22, c13=c23, c44=c55"""
36    c11,c12,c13,c22,c23,c33,c44,c55,c66 = ( # Seismologists start at 1 ...
37        c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5])
38    α=(c11+c22)/2
39    γ=(c13+c23)/2
40    δ=(c44+c55)/2
41    return Hooke.from_orthorombic(α,c12,γ,α,γ,c33,δ,δ,c66).hooke

Tetragonal Hooke tensors share the coefficients c11=c22, c13=c23, c44=c55

def proj_hexagonal(c):
43def proj_hexagonal(c):
44    """Hexagonal Hooke tensors are tetragonal, with the additional property that c66=(c11-c12)/2"""
45    c11,c12,c13,c22,c23,c33,c44,c55,c66 = ( # Seismologists start at 1 ...
46        c[0,0],c[0,1],c[0,2],c[1,1],c[1,2],c[2,2],c[3,3],c[4,4],c[5,5])
47    α=(3*(c11+c22)+2*c12+4*c66)/8
48    β=(c11+c22+6*c12-4*c66)/8
49    γ=(c13+c23)/2
50    δ=(c44+c55)/2
51    return Hooke.from_orthorombic(α,β,γ,α,γ,c33,δ,δ,(α-β)/2).hooke

Hexagonal Hooke tensors are tetragonal, with the additional property that c66=(c11-c12)/2

def rotation_from_ball(x):
53def rotation_from_ball(x):
54    """
55    Produces a rotation matrix from an element of the unit ball
56    B_3 -> S_3 (lower half) -> SO_3, via quaternions
57    B_1 -> SO_2, via rotation of angle pi*x
58    """
59    if   len(x)==3: return Sphere.rotation3_from_ball3(x)[0] 
60    elif len(x)==1: return lp.rotation(np.pi*x[0])
61    else: raise ValueError("Unsupported dimension")

Produces a rotation matrix from an element of the unit ball B_3 -> S_3 (lower half) -> SO_3, via quaternions B_1 -> SO_2, via rotation of angle pi*x

def ball_samples(vdim, dens):
63def ball_samples(vdim,dens):
64    """
65    Produce samples of the unit ball of dimension vdim.
66    Approx c(vdim) * dens^vdim elements.
67    """
68    aB,h = np.linspace(-1,1,dens,retstep=True,endpoint=False)
69    B = np.array(np.meshgrid(*(aB,)*vdim,indexing='ij'))
70    B += h*np.random.rand(*B.shape) # Add random perturbations
71    B = B[:,np.linalg.norm(B,axis=0)<=1]
72    return B.reshape(vdim,-1)

Produce samples of the unit ball of dimension vdim. Approx c(vdim) * dens^vdim elements.

def newton_extremize(f, x, niter, max_cond=10000000000.0):
74def newton_extremize(f,x,niter,max_cond=1e10):
75    """
76    Runs niter steps of Newton's method for extremizing f. 
77    (A.k.a, solve grad(f) = 0)
78    """
79    x_ad = ad.Dense2.identity(constant=x,shape_free=(len(x),))
80    for i in range(niter):
81        f_ad = f(x_ad)
82#        print(np.linalg.eigvalsh(f_ad.coef2[0]))
83        x_ad.value -= lp.solve_AV(f_ad.hessian(),f_ad.gradient())
84    return x_ad.value,f_ad.value

Runs niter steps of Newton's method for extremizing f. (A.k.a, solve grad(f) = 0)

def hooke_frame(c, proj, dens=8, niter=8):
86def hooke_frame(c,proj,dens=8,niter=8):
87    """
88    Optimize the frame score, via a Newton method, with a large number of initial seeds.
89    Return the best rotation and associated score.
90    """
91    def f(x): return frame_score(c,proj,rotation_from_ball(x))
92    x = ball_samples({2:1,3:3}[c.vdim],dens) 
93    x,f_x = newton_extremize(f,x,niter)
94    argmin = np.nanargmin(f_x)
95    return lp.transpose(rotation_from_ball(x[:,argmin])),f_x[argmin]

Optimize the frame score, via a Newton method, with a large number of initial seeds. Return the best rotation and associated score.