def E_field_from_SheetCurruent(XYZ, srcLoc, sig, f, E0=1., orientation='X', kappa=0., epsr=1., t=0.): """ Computing Analytic Electric fields from Plane wave in a Wholespace TODO: Add description of parameters """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr sig_hat = sig + 1j*omega(f)*epsilon k = np.sqrt( omega(f)**2. *mu*epsilon -1j*omega(f)*mu*sig ) # print t if orientation == "X": z = XYZ[:,2] Ex = E0*np.exp(1j*(k*(z-srcLoc)+omega(f)*t)) Ey = np.zeros_like(z) Ez = np.zeros_like(z) return Ex, Ey, Ez else: raise NotImplementedError()
def e_field_from_sheet_current(XYZ, srcLoc, sig, t, E0=1.0, orientation="X", kappa=0.0, epsr=1.0): """ Computing Analytic Electric fields from Plane wave in a Wholespace TODO: Add description of parameters """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) mu = mu_0 * (1 + kappa) if orientation == "X": z = XYZ[:, 2] bunja = -E0 * (mu * sig)**0.5 * z * np.exp(-(mu * sig * z**2) / (4 * t)) bunmo = 2 * np.pi**0.5 * t**1.5 Ex = bunja / bunmo Ey = np.zeros_like(z) Ez = np.zeros_like(z) return Ex, Ey, Ez else: raise NotImplementedError()
def h_field_from_sheet_current(XYZ, srcLoc, sig, t, E0=1.0, orientation="X", kappa=0.0, epsr=1.0): """ Plane wave propagating downward (negative z (depth)) """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) mu = mu_0 * (1 + kappa) if orientation == "X": z = XYZ[:, 2] Hx = np.zeros_like(z) Hy = (E0 * np.sqrt(sig / (np.pi * mu * t)) * np.exp(-(mu * sig * z**2) / (4 * t))) Hz = np.zeros_like(z) return Hx, Hy, Hz else: raise NotImplementedError()
def H_field_from_SheetCurruent(XYZ, srcLoc, sig, f, E0=1., orientation='X', kappa=0., epsr=1., t=0.): """ Plane wave propagating downward (negative z (depth)) """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr sig_hat = sig + 1j * omega(f) * epsilon k = np.sqrt(omega(f)**2. * mu * epsilon - 1j * omega(f) * mu * sig) Z = omega(f) * mu / k if orientation == "X": z = XYZ[:, 2] Hx = np.zeros_like(z) Hy = E0 / Z * np.exp(1j * (k * (z - srcLoc) + omega(f) * t)) Hz = np.zeros_like(z) return Hx, Hy, Hz else: raise NotImplementedError()
def j_field_from_sheet_current(XYZ, srcLoc, sig, f, E0=1.0, orientation="X", kappa=0.0, epsr=1.0, t=0.0): """ Plane wave propagating downward (negative z (depth)) """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr # sig_hat = sig + 1j * omega(f) * epsilon k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) if orientation == "X": z = XYZ[:, 2] Jx = sig * E0 * np.exp(1j * (k * (z - srcLoc) + omega(f) * t)) Jy = np.zeros_like(z) Jz = np.zeros_like(z) return Jx, Jy, Jz else: raise NotImplementedError()
def E_galvanic_from_ElectricDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, length=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0, ): """ Computing Galvanic portion of Electric fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr sig_hat = sig + 1j * omega(f) * epsilon XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4.0 * np.pi * sig_hat * r**3) * np.exp( -1j * k * r) mid = -k**2 * r**2 + 3 * 1j * k * r + 3 if orientation.upper() == "X": Ex_galvanic = front * ((dx**2 / r**2) * mid + (-1j * k * r - 1.0)) Ey_galvanic = front * (dx * dy / r**2) * mid Ez_galvanic = front * (dx * dz / r**2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic elif orientation.upper() == "Y": # x--> y, y--> z, z-->x Ey_galvanic = front * ((dy**2 / r**2) * mid + (-1j * k * r - 1.0)) Ez_galvanic = front * (dy * dz / r**2) * mid Ex_galvanic = front * (dy * dx / r**2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic elif orientation.upper() == "Z": # x --> z, y --> x, z --> y Ez_galvanic = front * ((dz**2 / r**2) * mid + (-1j * k * r - 1.0)) Ex_galvanic = front * (dz * dx / r**2) * mid Ey_galvanic = front * (dz * dy / r**2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic
def dHdt_from_MagneticDipoleWholeSpace(XYZ, srcLoc, sig, t, current=1., length=1., orientation='X', kappa=1., epsr=1.): """ Computing the analytic timd derivative of magnetic fields (dH/dt) from an magnetic dipole in a wholespace - You have the option of computing H for multiple times at a single reciever location or a single time at multiple locations :param numpy.array XYZ: reciever locations at which to evaluate H :param numpy.array srcLoc: [x,y,z] triplet defining the location of the electric dipole source :param float sig: value specifying the conductivity (S/m) of the wholespace :param numpy.array t: array of times at which to measure :param float current: size of the injected current (A), default is 1.0 A :param float length: length of the dipole (m), default is 1.0 m :param str orientation: orientation of dipole: 'X', 'Y', or 'Z' :param float kappa: magnetic susceptiblity value (unitless), default is 0. :param float epsr: relative permitivitty value (unitless), default is 1.0 :rtype: numpy.array :return: dHx/dt, dHy/dt, dHz/dt: arrays containing all 3 components of H evaluated at the specified locations and times. """ mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single time can be specified.") dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) theta = np.sqrt((mu*sig)/(4*t)) front = -4*(current*length)*theta**5 * np.exp(-(theta)**2 * (r)**2) front *= 1./(np.pi**1.5 * mu * sig) mid = (theta)**2 * (r)**2 extra = (1-(theta)**2 * (r)**2) if orientation.upper() == 'X': Hx = front*(dx**2 / r**2)*mid + front*extra Hy = front*(dx*dy / r**2)*mid Hz = front*(dx*dz / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Hy = front*(dy**2 / r**2)*mid + front*extra Hz = front*(dy*dz / r**2)*mid Hx = front*(dy*dx / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Hz = front*(dz**2 / r**2)*mid + front*extra Hx = front*(dz*dx / r**2)*mid Hy = front*(dz*dy / r**2)*mid return Hx, Hy, Hz
def AnalyticMagDipoleWholeSpace(XYZ, txLoc, sig, f, m=1., orientation='X'): """ Analytical solution for a dipole in a whole-space. Equation 2.57 of Ward and Hohmann TODOs: - set it up to instead take a mesh & survey - add E-fields - handle multiple frequencies - add divide by zero safety .. plot:: import simpegEM as EM import matplotlib.pyplot as plt freqs = np.logspace(-2,5,100) Bx, By, Bz = EM.Analytics.FDEM.AnalyticMagDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, m=1, orientation='Z') plt.loglog(freqs, np.abs(Bz.real)/mu_0, 'b') plt.loglog(freqs, np.abs(Bz.imag)/mu_0, 'r') plt.legend(('real','imag')) plt.show() """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-txLoc[0] dy = XYZ[:,1]-txLoc[1] dz = XYZ[:,2]-txLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu_0*sig ) kr = k*r front = m / (4.*pi * r**3.) * np.exp(-1j*kr) mid = -kr**2. + 3.*1j*kr + 3. if orientation.upper() == 'X': Hx = front*( (dx/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hy = front*( (dx*dy/r**2.) * mid ) Hz = front*( (dx*dz/r**2.) * mid ) elif orientation.upper() == 'Y': Hx = front*( (dy*dx/r**2.) * mid ) Hy = front*( (dy/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hz = front*( (dy*dz/r**2.) * mid ) elif orientation.upper() == 'Z': Hx = front*( (dx*dz/r**2.) * mid ) Hy = front*( (dy*dz/r**2.) * mid ) Hz = front*( (dz/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Bx = mu_0*Hx By = mu_0*Hy Bz = mu_0*Hz return Bx, By, Bz
def E_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, t, current=1., length=1., orientation='X', kappa=0., epsr=1.): """ Computing the analytic electric fields (E) from an electrical dipole in a wholespace - You have the option of computing E for multiple times at a single reciever location or a single time at multiple locations :param numpy.array XYZ: reciever locations at which to evaluate E :param numpy.array srcLoc: [x,y,z] triplet defining the location of the electric dipole source :param float sig: value specifying the conductivity (S/m) of the wholespace :param numpy.array t: array of times at which to measure :param float current: size of the injected current (A), default is 1.0 A :param float length: length of the dipole (m), default is 1.0 m :param str orientation: orientation of dipole: 'X', 'Y', or 'Z' :param float kappa: magnetic susceptiblity value (unitless), default is 0. :param float epsr: relative permitivitty value (unitless), default is 1.0 :rtype: numpy.array :return: Ex, Ey, Ez: arrays containing all 3 components of E evaluated at the specified locations and times. """ mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single time can be specified.") dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) theta = np.sqrt((mu*sig)/(4*t)) front = current * length / (4.* pi * sig * r**3) mid = 3 * erf(theta*r) - (4/np.sqrt(pi) * (theta)**3 * r**3 + 6/np.sqrt(pi) * theta * r) * np.exp(-(theta)**2 * (r)**2) extra = (erf(theta*r) - (4/np.sqrt(pi) * (theta)**3 * r**3 + 2/np.sqrt(pi) * theta * r) * np.exp(-(theta)**2 * (r)**2)) if orientation.upper() == 'X': Ex = front*(dx**2 / r**2)*mid - front*extra Ey = front*(dx*dy / r**2)*mid Ez = front*(dx*dz / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey = front*(dy**2 / r**2)*mid - front*extra Ez = front*(dy*dz / r**2)*mid Ex = front*(dy*dx / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez = front*(dz**2 / r**2)*mid - front*extra Ex = front*(dz*dx / r**2)*mid Ey = front*(dz*dy / r**2)*mid return Ex, Ey, Ez
def H_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0, ): """ Computing magnetic fields from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = m / (4.0 * np.pi * (r)**3) * np.exp(-1j * k * r) mid = -k**2 * r**2 + 3 * 1j * k * r + 3 if orientation.upper() == "X": Hx = front * ((dx**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.0)) Hy = front * (dx * dy / r**2) * mid Hz = front * (dx * dz / r**2) * mid return Hx, Hy, Hz elif orientation.upper() == "Y": # x--> y, y--> z, z-->x Hy = front * ((dy**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.0)) Hz = front * (dy * dz / r**2) * mid Hx = front * (dy * dx / r**2) * mid return Hx, Hy, Hz elif orientation.upper() == "Z": # x --> z, y --> x, z --> y Hz = front * ((dz**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.0)) Hx = front * (dz * dx / r**2) * mid Hy = front * (dz * dy / r**2) * mid return Hx, Hy, Hz
def E_inductive_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', kappa=1., epsr=1., t=0.): """ Computing Inductive portion of Electric fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr sig_hat = sig + 1j * omega(f) * epsilon XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2. + dy**2. + dz**2.) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f)**2. * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4. * np.pi * sig_hat * r**3) * np.exp( -1j * k * r) if orientation.upper() == 'X': Ex_inductive = front * (k**2 * r**2) Ey_inductive = np.zeros_like(Ex_inductive) Ez_inductive = np.zeros_like(Ex_inductive) return Ex_inductive, Ey_inductive, Ez_inductive elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey_inductive = front * (k**2 * r**2) Ez_inductive = np.zeros_like(Ey_inductive) Ex_inductive = np.zeros_like(Ey_inductive) return Ex_inductive, Ey_inductive, Ez_inductive elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez_inductive = front * (k**2 * r**2) Ex_inductive = np.zeros_like(Ez_inductive) Ey_inductive = np.zeros_like(Ez_inductive) return Ex_inductive, Ey_inductive, Ez_inductive
def E_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=0.0, epsr=1.0, t=0.0, ): """ Computing analytic electric fields from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = (((1j * omega(f) * mu * m) / (4.0 * np.pi * r**2)) * (1j * k * r + 1) * np.exp(-1j * k * r)) if orientation.upper() == "X": Ey = front * (dz / r) Ez = front * (-dy / r) Ex = np.zeros_like(Ey) return Ex, Ey, Ez elif orientation.upper() == "Y": Ex = front * (-dz / r) Ez = front * (dx / r) Ey = np.zeros_like(Ex) return Ex, Ey, Ez elif orientation.upper() == "Z": Ex = front * (dy / r) Ey = front * (-dx / r) Ez = np.zeros_like(Ex) return Ex, Ey, Ez
def F_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0, ): """ Computing magnetic vector potentials from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = (1j * omega(f) * mu * m) / (4.0 * np.pi * r) if orientation.upper() == "X": Fx = front * np.exp(-1j * k * r) Fy = np.zeros_like(Fx) Fz = np.zeros_like(Fx) return Fx, Fy, Fz elif orientation.upper() == "Y": Fy = front * np.exp(-1j * k * r) Fx = np.zeros_like(Fy) Fz = np.zeros_like(Fy) return Fx, Fy, Fz elif orientation.upper() == "Z": Fz = front * np.exp(-1j * k * r) Fx = np.zeros_like(Fy) Fy = np.zeros_like(Fy) return Fx, Fy, Fz
def E_from_MagneticDipoleWholeSpace(XYZ, srcLoc, sig, t, current=1., length=1., orientation='X', kappa=0., epsr=1.): """ Computing the analytic electric fields (E) from an magnetic dipole in a wholespace - You have the option of computing E for multiple times at a single reciever location or a single time at multiple locations :param numpy.array XYZ: reciever locations at which to evaluate E :param numpy.array srcLoc: [x,y,z] triplet defining the location of the electric dipole source :param float sig: value specifying the conductivity (S/m) of the wholespace :param numpy.array t: array of times at which to measure :param float current: size of the injected current (A), default is 1.0 A :param float length: length of the dipole (m), default is 1.0 m :param str orientation: orientation of dipole: 'X', 'Y', or 'Z' :param float kappa: magnetic susceptiblity value (unitless), default is 0. :param float epsr: relative permitivitty value (unitless), default is 1.0 :rtype: numpy.array :return: Ex, Ey, Ez: arrays containing all 3 components of E evaluated at the specified locations and times. """ mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single time can be specified.") dx = XYZ[:, 0]-srcLoc[0] dy = XYZ[:, 1]-srcLoc[1] dz = XYZ[:, 2]-srcLoc[2] r = np.sqrt(dx**2. + dy**2. + dz**2.) theta = np.sqrt((mu*sig)/(4*t)) front = 2.*(current * length) * theta**5 * np.exp(-(theta)**2 * (r)**2) mid = 1./(np.pi**1.5 * sig) if orientation.upper() == 'X': Ey = front * mid * -dz Ez = front * mid * dy Ex = np.zeros_like(Ey) return Hx, Hy, Hz elif orientation.upper() == 'Y': Ex = front * mid * dz Ez = front * mid * -dx Ey = np.zeros_like(Ex) return Hx, Hy, Hz elif orientation.upper() == 'Z': Ex = front * mid * -dy Ey = front * mid * dx Ez = np.zeros_like(Ex) return Ex, Ey, Ez
def H_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', kappa=1., epsr=1., t=0.): """ Computing Magnetic fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2. + dy**2. + dz**2.) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f)**2. * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4. * np.pi * (r)**2) * (1j * k * r + 1) * np.exp( -1j * k * r) if orientation.upper() == 'X': Hy = front * (-dz / r) Hz = front * (dy / r) Hx = np.zeros_like(Hy) return Hx, Hy, Hz elif orientation.upper() == 'Y': Hx = front * (dz / r) Hz = front * (-dx / r) Hy = np.zeros_like(Hx) return Hx, Hy, Hz elif orientation.upper() == 'Z': Hx = front * (-dy / r) Hy = front * (dx / r) Hz = np.zeros_like(Hx) return Hx, Hy, Hz
def A_from_ElectricDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, length=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0, ): """ Computing Electric vector potentials from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single frequency can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) k = np.sqrt(omega(f)**2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4.0 * np.pi * r) if orientation.upper() == "X": Ax = front * np.exp(-1j * k * r) Ay = np.zeros_like(Ax) Az = np.zeros_like(Ax) return Ax, Ay, Az elif orientation.upper() == "Y": Ay = front * np.exp(-1j * k * r) Ax = np.zeros_like(Ay) Az = np.zeros_like(Ay) return Ax, Ay, Az elif orientation.upper() == "Z": Az = front * np.exp(-1j * k * r) Ax = np.zeros_like(Ay) Ay = np.zeros_like(Ay) return Ax, Ay, Az
def getInterpolationMat(self, loc, locType, zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers """ if self._meshType == 'CYL' and self.isSymmetric and locType in ['Ex','Ez','Fy']: raise Exception('Symmetric CylMesh does not support %s interpolation, as this variable does not exist.' % locType) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array([v.mean() for v in self.getTensor('CC')]) if locType in ['Fx','Fy','Fz','Ex','Ey','Ez']: ind = {'x':0, 'y':1, 'z':2}[locType[1]] assert self.dim >= ind, 'mesh is not high enough dimension.' nF_nE = self.vnF if 'F' in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ['CC', 'N']: Q = Utils.interpmat(loc, *self.getTensor(locType)) else: raise NotImplementedError('getInterpolationMat: locType=='+locType+' and mesh.dim=='+str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()
def H_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0 ): """ Computing magnetic fields from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx ** 2.0 + dy ** 2.0 + dz ** 2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f) ** 2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = m / (4.0 * np.pi * (r) ** 3) * np.exp(-1j * k * r) mid = -k ** 2 * r ** 2 + 3 * 1j * k * r + 3 if orientation.upper() == "X": Hx = front * ((dx ** 2 / r ** 2) * mid + (k ** 2 * r ** 2 - 1j * k * r - 1.0)) Hy = front * (dx * dy / r ** 2) * mid Hz = front * (dx * dz / r ** 2) * mid return Hx, Hy, Hz elif orientation.upper() == "Y": # x--> y, y--> z, z-->x Hy = front * ((dy ** 2 / r ** 2) * mid + (k ** 2 * r ** 2 - 1j * k * r - 1.0)) Hz = front * (dy * dz / r ** 2) * mid Hx = front * (dy * dx / r ** 2) * mid return Hx, Hy, Hz elif orientation.upper() == "Z": # x --> z, y --> x, z --> y Hz = front * ((dz ** 2 / r ** 2) * mid + (k ** 2 * r ** 2 - 1j * k * r - 1.0)) Hx = front * (dz * dx / r ** 2) * mid Hy = front * (dz * dy / r ** 2) * mid return Hx, Hy, Hz
def E_galvanic_from_ElectricDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, length=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0 ): """ Computing Galvanic portion of Electric fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr sig_hat = sig + 1j * omega(f) * epsilon XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx ** 2.0 + dy ** 2.0 + dz ** 2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f) ** 2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4.0 * np.pi * sig_hat * r ** 3) * np.exp(-1j * k * r) mid = -k ** 2 * r ** 2 + 3 * 1j * k * r + 3 if orientation.upper() == "X": Ex_galvanic = front * ((dx ** 2 / r ** 2) * mid + (-1j * k * r - 1.0)) Ey_galvanic = front * (dx * dy / r ** 2) * mid Ez_galvanic = front * (dx * dz / r ** 2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic elif orientation.upper() == "Y": # x--> y, y--> z, z-->x Ey_galvanic = front * ((dy ** 2 / r ** 2) * mid + (-1j * k * r - 1.0)) Ez_galvanic = front * (dy * dz / r ** 2) * mid Ex_galvanic = front * (dy * dx / r ** 2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic elif orientation.upper() == "Z": # x --> z, y --> x, z --> y Ez_galvanic = front * ((dz ** 2 / r ** 2) * mid + (-1j * k * r - 1.0)) Ex_galvanic = front * (dz * dx / r ** 2) * mid Ey_galvanic = front * (dz * dy / r ** 2) * mid return Ex_galvanic, Ey_galvanic, Ez_galvanic
def E_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=0.0, epsr=1.0, t=0.0 ): """ Computing analytic electric fields from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx ** 2.0 + dy ** 2.0 + dz ** 2.0) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt(omega(f) ** 2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = ((1j * omega(f) * mu * m) / (4.0 * np.pi * r ** 2)) * (1j * k * r + 1) * np.exp(-1j * k * r) if orientation.upper() == "X": Ey = front * (dz / r) Ez = front * (-dy / r) Ex = np.zeros_like(Ey) return Ex, Ey, Ez elif orientation.upper() == "Y": Ex = front * (-dz / r) Ez = front * (dx / r) Ey = np.zeros_like(Ex) return Ex, Ey, Ez elif orientation.upper() == "Z": Ex = front * (dy / r) Ey = front * (-dx / r) Ez = np.zeros_like(Ex) return Ex, Ey, Ez
def E_inductive_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', kappa=1., epsr=1.): """ Computing Inductive portion of Electric fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr sig_hat = sig + 1j*omega(f)*epsilon XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt( omega(f)**2. *mu*epsilon -1j*omega(f)*mu*sig ) front = current * length / (4.*np.pi*sig_hat* r**3) * np.exp(-1j*k*r) if orientation.upper() == 'X': Ex_inductive = front*(k**2 * r**2) Ey_inductive = np.zeros_like(Ex_inductive) Ez_inductive = np.zeros_like(Ex_inductive) return Ex_inductive, Ey_inductive, Ez_inductive elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey_inductive = front*(k**2 * r**2) Ez_inductive = np.zeros_like(Ey_inductive) Ex_inductive = np.zeros_like(Ey_inductive) return Ex_inductive, Ey_inductive, Ez_inductive elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez_inductive = front*(k**2 * r**2) Ex_inductive = np.zeros_like(Ez_inductive) Ey_inductive = np.zeros_like(Ez_inductive) return Ex_inductive, Ey_inductive, Ez_inductive
def ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', mu=mu_0): XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2. + dy**2. + dz**2.) k = np.sqrt(-1j * 2. * np.pi * f * mu * sig) kr = k * r front = current * length / (4. * np.pi * sig * r**3) * np.exp(-1j * k * r) mid = -k**2 * r**2 + 3 * 1j * k * r + 3 # Ex = front*((dx**2 / r**2)*mid + (k**2 * r**2 -1j*k*r)) # Ey = front*(dx*dy / r**2)*mid # Ez = front*(dx*dz / r**2)*mid if orientation.upper() == 'X': Ex = front * ((dx**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.)) Ey = front * (dx * dy / r**2) * mid Ez = front * (dx * dz / r**2) * mid return Ex, Ey, Ez elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey = front * ((dy**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.)) Ez = front * (dy * dz / r**2) * mid Ex = front * (dy * dx / r**2) * mid return Ex, Ey, Ez elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez = front * ((dz**2 / r**2) * mid + (k**2 * r**2 - 1j * k * r - 1.)) Ex = front * (dz * dx / r**2) * mid Ey = front * (dz * dy / r**2) * mid return Ex, Ey, Ez
def F_from_MagneticDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, loopArea=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0 ): """ Computing magnetic vector potentials from Magnetic Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr m = current * loopArea XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx ** 2.0 + dy ** 2.0 + dz ** 2.0) k = np.sqrt(omega(f) ** 2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = (1j * omega(f) * mu * m) / (4.0 * np.pi * r) if orientation.upper() == "X": Fx = front * np.exp(-1j * k * r) Fy = np.zeros_like(Fx) Fz = np.zeros_like(Fx) return Fx, Fy, Fz elif orientation.upper() == "Y": Fy = front * np.exp(-1j * k * r) Fx = np.zeros_like(Fy) Fz = np.zeros_like(Fy) return Fx, Fy, Fz elif orientation.upper() == "Z": Fz = front * np.exp(-1j * k * r) Fx = np.zeros_like(Fy) Fy = np.zeros_like(Fy) return Fx, Fy, Fz
def A_from_ElectricDipoleWholeSpace( XYZ, srcLoc, sig, f, current=1.0, length=1.0, orientation="X", kappa=1.0, epsr=1.0, t=0.0 ): """ Computing Electric vector potentials from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0 * (1 + kappa) epsilon = epsilon_0 * epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx ** 2.0 + dy ** 2.0 + dz ** 2.0) k = np.sqrt(omega(f) ** 2.0 * mu * epsilon - 1j * omega(f) * mu * sig) front = current * length / (4.0 * np.pi * r) if orientation.upper() == "X": Ax = front * np.exp(-1j * k * r) Ay = np.zeros_like(Ax) Az = np.zeros_like(Ax) return Ax, Ay, Az elif orientation.upper() == "Y": Ay = front * np.exp(-1j * k * r) Ax = np.zeros_like(Ay) Az = np.zeros_like(Ay) return Ax, Ay, Az elif orientation.upper() == "Z": Az = front * np.exp(-1j * k * r) Ax = np.zeros_like(Ay) Ay = np.zeros_like(Ay) return Ax, Ay, Az
def H_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', kappa=1., epsr=1.): """ Computing Magnetic fields from Electrical Dipole in a Wholespace TODO: Add description of parameters """ mu = mu_0*(1+kappa) epsilon = epsilon_0*epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & f.shape[0] > 1: raise Exception("I/O type error: For multiple field locations only a single frequency can be specified.") dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) # k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) k = np.sqrt( omega(f)**2. *mu*epsilon -1j*omega(f)*mu*sig ) front = current * length / (4.*np.pi* r**2) * (-1j*k*r + 1) * np.exp(-1j*k*r) if orientation.upper() == 'X': Hy = front*(-dz / r) Hz = front*(dy / r) Hx = np.zeros_like(Hy) return Hx, Hy, Hz elif orientation.upper() == 'Y': Hx = front*(dz / r) Hz = front*(-dx / r) Hy = np.zeros_like(Hx) return Hx, Hy, Hz elif orientation.upper() == 'Z': Hx = front*(-dy / r) Hy = front*(dx / r) Hz = np.zeros_like(Hx) return Hx, Hy, Hz
def isInside(self, pts, locType='N'): """ Determines if a set of points are inside a mesh. :param numpy.ndarray pts: Location of points to test :rtype numpy.ndarray: :return: inside, numpy array of booleans """ pts = Utils.asArray_N_x_Dim(pts, self.dim) tensors = self.getTensor(locType) if locType == 'N' and self._meshType == 'CYL': #NOTE: for a CYL mesh we add a node to check if we are inside in the radial direction! tensors[0] = np.r_[0.,tensors[0]] tensors[1] = np.r_[tensors[1], 2.0*np.pi] inside = np.ones(pts.shape[0],dtype=bool) for i, tensor in enumerate(tensors): TOL = np.diff(tensor).min() * 1.0e-10 inside = inside & (pts[:,i] >= tensor.min()-TOL) & (pts[:,i] <= tensor.max()+TOL) return inside
def isInside(self, pts, locType='N'): """ Determines if a set of points are inside a mesh. :param numpy.ndarray pts: Location of points to test :rtype numpy.ndarray :return inside, numpy array of booleans """ pts = Utils.asArray_N_x_Dim(pts, self.dim) tensors = self.getTensor(locType) if locType == 'N' and self._meshType == 'CYL': #NOTE: for a CYL mesh we add a node to check if we are inside in the radial direction! tensors[0] = np.r_[0.,tensors[0]] tensors[1] = np.r_[tensors[1], 2.0*np.pi] inside = np.ones(pts.shape[0],dtype=bool) for i, tensor in enumerate(tensors): TOL = np.diff(tensor).min() * 1.0e-10 inside = inside & (pts[:,i] >= tensor.min()-TOL) & (pts[:,i] <= tensor.max()+TOL) return inside
def ElectricDipoleWholeSpace(XYZ, srcLoc, sig, f, current=1., length=1., orientation='X', mu=mu_0): XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) kr = k*r front = current * length / (4. * np.pi * sig * r**3) * np.exp(-1j*k*r) mid = -k**2 * r**2 + 3*1j*k*r + 3 # Ex = front*((dx**2 / r**2)*mid + (k**2 * r**2 -1j*k*r)) # Ey = front*(dx*dy / r**2)*mid # Ez = front*(dx*dz / r**2)*mid if orientation.upper() == 'X': Ex = front*((dx**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ey = front*(dx*dy / r**2)*mid Ez = front*(dx*dz / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Y': # x--> y, y--> z, z-->x Ey = front*((dy**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ez = front*(dy*dz / r**2)*mid Ex = front*(dy*dx / r**2)*mid return Ex, Ey, Ez elif orientation.upper() == 'Z': # x --> z, y --> x, z --> y Ez = front*((dz**2 / r**2)*mid + (k**2 * r**2 -1j*k*r-1.)) Ex = front*(dz*dx / r**2)*mid Ey = front*(dz*dy / r**2)*mid return Ex, Ey, Ez
def MagneticDipoleWholeSpace(XYZ, srcLoc, sig, f, moment=1., orientation='X', mu = mu_0): """ Analytical solution for a dipole in a whole-space. Equation 2.57 of Ward and Hohmann TODOs: - set it up to instead take a mesh & survey - add E-fields - handle multiple frequencies - add divide by zero safety .. plot:: from SimPEG import EM import matplotlib.pyplot as plt from scipy.constants import mu_0 freqs = np.logspace(-2,5,100) Bx, By, Bz = EM.Analytics.FDEM.MagneticDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, moment=1, orientation='Z') plt.loglog(freqs, np.abs(Bz.real)/mu_0, 'b') plt.loglog(freqs, np.abs(Bz.imag)/mu_0, 'r') plt.legend(('real','imag')) plt.show() """ XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) kr = k*r front = moment / (4.*pi * r**3.) * np.exp(-1j*kr) mid = -kr**2. + 3.*1j*kr + 3. if orientation.upper() == 'X': Hx = front*( (dx/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hy = front*( (dx*dy/r**2.) * mid ) Hz = front*( (dx*dz/r**2.) * mid ) elif orientation.upper() == 'Y': Hx = front*( (dy*dx/r**2.) * mid ) Hy = front*( (dy/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hz = front*( (dy*dz/r**2.) * mid ) elif orientation.upper() == 'Z': Hx = front*( (dx*dz/r**2.) * mid ) Hy = front*( (dy*dz/r**2.) * mid ) Hz = front*( (dz/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Bx = mu*Hx By = mu*Hy Bz = mu*Hz if Bx.ndim is 1: Bx = Utils.mkvc(Bx,2) if By.ndim is 1: By = Utils.mkvc(By,2) if Bz.ndim is 1: Bz = Utils.mkvc(Bz,2) return Bx, By, Bz
def getInterpolationMat(self, loc, locType="CC", zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers 'CCVx' -> x-component of vector field defined on cell centers 'CCVy' -> y-component of vector field defined on cell centers 'CCVz' -> z-component of vector field defined on cell centers """ if self._meshType == "CYL" and self.isSymmetric and locType in ["Ex", "Ez", "Fy"]: raise Exception( "Symmetric CylMesh does not support {0!s} interpolation, as this variable does not exist.".format( locType ) ) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array([v.mean() for v in self.getTensor("CC")]) if locType in ["Fx", "Fy", "Fz", "Ex", "Ey", "Ez"]: ind = {"x": 0, "y": 1, "z": 2}[locType[1]] assert self.dim >= ind, "mesh is not high enough dimension." nF_nE = self.vnF if "F" in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ["CC", "N"]: Q = Utils.interpmat(loc, *self.getTensor(locType)) elif locType in ["CCVx", "CCVy", "CCVz"]: Q = Utils.interpmat(loc, *self.getTensor("CC")) Z = Utils.spzeros(loc.shape[0], self.nC) if locType == "CCVx": Q = sp.hstack([Q, Z, Z]) elif locType == "CCVy": Q = sp.hstack([Z, Q, Z]) elif locType == "CCVz": Q = sp.hstack([Z, Z, Q]) else: raise NotImplementedError("getInterpolationMat: locType==" + locType + " and mesh.dim==" + str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()
def MagneticDipoleWholeSpace(XYZ, srcLoc, sig, f, moment=1., orientation='X', mu = mu_0): """ Analytical solution for a dipole in a whole-space. Equation 2.57 of Ward and Hohmann TODOs: - set it up to instead take a mesh & survey - add E-fields - handle multiple frequencies - add divide by zero safety .. plot:: from SimPEG import EM import matplotlib.pyplot as plt from scipy.constants import mu_0 freqs = np.logspace(-2,5,100) Bx, By, Bz = EM.Analytics.FDEM.MagneticDipoleWholeSpace([0,100,0], [0,0,0], 1e-2, freqs, moment=1, orientation='Z') plt.loglog(freqs, np.abs(Bz.real)/mu_0, 'b') plt.loglog(freqs, np.abs(Bz.imag)/mu_0, 'r') plt.legend(('real','imag')) plt.show() """ if not isinstance(orientation, str): if np.allclose(orientation, np.r_[1., 0., 0.]): orientation = 'X' elif np.allclose(orientation, np.r_[0., 1., 0.]): orientation = 'Y' elif np.allclose(orientation, np.r_[0., 0., 1.]): orientation = 'Z' else: raise NotImplementedError('arbitrary orientations not implemented') XYZ = Utils.asArray_N_x_Dim(XYZ, 3) dx = XYZ[:,0]-srcLoc[0] dy = XYZ[:,1]-srcLoc[1] dz = XYZ[:,2]-srcLoc[2] r = np.sqrt( dx**2. + dy**2. + dz**2.) k = np.sqrt( -1j*2.*np.pi*f*mu*sig ) kr = k*r front = moment / (4.*pi * r**3.) * np.exp(-1j*kr) mid = -kr**2. + 3.*1j*kr + 3. if orientation.upper() == 'X': Hx = front*( (dx/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hy = front*( (dx*dy/r**2.) * mid ) Hz = front*( (dx*dz/r**2.) * mid ) elif orientation.upper() == 'Y': Hx = front*( (dy*dx/r**2.) * mid ) Hy = front*( (dy/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Hz = front*( (dy*dz/r**2.) * mid ) elif orientation.upper() == 'Z': Hx = front*( (dx*dz/r**2.) * mid ) Hy = front*( (dy*dz/r**2.) * mid ) Hz = front*( (dz/r)**2. * mid + (kr**2. - 1j*kr - 1.) ) Bx = mu*Hx By = mu*Hy Bz = mu*Hz if Bx.ndim is 1: Bx = Utils.mkvc(Bx,2) if By.ndim is 1: By = Utils.mkvc(By,2) if Bz.ndim is 1: Bz = Utils.mkvc(Bz,2) return Bx, By, Bz
def H_from_ElectricDipoleWholeSpace(XYZ, srcLoc, sig, t, current=1.0, length=1.0, orientation="X", kappa=1.0, epsr=1.0): """ Computing the analytic magnetic fields (H) from an electrical dipole in a wholespace - You have the option of computing H for multiple times at a single reciever location or a single time at multiple locations :param numpy.array XYZ: reciever locations at which to evaluate H :param numpy.array srcLoc: [x,y,z] triplet defining the location of the electric dipole source :param float sig: value specifying the conductivity (S/m) of the wholespace :param numpy.array t: array of times at which to measure :param float current: size of the injected current (A), default is 1.0 A :param float length: length of the dipole (m), default is 1.0 m :param str orientation: orientation of dipole: 'X', 'Y', or 'Z' :param float kappa: magnetic susceptiblity value (unitless), default is 0. :param float epsr: relative permitivitty value (unitless), default is 1.0 :rtype: numpy.array :return: Hx, Hy, Hz: arrays containing all 3 components of H evaluated at the specified locations and times. """ mu = mu_0 * (1 + kappa) # epsilon = epsilon_0 * epsr XYZ = Utils.asArray_N_x_Dim(XYZ, 3) # Check if XYZ.shape[0] > 1 & t.shape[0] > 1: raise Exception( "I/O type error: For multiple field locations only a single time can be specified." ) dx = XYZ[:, 0] - srcLoc[0] dy = XYZ[:, 1] - srcLoc[1] dz = XYZ[:, 2] - srcLoc[2] r = np.sqrt(dx**2.0 + dy**2.0 + dz**2.0) theta = np.sqrt((mu * sig) / (4 * t)) front = (current * length) / (4.0 * pi * (r)**3) mid = erf(theta * r) - (2 / np.sqrt(pi)) * theta * r * np.exp(-( (theta)**2) * (r)**2) if orientation.upper() == "X": Hy = front * mid * -dz Hz = front * mid * dy Hx = np.zeros_like(Hy) return Hx, Hy, Hz elif orientation.upper() == "Y": Hx = front * mid * dz Hz = front * mid * -dx Hy = np.zeros_like(Hx) return Hx, Hy, Hz elif orientation.upper() == "Z": Hx = front * mid * -dy Hy = front * mid * dx Hz = np.zeros_like(Hx) return Hx, Hy, Hz
def getInterpolationMat(self, loc, locType='CC', zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers 'CCVx' -> x-component of vector field defined on cell centers 'CCVy' -> y-component of vector field defined on cell centers 'CCVz' -> z-component of vector field defined on cell centers """ if self._meshType == 'CYL' and self.isSymmetric and locType in [ 'Ex', 'Ez', 'Fy' ]: raise Exception( 'Symmetric CylMesh does not support %s interpolation, as this variable does not exist.' % locType) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array( [v.mean() for v in self.getTensor('CC')]) if locType in ['Fx', 'Fy', 'Fz', 'Ex', 'Ey', 'Ez']: ind = {'x': 0, 'y': 1, 'z': 2}[locType[1]] assert self.dim >= ind, 'mesh is not high enough dimension.' nF_nE = self.vnF if 'F' in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ['CC', 'N']: Q = Utils.interpmat(loc, *self.getTensor(locType)) elif locType in ['CCVx', 'CCVy', 'CCVz']: Q = Utils.interpmat(loc, *self.getTensor('CC')) Z = Utils.spzeros(loc.shape[0], self.nC) if locType == 'CCVx': Q = sp.hstack([Q, Z, Z]) elif locType == 'CCVy': Q = sp.hstack([Z, Q, Z]) elif locType == 'CCVz': Q = sp.hstack([Z, Z, Q]) else: raise NotImplementedError('getInterpolationMat: locType==' + locType + ' and mesh.dim==' + str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()