def genMesh(self, h=0.0, cs=3.0, ncx=15, ncz=30, npad=20): """ Generate cylindrically symmetric mesh """ # TODO: Make it adaptive due to z location hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] self.mesh = CylMesh([hx, 1, hz], "00C")
def make_example_mesh(): ncr = 20 # number of mesh cells in r ncz = 20 # number of mesh cells in z dh = 5. # cell width hr = [(dh, ncr), (dh, 5, 1.3)] hz = [(dh, 5, -1.3), (dh, ncz), (dh, 5, 1.3)] # Use flag of 1 to denote perfect rotational symmetry mesh = CylMesh([hr, 1, hz], '0CC') return mesh
def setupMesh(self, nc): """ For a given number of cells nc, generate a TensorMesh with uniform cells with edge length h=1/nc. """ if 'TensorMesh' in self._meshType: if 'uniform' in self._meshType: h = [nc, nc, nc] elif 'random' in self._meshType: h1 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h2 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h3 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h = [hi / np.sum(hi) for hi in [h1, h2, h3]] # normalize else: raise Exception('Unexpected meshType') self.M = TensorMesh(h[:self.meshDimension]) max_h = max([np.max(hi) for hi in self.M.h]) return max_h elif 'CylMesh' in self._meshType: if 'uniform' in self._meshType: h = [nc, nc, nc] else: raise Exception('Unexpected meshType') if self.meshDimension == 2: self.M = CylMesh([h[0], 1, h[2]]) max_h = max([np.max(hi) for hi in [self.M.hx, self.M.hz]]) elif self.meshDimension == 3: self.M = CylMesh(h) max_h = max([np.max(hi) for hi in self.M.h]) return max_h elif 'Curv' in self._meshType: if 'uniform' in self._meshType: kwrd = 'rect' elif 'rotate' in self._meshType: kwrd = 'rotate' else: raise Exception('Unexpected meshType') if self.meshDimension == 1: raise Exception('Lom not supported for 1D') elif self.meshDimension == 2: X, Y = Utils.exampleLrmGrid([nc, nc], kwrd) self.M = CurvilinearMesh([X, Y]) elif self.meshDimension == 3: X, Y, Z = Utils.exampleLrmGrid([nc, nc, nc], kwrd) self.M = CurvilinearMesh([X, Y, Z]) return 1. / nc elif 'Tree' in self._meshType: nc *= 2 if 'uniform' in self._meshType or 'notatree' in self._meshType: h = [nc, nc, nc] elif 'random' in self._meshType: h1 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h2 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h3 = np.random.rand(nc) * nc * 0.5 + nc * 0.5 h = [hi / np.sum(hi) for hi in [h1, h2, h3]] # normalize else: raise Exception('Unexpected meshType') levels = int(np.log(nc) / np.log(2)) self.M = Tree(h[:self.meshDimension], levels=levels) def function(cell): if 'notatree' in self._meshType: return levels - 1 r = cell.center - np.array([0.5] * len(cell.center)) dist = np.sqrt(r.dot(r)) if dist < 0.2: return levels return levels - 1 self.M.refine(function, balance=False) self.M.number(balance=False) # self.M.plotGrid(showIt=True) max_h = max([np.max(hi) for hi in self.M.h]) return max_h
class HarmonicVMDCylWidget(object): """FDEMCylWidgete""" survey = None srcList = None mesh = None f = None activeCC = None srcLoc = None mesh2D = None mu = None def __init__(self): self.genMesh() self.getCoreDomain() # url = "http://em.geosci.xyz/_images/disc_dipole.png" # response = requests.get(url) # self.im = Image.open(StringIO(response.content)) def mirrorArray(self, x, direction="x"): X = x.reshape((self.nx_core, self.ny_core), order="F") if direction == "x" or direction == "y": X2 = np.vstack((-np.flipud(X), X)) else: X2 = np.vstack((np.flipud(X), X)) return X2 def genMesh(self, h=0.0, cs=3.0, ncx=15, ncz=30, npad=20): """ Generate cylindrically symmetric mesh """ # TODO: Make it adaptive due to z location hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] self.mesh = CylMesh([hx, 1, hz], "00C") def getCoreDomain(self, mirror=False, xmax=100, zmin=-100, zmax=100.0): self.activeCC = (self.mesh.gridCC[:, 0] <= xmax) & (np.logical_and( self.mesh.gridCC[:, 2] >= zmin, self.mesh.gridCC[:, 2] <= zmax)) self.gridCCactive = self.mesh.gridCC[self.activeCC, :][:, [0, 2]] xind = self.mesh.vectorCCx <= xmax yind = np.logical_and(self.mesh.vectorCCz >= zmin, self.mesh.vectorCCz <= zmax) self.nx_core = xind.sum() self.ny_core = yind.sum() # if self.mesh2D is None: hx = np.r_[self.mesh.hx[xind][::-1], self.mesh.hx[xind]] hz = self.mesh.hz[yind] self.mesh2D = TensorMesh([hx, hz], x0="CC") def getCoreModel(self, Type): if Type == "Layer": active = self.mesh2D.vectorCCy < self.z0 ind1 = (self.mesh2D.vectorCCy < self.z0) & (self.mesh2D.vectorCCy >= self.z1) ind2 = (self.mesh2D.vectorCCy < self.z1) & (self.mesh2D.vectorCCy >= self.z2) mapping2D = maps.SurjectVertical1D( self.mesh2D) * maps.InjectActiveCells( self.mesh2D, active, self.sig0, nC=self.mesh2D.nCy) model2D = np.ones(self.mesh2D.nCy) * self.sig3 model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] elif Type == "Sphere": active = self.mesh2D.gridCC[:, 1] < self.z0 ind1 = (self.mesh2D.gridCC[:, 1] < self.z1) & (self.mesh2D.gridCC[:, 1] >= self.z1 - self.h) ind2 = (np.sqrt((self.mesh2D.gridCC[:, 0])**2 + (self.mesh2D.gridCC[:, 1] - self.z2)**2) <= self.R) mapping2D = maps.InjectActiveCells(self.mesh2D, active, self.sig0, nC=self.mesh2D.nC) model2D = np.ones(self.mesh2D.nC) * self.sigb model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] return model2D, mapping2D def getBiotSavrt(self, rxLoc): """ Compute Biot-Savart operator: Gz and Gx """ self.Gz = BiotSavartFun(self.mesh, rxLoc, component="z") self.Gx = BiotSavartFun(self.mesh, rxLoc, component="x") def setThreeLayerParam(self, h1=12, h2=12, sig0=1e-8, sig1=1e-1, sig2=1e-2, sig3=1e-2, chi=0.0): self.h1 = h1 # 1st layer thickness self.h2 = h2 # 2nd layer thickness self.z0 = 0.0 self.z1 = self.z0 - h1 self.z2 = self.z0 - h1 - h2 self.sig0 = sig0 # 0th layer \sigma (assumed to be air) self.sig1 = sig1 # 1st layer \sigma self.sig2 = sig2 # 2nd layer \sigma self.sig3 = sig3 # 3rd layer \sigma active = self.mesh.vectorCCz < self.z0 ind1 = (self.mesh.vectorCCz < self.z0) & (self.mesh.vectorCCz >= self.z1) ind2 = (self.mesh.vectorCCz < self.z1) & (self.mesh.vectorCCz >= self.z2) self.mapping = maps.SurjectVertical1D( self.mesh) * maps.InjectActiveCells( self.mesh, active, sig0, nC=self.mesh.nCz) model = np.ones(self.mesh.nCz) * sig3 model[ind1] = sig1 model[ind2] = sig2 self.m = model[active] self.mu = np.ones(self.mesh.nC) * mu_0 self.mu[self.mesh.gridCC[:, 2] < 0.0] = (1.0 + chi) * mu_0 return self.m def setLayerSphereParam(self, d1=6, h=6, d2=16, R=4, sig0=1e-8, sigb=1e-2, sig1=1e-1, sig2=1.0, chi=0.0): self.z0 = 0.0 # Surface elevation self.z1 = self.z0 - d1 # Depth to layer self.h = h # Thickness of layer self.z2 = self.z0 - d2 # Depth to center of sphere self.R = R # Radius of sphere self.sig0 = sig0 # Air conductivity self.sigb = sigb # Background conductivity self.sig1 = sig1 # Layer conductivity self.sig2 = sig2 # Sphere conductivity active = self.mesh.gridCC[:, 2] < self.z0 ind1 = (self.mesh.gridCC[:, 2] < self.z1) & (self.mesh.gridCC[:, 2] >= self.z1 - self.h) ind2 = (np.sqrt((self.mesh.gridCC[:, 0])**2 + (self.mesh.gridCC[:, 2] - self.z2)**2) <= self.R) self.mapping = maps.InjectActiveCells(self.mesh, active, sig0, nC=self.mesh.nC) model = np.ones(self.mesh.nC) * sigb model[ind1] = sig1 model[ind2] = sig2 self.m = model[active] self.mu = np.ones(self.mesh.nC) * mu_0 self.mu[self.mesh.gridCC[:, 2] < 0.0] = (1.0 + chi) * mu_0 return self.m def simulate(self, srcLoc, rxLoc, freqs): bzr = fdem.receivers.PointMagneticFluxDensitySecondary( rxLoc, orientation="z", component="real") bzi = fdem.receivers.PointMagneticFluxDensitySecondary( rxLoc, orientation="z", component="imag") self.srcList = [ fdem.sources.MagDipole([bzr, bzi], frequency=freq, location=srcLoc, orientation="Z") for freq in freqs ] survey = fdem.survey.Survey(self.srcList) sim = fdem.Simulation3DMagneticFluxDensity(self.mesh, survey=survey, sigmaMap=self.mapping, mu=self.mu, solver=Pardiso) self.f = sim.fields(self.m) self.sim = sim dpred = sim.dpred(self.m, f=self.f) self.srcLoc = srcLoc self.rxLoc = rxLoc return dpred def getFields(self, bType="b", ifreq=0): src = self.srcList[ifreq] Pfx = self.mesh.getInterpolationMat(self.mesh.gridCC[self.activeCC, :], locType="Fx") Pfz = self.mesh.getInterpolationMat(self.mesh.gridCC[self.activeCC, :], locType="Fz") Ey = self.mesh.aveE2CC * self.f[src, "e"] Jy = utils.sdiag(self.sim.sigma) * Ey self.Ey = utils.mkvc(self.mirrorArray(Ey[self.activeCC], direction="y")) self.Jy = utils.mkvc(self.mirrorArray(Jy[self.activeCC], direction="y")) self.Bx = utils.mkvc( self.mirrorArray(Pfx * self.f[src, bType], direction="x")) self.Bz = utils.mkvc( self.mirrorArray(Pfz * self.f[src, bType], direction="z")) def getData(self, bType="b"): Pfx = self.mesh.getInterpolationMat(self.rxLoc, locType="Fx") Pfz = self.mesh.getInterpolationMat(self.rxLoc, locType="Fz") Pey = self.mesh.getInterpolationMat(self.rxLoc, locType="Ey") self.Ey = (Pey * self.f[:, "e"]).flatten() self.Bx = (Pfx * self.f[:, bType]).flatten() self.Bz = (Pfz * self.f[:, bType]).flatten() def plotField( self, Field="B", ComplexNumber="real", view="vec", scale="linear", Frequency=100, Geometry=True, Scenario=None, ): # Printout for null cases if (Field == "B") & (view == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (view == "x") | (Field == "E") & (view == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) elif (Field == "J") & (view == "x") | (Field == "J") & (view == "z"): print( "Think about the problem geometry. There is NO Jx or Jz in this case. Only Jy." ) elif (Field == "E") & (view == "vec"): print( "Think about the problem geometry. E only has components along y. Vector plot not possible" ) elif (Field == "J") & (view == "vec"): print( "Think about the problem geometry. J only has components along y. Vector plot not possible" ) elif (view == "vec") & (ComplexNumber == "Amp") | (view == "vec") & ( ComplexNumber == "Phase"): print( "Cannot show amplitude or phase when vector plot selected. Set 'AmpDir=None' to see amplitude or phase." ) elif Field == "Model": plt.figure(figsize=(7, 6)) ax = plt.subplot(111) if Scenario == "Sphere": model2D, mapping2D = self.getCoreModel("Sphere") elif Scenario == "Layer": model2D, mapping2D = self.getCoreModel("Layer") out = self.mesh2D.plotImage(np.log10(mapping2D * model2D), ax=ax) cb = plt.colorbar(out[0], ax=ax, format="$10^{%.1f}$") cb.set_label("$\sigma$ (S/m)") ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") ax.set_title("Conductivity Model") plt.show() else: plt.figure(figsize=(10, 6)) ax = plt.subplot(111) vec = False if view == "vec": tname = "Vector " title = tname + Field + "-field" elif view == "amp": tname = "|" title = tname + Field + "|-field" else: if ComplexNumber == "real": tname = "Re(" elif ComplexNumber == "imag": tname = "Im(" elif ComplexNumber == "amplitude": tname = "Amp(" elif ComplexNumber == "phase": tname = "Phase(" title = tname + Field + view + ")-field" if Field == "B": label = "Magnetic field (T)" if view == "vec": vec = True if ComplexNumber == "real": val = np.c_[self.Bx.real, self.Bz.real] elif ComplexNumber == "imag": val = np.c_[self.Bx.imag, self.Bz.imag] else: return elif view == "x": if ComplexNumber == "real": val = self.Bx.real elif ComplexNumber == "imag": val = self.Bx.imag elif ComplexNumber == "amplitude": val = abs(self.Bx) elif ComplexNumber == "phase": val = np.angle(self.Bx) elif view == "z": if ComplexNumber == "real": val = self.Bz.real elif ComplexNumber == "imag": val = self.Bz.imag elif ComplexNumber == "amplitude": val = abs(self.Bz) elif ComplexNumber == "phase": val = np.angle(self.Bz) else: return elif Field == "E": label = "Electric field (V/m)" if view == "y": if ComplexNumber == "real": val = self.Ey.real elif ComplexNumber == "imag": val = self.Ey.imag elif ComplexNumber == "amplitude": val = abs(self.Ey) elif ComplexNumber == "phase": val = np.angle(self.Ey) else: return elif Field == "J": label = "Current density (A/m$^2$)" if view == "y": if ComplexNumber == "real": val = self.Jy.real elif ComplexNumber == "imag": val = self.Jy.imag elif ComplexNumber == "amplitude": val = abs(self.Jy) elif ComplexNumber == "phase": val = np.angle(self.Jy) else: return out = utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={"cmap": "viridis"}, ncontour=200, scale=scale, ) cb = plt.colorbar(out[0], ax=ax, format="%.2e") cb.set_label(label) xmax = self.mesh2D.gridCC[:, 0].max() if Geometry: if Scenario == "Layer": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "w-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z2, "w--", lw=1) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) elif Scenario == "Sphere": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "k-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * (self.z1 - self.h), "w--", lw=1) Phi = np.linspace(0, 2 * np.pi, 41) ax.plot( self.R * np.cos(Phi), self.z2 + self.R * np.sin(Phi), "w--", lw=1, ) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") title = title + "\nf = " + "{:.2e}".format(Frequency) + " Hz" ax.set_title(title) plt.show() ###################################################### # LAYER WIDGET ###################################################### def InteractivePlane_Layer(self, scale="log", fieldvalue="B", compvalue="z"): def foo( Field, AmpDir, Component, ComplexNumber, Sigma0, Sigma1, Sigma2, Sigma3, Sus, h1, h2, Scale, rxOffset, z, ifreq, Geometry=True, ): Frequency = 10**((ifreq - 1.0) / 3.0 - 2.0) if ComplexNumber == "Re": ComplexNumber = "real" elif ComplexNumber == "Im": ComplexNumber = "imag" elif ComplexNumber == "Amp": ComplexNumber = "amplitude" elif ComplexNumber == "Phase": ComplexNumber = "phase" if AmpDir == "Direction (B or Bsec)": # ComplexNumber = "real" Component = "vec" if Field == "Bsec": bType = "bSecondary" Field = "B" else: bType = "b" self.setThreeLayerParam( h1=h1, h2=h2, sig0=Sigma0, sig1=Sigma1, sig2=Sigma2, sig3=Sigma3, chi=Sus, ) srcLoc = np.array([0.0, 0.0, z]) rxLoc = np.array([[rxOffset, 0.0, z]]) self.simulate(srcLoc, rxLoc, np.r_[Frequency]) if Field != "Model": self.getFields(bType=bType) return self.plotField( Field=Field, ComplexNumber=ComplexNumber, view=Component, scale=Scale, Frequency=Frequency, Geometry=Geometry, Scenario="Layer", ) out = widgetify( foo, Field=widgets.ToggleButtons( options=["E", "B", "Bsec", "J", "Model"], value="E"), AmpDir=widgets.ToggleButtons( options=["None", "Direction (B or Bsec)"], value="None"), Component=widgets.ToggleButtons(options=["x", "y", "z"], value="y", description="Comp."), ComplexNumber=widgets.ToggleButtons( options=["Re", "Im", "Amp", "Phase"], value="Re", description="Re/Im"), Sigma0=widgets.FloatText(value=1e-8, continuous_update=False, description="$\sigma_0$ (S/m)"), Sigma1=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_1$ (S/m)"), Sigma2=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_2$ (S/m)"), Sigma3=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_3$ (S/m)"), Sus=widgets.FloatText(value=0.0, continuous_update=False, description="$\chi$"), h1=widgets.FloatSlider( min=2.0, max=40.0, step=2.0, value=10.0, continuous_update=False, description="$h_1$ (m)", ), h2=widgets.FloatSlider( min=2.0, max=40.0, step=2.0, value=10.0, continuous_update=False, description="$h_2$ (m)", ), Scale=widgets.ToggleButtons(options=["log", "linear"], value="linear"), rxOffset=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=10.0, continuous_update=False, description="$\Delta x$(m)", ), z=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$\Delta z$ (m)", ), ifreq=widgets.IntSlider( min=1, max=31, step=1, value=16, continuous_update=False, description="f index", ), ) return out def InteractiveData_Layer(self, fieldvalue="B", compvalue="z", z=0.0): frequency = np.logspace(2, 5, 31) self.simulate(self.srcLoc, self.rxLoc, frequency) def foo(Field, Component, Scale): # Printout for null cases if (Field == "B") & (Component == "y") | (Field == "Bsec") & ( Component == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (Component == "x") | (Field == "E") & ( Component == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) else: plt.figure() ax = plt.subplot(111) bType = "b" if (Field == "Bsec") or (Field == "B"): if Field == "Bsec": bType = "bSecondary" Field = "B" self.getData(bType=bType) label = "Magnetic field (T)" if Component == "x": title = "Bx" valr = self.Bx.real vali = self.Bx.imag elif Component == "z": title = "Bz" valr = self.Bz.real vali = self.Bz.imag else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) print( "Think about the problem geometry. There is NO By in this case." ) elif Field == "E": self.getData(bType=bType) label = "Electric field (V/m)" title = "Ey" if Component == "y": valr = self.Ey.real vali = self.Ey.imag else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) print( "Think about the problem geometry. There is NO Ex or Ez in this case." ) elif Field == "J": print( "The conductivity at the location is 0. Therefore there is no electrical current here." ) if Scale == "log": valr_p, valr_n = DisPosNegvalues(valr) vali_p, vali_n = DisPosNegvalues(vali) ax.plot(frequency, valr_p, "k-") ax.plot(frequency, valr_n, "k--") ax.plot(frequency, vali_p, "r-") ax.plot(frequency, vali_n, "r--") ax.legend(("Re (+)", "Re (-)", "Im (+)", "Im (-)"), loc=4, fontsize=10) else: ax.plot(frequency, valr, "k.-") ax.plot(frequency, vali, "r.-") ax.legend(("Re", "Im"), loc=4, fontsize=10) ax.set_xscale("log") ax.set_yscale(Scale) ax.set_xlabel("Frequency (Hz)") ax.set_ylabel(label) ax.set_title(title) ax.grid(True) plt.show() out = widgetify( foo, Field=widgets.ToggleButtons(options=["E", "B", "Bsec"], value=fieldvalue), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Scale=widgets.ToggleButtons(options=["log", "linear"], value="log"), ) return out ###################################################### # SPHERE WIDGET ###################################################### def InteractivePlane_Sphere(self, scale="log", fieldvalue="B", compvalue="z"): def foo( Field, AmpDir, Component, ComplexNumber, Sigma0, Sigmab, Sigma1, Sigma2, Sus, d1, h, d2, R, Scale, rxOffset, z, ifreq, Geometry=True, ): Frequency = 10**((ifreq - 1.0) / 3.0 - 2.0) if ComplexNumber == "Re": ComplexNumber = "real" elif ComplexNumber == "Im": ComplexNumber = "imag" elif ComplexNumber == "Amp": ComplexNumber = "amplitude" elif ComplexNumber == "Phase": ComplexNumber = "phase" if AmpDir == "Direction (B or Bsec)": # ComplexNumber = "real" Component = "vec" if Field == "Bsec": bType = "bSecondary" Field = "B" else: bType = "b" self.setLayerSphereParam( d1=d1, h=h, d2=d2, R=R, sig0=Sigma0, sigb=Sigmab, sig1=Sigma1, sig2=Sigma2, chi=Sus, ) srcLoc = np.array([0.0, 0.0, z]) rxLoc = np.array([[rxOffset, 0.0, z]]) self.simulate(srcLoc, rxLoc, np.r_[Frequency]) if Field != "Model": self.getFields(bType=bType) return self.plotField( Field=Field, ComplexNumber=ComplexNumber, Frequency=Frequency, view=Component, scale=Scale, Geometry=Geometry, Scenario="Sphere", ) out = widgetify( foo, Field=widgets.ToggleButtons( options=["E", "B", "Bsec", "J", "Model"], value="E"), AmpDir=widgets.ToggleButtons( options=["None", "Direction (B or Bsec)"], value="None"), Component=widgets.ToggleButtons(options=["x", "y", "z"], value="y", description="Comp."), ComplexNumber=widgets.ToggleButtons( options=["Re", "Im", "Amp", "Phase"], value="Re", description="Re/Im"), Sigma0=widgets.FloatText(value=1e-8, continuous_update=False, description="$\sigma_0$ (S/m)"), Sigmab=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_b$ (S/m)"), Sigma1=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_1$ (S/m)"), Sigma2=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_2$ (S/m)"), Sus=widgets.FloatText(value=0.0, continuous_update=False, description="$\chi$"), d1=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$d_1$ (m)", ), h=widgets.FloatSlider( min=2.0, max=20.0, step=2.0, value=10.0, continuous_update=False, description="$h$ (m)", ), d2=widgets.FloatSlider( min=10.0, max=50.0, step=2.0, value=30.0, continuous_update=False, description="$d_2$ (m)", ), R=widgets.FloatSlider( min=2.0, max=20.0, step=2.0, value=10.0, continuous_update=False, description="$R$ (m)", ), Scale=widgets.ToggleButtons(options=["log", "linear"], value="linear"), rxOffset=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=10.0, continuous_update=False, description="$\Delta x$(m)", ), z=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$\Delta z$ (m)", ), ifreq=widgets.IntSlider( min=1, max=31, step=1, value=16, continuous_update=False, description="f index", ), ) return out def InteractiveData_Sphere(self, fieldvalue="B", compvalue="z", z=0.0): frequency = np.logspace(2, 5, 31) self.simulate(self.srcLoc, self.rxLoc, frequency) def foo(Field, Component, Scale): # Printout for null cases if (Field == "B") & (Component == "y") | (Field == "Bsec") & ( Component == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (Component == "x") | (Field == "E") & ( Component == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) else: plt.figure() ax = plt.subplot(111) bType = "b" if (Field == "Bsec") or (Field == "B"): if Field == "Bsec": bType = "bSecondary" Field = "B" self.getData(bType=bType) label = "Magnetic field (T)" if Component == "x": title = "Bx" valr = self.Bx.real vali = self.Bx.imag elif Component == "z": title = "Bz" valr = self.Bz.real vali = self.Bz.imag else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) print( "Think about the problem geometry. There is NO By in this case." ) elif Field == "E": self.getData(bType=bType) label = "Electric field (V/m)" title = "Ey" if Component == "y": valr = self.Ey.real vali = self.Ey.imag else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) print( "Think about the problem geometry. There is NO Ex or Ez in this case." ) elif Field == "J": print( "The conductivity at the location is 0. Therefore there is no electrical current here." ) if Scale == "log": valr_p, valr_n = DisPosNegvalues(valr) vali_p, vali_n = DisPosNegvalues(vali) ax.plot(frequency, valr_p, "k-") ax.plot(frequency, valr_n, "k--") ax.plot(frequency, vali_p, "r-") ax.plot(frequency, vali_n, "r--") ax.legend(("Re (+)", "Re (-)", "Im (+)", "Im (-)"), loc=4, fontsize=10) else: ax.plot(frequency, valr, "k.-") ax.plot(frequency, vali, "r.-") ax.legend(("Re", "Im"), loc=4, fontsize=10) ax.set_xscale("log") ax.set_yscale(Scale) ax.set_xlabel("Frequency (Hz)") ax.set_ylabel(label) ax.set_title(title) ax.grid(True) plt.show() out = widgetify( foo, Field=widgets.ToggleButtons(options=["E", "B", "Bsec"], value=fieldvalue), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Scale=widgets.ToggleButtons(options=["log", "linear"], value="log"), ) return out
tdem_source_list.append( tdem.sources.MagDipole( tdem_receivers_list, location=source_locations[ii], waveform=tdem_waveform, moment=1.0, orientation="z", ) ) tdem_survey = tdem.Survey(tdem_source_list) # Define cylindrical mesh hr = [(10.0, 50), (10.0, 10, 1.5)] hz = [(10.0, 10, -1.5), (10.0, 100), (10.0, 10, 1.5)] mesh = CylMesh([hr, 1, hz], x0="00C") # Define model air_conductivity = 1e-8 background_conductivity = 1e-1 layer_conductivity = 1e-2 pipe_conductivity = 1e1 ind_active = mesh.gridCC[:, 2] < 0 model_map = maps.InjectActiveCells(mesh, ind_active, air_conductivity) conductivity_model = background_conductivity * np.ones(ind_active.sum()) ind_layer = (mesh.gridCC[ind_active, 2] > -200.0) & (mesh.gridCC[ind_active, 2] < -0) conductivity_model[ind_layer] = layer_conductivity ind_pipe = ( (mesh.gridCC[ind_active, 0] < 50.0)
class TDEMHorizontalLoopCylWidget(object): """TDEMCylWidgete""" survey = None srcList = None mesh = None f = None activeCC = None srcLoc = None mesh2D = None mu = None counter = 0 def __init__(self): self.genMesh() self.getCoreDomain() # url = "http://em.geosci.xyz/_images/disc_dipole.png" # response = requests.get(url) # self.im = Image.open(StringIO(response.content)) self.time = np.logspace(-5, -2, 41) def mirrorArray(self, x, direction="x"): X = x.reshape((self.nx_core, self.ny_core), order="F") if direction == "x" or direction == "y": X2 = np.vstack((-np.flipud(X), X)) else: X2 = np.vstack((np.flipud(X), X)) return X2 def genMesh(self, h=0.0, cs=3.0, ncx=15, ncz=30, npad=20): """ Generate cylindrically symmetric mesh """ # TODO: Make it adaptive due to z location hx = [(cs, ncx), (cs, npad, 1.3)] hz = [(cs, npad, -1.3), (cs, ncz), (cs, npad, 1.3)] self.mesh = CylMesh([hx, 1, hz], "00C") def getCoreDomain(self, mirror=False, xmax=200, zmin=-200, zmax=200.0): self.activeCC = (self.mesh.gridCC[:, 0] <= xmax) & (np.logical_and( self.mesh.gridCC[:, 2] >= zmin, self.mesh.gridCC[:, 2] <= zmax)) self.gridCCactive = self.mesh.gridCC[self.activeCC, :][:, [0, 2]] xind = self.mesh.vectorCCx <= xmax yind = np.logical_and(self.mesh.vectorCCz >= zmin, self.mesh.vectorCCz <= zmax) self.nx_core = xind.sum() self.ny_core = yind.sum() # if self.mesh2D is None: hx = np.r_[self.mesh.hx[xind][::-1], self.mesh.hx[xind]] hz = self.mesh.hz[yind] self.mesh2D = TensorMesh([hx, hz], x0="CC") def getCoreModel(self, Type): if Type == "Layer": active = self.mesh2D.vectorCCy < self.z0 ind1 = (self.mesh2D.vectorCCy < self.z0) & (self.mesh2D.vectorCCy >= self.z1) ind2 = (self.mesh2D.vectorCCy < self.z1) & (self.mesh2D.vectorCCy >= self.z2) mapping2D = maps.SurjectVertical1D( self.mesh2D) * maps.InjectActiveCells( self.mesh2D, active, self.sig0, nC=self.mesh2D.nCy) model2D = np.ones(self.mesh2D.nCy) * self.sig3 model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] elif Type == "Sphere": active = self.mesh2D.gridCC[:, 1] < self.z0 ind1 = (self.mesh2D.gridCC[:, 1] < self.z1) & (self.mesh2D.gridCC[:, 1] >= self.z1 - self.h) ind2 = (np.sqrt((self.mesh2D.gridCC[:, 0])**2 + (self.mesh2D.gridCC[:, 1] - self.z2)**2) <= self.R) mapping2D = maps.InjectActiveCells(self.mesh2D, active, self.sig0, nC=self.mesh2D.nC) model2D = np.ones(self.mesh2D.nC) * self.sigb model2D[ind1] = self.sig1 model2D[ind2] = self.sig2 model2D = model2D[active] return model2D, mapping2D def getBiotSavrt(self, rxLoc): """ Compute Biot-Savart operator: Gz and Gx """ self.Gz = BiotSavartFun(self.mesh, rxLoc, component="z") self.Gx = BiotSavartFun(self.mesh, rxLoc, component="x") def setThreeLayerParam(self, h1=12, h2=12, sig0=1e-8, sig1=1e-2, sig2=1e-2, sig3=1e-2, chi=0.0): self.h1 = h1 # 1st layer thickness self.h2 = h2 # 2nd layer thickness self.z0 = 0.0 self.z1 = self.z0 - h1 self.z2 = self.z0 - h1 - h2 self.sig0 = sig0 # 0th layer \sigma (assumed to be air) self.sig1 = sig1 # 1st layer \sigma self.sig2 = sig2 # 2nd layer \sigma self.sig3 = sig3 # 3rd layer \sigma active = self.mesh.vectorCCz < self.z0 ind1 = (self.mesh.vectorCCz < self.z0) & (self.mesh.vectorCCz >= self.z1) ind2 = (self.mesh.vectorCCz < self.z1) & (self.mesh.vectorCCz >= self.z2) self.mapping = maps.SurjectVertical1D( self.mesh) * maps.InjectActiveCells( self.mesh, active, sig0, nC=self.mesh.nCz) model = np.ones(self.mesh.nCz) * sig3 model[ind1] = sig1 model[ind2] = sig2 self.m = model[active] self.mu = np.ones(self.mesh.nC) * mu_0 self.mu[self.mesh.gridCC[:, 2] < 0.0] = (1.0 + chi) * mu_0 return self.m def setLayerSphereParam(self, d1=6, h=6, d2=16, R=4, sig0=1e-8, sigb=1e-2, sig1=1e-1, sig2=1.0, chi=0.0): self.z0 = 0.0 # Surface elevation self.z1 = self.z0 - d1 # Depth to layer self.h = h # Thickness of layer self.z2 = self.z0 - d2 # Depth to center of sphere self.R = R # Radius of sphere self.sig0 = sig0 # Air conductivity self.sigb = sigb # Background conductivity self.sig1 = sig1 # Layer conductivity self.sig2 = sig2 # Sphere conductivity active = self.mesh.gridCC[:, 2] < self.z0 ind1 = (self.mesh.gridCC[:, 2] < self.z1) & (self.mesh.gridCC[:, 2] >= self.z1 - self.h) ind2 = (np.sqrt((self.mesh.gridCC[:, 0])**2 + (self.mesh.gridCC[:, 2] - self.z2)**2) <= self.R) self.mapping = maps.InjectActiveCells(self.mesh, active, sig0, nC=self.mesh.nC) model = np.ones(self.mesh.nC) * sigb model[ind1] = sig1 model[ind2] = sig2 self.m = model[active] self.mu = np.ones(self.mesh.nC) * mu_0 self.mu[self.mesh.gridCC[:, 2] < 0.0] = (1.0 + chi) * mu_0 return self.m def simulate(self, srcLoc, rxLoc, time, radius=1.0): bz = tdem.receivers.PointMagneticFluxDensity(rxLoc, time, orientation="z") # dbzdt = EM.TDEM.Rx.Point_dbdt(rxLoc, time, orientation="z") src = tdem.sources.CircularLoop( [bz], waveform=tdem.sources.StepOffWaveform(), location=srcLoc, radius=radius) self.srcList = [src] survey = tdem.survey.Survey(self.srcList) sim = tdem.Simulation3DMagneticFluxDensity(self.mesh, survey=survey, sigmaMap=self.mapping) sim.time_steps = [ (1e-06, 10), (5e-06, 10), (1e-05, 10), (5e-5, 10), (1e-4, 10), (5e-4, 10), (1e-3, 10), ] self.f = sim.fields(self.m) self.sim = sim dpred = sim.dpred(self.m, f=self.f) return dpred @property def Pfx(self): if getattr(self, "_Pfx", None) is None: self._Pfx = self.mesh.getInterpolationMat( self.mesh.gridCC[self.activeCC, :], locType="Fx") return self._Pfx @property def Pfz(self): if getattr(self, "_Pfz", None) is None: self._Pfz = self.mesh.getInterpolationMat( self.mesh.gridCC[self.activeCC, :], locType="Fz") return self._Pfz def getFields(self, itime): src = self.srcList[0] Ey = self.mesh.aveE2CC * self.f[src, "e", itime] Jy = utils.sdiag(self.sim.sigma) * Ey self.Ey = utils.mkvc(self.mirrorArray(Ey[self.activeCC], direction="y")) self.Jy = utils.mkvc(self.mirrorArray(Jy[self.activeCC], direction="y")) self.Bx = utils.mkvc( self.mirrorArray(self.Pfx * self.f[src, "b", itime], direction="x")) self.Bz = utils.mkvc( self.mirrorArray(self.Pfz * self.f[src, "b", itime], direction="z")) self.dBxdt = utils.mkvc( self.mirrorArray(-self.Pfx * self.mesh.edgeCurl * self.f[src, "e", itime], direction="x")) self.dBzdt = utils.mkvc( self.mirrorArray(-self.Pfz * self.mesh.edgeCurl * self.f[src, "e", itime], direction="z")) def getData(self): src = self.srcList[0] Pfx = self.mesh.getInterpolationMat(self.rxLoc, locType="Fx") Pfz = self.mesh.getInterpolationMat(self.rxLoc, locType="Fz") Pey = self.mesh.getInterpolationMat(self.rxLoc, locType="Ey") self.Ey = (Pey * self.f[src, "e", :]).flatten() self.Bx = (Pfx * self.f[src, "b", :]).flatten() self.Bz = (Pfz * self.f[src, "b", :]).flatten() self.dBxdt = (-Pfx * self.mesh.edgeCurl * self.f[src, "e", :]).flatten() self.dBzdt = (-Pfz * self.mesh.edgeCurl * self.f[src, "e", :]).flatten() def plotField( self, Field="B", view="vec", scale="linear", itime=0, Geometry=True, Scenario=None, Fixed=False, vmin=None, vmax=None, ): # Printout for null cases if (Field == "B") & (view == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "dBdt") & (view == "y"): print( "Think about the problem geometry. There is NO dBy/dt in this case." ) elif (Field == "E") & (view == "x") | (Field == "E") & (view == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) elif (Field == "J") & (view == "x") | (Field == "J") & (view == "z"): print( "Think about the problem geometry. There is NO Jx or Jz in this case. Only Jy." ) elif (Field == "E") & (view == "vec"): print( "Think about the problem geometry. E only has components along y. Vector plot not possible" ) elif (Field == "J") & (view == "vec"): print( "Think about the problem geometry. J only has components along y. Vector plot not possible" ) elif Field == "Model": plt.figure(figsize=(7, 6)) ax = plt.subplot(111) if Scenario == "Sphere": model2D, mapping2D = self.getCoreModel("Sphere") elif Scenario == "Layer": model2D, mapping2D = self.getCoreModel("Layer") if Fixed: clim = (np.log10(vmin), np.log10(vmax)) else: clim = None out = self.mesh2D.plotImage(np.log10(mapping2D * model2D), ax=ax, clim=clim) cb = plt.colorbar(out[0], ax=ax, format="$10^{%.1f}$") cb.set_label("$\sigma$ (S/m)") ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") ax.set_title("Conductivity Model") plt.show() else: plt.figure(figsize=(10, 6)) ax = plt.subplot(111) vec = False if view == "vec": tname = "Vector " title = tname + Field + "-field" elif view == "amp": tname = "|" title = tname + Field + "|-field" else: title = Field + view + "-field" if Field == "B": label = "Magnetic field (T)" if view == "vec": vec = True val = np.c_[self.Bx, self.Bz] elif view == "x": val = self.Bx elif view == "z": val = self.Bz else: return elif Field == "dBdt": label = "Time derivative of magnetic field (T/s)" if view == "vec": vec = True val = np.c_[self.dBxdt, self.dBzdt] elif view == "x": val = self.dBxdt elif view == "z": val = self.dBzdt else: return elif Field == "E": label = "Electric field (V/m)" if view == "y": val = self.Ey else: return elif Field == "J": label = "Current density (A/m$^2$)" if view == "y": val = self.Jy else: return if Fixed: if scale == "log": vmin, vmax = (np.log10(vmin), np.log10(vmax)) out = ax.scatter(np.zeros(3) - 1000, np.zeros(3), c=np.linspace(vmin, vmax, 3)) utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={ "cmap": "viridis", "vmin": vmin, "vmax": vmax }, ncontour=200, scale=scale, ) else: out = utils.plot2Ddata( self.mesh2D.gridCC, val, vec=vec, ax=ax, contourOpts={"cmap": "viridis"}, ncontour=200, scale=scale, )[0] if scale == "linear": cb = plt.colorbar(out, ax=ax, format="%.2e") elif scale == "log": cb = plt.colorbar(out, ax=ax, format="$10^{%.1f}$") else: raise Exception("We consdier only linear and log scale!") cb.set_label(label) xmax = self.mesh2D.gridCC[:, 0].max() if Geometry: if Scenario == "Layer": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "w-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z2, "w--", lw=1) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) elif Scenario == "Sphere": ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.srcLoc[2], "k-", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z0, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * self.z1, "w--", lw=1) ax.plot(np.r_[-xmax, xmax], np.ones(2) * (self.z1 - self.h), "w--", lw=1) Phi = np.linspace(0, 2 * np.pi, 41) ax.plot( self.R * np.cos(Phi), self.z2 + self.R * np.sin(Phi), "w--", lw=1, ) ax.plot(0, self.srcLoc[2], "ko", ms=4) ax.plot(self.rxLoc[0, 0], self.srcLoc[2], "ro", ms=4) ax.set_xlabel("Distance (m)") ax.set_ylabel("Depth (m)") title = (title + "\nt = " + "{:.2e}".format(self.sim.times[itime] * 1e3) + " ms") ax.set_title(title) ax.set_xlim(-190, 190) ax.set_ylim(-190, 190) plt.show() ###################################################### # LAYER WIDGET ###################################################### def InteractivePlane_Layer(self, scale="log", fieldvalue="E", compvalue="y"): def foo( Update, Field, AmpDir, Component, Sigma0, Sigma1, Sigma2, Sigma3, Sus, h1, h2, Scale, rxOffset, z, radius, itime, Geometry=True, Fixed=False, vmin=None, vmax=None, ): if AmpDir == "Direction (B or dBdt)": Component = "vec" self.setThreeLayerParam( h1=h1, h2=h2, sig0=Sigma0, sig1=Sigma1, sig2=Sigma2, sig3=Sigma3, chi=Sus, ) self.srcLoc = np.array([0.0, 0.0, z]) self.rxLoc = np.array([[rxOffset, 0.0, z]]) self.radius = radius if Update: self.simulate(self.srcLoc, self.rxLoc, self.time, self.radius) self.getFields(itime) return self.plotField( Field=Field, view=Component, scale=Scale, Geometry=Geometry, itime=itime, Scenario="Layer", Fixed=Fixed, vmin=vmin, vmax=vmax, ) out = widgetify( foo, Update=widgets.widget_bool.Checkbox(value=True, description="Update"), Field=widgets.ToggleButtons( options=["E", "B", "dBdt", "J", "Model"], value=fieldvalue), AmpDir=widgets.ToggleButtons( options=["None", "Direction (B or dBdt)"], value="None"), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Sigma0=widgets.FloatText(value=1e-8, continuous_update=False, description="$\sigma_0$ (S/m)"), Sigma1=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_1$ (S/m)"), Sigma2=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_2$ (S/m)"), Sigma3=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_3$ (S/m)"), Sus=widgets.FloatText(value=0.0, continuous_update=False, description="$\chi$"), h1=widgets.FloatSlider( min=2.0, max=50.0, step=2.0, value=20.0, continuous_update=False, description="$h_1$ (m)", ), h2=widgets.FloatSlider( min=2.0, max=50.0, step=2.0, value=20.0, continuous_update=False, description="$h_2$ (m)", ), Scale=widgets.ToggleButtons(options=["log", "linear"], value="linear"), rxOffset=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=10.0, continuous_update=False, description="$\Delta x$(m)", ), z=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$\Delta z$ (m)", ), itime=widgets.IntSlider( min=1, max=70, step=1, value=1, continuous_update=False, description="Time index", ), radius=widgets.FloatSlider( min=2.0, max=50.0, step=2.0, value=2.0, continuous_update=False, description="Tx radius (m)", ), Fixed=widgets.widget_bool.Checkbox(value=False, description="Fixed"), vmin=FloatText(value=None, description="vmin"), vmax=FloatText(value=None, description="vmax"), ) return out def InteractiveData_Layer(self, fieldvalue="B", compvalue="z"): def foo(Field, Component, Scale): if (Field == "B") & (Component == "y") | (Field == "dBdt") & ( Component == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (Component == "x") | (Field == "E") & ( Component == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) else: plt.figure() ax = plt.subplot(111) # bType = "b" self.getData() if Field == "B": label = "Magnetic field (T)" if Component == "x": title = "Bx" val = self.Bx elif Component == "z": title = "Bz" val = self.Bz else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO By in this case." ) elif Field == "dBdt": label = "Time dervative of magnetic field (T/s)" if Component == "x": title = "dBx/dt" val = self.dBxdt elif Component == "z": title = "dBz/dt" val = self.dBzdt else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO dBy/dt in this case." ) elif Field == "E": label = "Electric field (V/m)" title = "Ey" if Component == "y": val = self.Ey else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO Ex or Ez in this case." ) elif Field == "J": print( "The conductivity at the location is 0. Therefore there is no electrical current here." ) if Scale == "log": val_p, val_n = DisPosNegvalues(val) ax.plot(self.sim.times[10:] * 1e3, val_p[10:], "k-") ax.plot(self.sim.times[10:] * 1e3, val_n[10:], "k--") ax.legend(("(+)", "(-)"), loc=1, fontsize=10) else: ax.plot(self.sim.times[10:] * 1e3, val[10:], "k.-") ax.set_xscale("log") ax.set_yscale(Scale) ax.set_xlabel("Time (ms)") ax.set_ylabel(label) ax.set_title(title) ax.grid(True) plt.show() out = widgetify( foo, Field=widgets.ToggleButtons(options=["E", "B", "dBdt"], value=fieldvalue), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Scale=widgets.ToggleButtons(options=["log", "linear"], value="log"), ) return out ###################################################### # SPHERE WIDGET ###################################################### def InteractivePlane_Sphere(self, scale="log", fieldvalue="E", compvalue="y"): def foo( Update, Field, AmpDir, Component, Sigma0, Sigmab, Sigma1, Sigma2, Sus, d1, h, d2, R, Scale, rxOffset, z, radius, itime, Geometry=True, Fixed=False, vmin=None, vmax=None, ): if AmpDir == "Direction (B or dBdt)": Component = "vec" self.setLayerSphereParam( d1=d1, h=h, d2=d2, R=R, sig0=Sigma0, sigb=Sigmab, sig1=Sigma1, sig2=Sigma2, chi=Sus, ) self.srcLoc = np.array([0.0, 0.0, z]) self.rxLoc = np.array([[rxOffset, 0.0, z]]) self.radius = radius if Update: self.simulate(self.srcLoc, self.rxLoc, self.time, self.radius) self.getFields(itime) return self.plotField( Field=Field, view=Component, scale=Scale, Geometry=Geometry, itime=itime, Scenario="Sphere", Fixed=Fixed, vmin=vmin, vmax=vmax, ) out = widgetify( foo, Update=widgets.widget_bool.Checkbox(value=True, description="Update"), Field=widgets.ToggleButtons( options=["E", "B", "dBdt", "J", "Model"], value=fieldvalue), AmpDir=widgets.ToggleButtons( options=["None", "Direction (B or dBdt)"], value="None"), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Sigma0=widgets.FloatText(value=1e-8, continuous_update=False, description="$\sigma_0$ (S/m)"), Sigmab=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_b$ (S/m)"), Sigma1=widgets.FloatText(value=0.01, continuous_update=False, description="$\sigma_1$ (S/m)"), Sigma2=widgets.FloatText(value=1.0, continuous_update=False, description="$\sigma_2$ (S/m)"), Sus=widgets.FloatText(value=0.0, continuous_update=False, description="$\chi$"), d1=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$d_1$ (m)", ), h=widgets.FloatSlider( min=2.0, max=40.0, step=2.0, value=20.0, continuous_update=False, description="$h$ (m)", ), d2=widgets.FloatSlider( min=20.0, max=80.0, step=2.0, value=60.0, continuous_update=False, description="$d_2$ (m)", ), R=widgets.FloatSlider( min=2.0, max=40.0, step=2.0, value=30.0, continuous_update=False, description="$R$ (m)", ), Scale=widgets.ToggleButtons(options=["log", "linear"], value="linear"), rxOffset=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=10.0, continuous_update=False, description="$\Delta x$(m)", ), z=widgets.FloatSlider( min=0.0, max=50.0, step=2.0, value=0.0, continuous_update=False, description="$\Delta z$ (m)", ), radius=widgets.FloatSlider( min=2.0, max=50.0, step=2.0, value=2.0, continuous_update=False, description="Tx radius (m)", ), itime=widgets.IntSlider( min=1, max=70, step=1, value=1, continuous_update=False, description="Time index", ), Fixed=widgets.widget_bool.Checkbox(value=False, description="Fixed"), vmin=FloatText(value=None, description="vmin"), vmax=FloatText(value=None, description="vmax"), ) return out def InteractiveData_Sphere(self, fieldvalue="B", compvalue="z"): def foo(Field, Component, Scale): if (Field == "B") & (Component == "y") | (Field == "dBdt") & ( Component == "y"): print( "Think about the problem geometry. There is NO By in this case." ) elif (Field == "E") & (Component == "x") | (Field == "E") & ( Component == "z"): print( "Think about the problem geometry. There is NO Ex or Ez in this case. Only Ey." ) else: plt.figure() ax = plt.subplot(111) # bType = "b" self.getData() if Field == "B": label = "Magnetic field (T)" if Component == "x": title = "Bx" val = self.Bx elif Component == "z": title = "Bz" val = self.Bz else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO By in this case." ) elif Field == "dBdt": label = "Time dervative of magnetic field (T/s)" if Component == "x": title = "dBx/dt" val = self.dBxdt elif Component == "z": title = "dBz/dt" val = self.dBzdt else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO dBy/dt in this case." ) elif Field == "E": label = "Electric field (V/m)" title = "Ey" if Component == "y": val = self.Ey else: # ax.imshow(self.im) ax.set_xticks([]) ax.set_yticks([]) plt.show() print( "Think about the problem geometry. There is NO Ex or Ez in this case." ) elif Field == "J": print( "The conductivity at the location is 0. Therefore there is no electrical current here." ) if Scale == "log": val_p, val_n = DisPosNegvalues(val) ax.plot(self.sim.times[10:] * 1e3, val_p[10:], "k-") ax.plot(self.sim.times[10:] * 1e3, val_n[10:], "k--") ax.legend(("(+)", "(-)"), loc=1, fontsize=10) else: ax.plot(self.sim.times[10:] * 1e3, val[10:], "k.-") ax.set_xscale("log") ax.set_yscale(Scale) ax.set_xlabel("Time (ms)") ax.set_ylabel(label) ax.set_title(title) ax.grid(True) plt.show() out = widgetify( foo, Field=widgets.ToggleButtons(options=["E", "B", "dBdt"], value=fieldvalue), Component=widgets.ToggleButtons(options=["x", "y", "z"], value=compvalue, description="Comp."), Scale=widgets.ToggleButtons(options=["log", "linear"], value="log"), ) return out
ncr = 10 # number of mesh cells in r ncp = 8 # number of mesh cells in phi ncz = 15 # number of mesh cells in z dr = 15 # cell width r dz = 10 # cell width z hr = dr * np.ones(ncr) hp = (2 * np.pi / ncp) * np.ones(ncp) hz = dz * np.ones(ncz) x0 = 0. y0 = 0. z0 = -150. mesh = CylMesh([hr, hp, hz], x0=[x0, y0, z0]) mesh.plotGrid() ############################################### # Padding Cells and Extracting Properties # --------------------------------------- # # For practical purposes, the user may want to define a region where the cell # widths are increasing/decreasing in size. For example, padding is often used # to define a large domain while reducing the total number of mesh cells. # Here we demonstrate how to create cylindrical meshes that have padding cells. # We then show some properties that can be extracted from cylindrical meshes. # ncr = 10 # number of mesh cells in r
def setupMesh(meshType, nC, nDim): """ For a given number of cells nc, generate a TensorMesh with uniform cells with edge length h=1/nc. """ if 'TensorMesh' in meshType: if 'uniform' in meshType: h = [nC, nC, nC] elif 'random' in meshType: h1 = np.random.rand(nC)*nC*0.5 + nC*0.5 h2 = np.random.rand(nC)*nC*0.5 + nC*0.5 h3 = np.random.rand(nC)*nC*0.5 + nC*0.5 h = [hi/np.sum(hi) for hi in [h1, h2, h3]] # normalize else: raise Exception('Unexpected meshType') mesh = TensorMesh(h[:nDim]) max_h = max([np.max(hi) for hi in mesh.h]) elif 'CylMesh' in meshType: if 'uniform' in meshType: h = [nC, nC, nC] elif 'random' in meshType: h1 = np.random.rand(nC)*nC*0.5 + nC*0.5 h2 = np.random.rand(nC)*nC*0.5 + nC*0.5 h3 = np.random.rand(nC)*nC*0.5 + nC*0.5 h = [hi/np.sum(hi) for hi in [h1, h2, h3]] # normalize h[1] = h[1]*2*np.pi else: raise Exception('Unexpected meshType') if nDim == 2: mesh = CylMesh([h[0], 1, h[2]]) max_h = max([np.max(hi) for hi in [mesh.hx, mesh.hz]]) elif nDim == 3: mesh = CylMesh(h) max_h = max([np.max(hi) for hi in mesh.h]) elif 'Curv' in meshType: if 'uniform' in meshType: kwrd = 'rect' elif 'rotate' in meshType: kwrd = 'rotate' else: raise Exception('Unexpected meshType') if nDim == 1: raise Exception('Lom not supported for 1D') elif nDim == 2: X, Y = utils.exampleLrmGrid([nC, nC], kwrd) mesh = CurvilinearMesh([X, Y]) elif nDim == 3: X, Y, Z = utils.exampleLrmGrid([nC, nC, nC], kwrd) mesh = CurvilinearMesh([X, Y, Z]) max_h = 1./nC elif 'Tree' in meshType: if Tree is None: raise Exception( "Tree Mesh not installed. Run 'python setup.py install'" ) nC *= 2 if 'uniform' in meshType or 'notatree' in meshType: h = [nC, nC, nC] elif 'random' in meshType: h1 = np.random.rand(nC)*nC*0.5 + nC*0.5 h2 = np.random.rand(nC)*nC*0.5 + nC*0.5 h3 = np.random.rand(nC)*nC*0.5 + nC*0.5 h = [hi/np.sum(hi) for hi in [h1, h2, h3]] # normalize else: raise Exception('Unexpected meshType') levels = int(np.log(nC)/np.log(2)) mesh = Tree(h[:nDim], levels=levels) def function(cell): if 'notatree' in meshType: return levels - 1 r = cell.center - 0.5 dist = np.sqrt(r.dot(r)) if dist < 0.2: return levels return levels - 1 mesh.refine(function) # mesh.number() # mesh.plotGrid(showIt=True) max_h = max([np.max(hi) for hi in mesh.h]) return mesh, max_h