def _checkAccuracy(A, b, X, accuracyTol): nrm = np.linalg.norm(mkvc(A*X - b), np.inf) nrm_b = np.linalg.norm(mkvc(b), np.inf) if nrm_b > 0: nrm /= nrm_b if nrm > accuracyTol: msg = '### SolverWarning ###: Accuracy on solve is above tolerance: %e > %e' % (nrm, accuracyTol) print msg warnings.warn(msg, RuntimeWarning)
def _checkAccuracy(A, b, X, accuracyTol): nrm = np.linalg.norm(mkvc(A * X - b), np.inf) nrm_b = np.linalg.norm(mkvc(b), np.inf) if nrm_b > 0: nrm /= nrm_b if nrm > accuracyTol: msg = '### SolverWarning ###: Accuracy on solve is above tolerance: {0:e} > {1:e}'.format( nrm, accuracyTol) print msg warnings.warn(msg, RuntimeWarning)
def surface2ind_topo(mesh, topo, gridLoc='CC'): # def genActiveindfromTopo(mesh, topo): """ Get active indices from topography """ if mesh.dim == 3: from scipy.interpolate import NearestNDInterpolator Ftopo = NearestNDInterpolator(topo[:,:2], topo[:,2]) if gridLoc == 'CC': XY = ndgrid(mesh.vectorCCx, mesh.vectorCCy) Zcc = mesh.gridCC[:,2].reshape((np.prod(mesh.vnC[:2]), mesh.nCz), order='F') gridTopo = Ftopo(XY) actind = [gridTopo[ixy] <= Zcc[ixy,:] for ixy in range(np.prod(mesh.vnC[0]))] actind = np.hstack(actind) elif gridLoc == 'N': XY = ndgrid(mesh.vectorNx, mesh.vectorNy) gridTopo = Ftopo(XY).reshape(mesh.vnN[:2], order='F') if mesh._meshType not in ['TENSOR', 'CYL', 'BASETENSOR']: raise NotImplementedError('Nodal surface2ind_topo not implemented for %s mesh'%mesh._meshType) Nz = mesh.vectorNz[1:] # TODO: this will only work for tensor meshes actind = np.array([False]*mesh.nC).reshape(mesh.vnC, order='F') for ii in range(mesh.nCx): for jj in range(mesh.nCy): actind[ii,jj,:] = [np.all(gridTopo[ii:ii+2, jj:jj+2] >= Nz[kk]) for kk in range(len(Nz)) ] elif mesh.dim == 2: from scipy.interpolate import interp1d Ftopo = interp1d(topo[:,0], topo[:,1]) if gridLoc == 'CC': gridTopo = Ftopo(mesh.gridCC[:,0]) actind = mesh.gridCC[:,1] <= gridTopo elif gridLoc == 'N': gridTopo = Ftopo(mesh.vectorNx) if mesh._meshType not in ['TENSOR', 'CYL', 'BASETENSOR']: raise NotImplementedError('Nodal surface2ind_topo not implemented for %s mesh'%mesh._meshType) Ny = mesh.vectorNy[1:] # TODO: this will only work for tensor meshes actind = np.array([False]*mesh.nC).reshape(mesh.vnC, order='F') for ii in range(mesh.nCx): actind[ii,:] = [np.all(gridTopo[ii:ii+2] > Ny[kk]) for kk in range(len(Ny)) ] else: raise NotImplementedError('surface2ind_topo not implemented for 1D mesh') return mkvc(actind)
def layeredModel(ccMesh, layerTops, layerValues): """ Define a layered model from layerTops (z-positive up) :param numpy.array ccMesh: cell-centered mesh :param numpy.array layerTops: z-locations of the tops of each layer :param numpy.array layerValue: values of the property to assign for each layer (starting at the top) :rtype: numpy.array :return: M, layered model on the mesh """ descending = np.linalg.norm(sorted(layerTops, reverse=True) - layerTops) < 1e-20 # TODO: put an error check to make sure that there is an ordering... needs to work with inf elts # assert ascending or descending, "Layers must be listed in either ascending or descending order" # start from bottom up if not descending: zprop = np.hstack([mkvc(layerTops, 2), mkvc(layerValues, 2)]) zprop.sort(axis=0) layerTops, layerValues = zprop[::-1, 0], zprop[::-1, 1] # put in vector form layerTops, layerValues = mkvc(layerTops), mkvc(layerValues) # initialize with bottom layer dim = ccMesh.shape[1] if dim == 3: z = ccMesh[:, 2] elif dim == 2: z = ccMesh[:, 1] elif dim == 1: z = ccMesh[:, 0] model = np.zeros(ccMesh.shape[0]) for i, top in enumerate(layerTops): zind = z <= top model[zind] = layerValues[i] return model
def layeredModel(ccMesh, layerTops, layerValues): """ Define a layered model from layerTops (z-positive up) :param numpy.array ccMesh: cell-centered mesh :param numpy.array layerTops: z-locations of the tops of each layer :param numpy.array layerValue: values of the property to assign for each layer (starting at the top) :rtype: numpy.array :return: M, layered model on the mesh """ descending = np.linalg.norm(sorted(layerTops, reverse=True) - layerTops) < 1e-20 # TODO: put an error check to make sure that there is an ordering... needs to work with inf elts # assert ascending or descending, "Layers must be listed in either ascending or descending order" # start from bottom up if not descending: zprop = np.hstack([mkvc(layerTops,2),mkvc(layerValues,2)]) zprop.sort(axis=0) layerTops, layerValues = zprop[::-1,0], zprop[::-1,1] # put in vector form layerTops, layerValues = mkvc(layerTops), mkvc(layerValues) # initialize with bottom layer dim = ccMesh.shape[1] if dim == 3: z = ccMesh[:,2] elif dim == 2: z = ccMesh[:,1] elif dim == 1: z = ccMesh[:,0] model = np.zeros(ccMesh.shape[0]) for i, top in enumerate(layerTops): zind = z <= top model[zind] = layerValues[i] return model
def defineBlock(ccMesh,p0,p1,vals=[0,1]): """ Build a block with the conductivity specified by condVal. Returns an array. vals[0] conductivity of the block vals[1] conductivity of the ground """ sigma = np.zeros(ccMesh.shape[0]) + vals[1] ind = getIndicesBlock(p0,p1,ccMesh) sigma[ind] = vals[0] return mkvc(sigma)
def defineBlock(ccMesh, p0, p1, vals=[0, 1]): """ Build a block with the conductivity specified by condVal. Returns an array. vals[0] conductivity of the block vals[1] conductivity of the ground """ sigma = np.zeros(ccMesh.shape[0]) + vals[1] ind = getIndicesBlock(p0, p1, ccMesh) sigma[ind] = vals[0] return mkvc(sigma)
def scalarConductivity(ccMesh, pFunction): """ Define the distribution conductivity in the mesh according to the analytical expression given in pFunction """ dim = np.size(ccMesh[0, :]) CC = [ccMesh[:, 0]] if dim > 1: CC.append(ccMesh[:, 1]) if dim > 2: CC.append(ccMesh[:, 2]) sigma = pFunction(*CC) return mkvc(sigma)
def interpmat(locs, x, y=None, z=None): """ Local interpolation computed for each receiver point in turn :param numpy.ndarray loc: Location of points to interpolate to :param numpy.ndarray x: Tensor vector of 1st dimension of grid. :param numpy.ndarray y: Tensor vector of 2nd dimension of grid. None by default. :param numpy.ndarray z: Tensor vector of 3rd dimension of grid. None by default. :rtype: scipy.sparse.csr.csr_matrix :return: Interpolation matrix .. plot:: import SimPEG import numpy as np import matplotlib.pyplot as plt locs = np.random.rand(50)*0.8+0.1 x = np.linspace(0,1,7) dense = np.linspace(0,1,200) fun = lambda x: np.cos(2*np.pi*x) Q = SimPEG.Utils.interpmat(locs, x) plt.plot(x, fun(x), 'bs-') plt.plot(dense, fun(dense), 'y:') plt.plot(locs, Q*fun(x), 'mo') plt.plot(locs, fun(locs), 'rx') plt.show() """ npts = locs.shape[0] locs = locs.astype(float) x = x.astype(float) if y is None and z is None: shape = [ x.size, ] inds, vals = _interpmat1D(mkvc(locs), x) elif z is None: y = y.astype(float) shape = [x.size, y.size] inds, vals = _interpmat2D(locs, x, y) else: y = y.astype(float) z = z.astype(float) shape = [x.size, y.size, z.size] inds, vals = _interpmat3D(locs, x, y, z) I = np.repeat(range(npts), 2**len(shape)) J = sub2ind(shape, inds) Q = sp.csr_matrix((vals, (I, J)), shape=(npts, np.prod(shape))) return Q
def interpmat(locs, x, y=None, z=None): """ Local interpolation computed for each receiver point in turn :param numpy.ndarray loc: Location of points to interpolate to :param numpy.ndarray x: Tensor vector of 1st dimension of grid. :param numpy.ndarray y: Tensor vector of 2nd dimension of grid. None by default. :param numpy.ndarray z: Tensor vector of 3rd dimension of grid. None by default. :rtype: scipy.sparse.csr_matrix :return: Interpolation matrix .. plot:: import SimPEG import numpy as np import matplotlib.pyplot as plt locs = np.random.rand(50)*0.8+0.1 x = np.linspace(0,1,7) dense = np.linspace(0,1,200) fun = lambda x: np.cos(2*np.pi*x) Q = SimPEG.Utils.interpmat(locs, x) plt.plot(x, fun(x), 'bs-') plt.plot(dense, fun(dense), 'y:') plt.plot(locs, Q*fun(x), 'mo') plt.plot(locs, fun(locs), 'rx') plt.show() """ npts = locs.shape[0] locs = locs.astype(float) x = x.astype(float) if y is None and z is None: shape = [x.size,] inds, vals = _interpmat1D(mkvc(locs), x) elif z is None: y = y.astype(float) shape = [x.size, y.size] inds, vals = _interpmat2D(locs, x, y) else: y = y.astype(float) z = z.astype(float) shape = [x.size, y.size, z.size] inds, vals = _interpmat3D(locs, x, y, z) I = np.repeat(range(npts),2**len(shape)) J = sub2ind(shape,inds) Q = sp.csr_matrix((vals,(I, J)), shape=(npts, np.prod(shape))) return Q
def scalarConductivity(ccMesh,pFunction): """ Define the distribution conductivity in the mesh according to the analytical expression given in pFunction """ dim = np.size(ccMesh[0,:]) CC = [ccMesh[:,0]] if dim>1: CC.append(ccMesh[:,1]) if dim>2: CC.append(ccMesh[:,2]) sigma = pFunction(*CC) return mkvc(sigma)
def writeUBCTensorModel(fileName, mesh, model): """ Writes a model associated with a SimPEG TensorMesh to a UBC-GIF format model file. :param str fileName: File to write to :param simpeg.Mesh.TensorMesh mesh: The mesh :param numpy.ndarray model: The model """ # Reshape model to a matrix modelMat = mesh.r(model,'CC','CC','M') # Transpose the axes modelMatT = modelMat.transpose((2,0,1)) # Flip z to positive down modelMatTR = mkvc(modelMatT[::-1,:,:]) np.savetxt(fileName, modelMatTR.ravel())
def readUBCTensorModel(fileName, mesh): """ Read UBC 3DTensor mesh model and generate 3D Tensor mesh model in simpeg Input: :param fileName, path to the UBC GIF mesh file to read :param mesh, TensorMesh object, mesh that coresponds to the model Output: :return numpy array, model with TensorMesh ordered """ f = open(fileName, 'r') model = np.array(map(float, f.readlines())) f.close() model = np.reshape(model, (mesh.nCz, mesh.nCx, mesh.nCy), order = 'F') model = model[::-1,:,:] model = np.transpose(model, (1, 2, 0)) model = mkvc(model) return model
def defineTwoLayers(ccMesh,depth,vals=None): """ Define a two layered model. Depth of the first layer must be specified. CondVals vector with the conductivity values of the layers. Eg: Convention to number the layers:: <----------------------------|------------------------------------> 0 depth zf 1st layer 2nd layer """ if vals is None: vals = [0,1] sigma = np.zeros(ccMesh.shape[0]) + vals[1] dim = np.size(ccMesh[0,:]) p0 = np.zeros(dim) p1 = np.zeros(dim) # Identify 1st cell centered reference point p0[0] = ccMesh[0,0] if dim>1: p0[1] = ccMesh[0,1] if dim>2: p0[2] = ccMesh[0,2] # Identify the last cell-centered reference point p1[0] = ccMesh[-1,0] if dim>1: p1[1] = ccMesh[-1,1] if dim>2: p1[2] = ccMesh[-1,2] # The depth is always defined on the last one. p1[len(p1)-1] -= depth ind = getIndicesBlock(p0,p1,ccMesh) sigma[ind] = vals[0]; return mkvc(sigma)
def surface2ind_topo(mesh, topo, gridLoc='CC'): # def genActiveindfromTopo(mesh, topo): """ Get active indices from topography """ if mesh.dim == 3: from scipy.interpolate import NearestNDInterpolator Ftopo = NearestNDInterpolator(topo[:, :2], topo[:, 2]) if gridLoc == 'CC': XY = ndgrid(mesh.vectorCCx, mesh.vectorCCy) Zcc = mesh.gridCC[:, 2].reshape((np.prod(mesh.vnC[:2]), mesh.nCz), order='F') gridTopo = Ftopo(XY) actind = [ gridTopo[ixy] <= Zcc[ixy, :] for ixy in range(np.prod(mesh.vnC[0])) ] actind = np.hstack(actind) elif gridLoc == 'N': XY = ndgrid(mesh.vectorNx, mesh.vectorNy) gridTopo = Ftopo(XY).reshape(mesh.vnN[:2], order='F') if mesh._meshType not in ['TENSOR', 'CYL', 'BASETENSOR']: raise NotImplementedError( 'Nodal surface2ind_topo not implemented for {0!s} mesh'. format(mesh._meshType)) Nz = mesh.vectorNz[ 1:] # TODO: this will only work for tensor meshes actind = np.array([False] * mesh.nC).reshape(mesh.vnC, order='F') for ii in range(mesh.nCx): for jj in range(mesh.nCy): actind[ii, jj, :] = [ np.all(gridTopo[ii:ii + 2, jj:jj + 2] >= Nz[kk]) for kk in range(len(Nz)) ] elif mesh.dim == 2: from scipy.interpolate import interp1d Ftopo = interp1d(topo[:, 0], topo[:, 1]) if gridLoc == 'CC': gridTopo = Ftopo(mesh.gridCC[:, 0]) actind = mesh.gridCC[:, 1] <= gridTopo elif gridLoc == 'N': gridTopo = Ftopo(mesh.vectorNx) if mesh._meshType not in ['TENSOR', 'CYL', 'BASETENSOR']: raise NotImplementedError( 'Nodal surface2ind_topo not implemented for {0!s} mesh'. format(mesh._meshType)) Ny = mesh.vectorNy[ 1:] # TODO: this will only work for tensor meshes actind = np.array([False] * mesh.nC).reshape(mesh.vnC, order='F') for ii in range(mesh.nCx): actind[ii, :] = [ np.all(gridTopo[ii:ii + 2] > Ny[kk]) for kk in range(len(Ny)) ] else: raise NotImplementedError( 'surface2ind_topo not implemented for 1D mesh') return mkvc(actind)
def faceInfo(xyz, A, B, C, D, average=True, normalizeNormals=True): """ function [N] = faceInfo(y,A,B,C,D) Returns the averaged normal, area, and edge lengths for a given set of faces. If average option is FALSE then N is a cell array {nA,nB,nC,nD} Input: xyz - X,Y,Z vertex vector A,B,C,D - vert index of the face (counter clockwize) Options: average - [true]/false, toggles returning all normals or the average Output: N - average face normal or {nA,nB,nC,nD} if average = false area - average face area edgeLengths - exact edge Lengths, 4 column vector [AB, BC, CD, DA] see also testFaceNormal testFaceArea @author Rowan Cockett Last modified on: 2013/07/26 """ assert type(average) is bool, 'average must be a boolean' assert type(normalizeNormals) is bool, 'normalizeNormals must be a boolean' # compute normal that is pointing away from you. # # A -------A-B------- B # | | # | | # D-A (X) B-C # | | # | | # D -------C-D------- C AB = xyz[B, :] - xyz[A, :] BC = xyz[C, :] - xyz[B, :] CD = xyz[D, :] - xyz[C, :] DA = xyz[A, :] - xyz[D, :] def cross(X, Y): return np.c_[X[:, 1] * Y[:, 2] - X[:, 2] * Y[:, 1], X[:, 2] * Y[:, 0] - X[:, 0] * Y[:, 2], X[:, 0] * Y[:, 1] - X[:, 1] * Y[:, 0]] nA = cross(AB, DA) nB = cross(BC, AB) nC = cross(CD, BC) nD = cross(DA, CD) length = lambda x: np.sqrt(x[:, 0]**2 + x[:, 1]**2 + x[:, 2]**2) normalize = lambda x: x / np.kron(np.ones( (1, x.shape[1])), mkvc(length(x), 2)) if average: # average the normals at each vertex. N = (nA + nB + nC + nD) / 4 # this is intrinsically weighted by area # normalize N = normalize(N) else: if normalizeNormals: N = [normalize(nA), normalize(nB), normalize(nC), normalize(nD)] else: N = [nA, nB, nC, nD] # Area calculation # # Approximate by 4 different triangles, and divide by 2. # Each triangle is one half of the length of the cross product # # So also could be viewed as the average parallelogram. # # TODO: This does not compute correctly for concave quadrilaterals area = (length(nA) + length(nB) + length(nC) + length(nD)) / 4 return N, area
def faceInfo(xyz, A, B, C, D, average=True, normalizeNormals=True): """ function [N] = faceInfo(y,A,B,C,D) Returns the averaged normal, area, and edge lengths for a given set of faces. If average option is FALSE then N is a cell array {nA,nB,nC,nD} Input: xyz - X,Y,Z vertex vector A,B,C,D - vert index of the face (counter clockwize) Options: average - [true]/false, toggles returning all normals or the average Output: N - average face normal or {nA,nB,nC,nD} if average = false area - average face area edgeLengths - exact edge Lengths, 4 column vector [AB, BC, CD, DA] see also testFaceNormal testFaceArea @author Rowan Cockett Last modified on: 2013/07/26 """ assert type(average) is bool, 'average must be a boolean' assert type(normalizeNormals) is bool, 'normalizeNormals must be a boolean' # compute normal that is pointing away from you. # # A -------A-B------- B # | | # | | # D-A (X) B-C # | | # | | # D -------C-D------- C AB = xyz[B, :] - xyz[A, :] BC = xyz[C, :] - xyz[B, :] CD = xyz[D, :] - xyz[C, :] DA = xyz[A, :] - xyz[D, :] def cross(X, Y): return np.c_[X[:, 1]*Y[:, 2] - X[:, 2]*Y[:, 1], X[:, 2]*Y[:, 0] - X[:, 0]*Y[:, 2], X[:, 0]*Y[:, 1] - X[:, 1]*Y[:, 0]] nA = cross(AB, DA) nB = cross(BC, AB) nC = cross(CD, BC) nD = cross(DA, CD) length = lambda x: np.sqrt(x[:, 0]**2 + x[:, 1]**2 + x[:, 2]**2) normalize = lambda x: x/np.kron(np.ones((1, x.shape[1])), mkvc(length(x), 2)) if average: # average the normals at each vertex. N = (nA + nB + nC + nD)/4 # this is intrinsically weighted by area # normalize N = normalize(N) else: if normalizeNormals: N = [normalize(nA), normalize(nB), normalize(nC), normalize(nD)] else: N = [nA, nB, nC, nD] # Area calculation # # Approximate by 4 different triangles, and divide by 2. # Each triangle is one half of the length of the cross product # # So also could be viewed as the average parallelogram. # # TODO: This does not compute correctly for concave quadrilaterals area = (length(nA)+length(nB)+length(nC)+length(nD))/4 return N, area