def __init__(self, domain, omega, w, data, F, coordinates=None, fixAtBottom=False, tol=1e-8, saveMemory=True, scaleF=True): """ initializes a new forward model with acoustic wave form inversion. :param domain: domain of the model :type domain: `Domain` :param w: weighting factors :type w: ``Scalar`` :param data: real and imaginary part of data :type data: ``Data`` of shape (2,) :param F: real and imaginary part of source given at Dirac points, on surface or at volume. :type F: ``Data`` of shape (2,) :param coordinates: defines coordinate system to be used (not supported yet) :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param saveMemory: if true stiffness matrix is deleted after solution of PDE to minimize memory requests. This will require more compute time as the matrix needs to be reallocated. :type saveMemory: ``bool`` :param scaleF: if true source F is scaled to minimize defect. :type scaleF: ``bool`` :param fixAtBottom: if true pressure is fixed to zero at the bottom of the domain :type fixAtBottom: ``bool`` """ super(AcousticWaveForm, self).__init__() self.__trafo = makeTransformation(domain, coordinates) if not self.getCoordinateTransformation().isCartesian(): raise ValueError("Non-Cartesian Coordinates are not supported yet.") if not isinstance(data, Data): raise ValueError("data must be an escript.Data object.") if not data.getFunctionSpace() == FunctionOnBoundary(domain): raise ValueError("data must be defined on boundary") if not data.getShape() == (2,): raise ValueError("data must have shape (2,) (real and imaginary part).") if w is None: w = 1. if not isinstance(w, Data): w = Data(w, FunctionOnBoundary(domain)) else: if not w.getFunctionSpace() == FunctionOnBoundary(domain): raise ValueError("Weights must be defined on boundary.") if not w.getShape() == (): raise ValueError("Weights must be scalar.") self.__domain = domain self.__omega = omega self.__weight = w self.__data = data self.scaleF = scaleF if scaleF: A = integrate(self.__weight*length(self.__data)**2) if A > 0: self.__data*=1./sqrt(A) self.__BX = boundingBox(domain) self.edge_lengths = np.asarray(boundingBoxEdgeLengths(domain)) if not isinstance(F, Data): F=interpolate(F, DiracDeltaFunctions(domain)) if not F.getShape() == (2,): raise ValueError("Source must have shape (2,) (real and imaginary part).") self.__F=Data() self.__f=Data() self.__f_dirac=Data() if F.getFunctionSpace() == DiracDeltaFunctions(domain): self.__f_dirac=F elif F.getFunctionSpace() == FunctionOnBoundary(domain): self.__f=F else: self.__F=F self.__tol=tol self.__fixAtBottom=fixAtBottom self.__pde=None if not saveMemory: self.__pde=self.setUpPDE()