# Forward Problem¶

## Problem Class¶

The problem is a partial differential equation of the form:

$c(m, u) = 0$

Here, $$m$$ is the model and u is the field (or fields). Given the model, $$m$$, we can calculate the fields $$u(m)$$, however, the data we collect is a subset of the fields, and can be defined by a linear projection, $$P$$.

$d_\text{pred} = P u(m)$

For the inverse problem, we are interested in how changing the model transforms the data, as such we can take write the Taylor expansion:

$Pu(m + hv) = Pu(m) + hP\frac{\partial u(m)}{\partial m} v + \mathcal{O}(h^2 \left\| v \right\| )$

We can linearize and define the sensitivity matrix as:

$J = P\frac{\partial u}{\partial m}$

The sensitivity matrix, and it’s transpose will be used in the inverse problem to (locally) find how model parameters change the data, and optimize!

Working with the general PDE, $$c(m, u) = 0$$, where m is the model and u is the field, the sensitivity is defined as:

$J = P\frac{\partial u}{\partial m}$

We can take the derivative of the PDE:

$\nabla_m c(m, u) \partial m + \nabla_u c(m, u) \partial u = 0$

If the forward problem is invertible, then we can rearrange for $$\frac{\partial u}{\partial m}$$:

$J = - P \left( \nabla_u c(m, u) \right)^{-1} \nabla_m c(m, u)$

This can often be computed given a vector (i.e. $$J(v)$$) rather than stored, as $$J$$ is a large dense matrix.

## The API¶

### Problem¶

class SimPEG.Problem.BaseProblem(mesh, **kwargs)
Problem is the base class for all geophysical forward problems
in SimPEG.

Optional Properties:

• model (Model): Inversion model., a numpy array of <type ‘float’>, <type ‘int’> with shape (*)
Jtvec(m, v, f=None)

Effect of transpose of J(m) on a vector v.

Parameters: m (numpy.array) – model v (numpy.array) – vector to multiply f (Fields) – fields numpy.array JTv
Jtvec_approx(m, v, f=None)

Approximate effect of transpose of J(m) on a vector v.

Parameters: m (numpy.array) – model v (numpy.array) – vector to multiply f (Fields) – fields numpy.array JTv
Jvec(m, v, f=None)

Effect of J(m) on a vector v.

Parameters: m (numpy.array) – model v (numpy.array) – vector to multiply f (Fields) – fields numpy.array Jv
Jvec_approx(m, v, f=None)

Approximate effect of J(m) on a vector v

Parameters: m (numpy.array) – model v (numpy.array) – vector to multiply f (Fields) – fields numpy.array approxJv
class Solver(A, **kwargs)
clean()
counter = None
curModel

Setting the curModel is depreciated.

deleteTheseOnModelUpdate = []
fields(m)

The field given the model.

Parameters: m (numpy.array) – model numpy.array u, the fields
ispaired

True if the problem is paired to a survey.

mapPair

alias of IdentityMap

mapping

Setting an unnamed mapping has been depreciated in v0.4.0. Please see the release notes for more details.

mesh = None
pair(d)

Bind a survey to this problem instance using pointers.

solverOpts = {}
survey

The survey object for this problem.

surveyPair

alias of BaseSurvey

unpair()

Unbind a survey from this problem instance.

class SimPEG.Problem.BaseTimeProblem(mesh, **kwargs)

Sets up that basic needs of a time domain problem.

Optional Properties:

• model (Model): Inversion model., a numpy array of <type ‘float’>, <type ‘int’> with shape (*)
nT

Number of time steps.

t0
timeMesh
timeSteps

Sets/gets the timeSteps for the time domain problem.

You can set as an array of dt’s or as a list of tuples/floats. Tuples must be length two with [..., (dt, repeat), ...]

For example, the following setters are the same:

prob.timeSteps = [(1e-6, 3), 1e-5, (1e-4, 2)]
prob.timeSteps = np.r_[1e-6,1e-6,1e-6,1e-5,1e-4,1e-4]

times

Modeling times

### Fields¶

class SimPEG.Fields.Fields(mesh, survey, **kwargs)

Fancy Field Storage

u[:,’phi’] = phi print(u[src0,’phi’])

aliasFields = None
approxSize

The approximate cost to storing all of the known fields.

dtype

alias of float

knownFields = None
startup()
class SimPEG.Fields.TimeFields(mesh, survey, **kwargs)

Fancy Field Storage for time domain problems

u[:,’phi’, timeInd] = phi print(u[src0,’phi’])

### Survey¶

class SimPEG.Survey.BaseSurvey(**kwargs)

Survey holds the observed data, and the standard deviations.

counter = None
dobs = None
dpred(m, f=None)

Create the projected data from a model. The fields, f, (if provided) will be used for the predicted data instead of recalculating the fields (which may be expensive!).

$d_\text{pred} = P(f(m))$

Where P is a projection of the fields onto the data space.

Note

To use survey.dpred(), SimPEG requires that a problem be bound to the survey. If a problem has not been bound, an Exception will be raised. To bind a problem to the Data object:

survey.pair(myProblem)

dtrue = None
eps = None
eval(f)

This function projects the fields onto the data space.

$d_\text{pred} = \mathbf{P} f(m)$
evalDeriv(f)

This function s the derivative of projects the fields onto the data space.

$\frac{\partial d_\text{pred}}{\partial u} = \mathbf{P}$
getSourceIndex(sources)
isSynthetic

Check if the data is synthetic.

ispaired
makeSyntheticData(m, std=0.05, f=None, force=False)

Make synthetic data given a model, and a standard deviation.

Parameters: m (numpy.array) – geophysical model std (numpy.array) – standard deviation u (numpy.array) – fields for the given model (if pre-calculated) force (bool) – force overwriting of dobs
mesh

Mesh of the paired problem.

mtrue = None
nD

Number of data

nSrc

Number of Sources

pair(p)

Bind a problem to this survey instance using pointers

prob

The geophysical problem that explains this survey, use:

survey.pair(prob)

residual(m, f=None)
Parameters: m (numpy.array) – geophysical model f (numpy.array) – fields numpy.array data residual

The data residual:

$\mu_\text{data} = \mathbf{d}_\text{pred} - \mathbf{d}_\text{obs}$
srcList

Source List

srcPair

alias of BaseSrc

std = None
unpair()

Unbind a problem from this survey instance

vnD

Vector number of data

class SimPEG.Survey.BaseSrc(rxList, **kwargs)

SimPEG Source Object

loc = None
nD

Number of data

rxList = None
rxPair

alias of BaseRx

vnD

Vector number of data

class SimPEG.Survey.BaseRx(locs, rxType, **kwargs)

getP(mesh, projGLoc=None)

Returns the projection matrices as a list for all components collected by the receivers.

Note

Projection matrices are stored as a dictionary listed by meshes.

knownRxTypes = None
locs = None
nD

Number of data in the receiver.

projGLoc = 'CC'
rxType

storeProjections = True
class SimPEG.Survey.BaseTimeRx(locs, times, rxType, **kwargs)

getP(mesh, timeMesh)

Returns the projection matrices as a list for all components collected by the receivers.

Note

Projection matrices are stored as a dictionary (mesh, timeMesh) if storeProjections is True

getSpatialP(mesh)

Returns the spatial projection matrix.

Note

This is not stored in memory, but is created on demand.

getTimeP(timeMesh)

Returns the time projection matrix.

Note

This is not stored in memory, but is created on demand.

nD

Number of data in the receiver.

projTLoc = 'N'
times = None
class SimPEG.Survey.Data(survey, dobs=None, standard_deviation=None, floor=None)

Storage of data, standard_deviation and floor storage with fancy [Src,Rx] indexing.

Requried :param Survey survey: The survey descriping the layout of the data

Optional :param ndarray dobs: The data vector matching the src and rx in survey :param ndarray standard_deviation: The standard deviation vector matching the src and rx in survey :param ndarray floor: The floor vector for the data matching the src and rx in survey

calculate_uncertainty()

Return the uncertainty base on standard_devation * np.abs(data) + floor