def inv2D(self, nlay, lam=100., resL=1., resU=1000., thkL=1., thkU=100., minErr=1.0): """2d LCI inversion class.""" if isinstance(nlay, int): modVec = pg.RVector(nlay * 2 - 1, 30.) cType = 0 # no reference model else: modVec = nlay cType = 10 # use this as referencemodel nlay = (len(modVec) + 1) / 2 # init forward operator self.f2d = self.FOP2d(nlay) # transformations self.transData = pg.RTrans() self.transThk = pg.RTransLogLU(thkL, thkU) self.transRes = pg.RTransLogLU(resL, resU) for i in range(nlay - 1): self.f2d.region(i).setTransModel(self.transThk) for i in range(nlay - 1, nlay * 2 - 1): self.f2d.region(i).setTransModel(self.transRes) # set constraints self.f2d.region(0).setConstraintType(cType) self.f2d.region(1).setConstraintType(cType) # collect data vector datvec = pg.RVector(0) for i in range(len(self.x)): datvec = pg.cat(datvec, self.datavec(i)) # collect error vector if self.ERR is None: error = 1.0 else: error = [] for i in range(len(self.x)): err = np.maximum(self.ERR[i][self.activeFreq] * 0.701, minErr) error.extend(err) # generate starting model by repetition model = pg.asvector(np.repeat(modVec, len(self.x))) INV = pg.RInversion(datvec, self.f2d, self.transData) INV.setAbsoluteError(error) INV.setLambda(lam) INV.setModel(model) INV.setReferenceModel(model) return INV
def qtblockmodelling(mydir, nlay, startvec=None, lowerbound=None, upperbound=None): """Loads data from dir, creates forward operator (old style) Parameters ---------- mydir : string directory to load the files (kernel, data) from nlay : int number of layers startvec : array starting vector lowerbound : tuple/list of 3 values lower bound for thickness, water content and relaxation time upperbound : tuple/list of 3 values upper bound for thickness, water content and relaxation time Returns ------- t : array time vector datvec : array data cube in a vector f : pygimli modelling class forward operator Examples -------- t,datvec,f = qtblockmodelling(mydir,nlay,startvec=(10,0.3,0.2), lowerbound=(0.1,0,0.02), upperbound(100.,0.45,,0.5)) """ KR, KI, zvec, t, datvec = loadmrsproject(mydir) if startvec is None: startvec = [10., 0.3, 0.2] if lowerbound is None: lowerbound = [0.1, 0.0, 0.02] if upperbound is None: upperbound = [100., 0.45, 0.5] # modelling operator f = MRS1dBlockQTModelling(nlay, KR, KI, zvec, t) # A[0]) f.region(0).setStartValue(startvec[0]) f.region(1).setStartValue(startvec[1]) f.region(2).setStartValue(startvec[2]) # Model transformations f.transTH = pg.RTransLogLU(lowerbound[0], upperbound[0]) f.transWC = pg.RTransLogLU(lowerbound[1], upperbound[1]) f.transT2 = pg.RTransLogLU(lowerbound[2], upperbound[2]) f.region(0).setTransModel(f.transTH) f.region(1).setTransModel(f.transWC) f.region(2).setTransModel(f.transT2) return t, datvec, f
def createInv(self, fop, verbose=True, dosave=False): """Create inversion instance.""" self.tD = pg.RTransLog() self.tM = pg.RTransLogLU() inv = pg.RInversion(verbose, dosave) inv.setTransData(self.tD) inv.setTransModel(self.tM) inv.setForwardOperator(fop) return inv
def createFOP(self, nlay, verbose=False): """creates forward operator for given number of layers""" self.nlay = nlay self.f = MRSVESBlockModelling(nlay, self.K, self.z, self.t, self.ab2, self.mn2, verbose) self.trans = [] # save in class to keep them alive for i in range(4): # thk, cw, T2*, res self.f.region(i).setStartValue(self.startval[i]) self.trans.append( pg.RTransLogLU(self.lowerBound[i], self.upperBound[i])) self.f.region(i).setTransModel(self.trans[-1])
def createInv(self, fop, verbose=True, doSave=False): """Create default inversion instance for Traveltime inversion. base api (typically done by run) """ self.tD = pg.RTrans() self.tM = pg.RTransLogLU() inv = pg.RInversion(verbose, doSave) inv.setTransData(self.tD) inv.setTransModel(self.tM) inv.setForwardOperator(fop) return inv
def __init__(self, fop, data, error, startmodel, lam=20, beta=10000, maxIter=50, fwmin=0, fwmax=1, fimin=0, fimax=1, famin=0, famax=1, frmin=0, frmax=1): LSQRInversion.__init__(self, data, fop, verbose=True, dosave=True) self._error = pg.RVector(error) # Set data transformations self.logtrans = pg.RTransLog() self.trans = pg.RTrans() self.dcumtrans = pg.RTransCumulative() self.dcumtrans.add(self.trans, self.forwardOperator().RST.dataContainer.size()) self.dcumtrans.add(self.logtrans, self.forwardOperator().ERT.data.size()) self.setTransData(self.dcumtrans) # Set model transformation n = self.forwardOperator().cellCount self.mcumtrans = pg.TransCumulative() self.transforms = [] phase_limits = [[fwmin, fwmax], [fimin, fimax], [famin, famax], [frmin, frmax]] for i, (lower, upper) in enumerate(phase_limits): if lower == 0: lower = 0.001 self.transforms.append(pg.RTransLogLU(lower, upper)) self.mcumtrans.add(self.transforms[i], n) self.setTransModel(self.mcumtrans) # Set error self.setRelativeError(self._error) # Set some defaults # Set maximum number of iterations (default is 20) self.setMaxIter(maxIter) # Regularization strength self.setLambda(lam) self.setDeltaPhiAbortPercent(0.25) fop = self.forwardOperator() fop.createConstraints() # Important! ones = pg.RVector(fop._I.rows(), 1.0) phiVec = pg.cat(ones, startmodel) self.setParameterConstraints(fop._G, phiVec, beta) self.setModel(startmodel)
mn2 = ab2 / 3. # MN/2 distance (potential electrodes) ############################################################################### # initialize the forward modelling operator f = pg.DC1dModelling(nlay, ab2, mn2) ############################################################################### # other ways are by specifying a Data Container or am/an/bm/bn distances synres = [100., 500., 20., 800.] # synthetic resistivity synthk = [0.5, 3.5, 6.] # synthetic thickness (nlay-th layer is infinite) ############################################################################### # the forward operator can be called by f.response(model) or simply f(model) rhoa = f(synthk + synres) rhoa = rhoa * (pg.randn(len(rhoa)) * errPerc / 100. + 1.) ############################################################################### # create some transformations used for inversion transThk = pg.RTransLog() # log-transform ensures thk>0 transRho = pg.RTransLogLU(1, 1000) # lower and upper bound transRhoa = pg.RTransLog() # log transformation for data ############################################################################### # set model transformation for thickness and resistivity f.region(0).setTransModel(transThk) # 0=thickness f.region(1).setTransModel(transRho) # 1=resistivity ############################################################################### # generate start model values from median app. resistivity & spread paraDepth = max(ab2) / 3. # rule-of-thumb for Wenner/Schlumberger f.region(0).setStartValue(paraDepth / nlay / 2) f.region(1).setStartValue(np.median(rhoa)) ############################################################################### # set up inversion inv = pg.RInversion(rhoa, f, transRhoa, True) # data vector, fop, verbose # could also be set by inv.setTransData(transRhoa) ###############################################################################
import pygimli as g import pylab as P from pygimli.utils.base import draw1dmodel nlay = 4 lam = 200. errPerc = 3. abmnr = g.RMatrix() g.loadMatrixCol(abmnr, "sond1-100.ves") ab2 = abmnr[0] mn2 = abmnr[1] rhoa = abmnr[2] transRho = g.RTransLogLU(1., 1000.) transThk = g.RTransLog() transRhoa = g.RTransLog() f = g.DC1dModelling(nlay, ab2, mn2) f.region(0).setTransModel(transThk) f.region(1).setTransModel(transRho) paraDepth = max(ab2) / 3 f.region(0).setStartValue(max(ab2) / 3. / nlay / 2.) f.region(1).setStartValue(P.median(rhoa)) model = f.createStartVector() model[nlay] *= 1.5 inv = g.RInversion(rhoa, f, True)
def main(): # read config file conf_file = "inv.conf" with open(conf_file, "r") as fd: conf = json.load(fd) # res = pb.Resistivity("input.dat") # res.invert() # np.savetxt('resistivity.vector', res.resistivity) # return # load data file data = pg.DataContainerERT("input.dat") # remove invalid data oldsize = data.size() data.removeInvalid() newsize = data.size() if newsize < oldsize: print('Removed ' + str(oldsize - newsize) + ' values.') if not data.allNonZero('rhoa'): print("No or partial rhoa values.") return # check, compute error if data.allNonZero('err'): error = data('err') else: print("estimate data error") error = conf["relativeError"] + conf["absoluteError"] / data('rhoa') # create FOP fop = pg.DCSRMultiElectrodeModelling(verbose=conf["verbose"]) fop.setThreadCount(psutil.cpu_count(logical=False)) fop.setData(data) # create Inv inv = pg.RInversion(verbose=conf["verbose"], dosave=False) # variables tD, tM are needed to prevent destruct objects tD = pg.RTransLog() tM = pg.RTransLogLU() inv.setTransData(tD) inv.setTransModel(tM) inv.setForwardOperator(fop) # mesh if conf["meshFile"] == "": depth = conf["depth"] if depth is None: depth = pg.DCParaDepth(data) poly = pg.meshtools.createParaMeshPLC( data.sensorPositions(), paraDepth=depth, paraDX=conf["paraDX"], paraMaxCellSize=conf["maxCellArea"], paraBoundary=2, boundary=2) if conf["verbose"]: print("creating mesh...") mesh = pg.meshtools.createMesh(poly, quality=conf["quality"], smooth=(1, 10)) else: mesh = pg.Mesh(pg.load(conf["meshFile"])) mesh.createNeighbourInfos() if conf["verbose"]: print(mesh) sys.stdout.flush() # flush before multithreading fop.setMesh(mesh) fop.regionManager().setConstraintType(1) if not conf["omitBackground"]: if fop.regionManager().regionCount() > 1: fop.regionManager().region(1).setBackground(True) if conf["meshFile"] == "": fop.createRefinedForwardMesh(True, False) else: fop.createRefinedForwardMesh(conf["refineMesh"], conf["refineP2"]) paraDomain = fop.regionManager().paraDomain() inv.setForwardOperator(fop) # necessary? # inversion parameters inv.setData(data('rhoa')) inv.setRelativeError(error) fop.regionManager().setZWeight(conf['zWeight']) inv.setLambda(conf['lam']) inv.setMaxIter(conf['maxIter']) inv.setRobustData(conf['robustData']) inv.setBlockyModel(conf['blockyModel']) inv.setRecalcJacobian(conf['recalcJacobian']) pc = fop.regionManager().parameterCount() startModel = pg.RVector(pc, pg.median(data('rhoa'))) inv.setModel(startModel) # Run the inversion sys.stdout.flush() # flush before multithreading model = inv.run() resistivity = model(paraDomain.cellMarkers()) np.savetxt('resistivity.vector', resistivity) print("Done.")
# Reflect the fix value setting here!!!! fop.createRefinedForwardMesh(refine=False, pRefine=False) # Connect all regions for i in range(2, fop.regionManager().regionCount()): for j in range(i + 1, fop.regionManager().regionCount()): fop.regionManager().setInterRegionConstraint(i, j, 1.0) startModel = pg.RVector(fop.regionManager().parameterCount(), 1e-3) fop.setStartModel(startModel) inv = pg.RInversion(rhoaR.flatten(), fop, verbose=1, dosave=0) tD = pg.RTransLog() tM = pg.RTransLogLU(1e-9, 1e-2) inv.setTransData(tD) inv.setTransModel(tM) inv.setRelativeError(err.flatten()) inv.setMaxIter(50) inv.setLineSearch(True) inv.setLambda(1000) outPath = "permModel_h-" + str(paraRefine) if not os.path.exists(outPath): os.mkdir(outPath) paraMesh.save(outPath + '/paraMesh') fop.mesh().save(outPath + "/fopMesh") fop.regionManager().paraDomain().save(outPath + '/paraDomain')
nf = 10 freq = pg.RVector(nf, 110.) for i in range(nf - 1): freq[i + 1] = freq[i] * 2. fEM = pg.FDEM1dModelling(nlay, freq, coilspacing) dataEM = fEM(model) for i in range(len(dataEM)): dataEM[i] += np.random.randn(1)[0] * noiseEM ############################################################################### # We define model transformations: logarithms and log with upper+lower bounds transRhoa = pg.RTransLog() transThk = pg.RTransLog() transRes = pg.RTransLogLU(1., 1000.) transEM = pg.RTrans() fEM.region(0).setTransModel(transThk) fEM.region(1).setTransModel(transRes) ############################################################################### # We set up the independent EM inversion and run the model. invEM = pg.RInversion(dataEM, fEM, transEM, verbose) modelEM = pg.RVector(nlay * 2 - 1, 50.) invEM.setModel(modelEM) invEM.setAbsoluteError(noiseEM) invEM.setLambda(lamEM) invEM.setMarquardtScheme(0.9) modelEM = invEM.run() respEM = invEM.response()
def invBlock(self, xpos=0, nlay=2, noise=1.0, stmod=30., lam=100., lBound=0., uBound=0., verbose=False): """Create and return Gimli inversion instance for block inversion. Parameters ---------- xpos : array position vector nLay : int Number of layers of the model to be determined OR vector of layer numbers OR forward operator noise : float Absolute data err in percent stmod : float or pg.RVector Starting model lam : float Global regularization parameter lambda. lBound : float Lower boundary for the model uBound : float Upper boundary for the model. 0 means no upper booundary verbose : bool Be verbose """ self.transThk = pg.RTransLog() self.transRes = pg.RTransLogLU(lBound, uBound) self.transData = pg.RTrans() # EM forward operator if isinstance(nlay, pg.FDEM1dModelling): self.fop = nlay else: self.fop = self.FOP(nlay) data = self.datavec(xpos) self.fop.region(0).setTransModel(self.transThk) self.fop.region(1).setTransModel(self.transRes) if isinstance(noise, float): noiseVec = pg.RVector(len(data), noise) else: noiseVec = pg.asvector(noise) # independent EM inversion self.inv = pg.RInversion(data, self.fop, self.transData, verbose) if isinstance(stmod, float): # real model given model = pg.RVector(nlay * 2 - 1, stmod) model[0] = 2. else: if len(stmod) == nlay * 2 - 1: model = pg.asvector(stmod) else: model = pg.RVector(nlay * 2 - 1, 30.) self.inv.setAbsoluteError(noiseVec) self.inv.setLambda(lam) self.inv.setMarquardtScheme(0.8) self.inv.setDeltaPhiAbortPercent(0.5) self.inv.setModel(model) self.inv.setReferenceModel(model) return self.inv