Files
simpeg/codeScraps/sourcesKris.py
T

220 lines
7.2 KiB
Python

import numpy as np
class Sources(object):
"""
Class creates base sources
"""
def __init__(self):
raise Exception('Sources is a base class that requires a mesh. Inherit to your favorite Mesh class.')
def magneticDipoleSource(self,dipoleLoc,dimDip=3):
"""
Calculates the response from magnetic dipole source(s).
Inputs:
mesh - mesh object
dipoleLoc - an array of [n x 3] dipole locations (xyz)
dimDip - dipole dimension (e.g., x = 1,y = 2,z = 3)
Outputs:
b - the magnetic field on the face grid
"""
def getMagneticDipolePotential(loc,m,grid,dimAxis):
# Get the potential of the dipole
# Returns A(# faces x # transmitters)
nL = grid.shape[0]
nT = loc.shape[0]
fullLoc = np.ones((nL,3))
A = np.zeros((nL,nT))
for ii in range(nT):
fullM = np.ones((nL,3))*m[ii,:]
br = grid - fullLoc*loc[ii,:]
cp = np.cross(fullM,br)
r = np.sqrt(br[:,0]**2 + br[:,1]**2 + br[:,2]**2)
A[:,ii] = ((1e-6)*cp[:,dimAxis-1])/r**3
return A
dipoleLoc = np.atleast_2d(dipoleLoc)
dimDip = np.atleast_2d(dimDip)
m = np.zeros((dipoleLoc.shape[0],3))
if (dimDip.shape[0] == 1):
try:
m[:,dimDip-1] = 1
except IndexError:
print "magneticSource:Error: Dipole dimension should be 1 (x), 2 (y), or 3 (z)."
raise
elif (dimDip.shape[0] == dipoleLoc.shape[0]):
try:
for jj in range(dipoleLoc.shape[0]):
m[jj,dimDip[jj] - 1] = 1
except IndexError:
print "magneticSource:Error: Dipole dimension should be 1 (x), 2 (y), or 3 (z)."
raise
else:
print "magneticSource:Error: Dipole direction should also be vector of same length as dipole locations."
raise
# Get magnetic potential at each set of orthogonal faces:
Ax = getMagneticDipolePotential(dipoleLoc,m,self.gridEx,1)
Ay = getMagneticDipolePotential(dipoleLoc,m,self.gridEy,2)
Az = getMagneticDipolePotential(dipoleLoc,m,self.gridEz,3)
# Combine potential
A = np.concatenate((Ax, Ay, Az),axis=0)
# B = curl A
CURL = self.edgeCurl
self._src = CURL*A
return self._src
def simpleLoopSource(self,loc,Lx,Ly=None):
"""
Returns unit values for a simple loop source(s)
Inputs:
mesh - mesh object
loc - an array of [n x 3] loop centre location (xyz)
Lx - length of loop in x-direction (meters)
Ly - length of loop in y-direction (default is Lx)
Outputs:
e - Unit values of current on the edge grid
"""
# Check for default value of Ly:
Lx = np.atleast_2d(Lx)
if Ly is None:
Ly = Lx
else:
Ly = np.atleast_2d(Ly)
# Number of loops
loc = np.atleast_2d(loc)
nL = loc.shape[0]
normLoc = np.zeros((nL,3))
sub = np.zeros((nL,3),'i')
# Check number of values for loop sizes:
if (Lx.shape[0] != Ly.shape[0]):
print "simpleLoopSource:Error: Lx and Ly differ in lengths"
raise
if (Lx.shape[0] == 1):
Lx = np.ones((nL,1))*Lx
Ly = np.ones((nL,1))*Ly
# widths of cells:
hx = self.x0[0] + np.cumsum(self.hx)
hy = self.x0[1] + np.cumsum(self.hy)
hz = self.x0[2] + np.cumsum(self.hz)
# Normalize the location to the grid:
for ii in range(nL):
# x
diff = abs(loc[ii,0] - hx)
iInd = np.argmin(diff)
normLoc[ii,0] = iInd + diff[iInd]/hx[iInd]
# y
diff = abs(loc[ii,1] - hy)
jInd = np.argmin(diff)
normLoc[ii,1] = jInd + diff[jInd]/hy[jInd]
# z
diff = abs(loc[ii,2] - hz)
kInd = np.argmin(diff)
normLoc[ii,2] = kInd - diff[kInd]/hz[kInd]
sub[ii,0] = iInd
sub[ii,1] = jInd
sub[ii,2] = kInd
# Get node and edge grids
self._src = np.zeros((self.edge.shape[0],nL))
# Edge grid matrix
[Ex,Ey,Ez] = self.r(self.edge,'E','E','M')
# No topo for now, but this could be changed
EzSource = np.zeros((Ez.shape))
ezF = self.r(EzSource,'Ez','Ez','V')
# Loops for each loc
for ii in range(nL):
ExSource = np.zeros((Ex.shape))
EySource = np.zeros((Ey.shape))
# Find the node closest to loc (round)
nodeLoc = np.around(normLoc[ii,:])
# Put at bottom of cell
nodeLoc[2] = np.floor(normLoc[ii,2])
# Fill edges in counter-clockwise format
# First x:
i = sub[ii,0]
j = sub[ii,1]
k = sub[ii,2]
eDist1 = 0.0; eDist2 = 0.0
end1 = False; end2 = False
i1 = i-1; i2 = i+1
#### GET I1,I2,J1,J2 FIRST AND THEN FILL EX AND EY. NEED THEM FOR BOTH
while True:
try:
eDist1 = eDist1 + Ex[i1,j,k]
eDist2 = eDist2 + Ex[i2,j,k]
except IndexError:
print "simpleLoopSource:Error: Loop goes off of x-edge of mesh."
raise
if (np.around(abs(eDist1 - Lx[ii,0]/2)/Ex[i1,j,k]) < 1 and end1 == False):
end1 = True
else:
i1 = i1 - 1
if (np.around(abs(eDist2 - Lx[ii,0]/2)/Ex[i2,j,k]) < 1 and end2 == False):
end2 = True
else:
i2 = i2 + 1
if (end1 == True and end2 == True):
break
eDist1 = 0.0; eDist2 = 0.0
end1 = False; end2 = False
j1 = j-1; j2 = j+1
while True:
try:
eDist1 = eDist1 + Ey[i1,j1,k]
eDist2 = eDist2 + Ey[i2,j2,k]
except IndexError:
print "simpleLoopSource:Error: Loop goes off of y-edge of mesh."
raise
if (np.around(abs(eDist1 - Ly[ii,0]/2)/Ey[i1,j1,k]) < 1 and end1 == False):
end1 = True
else:
j1 = j1 - 1
if (np.around(abs(eDist2 - Ly[ii,0]/2)/Ey[i2,j2,k]) < 1 and end2 == False):
end2 = True
else:
j2 = j2 + 1
if (end1 == True and end2 == True):
break
# Fill values counter-clockwise:
for jj in range(i1,i2):
ExSource[jj,j1,k] = 1.0
ExSource[jj,j2,k] = -1.0
for jj in range(j1,j2):
EySource[i1,jj,k] = -1.0
EySource[i2,jj,k] = 1.0
exF = self.r(ExSource,'Ex','Ex','V')
eyF = self.r(ExSource,'Ey','Ey','V')
# Set final e:
self._src[:,ii] = np.concatenate((exF, eyF, ezF),axis=0)
#Finished: return e
return self._src