Some tutorial about geometry

本文提供两个链接资源,分别介绍视觉定位系统的估计方法及数学在线课程。前者由INRIA研究机构提供,深入探讨了机器人视觉定位中目标估计的技术细节;后者则是一门在线数学课程,覆盖了与视觉定位密切相关的数学基础知识。
""" 3D Forward Simulation with User-Defined Waveforms ================================================= Here we use the module *simpeg.electromagnetics.time_domain* to predict the TDEM response for a trapezoidal waveform. We consider an airborne survey which uses a horizontal coplanar geometry. For this tutorial, we focus on the following: - How to define the transmitters and receivers - How to define more complicated transmitter waveforms - How to define the time-stepping - How to define the survey - How to solve TDEM problems on an OcTree mesh - How to include topography - The units of the conductivity model and resulting data Please note that we have used a coarse mesh and larger time-stepping to shorten the time of the simulation. Proper discretization in space and time is required to simulate the fields at each time channel with sufficient accuracy. """ ######################################################################### # Import Modules # -------------- # from discretize import TreeMesh from discretize.utils import mkvc, refine_tree_xyz, active_from_xyz from simpeg.utils import plot2Ddata from simpeg import maps import simpeg.electromagnetics.time_domain as tdem from tqdm import tqdm from simpeg.electromagnetics.time_domain import sources, receivers import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt import os save_file = False # sphinx_gallery_thumbnail_number = 3 ############################################################### # Defining Topography # ------------------- # # Here we define surface topography as an (N, 3) numpy array. Topography could # also be loaded from a file. Here we define flat topography, however more # complex topographies can be considered. # xx, yy = np.meshgrid(np.linspace(-3000, 3000, 101), np.linspace(-3000, 3000, 101)) zz = np.zeros(np.shape(xx)) topo_xyz = np.c_[mkvc(xx), mkvc(yy), mkvc(zz)] ############################################################### # Defining the Waveform # --------------------- # # Under *simpeg.electromagnetic.time_domain.sources* # there are a multitude of waveforms that can be defined (VTEM, Ramp-off etc...). # Here, we consider a trapezoidal waveform, which consists of a # linear ramp-on followed by a linear ramp-off. For each waveform, it # is important you are cognizant of the off time!!! # # Define a discrete set of times for which your transmitter is 'on'. Here # the waveform is on from -0.002 s to 0 s. waveform_times = np.linspace(-0.002, 0, 21) # For each waveform type, you must define the necessary set of kwargs. # For the trapezoidal waveform we define the ramp on interval, the # ramp-off interval and the off-time. waveform = tdem.sources.TrapezoidWaveform( ramp_on=np.r_[-0.002, -0.001], ramp_off=np.r_[-0.001, 0.0], off_time=0.0 ) # Uncomment to try a quarter sine wave ramp on, followed by a linear ramp-off. # waveform = tdem.sources.QuarterSineRampOnWaveform( # ramp_on=np.r_[-0.002, -0.001], ramp_off=np.r_[-0.001, 0.], off_time=0. # ) # Uncomment to try a custom waveform (just a linear ramp-off). This requires # defining a function for your waveform. # def wave_function(t): # return - t/(np.max(waveform_times) - np.min(waveform_times)) # # waveform = tdem.sources.RawWaveform(waveform_function=wave_function, off_time=0.) # Evaluate the waveform for each on time. waveform_value = [waveform.eval(t) for t in waveform_times] # Plot the waveform fig = plt.figure(figsize=(10, 4)) ax1 = fig.add_subplot(111) ax1.plot(waveform_times, waveform_value, lw=2) ax1.set_xlabel("Times [s]") ax1.set_ylabel("Waveform value") ax1.set_title("Waveform") ##################################################################### # Create Airborne Survey # ---------------------- # # Here we define the survey used in our simulation. For time domain # simulations, we must define the geometry of the source and its waveform. # the receivers, we define their geometry, the type of field they measure and # the time channels at which they measure the field. For this example, # the survey consists of a uniform grid of airborne measurements. # # Observation times for response (time channels) n_times = 10 time_channels = np.logspace(-5, -2.3, n_times) # Defining transmitter locations n_tx =4 xtx, ytx, ztx = np.meshgrid( np.linspace(-50, 50, n_tx), np.linspace(-50, 50, n_tx), [40] ) source_locations = np.c_[mkvc(xtx), mkvc(ytx), mkvc(ztx)] ntx = np.size(xtx) # Define receiver locations xrx, yrx, zrx = np.meshgrid( np.linspace(-50, 50, n_tx), np.linspace(-50, 50, n_tx), [30] ) receiver_locations = np.c_[mkvc(xrx), mkvc(yrx), mkvc(zrx)] source_list = [] # Create empty list to store sources # Each unique location defines a new transmitter for ii in range(ntx): # Here we define receivers that measure the h-field in A/m dbzdt_receiver = tdem.receivers.PointMagneticFluxTimeDerivative( receiver_locations[ii, :], time_channels, "z" ) receivers_list = [ dbzdt_receiver ] # Make a list containing all receivers even if just one # Must define the transmitter properties and associated receivers source = sources.CircularLoop( receivers_list, location=source_locations[ii], # 线圈中心位置 waveform=waveform, # 使用前面定义的波形 radius=5.0, # 设置线圈半径(单位:m) orientation="z", # 线圈法向方向 current=50.0 # 发射电流(A) ) source_list.append(source) survey = tdem.Survey(source_list) ############################################################### # Create OcTree Mesh # ------------------ # # Here we define the OcTree mesh that is used for this example. # We chose to design a coarser mesh to decrease the run time. # When designing a mesh to solve practical time domain problems: # # - Your smallest cell size should be 10%-20% the size of your smallest diffusion distance # - The thickness of your padding needs to be 2-3 times biggest than your largest diffusion distance # - The diffusion distance is ~1260*np.sqrt(rho*t) # # dh = 2.0 # base cell width dom_width = 400.0 # domain width nbc = 2 ** int(np.round(np.log(dom_width / dh) / np.log(2.0))) # num. base cells # Define the base mesh h = [(dh, nbc)] mesh = TreeMesh([h, h, h], x0="CCC") # Mesh refinement based on topography mesh = refine_tree_xyz( mesh, topo_xyz, octree_levels=[0, 0, 1], method="surface", finalize=False ) # Mesh refinement near transmitters and receivers mesh = refine_tree_xyz( mesh, receiver_locations, octree_levels=[ 2,4], method="radial", finalize=False ) # Refine core mesh region xp, yp, zp = np.meshgrid([-80.0, 80.0], [-80.0, 80.0], [-60.0, 0.0]) xyz = np.c_[mkvc(xp), mkvc(yp), mkvc(zp)] mesh = refine_tree_xyz(mesh, xyz, octree_levels=[0, 2,4], method="box", finalize=False) mesh.finalize() ############################################################### # Create Conductivity Model and Mapping for OcTree Mesh # ----------------------------------------------------- # # Here, we define the electrical properties of the Earth as a conductivity # model. The model consists of a conductive block within a more # resistive background. # # Conductivity in S/m air_conductivity = 1e-8 background_conductivity = 2e-3 block_conductivity = 2e0 # Active cells are cells below the surface. ind_active = active_from_xyz(mesh, topo_xyz) if ind_active.sum() == 0: raise ValueError("No active cells detected below topography — check topo or mesh alignment.") model_map = maps.InjectActiveCells(mesh, ind_active, air_conductivity) # Define the model model = background_conductivity * np.ones(ind_active.sum()) ind_block = ( (mesh.gridCC[ind_active, 0] < 10.0) & (mesh.gridCC[ind_active, 0] > -10.0) & (mesh.gridCC[ind_active, 1] < 10.0) & (mesh.gridCC[ind_active, 1] > -10.0) & (mesh.gridCC[ind_active, 2] > -20.0) & (mesh.gridCC[ind_active, 2] < -15.0) ) model[ind_block] = block_conductivity # Plot log-conductivity model mpl.rcParams.update({"font.size": 12}) fig = plt.figure(figsize=(7, 6)) log_model = np.log10(model) plotting_map = maps.InjectActiveCells(mesh, ind_active, np.nan) ax1 = fig.add_axes([0.13, 0.1, 0.6, 0.85]) mesh.plot_slice( plotting_map * log_model, normal="Y", ax=ax1, ind=int(mesh.h[0].size / 2), grid=True, clim=(np.min(log_model), np.max(log_model)), ) ax1.set_title("Conductivity Model at Y = 0 m") ax2 = fig.add_axes([0.75, 0.1, 0.05, 0.85]) norm = mpl.colors.Normalize(vmin=np.min(log_model), vmax=np.max(log_model)) cbar = mpl.colorbar.ColorbarBase( ax2, norm=norm, orientation="vertical", format="$10^{%.1f}$" ) cbar.set_label("Conductivity [S/m]", rotation=270, labelpad=15, size=12) ###################################################### # Define the Time-Stepping # ------------------------ # # Stuff about time-stepping and some rule of thumb # time_steps = [(5e-6, 10), (1e-5, 10), (5e-5, 10), (1e-4, 20), (5e-4, 10), (1e-3, 5) ] ####################################################################### # Simulation: Time-Domain Response # -------------------------------- # # Here we define the formulation for solving Maxwell's equations. Since we are # measuring the time-derivative of the magnetic flux density and working with # a resistivity model, the EB formulation is the most natural. We must also # remember to define the mapping for the conductivity model. # We defined a waveform 'on-time' is from -0.002 s to 0 s. As a result, we need # to set the start time for the simulation to be at -0.002 s. # simulation = tdem.simulation.Simulation3DMagneticFluxDensity( mesh, survey=survey, sigmaMap=model_map, t0=-0.002 ) # Set the time-stepping for the simulation simulation.time_steps = time_steps ######################################################################## # Predict Data and Plot # --------------------- print("开始进行 3D 正演模拟 (dpred)...") # SimPEG 的 dpred 实际上是计算每个源的响应,然后拼接起来 # 我们可以手动循环源列表,并用 tqdm 跟踪进度 dpred_list = [] # 使用 tqdm 包装 simulation.survey.source_list 来显示进度 for src in tqdm(simulation.survey.source_list, desc="计算每个发射源的响应"): # 临时创建一个只包含当前源的 Survey 对象 temp_survey = tdem.Survey([src]) # 将 simulation 对象的 survey 临时设置为 temp_survey original_survey = simulation.survey simulation.survey = temp_survey # 预测当前源的数据 # 注意: SimPEG 模型的 dpred 方法需要完整的模型,即使只计算一个源 # 如果 SimPEG 版本较新,且支持对单个源进行计算,可能更简洁 # 否则,这种临时替换 survey 的方式是通用的 dpred_list.append(simulation.dpred(model)) # 恢复 simulation 对象的 survey simulation.survey = original_survey # 将所有源的预测数据拼接起来 dpred = np.concatenate(dpred_list) print("3D 正演模拟完成。") # Predict data for a given model dpred = simulation.dpred(model) # Data were organized by location, then by time channel dpred_plotting = np.reshape(dpred, (n_tx**2, n_times)) # Plot fig = plt.figure(figsize=(10, 4)) # dB/dt at early time v_max = np.max(np.abs(dpred_plotting[:, 0])) ax11 = fig.add_axes([0.05, 0.05, 0.35, 0.9]) plot2Ddata( receiver_locations[:, 0:2], dpred_plotting[:, 0], ax=ax11, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax11.set_title("dBz/dt at 0.0001 s") ax12 = fig.add_axes([0.42, 0.05, 0.02, 0.9]) norm1 = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar1 = mpl.colorbar.ColorbarBase( ax12, norm=norm1, orientation="vertical", cmap=mpl.cm.bwr ) cbar1.set_label("$T/s$", rotation=270, labelpad=15, size=12) # dB/dt at later times v_max = np.max(np.abs(dpred_plotting[:, -1])) ax21 = fig.add_axes([0.55, 0.05, 0.35, 0.9]) plot2Ddata( receiver_locations[:, 0:2], dpred_plotting[:, -1], ax=ax21, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax21.set_title("dBz/dt at 0.001 s") ax22 = fig.add_axes([0.92, 0.05, 0.02, 0.9]) norm2 = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar2 = mpl.colorbar.ColorbarBase( ax22, norm=norm2, orientation="vertical", cmap=mpl.cm.bwr ) cbar2.set_label("$T/s$", rotation=270, labelpad=15, size=12) plt.show() ####################################################### # Optional: Export Data # --------------------- for i in range(n_times): fig = plt.figure(figsize=(6, 4)) v_max = np.max(np.abs(dpred_plotting[:, i])) ax = fig.add_axes([0.1, 0.1, 0.75, 0.8]) plot2Ddata( receiver_locations[:, 0:2], dpred_plotting[:, i], ax=ax, ncontour=30, clim=(-v_max, v_max), contourOpts={"cmap": "bwr"}, ) ax.set_title(f"dBz/dt at t = {time_channels[i]:.6f} s") # 加色条 cax = fig.add_axes([0.88, 0.1, 0.03, 0.8]) norm = mpl.colors.Normalize(vmin=-v_max, vmax=v_max) cbar = mpl.colorbar.ColorbarBase(cax, norm=norm, orientation="vertical", cmap=mpl.cm.bwr) cbar.set_label("$T/s$", rotation=270, labelpad=15, size=12) plt.show() # Write the true model, data and topography # if save_file: dir_path = os.path.dirname(tdem.__file__).split(os.path.sep)[:-3] dir_path.extend(["tutorials", "assets", "tdem"]) dir_path = os.path.sep.join(dir_path) + os.path.sep fname = dir_path + "tdem_topo.txt" np.savetxt(fname, np.c_[topo_xyz], fmt="%.4e") # Write data with 2% noise added fname = dir_path + "tdem_data.obs" dpred = dpred + 0.02 * np.abs(dpred) * np.random.randn(len(dpred)) t_vec = np.kron(np.ones(ntx), time_channels) receiver_locations = np.kron(receiver_locations, np.ones((len(time_channels), 1))) np.savetxt(fname, np.c_[receiver_locations, t_vec, dpred], fmt="%.4e") # Plot true model output_model = plotting_map * model output_model[np.isnan(output_model)] = 1e-8 fname = dir_path + "true_model.txt" np.savetxt(fname, output_model, fmt="%.4e") 此代码中,正演模拟time_channels和time_steps如何设置参数
最新发布
10-21
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值