From 0ac4b260f4a7c4ee9c030cf6cb560134f9622297 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 09:27:22 -0700 Subject: [PATCH 01/11] Change model to maps.py --- SimPEG/{Model.py => Maps.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename SimPEG/{Model.py => Maps.py} (100%) diff --git a/SimPEG/Model.py b/SimPEG/Maps.py similarity index 100% rename from SimPEG/Model.py rename to SimPEG/Maps.py From 25421f739f3e70c43e57651aa2fc58fd90a51a90 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 09:43:10 -0700 Subject: [PATCH 02/11] testMaps Working! --- SimPEG/Maps.py | 39 +++++++++++--------- SimPEG/Problem.py | 21 +++++------ SimPEG/Regularization.py | 26 +++++++------ SimPEG/Tests/{test_model.py => test_maps.py} | 18 ++++----- SimPEG/__init__.py | 2 +- 5 files changed, 55 insertions(+), 51 deletions(-) rename SimPEG/Tests/{test_model.py => test_maps.py} (61%) diff --git a/SimPEG/Maps.py b/SimPEG/Maps.py index 00f8f302..dde3e752 100644 --- a/SimPEG/Maps.py +++ b/SimPEG/Maps.py @@ -1,7 +1,7 @@ import Utils, Parameters, numpy as np, scipy.sparse as sp from Tests import checkDerivative -class BaseModel(object): +class IdentityMap(object): """ SimPEG Model @@ -66,9 +66,14 @@ class BaseModel(object): kwargs['plotIt'] = False return checkDerivative(lambda m : [self.transform(m), self.transformDeriv(m)], m, **kwargs) -class BaseNonLinearModel(object): + def _assertMatchesPair(self, pair): + assert (isinstance(self, pair) or + isinstance(self, ComboMap) and isinstance(self.models[0], pair) + ), "Model object must be an instance of a %s class."%(pair.__name__) + +class NonLinearMap(object): """ - SimPEG BaseNonLinearModel + SimPEG NonLinearMap """ @@ -129,11 +134,11 @@ class BaseNonLinearModel(object): raise NotImplementedError('The test is not implemented.') -class LogModel(BaseModel): - """SimPEG LogModel""" +class ExpMap(IdentityMap): + """SimPEG ExpMap""" def __init__(self, mesh, **kwargs): - BaseModel.__init__(self, mesh, **kwargs) + IdentityMap.__init__(self, mesh, **kwargs) def transform(self, m): """ @@ -197,8 +202,8 @@ class LogModel(BaseModel): """ return Utils.sdiag(np.exp(Utils.mkvc(m))) -class Vertical1DModel(BaseModel): - """Vertical1DModel +class Vertical1DMap(IdentityMap): + """Vertical1DMap Given a 1D vector through the last dimension of the mesh, this will extend to the full @@ -206,7 +211,7 @@ class Vertical1DModel(BaseModel): """ def __init__(self, mesh, **kwargs): - BaseModel.__init__(self, mesh, **kwargs) + IdentityMap.__init__(self, mesh, **kwargs) @property def nP(self): @@ -238,7 +243,7 @@ class Vertical1DModel(BaseModel): ), shape=(repNum, 1)) return sp.kron(sp.identity(self.nP), repVec) -class Mesh2Mesh(BaseModel): +class Mesh2Mesh(IdentityMap): """ Takes a model on one mesh are translates it to another mesh. @@ -251,8 +256,8 @@ class Mesh2Mesh(BaseModel): M2 = Mesh.TensorMesh([h1,h1]) V = Utils.ModelBuilder.randomModel(M.vnC, seed=79, its=50) v = Utils.mkvc(V) - modh = Model.Mesh2Mesh([M,M2]) - modH = Model.Mesh2Mesh([M2,M]) + modh = Maps.Mesh2Mesh([M,M2]) + modH = Maps.Mesh2Mesh([M2,M]) H = modH.transform(v) h = modh.transform(H) ax = plt.subplot(131) @@ -289,7 +294,7 @@ class Mesh2Mesh(BaseModel): return self.P -class ActiveModel(BaseModel): +class ActiveCells(IdentityMap): """ Active model parameters. @@ -329,15 +334,15 @@ class ActiveModel(BaseModel): def transformDeriv(self, m): return self.P -class ComboModel(BaseModel): +class ComboMap(IdentityMap): """Combination of various models.""" def __init__(self, mesh, models, **kwargs): - BaseModel.__init__(self, mesh, **kwargs) + IdentityMap.__init__(self, mesh, **kwargs) self.models = [] for m in models: - if not isinstance(m, BaseModel): + if not isinstance(m, IdentityMap): self.models += [m(mesh, **kwargs)] else: self.models += [m] @@ -366,7 +371,7 @@ class ComboModel(BaseModel): if __name__ == '__main__': from SimPEG import * mesh = Mesh.TensorMesh([10,8]) - combo = ComboModel(mesh, [LogModel, Vertical1DModel]) + combo = ComboMap(mesh, [ExpMap, Vertical1DMap]) m = combo.example() print m.shape print combo.test(np.arange(8)) diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index 477ba604..7e6ba0d7 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -1,5 +1,5 @@ import Utils, Survey, numpy as np, scipy.sparse as sp -import Model +import Maps class BaseProblem(object): """ @@ -11,19 +11,16 @@ class BaseProblem(object): counter = None #: A SimPEG.Utils.Counter object surveyPair = Survey.BaseSurvey #: A SimPEG.Survey Class - modelPair = Model.BaseModel #: A SimPEG.Model Class + mapPair = Maps.IdentityMap #: A SimPEG.Map Class - def __init__(self, model, **kwargs): + mapping = None #: A SimPEG.Map instance. + mesh = None #: A SimPEG.Mesh instance. + + def __init__(self, mesh, mapping=None, **kwargs): Utils.setKwargs(self, **kwargs) - assert (isinstance(model, self.modelPair) or - isinstance(model, Model.ComboModel) and isinstance(model.models[0], self.modelPair) - ), "Model object must be an instance of a %s class."%(self.modelPair.__name__) - self.model = model - - @property - def mesh(self): - """SimPEG mesh that is associated with the model provided.""" - return self.model.mesh + self.mesh = mesh + self.mapping = mapping or Maps.IdentityMap(mesh) + self.mapping._assertMatchesPair(mapPair) @property def survey(self): diff --git a/SimPEG/Regularization.py b/SimPEG/Regularization.py index 8f7b9ede..cc78df36 100644 --- a/SimPEG/Regularization.py +++ b/SimPEG/Regularization.py @@ -1,4 +1,4 @@ -import Utils, Model, Parameters, numpy as np, scipy.sparse as sp +import Utils, Maps, Parameters, numpy as np, scipy.sparse as sp class BaseRegularization(object): """ @@ -12,16 +12,20 @@ class BaseRegularization(object): __metaclass__ = Utils.SimPEGMetaClass - modelPair = Model.BaseModel #: Some regularizations only work on specific models - model = None #: A SimPEG.Model instance. counter = None - def __init__(self, model, **kwargs): + mapPair = Maps.IdentityMap #: A SimPEG.Map Class + + mapping = None #: A SimPEG.Map instance. + mesh = None #: A SimPEG.Mesh instance. + + def __init__(self, mesh, mapping=None, **kwargs): Utils.setKwargs(self, **kwargs) - assert isinstance(model, self.modelPair), "Incorrect model for this regularization" - self.model = model + self.mesh = mesh + self.mapping = mapping or Maps.IdentityMap(mesh) + self.mapping._assertMatchesPair(mapPair) mref = Parameters.ParameterProperty('mref', default=None, doc='Reference model.') @@ -47,8 +51,6 @@ class BaseRegularization(object): def prob(self): return self.parent.prob @property def survey(self): return self.parent.survey - @property - def mesh(self): return self.model.mesh @property @@ -59,7 +61,7 @@ class BaseRegularization(object): @Utils.timeIt def modelObj(self, m): - r = self.W * self.model.transform(m - self.mref) + r = self.W * self.mapping.transform(m - self.mref) return 0.5*r.dot(r) @Utils.timeIt @@ -79,8 +81,8 @@ class BaseRegularization(object): R(m) = \mathbf{W^\\top W (m-m_\\text{ref})} """ - mTd = self.model.transformDeriv(m - self.mref) - return mTd.T * ( self.W.T * ( self.W * self.model.transform(m - self.mref) ) ) + mTd = self.mapping.transformDeriv(m - self.mref) + return mTd.T * ( self.W.T * ( self.W * self.mapping.transform(m - self.mref) ) ) @Utils.timeIt def modelObj2Deriv(self, m, v=None): @@ -104,7 +106,7 @@ class BaseRegularization(object): R(m) = \mathbf{W^\\top W} """ - mTd = self.model.transformDeriv(m - self.mref) + mTd = self.mapping.transformDeriv(m - self.mref) if v is None: return mTd.T * self.W.T * self.W * mTd diff --git a/SimPEG/Tests/test_model.py b/SimPEG/Tests/test_maps.py similarity index 61% rename from SimPEG/Tests/test_model.py rename to SimPEG/Tests/test_maps.py index cd4a0e07..abd5701f 100644 --- a/SimPEG/Tests/test_model.py +++ b/SimPEG/Tests/test_maps.py @@ -5,7 +5,7 @@ from TestUtils import checkDerivative from scipy.sparse.linalg import dsolve -class ModelTests(unittest.TestCase): +class MapTests(unittest.TestCase): def setUp(self): @@ -15,22 +15,22 @@ class ModelTests(unittest.TestCase): self.mesh22 = Mesh.TensorMesh([b, a], x0=np.array([3, 5])) def test_modelTransforms(self): - for M in dir(Model): + for M in dir(Maps): try: - model = getattr(Model, M)(self.mesh2) - assert isinstance(model, Model.BaseModel) + model = getattr(Maps, M)(self.mesh2) + assert isinstance(model, Maps.BaseModel) except Exception, e: continue self.assertTrue(model.test()) - def test_Mesh2MeshModel(self): - model = Model.Mesh2Mesh([self.mesh22, self.mesh2]) + def test_Mesh2MeshMap(self): + model = Maps.Mesh2Mesh([self.mesh22, self.mesh2]) self.assertTrue(model.test()) - def test_comboModels(self): - combos = [(Model.LogModel, Model.Vertical1DModel)] + def test_comboMaps(self): + combos = [(Maps.ExpMap, Maps.Vertical1DMap)] for combo in combos: - model = Model.ComboModel(self.mesh2, combo) + model = Maps.ComboMap(self.mesh2, combo) self.assertTrue(model.test()) diff --git a/SimPEG/__init__.py b/SimPEG/__init__.py index 874f4ffe..49061e09 100644 --- a/SimPEG/__init__.py +++ b/SimPEG/__init__.py @@ -3,7 +3,7 @@ import scipy.sparse as sp import Utils from Solver import Solver import Mesh -import Model +import Maps import Problem import Survey import Regularization From f10d6cc2b7602ea990ea37524249e64825471327 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 09:47:01 -0700 Subject: [PATCH 03/11] Regularization tests --- SimPEG/Regularization.py | 8 ++++---- SimPEG/Tests/test_regularization.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SimPEG/Regularization.py b/SimPEG/Regularization.py index cc78df36..68e528e3 100644 --- a/SimPEG/Regularization.py +++ b/SimPEG/Regularization.py @@ -25,7 +25,7 @@ class BaseRegularization(object): Utils.setKwargs(self, **kwargs) self.mesh = mesh self.mapping = mapping or Maps.IdentityMap(mesh) - self.mapping._assertMatchesPair(mapPair) + self.mapping._assertMatchesPair(self.mapPair) mref = Parameters.ParameterProperty('mref', default=None, doc='Reference model.') @@ -56,7 +56,7 @@ class BaseRegularization(object): @property def W(self): """Full regularization weighting matrix W.""" - return sp.identity(self.model.nP) + return sp.identity(self.mapping.nP) @Utils.timeIt @@ -206,8 +206,8 @@ class Tikhonov(BaseRegularization): alpha_yy = Utils.dependentProperty('_alpha_yy', 0.0, ['_W', '_Wyy'], "Weight for the second derivative in the y direction") alpha_zz = Utils.dependentProperty('_alpha_zz', 0.0, ['_W', '_Wzz'], "Weight for the second derivative in the z direction") - def __init__(self, model, **kwargs): - BaseRegularization.__init__(self, model, **kwargs) + def __init__(self, mesh, mapping=None, **kwargs): + BaseRegularization.__init__(self, mesh, mapping=mapping, **kwargs) @property def Ws(self): diff --git a/SimPEG/Tests/test_regularization.py b/SimPEG/Tests/test_regularization.py index 3df9180c..71265456 100644 --- a/SimPEG/Tests/test_regularization.py +++ b/SimPEG/Tests/test_regularization.py @@ -19,10 +19,10 @@ class RegularizationTests(unittest.TestCase): continue # if 'Regularization' not in R: continue print 'Check:', R - model = r.modelPair(self.mesh2) - reg = r(model) - m = model.example() - reg.mref = model.example()*0 + mapping = r.mapPair(self.mesh2) + reg = r(self.mesh2, mapping=mapping) + m = mapping.example() + reg.mref = mapping.example()*0 passed = checkDerivative(lambda m : [reg.modelObj(m), reg.modelObjDeriv(m)], m, plotIt=False) self.assertTrue(passed) From 9b9ed41ec726d300b82eb398cd5b36cf11c5d09a Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 09:51:29 -0700 Subject: [PATCH 04/11] Linear Problem Working --- SimPEG/Parameters.py | 2 +- SimPEG/Problem.py | 2 +- Tutorials/Linear.py | 23 +++++++++++------------ 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/SimPEG/Parameters.py b/SimPEG/Parameters.py index fa15ff67..e138ee17 100644 --- a/SimPEG/Parameters.py +++ b/SimPEG/Parameters.py @@ -45,7 +45,7 @@ class Parameter(object): @property def prob(self): return self.parent.prob @property - def model(self): return self.parent.model + def mapping(self): return self.parent.mapping @property def mesh(self): return self.parent.mesh diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index 7e6ba0d7..f88fdb9a 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -20,7 +20,7 @@ class BaseProblem(object): Utils.setKwargs(self, **kwargs) self.mesh = mesh self.mapping = mapping or Maps.IdentityMap(mesh) - self.mapping._assertMatchesPair(mapPair) + self.mapping._assertMatchesPair(self.mapPair) @property def survey(self): diff --git a/Tutorials/Linear.py b/Tutorials/Linear.py index 1bfa7339..1f4bf94e 100644 --- a/Tutorials/Linear.py +++ b/Tutorials/Linear.py @@ -24,42 +24,41 @@ class LinearProblem(Problem.BaseProblem): def example(N): - M = Mesh.TensorMesh([N]) + mesh = Mesh.TensorMesh([N]) nk = 20 jk = np.linspace(1.,20.,nk) p = -0.25 q = 0.25 - g = lambda k: np.exp(p*jk[k]*M.vectorCCx)*np.cos(2*np.pi*q*jk[k]*M.vectorCCx) + g = lambda k: np.exp(p*jk[k]*mesh.vectorCCx)*np.cos(2*np.pi*q*jk[k]*mesh.vectorCCx) - G = np.empty((nk, M.nC)) + G = np.empty((nk, mesh.nC)) for i in range(nk): G[i,:] = g(i) - mtrue = np.zeros(M.nC) - mtrue[M.vectorCCx > 0.3] = 1. - mtrue[M.vectorCCx > 0.45] = -0.5 - mtrue[M.vectorCCx > 0.6] = 0 + mtrue = np.zeros(mesh.nC) + mtrue[mesh.vectorCCx > 0.3] = 1. + mtrue[mesh.vectorCCx > 0.45] = -0.5 + mtrue[mesh.vectorCCx > 0.6] = 0 - model = Model.BaseModel(M) - prob = LinearProblem(model, G) + prob = LinearProblem(mesh, G) survey = prob.createSyntheticSurvey(mtrue, std=0.01) - return prob, survey, model + return prob, survey, mesh if __name__ == '__main__': import matplotlib.pyplot as plt - prob, survey, model = example(100) + prob, survey, mesh = example(100) M = prob.mesh - reg = Regularization.Tikhonov(model) + reg = Regularization.Tikhonov(mesh) beta = Parameters.BetaSchedule() objFunc = ObjFunction.BaseObjFunction(survey, reg, beta=beta) opt = Optimization.InexactGaussNewton(maxIter=20) From 36ca4937f24243d4d65541b5651af00c399e95e7 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 10:05:07 -0700 Subject: [PATCH 05/11] updates to problem --- SimPEG/Maps.py | 28 ++++++++++++++-------------- SimPEG/Problem.py | 3 ++- SimPEG/Tests/test_maps.py | 16 ++++++++-------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/SimPEG/Maps.py b/SimPEG/Maps.py index dde3e752..4b219f22 100644 --- a/SimPEG/Maps.py +++ b/SimPEG/Maps.py @@ -68,8 +68,8 @@ class IdentityMap(object): def _assertMatchesPair(self, pair): assert (isinstance(self, pair) or - isinstance(self, ComboMap) and isinstance(self.models[0], pair) - ), "Model object must be an instance of a %s class."%(pair.__name__) + isinstance(self, ComboMap) and isinstance(self.maps[0], pair) + ), "Mapping object must be an instance of a %s class."%(pair.__name__) class NonLinearMap(object): """ @@ -335,17 +335,17 @@ class ActiveCells(IdentityMap): return self.P class ComboMap(IdentityMap): - """Combination of various models.""" + """Combination of various maps.""" - def __init__(self, mesh, models, **kwargs): + def __init__(self, mesh, maps, **kwargs): IdentityMap.__init__(self, mesh, **kwargs) - self.models = [] - for m in models: + self.maps = [] + for m in maps: if not isinstance(m, IdentityMap): - self.models += [m(mesh, **kwargs)] + self.maps += [m(mesh, **kwargs)] else: - self.models += [m] + self.maps += [m] @property def nP(self): @@ -353,19 +353,19 @@ class ComboMap(IdentityMap): The number of cells in the last dimension of the mesh.""" - return self.models[-1].nP + return self.maps[-1].nP def transform(self, m): - for model in reversed(self.models): - m = model.transform(m) + for map_i in reversed(self.maps): + m = map_i.transform(m) return m def transformDeriv(self, m): deriv = 1 mi = m - for model in reversed(self.models): - deriv = model.transformDeriv(mi) * deriv - mi = model.transform(mi) + for map_i in reversed(self.maps): + deriv = map_i.transformDeriv(mi) * deriv + mi = map_i.transform(mi) return deriv if __name__ == '__main__': diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index f88fdb9a..2175c24d 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -1,5 +1,5 @@ import Utils, Survey, numpy as np, scipy.sparse as sp -import Maps +import Maps, Mesh class BaseProblem(object): """ @@ -18,6 +18,7 @@ class BaseProblem(object): def __init__(self, mesh, mapping=None, **kwargs): Utils.setKwargs(self, **kwargs) + assert isinstance(mesh, Mesh.BaseMesh), "mesh must be a SimPEG.Mesh object." self.mesh = mesh self.mapping = mapping or Maps.IdentityMap(mesh) self.mapping._assertMatchesPair(self.mapPair) diff --git a/SimPEG/Tests/test_maps.py b/SimPEG/Tests/test_maps.py index abd5701f..3b417fe6 100644 --- a/SimPEG/Tests/test_maps.py +++ b/SimPEG/Tests/test_maps.py @@ -14,24 +14,24 @@ class MapTests(unittest.TestCase): self.mesh2 = Mesh.TensorMesh([a, b], x0=np.array([3, 5])) self.mesh22 = Mesh.TensorMesh([b, a], x0=np.array([3, 5])) - def test_modelTransforms(self): + def test_transforms(self): for M in dir(Maps): try: - model = getattr(Maps, M)(self.mesh2) - assert isinstance(model, Maps.BaseModel) + maps = getattr(Maps, M)(self.mesh2) + assert isinstance(maps, Maps.BaseModel) except Exception, e: continue - self.assertTrue(model.test()) + self.assertTrue(maps.test()) def test_Mesh2MeshMap(self): - model = Maps.Mesh2Mesh([self.mesh22, self.mesh2]) - self.assertTrue(model.test()) + maps = Maps.Mesh2Mesh([self.mesh22, self.mesh2]) + self.assertTrue(maps.test()) def test_comboMaps(self): combos = [(Maps.ExpMap, Maps.Vertical1DMap)] for combo in combos: - model = Maps.ComboMap(self.mesh2, combo) - self.assertTrue(model.test()) + maps = Maps.ComboMap(self.mesh2, combo) + self.assertTrue(maps.test()) if __name__ == '__main__': From d88fc1c383b2f41847d7e5dd5c90421206f5fd27 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 10:20:32 -0700 Subject: [PATCH 06/11] Some Changes to Maps and documentation --- SimPEG/Maps.py | 2 +- SimPEG/Mesh/BaseMesh.py | 2 +- SimPEG/Regularization.py | 3 ++- SimPEG/Tests/test_maps.py | 2 +- docs/{api_Model.rst => api_Maps.rst} | 30 ++++++++++++++-------------- docs/index.rst | 2 +- 6 files changed, 21 insertions(+), 20 deletions(-) rename docs/{api_Model.rst => api_Maps.rst} (53%) diff --git a/SimPEG/Maps.py b/SimPEG/Maps.py index 4b219f22..37b210d9 100644 --- a/SimPEG/Maps.py +++ b/SimPEG/Maps.py @@ -3,7 +3,7 @@ from Tests import checkDerivative class IdentityMap(object): """ - SimPEG Model + SimPEG Map """ diff --git a/SimPEG/Mesh/BaseMesh.py b/SimPEG/Mesh/BaseMesh.py index 2d70093c..a1b631d1 100644 --- a/SimPEG/Mesh/BaseMesh.py +++ b/SimPEG/Mesh/BaseMesh.py @@ -51,7 +51,7 @@ class BaseMesh(object): @property def nC(self): """ - Total number of cells in the model. + Total number of cells in the mesh. :rtype: int :return: nC diff --git a/SimPEG/Regularization.py b/SimPEG/Regularization.py index 68e528e3..7760f4f3 100644 --- a/SimPEG/Regularization.py +++ b/SimPEG/Regularization.py @@ -6,7 +6,7 @@ class BaseRegularization(object): This is used to regularize the model space:: - reg = Regularization(mesh, model) + reg = Regularization(mesh) """ @@ -24,6 +24,7 @@ class BaseRegularization(object): def __init__(self, mesh, mapping=None, **kwargs): Utils.setKwargs(self, **kwargs) self.mesh = mesh + assert isinstance(mesh, Mesh.BaseMesh), "mesh must be a SimPEG.Mesh object." self.mapping = mapping or Maps.IdentityMap(mesh) self.mapping._assertMatchesPair(self.mapPair) diff --git a/SimPEG/Tests/test_maps.py b/SimPEG/Tests/test_maps.py index 3b417fe6..e689c597 100644 --- a/SimPEG/Tests/test_maps.py +++ b/SimPEG/Tests/test_maps.py @@ -18,7 +18,7 @@ class MapTests(unittest.TestCase): for M in dir(Maps): try: maps = getattr(Maps, M)(self.mesh2) - assert isinstance(maps, Maps.BaseModel) + assert isinstance(maps, Maps.IdentityMap) except Exception, e: continue self.assertTrue(maps.test()) diff --git a/docs/api_Model.rst b/docs/api_Maps.rst similarity index 53% rename from docs/api_Model.rst rename to docs/api_Maps.rst index 05963ff0..7974c272 100644 --- a/docs/api_Model.rst +++ b/docs/api_Maps.rst @@ -1,45 +1,45 @@ -.. _api_Model: +.. _api_Maps: -Model -***** +Maps +**** -A SimPEG model operates on a vector and transforms it to another space. +A SimPEG Map operates on a vector and transforms it to another space. We will use an example commonly applied in electromagnetics (EM) of the -log-conductivity model (:class:`SimPEG.Model.LogModel`). +log-conductivity model. Electrical conductivity varies over many orders of magnitude, so it is a common technique when solving the inverse problem to parameterize and optimize in terms of log conductivity. This makes sense not only because it ensures all conductivities will be positive, but because this is fundamentally the space where conductivity -lives (i.e. it varies logarithmically). In SimPEG, we use the term Model to -describe how to get between these two spaces. +lives (i.e. it varies logarithmically). In SimPEG, we use a (:class:`SimPEG.Maps.ExpMap`) to +describe how to map back to conductivity. The API ======= -.. autoclass:: SimPEG.Model.BaseModel +.. autoclass:: SimPEG.Maps.IdentityMap :members: :undoc-members: -.. autoclass:: SimPEG.Model.BaseNonLinearModel +.. autoclass:: SimPEG.Maps.NonLinearMap :members: :undoc-members: -.. autoclass:: SimPEG.Model.ComboModel +.. autoclass:: SimPEG.Maps.ComboMap :members: :undoc-members: -Common Models -============= +Common Maps +=========== -.. autoclass:: SimPEG.Model.LogModel +.. autoclass:: SimPEG.Maps.ExpMap :members: :undoc-members: -.. autoclass:: SimPEG.Model.Vertical1DModel +.. autoclass:: SimPEG.Maps.Vertical1DMap :members: :undoc-members: -.. autoclass:: SimPEG.Model.Mesh2Mesh +.. autoclass:: SimPEG.Maps.Mesh2Mesh :members: :undoc-members: diff --git a/docs/index.rst b/docs/index.rst index 98f4efb7..2de51960 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -39,7 +39,7 @@ Forward Problems .. toctree:: :maxdepth: 2 - api_Model + api_Maps api_Survey api_Problem From 1f46e37cdadcb0cecb01bf98c966df33341a8f96 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 10:28:48 -0700 Subject: [PATCH 07/11] Documentation Updates --- SimPEG/Problem.py | 12 ++++++++---- docs/api_Mesh.rst | 7 +++---- docs/api_MeshCode.rst | 8 -------- docs/index.rst | 6 +++--- docs/simpeg-framework.png | Bin 20636 -> 19442 bytes 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/SimPEG/Problem.py b/SimPEG/Problem.py index 2175c24d..0d502e90 100644 --- a/SimPEG/Problem.py +++ b/SimPEG/Problem.py @@ -51,7 +51,8 @@ class BaseProblem(object): @Utils.timeIt def Jvec(self, m, v, u=None): - """ + """Jvec(m, v, u=None) + Effect of J(m) on a vector v. :param numpy.array m: model @@ -64,7 +65,8 @@ class BaseProblem(object): @Utils.timeIt def Jtvec(self, m, v, u=None): - """ + """Jtvec(m, v, u=None) + Effect of transpose of J(m) on a vector v. :param numpy.array m: model @@ -78,7 +80,8 @@ class BaseProblem(object): @Utils.timeIt def Jvec_approx(self, m, v, u=None): - """ + """Jvec_approx(m, v, u=None) + Approximate effect of J(m) on a vector v :param numpy.array m: model @@ -91,7 +94,8 @@ class BaseProblem(object): @Utils.timeIt def Jtvec_approx(self, m, v, u=None): - """ + """Jtvec_approx(m, v, u=None) + Approximate effect of transpose of J(m) on a vector v. :param numpy.array m: model diff --git a/docs/api_Mesh.rst b/docs/api_Mesh.rst index 065dc58e..45172365 100644 --- a/docs/api_Mesh.rst +++ b/docs/api_Mesh.rst @@ -197,7 +197,6 @@ other types of meshes in this SimPEG framework. The API ======= -.. toctree:: - :maxdepth: 2 - - api_MeshCode +.. automodule:: SimPEG.Mesh.BaseMesh + :members: + :undoc-members: diff --git a/docs/api_MeshCode.rst b/docs/api_MeshCode.rst index 65820fc8..4f9927bd 100644 --- a/docs/api_MeshCode.rst +++ b/docs/api_MeshCode.rst @@ -25,11 +25,3 @@ Cylindrical 1D Mesh :show-inheritance: :members: :undoc-members: - - -Base Mesh -========= - -.. automodule:: SimPEG.Mesh.BaseMesh - :members: - :undoc-members: diff --git a/docs/index.rst b/docs/index.rst index 2de51960..fea8b612 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,7 +27,7 @@ Meshing & Operators ******************* .. toctree:: - :maxdepth: 2 + :maxdepth: 3 api_Mesh api_DiffOps @@ -39,9 +39,9 @@ Forward Problems .. toctree:: :maxdepth: 2 - api_Maps - api_Survey api_Problem + api_Survey + api_Maps Inversion ********* diff --git a/docs/simpeg-framework.png b/docs/simpeg-framework.png index f90f8260a2d465fd36a9a1a79eb8498bc911b40e..0d020d6320e8cf28b01ff6ba0ca9f388770a93ab 100644 GIT binary patch literal 19442 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 literal 20636 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 MoV}bVCqu6P3zX2`+yDRo From 2a4b4483566412d705face6a3cae39dd22402323 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 10:32:52 -0700 Subject: [PATCH 08/11] meshing docs updates --- docs/api_MeshCode.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/api_MeshCode.rst b/docs/api_MeshCode.rst index 4f9927bd..9bf3ae4f 100644 --- a/docs/api_MeshCode.rst +++ b/docs/api_MeshCode.rst @@ -9,6 +9,15 @@ Tensor Mesh :undoc-members: +Tree Mesh +========= + +.. autoclass:: SimPEG.Mesh.TreeMesh.TreeMesh + :show-inheritance: + :members: + :undoc-members: + + Logically Rectangular Mesh ========================== From 987b759088723c501efe2cf0342161f308abd38a Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 11:04:17 -0700 Subject: [PATCH 09/11] Fix bug in regularization --- SimPEG/Regularization.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SimPEG/Regularization.py b/SimPEG/Regularization.py index 7760f4f3..5318b7da 100644 --- a/SimPEG/Regularization.py +++ b/SimPEG/Regularization.py @@ -1,4 +1,4 @@ -import Utils, Maps, Parameters, numpy as np, scipy.sparse as sp +import Utils, Maps, Mesh, Parameters, numpy as np, scipy.sparse as sp class BaseRegularization(object): """ From c39163bd6e91ca17f123c5919885b90105efc7c4 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 11:44:41 -0700 Subject: [PATCH 10/11] Add BaseMesh to the init file. --- SimPEG/Mesh/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/SimPEG/Mesh/__init__.py b/SimPEG/Mesh/__init__.py index a79e93dc..1bfa4c6f 100644 --- a/SimPEG/Mesh/__init__.py +++ b/SimPEG/Mesh/__init__.py @@ -3,3 +3,4 @@ from CylMesh import CylMesh from Cyl1DMesh import Cyl1DMesh from LogicallyRectMesh import LogicallyRectMesh from TreeMesh import TreeMesh +from BaseMesh import BaseMesh From dd579ddbd4c93bde2fc9ddb9933aefa334d91697 Mon Sep 17 00:00:00 2001 From: rowanc1 Date: Tue, 15 Apr 2014 15:12:19 -0700 Subject: [PATCH 11/11] minor updates in interpolation in TensorMesh --- SimPEG/Mesh/TensorMesh.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SimPEG/Mesh/TensorMesh.py b/SimPEG/Mesh/TensorMesh.py index 4d1b16a2..a8e29768 100644 --- a/SimPEG/Mesh/TensorMesh.py +++ b/SimPEG/Mesh/TensorMesh.py @@ -220,8 +220,12 @@ class BaseTensorMesh(BaseRectangularMesh): if type(loc) == list: loc = np.array(loc) assert type(loc) == np.ndarray, "must be a numpy array" + + if loc.size == self.dim: + loc = np.atleast_2d(loc) + if self.dim > 1: - assert loc.shape[1] == self.dim, "must be a column vector of shape (nPts, mesh.dim)" + assert loc.shape[1] == self.dim, "must be a column vector of shape (nPts, mesh.dim) not (%d,%d)" % loc.shape elif len(loc.shape) == 1: loc = loc[:,np.newaxis] else: