你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-08 07:24:19 +08:00
Further changes/updates towards getting sub-gridding example with GSSI 400 working.
这个提交包含在:
@@ -73,7 +73,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
|
||||
# If there is only 1 bin then a normal material is being used, otherwise a mixing model
|
||||
if volume.nbins == 1:
|
||||
volume.fractalvolume = np.ones((volume.nx, volume.ny, volume.nz), dtype=config.sim_config.dtype['float_or_double'])
|
||||
volume.fractalvolume = np.ones((volume.nx, volume.ny, volume.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
materialnumID = next(x.numID for x in grid.materials if x.ID == volume.operatingonID)
|
||||
volume.fractalvolume *= materialnumID
|
||||
else:
|
||||
@@ -115,7 +116,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
if surface.fractalsurface[j - surface.ys, k - surface.zs] > 0:
|
||||
height = 0
|
||||
for i in range(volume.xs, surface.fractalrange[1]):
|
||||
if i < surface.fractalsurface[j - surface.ys, k - surface.zs] and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1:
|
||||
if (i < surface.fractalsurface[j - surface.ys, k - surface.zs] and
|
||||
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
|
||||
y, z = g.calculate_blade_geometry(blade, height)
|
||||
# Add y, z coordinates to existing location
|
||||
yy = int(j - volume.ys + y)
|
||||
@@ -136,7 +138,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
depth = 0
|
||||
i = volume.xf - 1
|
||||
while i > volume.xs:
|
||||
if i > volume.originalxf - (surface.fractalsurface[j - surface.ys, k - surface.zs] - volume.originalxf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1:
|
||||
if (i > volume.originalxf - (surface.fractalsurface[j - surface.ys, k - surface.zs] -
|
||||
volume.originalxf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
|
||||
y, z = g.calculate_root_geometry(root, depth)
|
||||
# Add y, z coordinates to existing location
|
||||
yy = int(j - volume.ys + y)
|
||||
@@ -181,7 +184,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
if surface.fractalsurface[i - surface.xs, k - surface.zs] > 0:
|
||||
height = 0
|
||||
for j in range(volume.ys, surface.fractalrange[1]):
|
||||
if j < surface.fractalsurface[i - surface.xs, k - surface.zs] and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1:
|
||||
if (j < surface.fractalsurface[i - surface.xs, k - surface.zs] and
|
||||
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
|
||||
x, z = g.calculate_blade_geometry(blade, height)
|
||||
# Add x, z coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
@@ -202,7 +206,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
depth = 0
|
||||
j = volume.yf - 1
|
||||
while j > volume.ys:
|
||||
if j > volume.originalyf - (surface.fractalsurface[i - surface.xs, k - surface.zs] - volume.originalyf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1:
|
||||
if (j > volume.originalyf - (surface.fractalsurface[i - surface.xs, k - surface.zs] -
|
||||
volume.originalyf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
|
||||
x, z = g.calculate_root_geometry(root, depth)
|
||||
# Add x, z coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
@@ -247,7 +252,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
if surface.fractalsurface[i - surface.xs, j - surface.ys] > 0:
|
||||
height = 0
|
||||
for k in range(volume.zs, surface.fractalrange[1]):
|
||||
if k < surface.fractalsurface[i - surface.xs, j - surface.ys] and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1:
|
||||
if (k < surface.fractalsurface[i - surface.xs, j - surface.ys] and
|
||||
volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] != 1):
|
||||
x, y = g.calculate_blade_geometry(blade, height)
|
||||
# Add x, y coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
@@ -268,7 +274,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
depth = 0
|
||||
k = volume.zf - 1
|
||||
while k > volume.zs:
|
||||
if k > volume.originalzf - (surface.fractalsurface[i - surface.xs, j - surface.ys] - volume.originalzf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1:
|
||||
if (k > volume.originalzf - (surface.fractalsurface[i - surface.xs, j - surface.ys] -
|
||||
volume.originalzf) and volume.mask[i - volume.xs, j - volume.ys, k - volume.zs] == 1):
|
||||
x, y = g.calculate_root_geometry(root, depth)
|
||||
# Add x, y coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
@@ -287,7 +294,10 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
grassnumID = next((x.numID for x in grid.materials if x.ID == 'grass'), 0)
|
||||
data = volume.fractalvolume.astype('int16', order='C')
|
||||
mask = volume.mask.copy(order='C')
|
||||
build_voxels_from_array_mask(volume.xs, volume.ys, volume.zs, waternumID, grassnumID, volume.averaging, mask, data, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_voxels_from_array_mask(volume.xs, volume.ys, volume.zs,
|
||||
waternumID, grassnumID, volume.averaging,
|
||||
mask, data, grid.solid, grid.rigidE,
|
||||
grid.rigidH, grid.ID)
|
||||
|
||||
else:
|
||||
if volume.nbins == 1:
|
||||
@@ -297,4 +307,6 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
volume.fractalvolume += volume.mixingmodel.startmaterialnum
|
||||
|
||||
data = volume.fractalvolume.astype('int16', order='C')
|
||||
build_voxels_from_array(volume.xs, volume.ys, volume.zs, 0, volume.averaging, data, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_voxels_from_array(volume.xs, volume.ys, volume.zs, 0,
|
||||
volume.averaging, data, grid.solid,
|
||||
grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
@@ -26,6 +26,7 @@ from .cmds_geometry.cmds_geometry import UserObjectGeometry
|
||||
from .exceptions import CmdInputError
|
||||
from .geometry_outputs import GeometryObjects as GeometryObjectsUser
|
||||
from .materials import Material as MaterialUser
|
||||
from .materials import DispersiveMaterial as DispersiveMaterialUser
|
||||
from .materials import PeplinskiSoil as PeplinskiSoilUser
|
||||
from .pml import CFSParameter
|
||||
from .pml import CFS
|
||||
@@ -508,7 +509,7 @@ class Rx(UserObjectMulti):
|
||||
|
||||
try:
|
||||
r.ID = self.kwargs['id']
|
||||
outputs = self.kwargs['outputs']
|
||||
outputs = [self.kwargs['outputs']]
|
||||
# Get allowable outputs
|
||||
allowableoutputs = RxUser.allowableoutputs_gpu if config.sim_config.general['cuda'] else RxUser.allowableoutputs
|
||||
# Check and add field output names
|
||||
@@ -767,20 +768,28 @@ class AddDebyeDispersion(UserObjectMulti):
|
||||
raise CmdInputError(f"'{self.params_str()}' material(s) {notfound} do not exist")
|
||||
|
||||
for material in materials:
|
||||
material.type = 'debye'
|
||||
material.poles = poles
|
||||
material.averagable = False
|
||||
disp_material = DispersiveMaterialUser(material.numID, material.ID)
|
||||
disp_material.er = material.er
|
||||
disp_material.se = material.se
|
||||
disp_material.mr = material.mr
|
||||
disp_material.sm = material.sm
|
||||
disp_material.type = 'debye'
|
||||
disp_material.poles = poles
|
||||
disp_material.averagable = False
|
||||
for i in range(0, poles):
|
||||
# N.B Not checking if relaxation times are greater than time-step
|
||||
if tau[i] > 0:
|
||||
material.deltaer.append(er_delta[i])
|
||||
material.tau.append(tau[i])
|
||||
log.debug('Not checking if relaxation times are greater than time-step')
|
||||
disp_material.deltaer.append(er_delta[i])
|
||||
disp_material.tau.append(tau[i])
|
||||
else:
|
||||
raise CmdInputError(f"'{self.params_str()}' requires positive values for the permittivity difference.")
|
||||
if material.poles > MaterialUser.maxpoles:
|
||||
MaterialUser.maxpoles = material.poles
|
||||
if disp_material.poles > config.model_configs[grid.model_num].materials['maxpoles']:
|
||||
config.model_configs[grid.model_num].materials['maxpoles'] = disp_material.poles
|
||||
|
||||
log.info(f"Debye disperion added to {material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in material.deltaer)}, and tau={', '.join('%4.3e' % tau for tau in material.tau)} secs created.")
|
||||
# Replace original material with newly created DispersiveMaterial
|
||||
grid.materials = [disp_material if mat.numID==material.numID else mat for mat in grid.materials]
|
||||
|
||||
log.info(f"Debye disperion added to {disp_material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in disp_material.deltaer)}, and tau={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs created.")
|
||||
|
||||
|
||||
class AddLorentzDispersion(UserObjectMulti):
|
||||
@@ -1028,7 +1037,7 @@ class GeometryView(UserObjectMulti):
|
||||
|
||||
g = GeometryViewUser(xs, ys, zs, xf, yf, zf, dx, dy, dz, filename, fileext, grid)
|
||||
|
||||
log.info(f'Geometry view from {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m, discretisation {dx * grid.dx:g}m, {dy * grid.dy:g}m, {dz * grid.dz:g}m, multi_grid={self.multi_grid}, grid={grid.name}, with filename base {g.basefilename} created.')
|
||||
log.info(f'Geometry view from {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m, discretisation {dx * grid.dx:g}m, {dy * grid.dy:g}m, {dz * grid.dz:g}m, multi_grid={self.multi_grid}, grid={grid.name}, with filename base {g.filename} created.')
|
||||
|
||||
# Append the new GeometryView object to the geometry views list
|
||||
grid.geometryviews.append(g)
|
||||
|
@@ -187,7 +187,7 @@ class SimulationConfig:
|
||||
'cuda': False,
|
||||
'opencl': False,
|
||||
'precision': 'single',
|
||||
'autotranslate': False}
|
||||
'autotranslate': self.args.autotranslate}
|
||||
log.debug('Should autotranslate be a ModelConfig parameter?')
|
||||
|
||||
self.em_consts = {'c': c, # Speed of light in free space (m/s)
|
||||
|
@@ -19,7 +19,6 @@
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
@@ -61,7 +60,7 @@ class GeometryView:
|
||||
self.dx = dx
|
||||
self.dy = dy
|
||||
self.dz = dz
|
||||
self.basefilename = filename
|
||||
self.filename = filename
|
||||
self.fileext = fileext
|
||||
self.G = G
|
||||
|
||||
@@ -89,19 +88,19 @@ class GeometryView:
|
||||
self.vtk_nylines = self.ny * (self.nx + 1) * (self.nz + 1)
|
||||
self.vtk_nzlines = self.nz * (self.nx + 1) * (self.ny + 1)
|
||||
self.vtk_numlines = self.vtk_nxlines + self.vtk_nylines + self.vtk_nzlines
|
||||
self.vtk_connectivity_offset = round_value((self.vtk_numpoints *
|
||||
self.vtk_numpoint_components *
|
||||
np.dtype(np.float32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.vtk_offsets_offset = round_value(self.vtk_connectivity_offset +
|
||||
(self.vtk_numlines *
|
||||
self.vtk_numline_components *
|
||||
np.dtype(np.uint32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.vtk_materials_offset = round_value(self.vtk_offsets_offset +
|
||||
(self.vtk_numlines *
|
||||
np.dtype(np.uint32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.vtk_connectivity_offset = ((self.vtk_numpoints *
|
||||
self.vtk_numpoint_components *
|
||||
np.dtype(np.float32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.vtk_offsets_offset = (self.vtk_connectivity_offset +
|
||||
(self.vtk_numlines *
|
||||
self.vtk_numline_components *
|
||||
np.dtype(np.uint32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.vtk_materials_offset = (self.vtk_offsets_offset +
|
||||
(self.vtk_numlines *
|
||||
np.dtype(np.uint32).itemsize) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
vtk_cell_offsets = (((self.vtk_numline_components * self.vtk_numlines) +
|
||||
self.vtk_numline_components - self.vtk_numline_components - 1) //
|
||||
self.vtk_numline_components + 1)
|
||||
@@ -114,8 +113,8 @@ class GeometryView:
|
||||
|
||||
def set_filename(self):
|
||||
"""Construct filename from user-supplied name and model run number."""
|
||||
parts = config.model_configs[self.G.model_num].output_file_path.with_suffix('').parts
|
||||
self.filename = Path(*parts[:-1], parts[-1])
|
||||
parts = config.model_configs[self.G.model_num].output_file_path.parts
|
||||
self.filename = Path(*parts[:-1], self.filename + config.model_configs[self.G.model_num].appendmodelnumber)
|
||||
self.filename = self.filename.with_suffix(self.fileext)
|
||||
|
||||
def write_vtk(self, G, pbar):
|
||||
@@ -142,19 +141,15 @@ class GeometryView:
|
||||
for index, rx in enumerate(G.rxs):
|
||||
self.rxs[rx.xcoord, rx.ycoord, rx.zcoord] = index + 1
|
||||
|
||||
vtk_srcs_pml_offset = round_value((np.dtype(np.uint32).itemsize *
|
||||
self.vtk_nxcells *
|
||||
self.vtk_nycells *
|
||||
self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
vtk_rxs_offset = round_value((np.dtype(np.uint32).itemsize *
|
||||
self.vtk_nxcells * self.vtk_nycells *
|
||||
self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize +
|
||||
(np.dtype(np.int8).itemsize *
|
||||
self.vtk_nxcells * self.vtk_nycells *
|
||||
self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
vtk_srcs_pml_offset = ((np.dtype(np.uint32).itemsize * self.vtk_nxcells *
|
||||
self.vtk_nycells * self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
vtk_rxs_offset = ((np.dtype(np.uint32).itemsize * self.vtk_nxcells *
|
||||
self.vtk_nycells * self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize +
|
||||
(np.dtype(np.int8).itemsize * self.vtk_nxcells *
|
||||
self.vtk_nycells * self.vtk_nzcells) +
|
||||
np.dtype(np.uint32).itemsize)
|
||||
|
||||
with open(self.filename, 'wb') as f:
|
||||
f.write('<?xml version="1.0"?>\n'.encode('utf-8'))
|
||||
@@ -428,7 +423,7 @@ class GeometryViewFineMultiGrid:
|
||||
self.nx = G.nx
|
||||
self.ny = G.ny
|
||||
self.nz = G.nz
|
||||
self.basefilename = filename
|
||||
self.filename = filename
|
||||
self.fileext = '.vtp'
|
||||
self.sg_views = []
|
||||
|
||||
@@ -455,8 +450,8 @@ class GeometryViewFineMultiGrid:
|
||||
|
||||
def set_filename(self):
|
||||
"""Construct filename from user-supplied name and model run number."""
|
||||
parts = config.model_configs[self.G.model_num].input_file_path.parts
|
||||
self.filename = Path(*parts[:-1], parts[-1] + config.model_configs[self.G.model_num].appendmodelnumber)
|
||||
parts = config.model_configs[self.G.model_num].output_file_path.parts
|
||||
self.filename = Path(*parts[:-1], self.filename + config.model_configs[self.G.model_num].appendmodelnumber)
|
||||
self.filename = self.filename.with_suffix(self.fileext)
|
||||
|
||||
def write_vtk(self, *args):
|
||||
|
@@ -37,6 +37,7 @@ def run(
|
||||
mpicomm=None,
|
||||
gpu=None,
|
||||
subgrid=None,
|
||||
autotranslate=False,
|
||||
geometry_only=False,
|
||||
geometry_fixed=False,
|
||||
write_processed=False,
|
||||
@@ -45,10 +46,13 @@ def run(
|
||||
programming interface (API). Run the simulation for the
|
||||
given list of scenes.
|
||||
|
||||
:param scenes: list of the scenes to run the model. Multiple scene objects can given in order to run multiple simulation runs. Each scene must contain the essential simulation objects
|
||||
:param scenes: list of the scenes to run the model. Multiple scene objects
|
||||
can given in order to run multiple simulation runs. Each
|
||||
scene must contain the essential simulation objects
|
||||
:type scenes: list, optional
|
||||
|
||||
:param inputfile: input file path. Can also run simulation by providing an input file.
|
||||
:param inputfile: input file path. Can also run simulation by providing an
|
||||
input file.
|
||||
:type inputfile: str, optional
|
||||
|
||||
:param outputfile: file path to the output data file.
|
||||
@@ -57,32 +61,54 @@ def run(
|
||||
:param n: number of required simulation runs.
|
||||
:type n: int, non-optional
|
||||
|
||||
:param task: task identifier (model number) when running simulation as a job array on open grid scheduler/grid engine. for further details see the parallel performance section of the user guide
|
||||
:param task: task identifier (model number) when running simulation as a
|
||||
job array on open grid scheduler/grid engine. For further
|
||||
details see the parallel performance section of the User Guide.
|
||||
:type task: int, optional
|
||||
|
||||
:param restart: model number to start/restart simulation from. It would typically be used to restart a series of models from a specific model number, with the n argument, e.g. to restart from A-scan 45 when creating a B-scan with 60 traces
|
||||
:param restart: model number to start/restart simulation from. It would
|
||||
typically be used to restart a series of models from a
|
||||
specific model number, with the n argument, e.g. to restart
|
||||
from A-scan 45 when creating a B-scan with 60 traces.
|
||||
:type restart: int, optional
|
||||
|
||||
:param mpi: number of Message Passing Interface (MPI) tasks, i.e. master + workers, for MPI task farm. This option is most usefully combined with n to allow individual models to be farmed out using a MPI task farm, e.g. to create a B-scan with 60 traces and use MPI to farm out each trace1. For further details see the parallel performance section of the User Guide
|
||||
:param mpi: number of Message Passing Interface (MPI) tasks,
|
||||
i.e. master + workers, for MPI task farm. This option is most
|
||||
usefully combined with n to allow individual models to be farmed
|
||||
out using a MPI task farm, e.g. to create a B-scan with 60 traces
|
||||
and use MPI to farm out each trace1. For further details see the
|
||||
parallel performance section of the User Guide.
|
||||
:type mpi: int, optional
|
||||
|
||||
:param mpi_no_spawn: flag to use MPI task farm without spawn mechanism. For further details see the parallel performance section of the User Guide.
|
||||
:param mpi_no_spawn: flag to use MPI task farm without spawn mechanism.
|
||||
For further details see the parallel performance
|
||||
section of the User Guide.
|
||||
:type mpi_no_spawn: bool, optional
|
||||
|
||||
:param gpu: flag to use NVIDIA GPU or list of NVIDIA GPU device ID(s) for specific GPU card(s)
|
||||
:param gpu: flag to use NVIDIA GPU or list of NVIDIA GPU device ID(s) for
|
||||
specific GPU card(s).
|
||||
:type gpu: list or bool, optional
|
||||
|
||||
:param subgrid: flag to use sub-gridding.
|
||||
:type subgrid: bool, optional
|
||||
|
||||
:param geometry_only: build a model and produce any geometry views but do not run the simulation.
|
||||
:param autotranslate: for sub-gridding - auto translate objects with main grid
|
||||
coordinates to their equivalent local grid coordinate
|
||||
within the subgrid. If this option is off users must
|
||||
specify sub-grid object point within the global
|
||||
subgrid space.
|
||||
:type autotranslate: bool, optional
|
||||
|
||||
:param geometry_only: build a model and produce any geometry views but do
|
||||
not run the simulation.
|
||||
:type geometry_only: bool, optional
|
||||
|
||||
:param geometry_fixed: build a model and produce any geometry views but do not run the simulation.
|
||||
:param geometry_fixed: run a series of models where the geometry does not
|
||||
change between models.
|
||||
:type geometry_fixed: bool, optional
|
||||
|
||||
:param write_processed: write another input file after any Python code and
|
||||
in the original input file has been processed.
|
||||
in the original input file has been processed.
|
||||
:type write_processed: bool, optional
|
||||
"""
|
||||
|
||||
@@ -101,7 +127,8 @@ def run(
|
||||
args.mpi_no_spawn = mpi_no_spawn
|
||||
args.mpicomm = mpicomm
|
||||
args.gpu = gpu
|
||||
args.subgrid=subgrid
|
||||
args.subgrid = subgrid
|
||||
args.autotranslate = autotranslate
|
||||
args.geometry_only = geometry_only
|
||||
args.geometry_fixed = geometry_fixed
|
||||
args.write_processed = write_processed
|
||||
|
@@ -48,7 +48,7 @@ class FDTDGrid:
|
||||
"""
|
||||
|
||||
self.title = ''
|
||||
self.name = 'Main'
|
||||
self.name = 'main_grid'
|
||||
self.model_num = model_num
|
||||
|
||||
self.nx = 0
|
||||
@@ -346,7 +346,7 @@ class CUDAGrid(FDTDGrid):
|
||||
|
||||
def reset_fields(self):
|
||||
"""Clear arrays for field components and PMLs."""
|
||||
|
||||
|
||||
super().reset_fields()
|
||||
|
||||
# Clear arrays for field components
|
||||
|
@@ -62,7 +62,7 @@ def process_python_include_code(inputfile, usernamespace):
|
||||
|
||||
# Process any Python code
|
||||
if(inputlines[x].startswith('#python:')):
|
||||
|
||||
log.warning('#python blocks are deprecated and will be removed in the next release of gprMax. Please convert your model to use our Python API instead.')
|
||||
# String to hold Python code to be executed
|
||||
pythoncode = ''
|
||||
x += 1
|
||||
|
@@ -209,16 +209,17 @@ class ModelBuildRun:
|
||||
gb.build_materials()
|
||||
|
||||
# Check to see if numerical dispersion might be a problem
|
||||
results = dispersion_analysis(G)
|
||||
if results['error']:
|
||||
log.warning(Fore.RED + f"\nNumerical dispersion analysis not carried out as {results['error']}" + Style.RESET_ALL)
|
||||
elif results['N'] < config.model_configs[G.model_num].numdispersion['mingridsampling']:
|
||||
raise GeneralError(f"Non-physical wave propagation: Material '{results['material'].ID}' has wavelength sampled by {results['N']} cells, less than required minimum for physical wave propagation. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
|
||||
elif (results['deltavp'] and np.abs(results['deltavp']) >
|
||||
config.model_configs[G.model_num].numdispersion['maxnumericaldisp']):
|
||||
log.warning(Fore.RED + f"\nPotentially significant numerical dispersion. Estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz" + Style.RESET_ALL)
|
||||
elif results['deltavp']:
|
||||
log.info(f"\nNumerical dispersion analysis: estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
|
||||
for grid in grids:
|
||||
results = dispersion_analysis(grid)
|
||||
if results['error']:
|
||||
log.warning(Fore.RED + f"\nNumerical dispersion analysis ({grid.name}) not carried out as {results['error']}" + Style.RESET_ALL)
|
||||
elif results['N'] < config.model_configs[G.model_num].numdispersion['mingridsampling']:
|
||||
raise GeneralError(f"\nNon-physical wave propagation in {grid.name} detected. Material '{results['material'].ID}' has wavelength sampled by {results['N']} cells, less than required minimum for physical wave propagation. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
|
||||
elif (results['deltavp'] and np.abs(results['deltavp']) >
|
||||
config.model_configs[G.model_num].numdispersion['maxnumericaldisp']):
|
||||
log.warning(Fore.RED + f"\n{grid.name} has potentially significant numerical dispersion. Estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz" + Style.RESET_ALL)
|
||||
elif results['deltavp']:
|
||||
log.info(f"\nNumerical dispersion analysis ({grid.name}): estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
|
||||
|
||||
def reuse_geometry(self):
|
||||
# Reset iteration number
|
||||
@@ -293,8 +294,6 @@ class ModelBuildRun:
|
||||
tsolve (float): time taken to execute solving (seconds).
|
||||
"""
|
||||
|
||||
log.info(f'\nOutput file: {config.model_configs[self.G.model_num].output_file_path_ext.name}')
|
||||
|
||||
# Check number of OpenMP threads
|
||||
if config.sim_config.general['cpu']:
|
||||
log.info(f'CPU (OpenMP) threads for solving: {config.model_configs[self.G.model_num].ompthreads}\n')
|
||||
@@ -306,7 +305,7 @@ class ModelBuildRun:
|
||||
|
||||
# Prepare iterator
|
||||
if config.sim_config.is_messages():
|
||||
iterator = tqdm(range(self.G.iterations), desc='Running simulation, model ' + str(self.G.model_num + 1) + '/' + str(config.sim_config.model_end), ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.sim_config.general['progressbars'])
|
||||
iterator = tqdm(range(self.G.iterations), desc=f'Running model {self.G.model_num + 1}/{config.sim_config.model_end}, {config.model_configs[self.G.model_num].output_file_path_ext.name}', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.sim_config.general['progressbars'])
|
||||
else:
|
||||
iterator = range(self.G.iterations)
|
||||
|
||||
@@ -329,7 +328,7 @@ class GridBuilder:
|
||||
def build_pmls(self):
|
||||
log.info('')
|
||||
pbar = tqdm(total=sum(1 for value in self.grid.pmlthickness.values() if value > 0),
|
||||
desc=f'Building {self.grid.name} Grid PML boundaries',
|
||||
desc=f'Building PML boundaries ({self.grid.name})',
|
||||
ncols=get_terminal_width() - 1, file=sys.stdout,
|
||||
disable=not config.sim_config.general['progressbars'])
|
||||
for pml_id, thickness in self.grid.pmlthickness.items():
|
||||
@@ -342,7 +341,7 @@ class GridBuilder:
|
||||
# Build the model, i.e. set the material properties (ID) for every edge
|
||||
# of every Yee cell
|
||||
log.info('')
|
||||
pbar = tqdm(total=2, desc=f'Building {self.grid.name} Grid',
|
||||
pbar = tqdm(total=2, desc=f'Building Yee cells ({self.grid.name})',
|
||||
ncols=get_terminal_width() - 1, file=sys.stdout,
|
||||
disable=not config.sim_config.general['progressbars'])
|
||||
build_electric_components(self.grid.solid, self.grid.rigidE, self.grid.ID, self.grid)
|
||||
@@ -373,5 +372,5 @@ class GridBuilder:
|
||||
materialstable.outer_border = False
|
||||
materialstable.justify_columns[0] = 'right'
|
||||
|
||||
log.info(f'\n{self.grid.name} Grid Materials:')
|
||||
log.info(f'\nMaterials ({self.grid.name}):')
|
||||
log.info(materialstable.table)
|
||||
|
@@ -133,11 +133,6 @@ class Scene:
|
||||
# Process main grid multiple commands
|
||||
self.process_cmds(self.multiple_cmds, G)
|
||||
|
||||
# Estimate and check memory (RAM) usage
|
||||
log.debug('Fix memory checks')
|
||||
# G.memory_check()
|
||||
#snapshot_memory_check(G)
|
||||
|
||||
# Initialise an array for volumetric material IDs (solid), boolean
|
||||
# arrays for specifying materials not to be averaged (rigid),
|
||||
# an array for cell edge IDs (ID)
|
||||
|
@@ -24,8 +24,8 @@ from ..grid import FDTDGrid
|
||||
|
||||
class SubGridBase(FDTDGrid):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__()
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(args[0])
|
||||
|
||||
self.mode = '3D'
|
||||
self.ratio = kwargs['ratio']
|
||||
|
@@ -30,8 +30,8 @@ class SubGridHSG(SubGridBase):
|
||||
|
||||
gridtype = '3DSUBGRID'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
def __init__(self, model_num, **kwargs):
|
||||
super().__init__(model_num, **kwargs)
|
||||
self.gridtype = SubGridHSG.gridtype
|
||||
|
||||
def update_magnetic_is(self, precursors):
|
||||
@@ -40,7 +40,7 @@ class SubGridHSG(SubGridBase):
|
||||
Args:
|
||||
nwl, nwm, nwn, face, field, inc_field, lookup_id, sign, mod, co
|
||||
"""
|
||||
|
||||
|
||||
# Hz = c0Hz - c1Ey + c2Ex
|
||||
# Hy = c0Hy - c3Ex + c1Ez
|
||||
# Hx = c0Hx - c2Ez + c3Ey
|
||||
@@ -131,37 +131,29 @@ class SubGridHSG(SubGridBase):
|
||||
|
||||
def __str__(self):
|
||||
|
||||
self.memory_estimate_basic()
|
||||
mem_use = self.mem_est_basic()
|
||||
|
||||
s = '\n'
|
||||
s += Fore.CYAN
|
||||
s += 'Sub Grid HSG\n'
|
||||
s += 'Name: {}\n'.format(self.name)
|
||||
s += 'dx, dy, dz: {}m {}m {}m\n'.format(self.dx, self.dy, self.dz)
|
||||
s += 'dt: {}s\n'.format(self.dt)
|
||||
s += 'Memory Estimate: {}\n'.format(human_size(self.memoryusage))
|
||||
s += 'Position: ({}m, {}m, {}m), ({}m, {}m, {}m)\n'.format(self.x1,
|
||||
self.y1,
|
||||
self.z1,
|
||||
self.x2,
|
||||
self.y2,
|
||||
self.z2)
|
||||
s += 'Main Grid Indices: lower left({}, {}, {}), upper right({}, {}, {})\n'.format(self.i0, self.j0, self.k0, self.i1, self.j1, self.k1)
|
||||
s += 'Total Cells: {} {} {}\n'.format(self.nx, self.ny, self.nz)
|
||||
s += 'Working Region Cells: {} {} {}\n'.format(self.nwx,
|
||||
self.nwy,
|
||||
self.nwz)
|
||||
s += f'Name: {self.name}\n'
|
||||
s += f'dx, dy, dz: {self.dx}m {self.dy}m {self.dz}m\n'
|
||||
s += f'dt: {self.dt}s\n'
|
||||
s += f'Memory Estimate: {human_size(mem_use)}\n'
|
||||
s += f'Position: ({self.x1}m, {self.y1}m, {self.z1}m), ({self.x2}m, {self.y2}m, {self.z2}m)\n'
|
||||
s += f'Main Grid Indices: lower left({self.io}, {self.j0}, {self.k0}), upper right({self.i1}, {self.j1}, {self.k1})\n'
|
||||
s += f'Total Cells: {self.nx} {self.ny} {self.nz}\n'
|
||||
s += f'Working Region Cells: {self.nwx} {self.nwy} {self.nwz}\n'
|
||||
|
||||
for h in self.hertziandipoles:
|
||||
s += 'Hertizian dipole: {} {} {}\n'.format(h.xcoord,
|
||||
h.ycoord,
|
||||
h.zcoord)
|
||||
s += f'Hertizian dipole: {h.xcoord} {h.ycoord} {h.zcoord}\n'
|
||||
s += str([x for x in self.waveforms
|
||||
if x.ID == h.waveformID][0]) + '\n'
|
||||
for r in self.rxs:
|
||||
s += 'Receiver: {} {} {}\n'.format(r.xcoord, r.ycoord, r.zcoord)
|
||||
s += f'Receiver: {r.xcoord} {r.ycoord} {r.zcoord}\n'
|
||||
|
||||
for tl in self.transmissionlines:
|
||||
s += 'Transmission Line: {} {} {}\n'.format(tl.xcoord, tl.ycoord, tl.zcoord)
|
||||
s += f'Transmission Line: {tl.xcoord} {tl.ycoord} {tl.zcoord}\n'
|
||||
s += str([x for x in self.waveforms
|
||||
if x.ID == tl.waveformID][0]) + '\n'
|
||||
s += Style.RESET_ALL
|
||||
|
@@ -96,9 +96,6 @@ class SubGridBase(UserObjectMulti):
|
||||
# Set the temporal discretisation
|
||||
sg.calculate_dt()
|
||||
|
||||
# ensure stability
|
||||
sg.round_time_step()
|
||||
|
||||
# set the indices related to the subgrids main grid placement
|
||||
self.set_main_grid_indices(sg, grid, uip, p1, p2)
|
||||
|
||||
@@ -128,8 +125,6 @@ class SubGridBase(UserObjectMulti):
|
||||
|
||||
# Copy over built in materials
|
||||
sg.materials = [copy(m) for m in grid.materials if m.numID in range(0, grid.n_built_in_materials + 1)]
|
||||
# use same number of threads
|
||||
sg.nthreads = grid.nthreads
|
||||
|
||||
# Dont mix and match different subgrids
|
||||
for sg_made in grid.subgrids:
|
||||
@@ -194,10 +189,8 @@ class SubGridHSG(SubGridBase):
|
||||
self.hash = '#subgrid_hsg'
|
||||
|
||||
def create(self, grid, uip):
|
||||
sg = SubGridHSGUser(**self.kwargs)
|
||||
sg = SubGridHSGUser(grid.model_num, **self.kwargs)
|
||||
self.setup(sg, grid, uip)
|
||||
if config.is_messages():
|
||||
print(sg)
|
||||
return sg
|
||||
|
||||
|
||||
@@ -219,4 +212,4 @@ class ReferenceRx(Rx):
|
||||
r.offset = ratio // 2
|
||||
|
||||
except KeyError:
|
||||
raise CmdInputError("'{}' has an no ratio parameter".format(self.__str__()))
|
||||
raise CmdInputError(f"'{self.__str__()}' has an no ratio parameter")
|
||||
|
@@ -46,10 +46,10 @@ def create_user_input_points(grid, user_obj):
|
||||
if isinstance(grid, SubGridBase):
|
||||
# Local object configuration trumps. User can turn of autotranslate for
|
||||
# specfic objects.
|
||||
if not user_obj.autotranslate and config.general['autotranslate']:
|
||||
if not user_obj.autotranslate and config.sim_config.general['autotranslate']:
|
||||
return MainGridUserInput(grid)
|
||||
|
||||
if config.general['autotranslate']:
|
||||
if config.sim_config.general['autotranslate']:
|
||||
return SubgridUserInput(grid)
|
||||
else:
|
||||
return MainGridUserInput(grid)
|
||||
|
@@ -28,7 +28,7 @@ import subprocess
|
||||
from shutil import get_terminal_size
|
||||
import sys
|
||||
import textwrap
|
||||
from time import process_time
|
||||
from time import perf_counter
|
||||
|
||||
from colorama import init
|
||||
from colorama import Fore
|
||||
@@ -485,4 +485,4 @@ def detect_check_gpus(deviceIDs):
|
||||
|
||||
def timer():
|
||||
"""Function to return the current process wide time in fractional seconds."""
|
||||
return process_time()
|
||||
return perf_counter()
|
||||
|
@@ -18,7 +18,6 @@
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
@@ -51,7 +50,7 @@ def mpl_plot(filename, outputs=Rx.defaultoutputs, fft=False):
|
||||
|
||||
# Check there are any receivers
|
||||
if nrx == 0:
|
||||
raise CmdInputError('No receivers found in {}'.format(filename))
|
||||
raise CmdInputError(f'No receivers found in {filename}')
|
||||
|
||||
# Check for single output component when doing a FFT
|
||||
if fft:
|
||||
@@ -77,7 +76,7 @@ def mpl_plot(filename, outputs=Rx.defaultoutputs, fft=False):
|
||||
output = outputs[0]
|
||||
|
||||
if output not in availableoutputs:
|
||||
raise CmdInputError('{} output requested to plot, but the available output for receiver 1 is {}'.format(output, ', '.join(availableoutputs)))
|
||||
raise CmdInputError(f"{output} output requested to plot, but the available output for receiver 1 is {', '.join(availableoutputs)}")
|
||||
|
||||
outputdata = f[path + output][:] * polarity
|
||||
|
||||
@@ -165,7 +164,7 @@ def mpl_plot(filename, outputs=Rx.defaultoutputs, fft=False):
|
||||
|
||||
# Check if requested output is in file
|
||||
if output not in availableoutputs:
|
||||
raise CmdInputError('Output(s) requested to plot: {}, but available output(s) for receiver {} in the file: {}'.format(', '.join(outputs), rx, ', '.join(availableoutputs)))
|
||||
raise CmdInputError(f"Output(s) requested to plot: {', '.join(outputs)}, but available output(s) for receiver {rx} in the file: {', '.join(availableoutputs)}")
|
||||
|
||||
outputdata = f[path + output][:] * polarity
|
||||
|
||||
|
@@ -1,64 +0,0 @@
|
||||
import gprMax
|
||||
|
||||
scene = gprMax.Scene()
|
||||
|
||||
# global configuration
|
||||
# objects within the inner surface can be positioned automatically
|
||||
# in this configuration coordinates in the main grid Space
|
||||
# are converted to subgrid local space automatically
|
||||
# if objects or required in the region between the inner Surface
|
||||
# and the outer surface autotranslate must be set to False
|
||||
# and the local position must be set explicitly. Addionally,
|
||||
# in this instance, objects which occur within the IS OS gap
|
||||
# must be positioned in the subgrid and the main grid.
|
||||
gprMax.config.general['autotranslate'] = True
|
||||
|
||||
# Points are specified as iterables
|
||||
p1 = (1, 1, 1)
|
||||
|
||||
# single objects
|
||||
dxdydz = gprMax.Discretisation(p1=(1e-2, 1e-2, 1e-2))
|
||||
messages = gprMax.Messages(yn='y')
|
||||
tw = gprMax.TimeWindow(iterations=250)
|
||||
domain = gprMax.Domain(p1=p1)
|
||||
title = gprMax.Title(name='mysimulation')
|
||||
waveform = gprMax.Waveform(wave_type='gaussiandotnorm', amp=1, freq=400e6, id='mywaveform')
|
||||
|
||||
# position in subgrid automatically
|
||||
dipole = gprMax.HertzianDipole(p1=(0.5, 0.5, 0.5), polarisation='y', waveform_id='mywaveform')
|
||||
|
||||
# equivalent position when autotranslate is false
|
||||
#rx = gprMax.Rx(p1=(50 * 1e-2 / 5, 50 * 1e-2 / 5, 50 * 1e-2 / 5))
|
||||
|
||||
# rx in the subgrid
|
||||
# subgrid data is stored in an additional output file called
|
||||
# outputfile_<subgrid_id>.out
|
||||
rx1 = gprMax.Rx(p1=(0.52, 0.5, 0.5))
|
||||
|
||||
# rx in the main grid
|
||||
rx2 = gprMax.Rx(p1=(0.2, 0.5, 0.5))
|
||||
|
||||
# set the position of the Inner Surface
|
||||
subgrid = gprMax.SubGridHSG(p1=(45e-2, 45e-2, 45e-2),
|
||||
p2=(55e-2, 55e-2, 55e-2),
|
||||
ratio=3,
|
||||
id='subgrid1',
|
||||
filter=False)
|
||||
#pml_separation=6,
|
||||
#subgrid_pml_thickness=10)
|
||||
|
||||
scene = gprMax.Scene()
|
||||
scene.add(dxdydz)
|
||||
scene.add(messages)
|
||||
scene.add(tw)
|
||||
scene.add(domain)
|
||||
scene.add(title)
|
||||
scene.add(subgrid)
|
||||
scene.add(rx2)
|
||||
|
||||
subgrid.add(waveform)
|
||||
subgrid.add(dipole)
|
||||
subgrid.add(rx1)
|
||||
|
||||
#gprMax.run(scenes=[scene], n=1, geometry_only=False, outputfile='mysimulation', geometry_fixed=False, subgrid=True)
|
||||
gprMax.run(scenes=[scene], n=1, geometry_only=False, outputfile='mysimulation', geometry_fixed=False, subgrid=True)
|
@@ -0,0 +1,137 @@
|
||||
# Copyright (C) 2015-2019, John Hartley
|
||||
#
|
||||
# This module is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
# To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import gprMax
|
||||
from user_libs.antennas.GSSI import antenna_like_GSSI_400
|
||||
|
||||
import numpy as np
|
||||
|
||||
# file path step
|
||||
fn = Path(__file__).with_suffix('')
|
||||
parts = fn.parts
|
||||
|
||||
# subgrid Discretisation is 1 mm in x, y, z directions. This allows us
|
||||
# to model the geometry of the antenna
|
||||
dl_s = 1e-3
|
||||
# subgridding ratio. This must always be an odd integer multiple. In this case
|
||||
# the main grid discrestisation is 9e-3 m.
|
||||
ratio = 9
|
||||
dl = dl_s * 9
|
||||
|
||||
# estimated return time for signal to propagate 1 metre and back
|
||||
tw = 2 / 3e8 * (np.sqrt(3.2) + np.sqrt(9))
|
||||
|
||||
# domain extent
|
||||
x = 3
|
||||
y = 1
|
||||
z = 2
|
||||
|
||||
scene = gprMax.Scene()
|
||||
|
||||
title_gpr = gprMax.Title(name=fn.name)
|
||||
dxdydz = gprMax.Discretisation(p1=(dl, dl, dl))
|
||||
domain = gprMax.Domain(p1=(x, y, z))
|
||||
time_window = gprMax.TimeWindow(time=tw)
|
||||
|
||||
scene.add(domain)
|
||||
scene.add(title_gpr)
|
||||
scene.add(dxdydz)
|
||||
scene.add(time_window)
|
||||
|
||||
# half space material
|
||||
halfspace_m = gprMax.Material(er=3.2, se=0.397e-3, mr=1, sm=0, id='soil')
|
||||
scene.add(halfspace_m)
|
||||
|
||||
antenna_case = (0.3, 0.3, 0.178)
|
||||
|
||||
bounding_box = 2 * dl
|
||||
|
||||
# pml + boundary_cells + is_os + subgrid+boundary + half antenna
|
||||
x0 = (10 + 15 + 5 + 2) * dl + antenna_case[0] / 2
|
||||
|
||||
#antenna_p = (x / 2, y / 2, z - 30 * dl - bounding_box - antenna_case[2])
|
||||
|
||||
# Position of antenna base
|
||||
antenna_p = (x / 2, y / 2, 170 * dl)
|
||||
|
||||
sg_x0 = antenna_p[0] - antenna_case[0] / 2 - bounding_box
|
||||
sg_y0 = antenna_p[1] - antenna_case[1] / 2 - bounding_box
|
||||
sg_z0 = antenna_p[2] - bounding_box
|
||||
|
||||
sg_x1 = antenna_p[0] + antenna_case[0] / 2 + bounding_box
|
||||
sg_y1 = antenna_p[1] + antenna_case[1] / 2 + bounding_box
|
||||
sg_z1 = antenna_p[2] + antenna_case[2] + bounding_box
|
||||
|
||||
sg = gprMax.SubGridHSG(p1=[sg_x0, sg_y0, sg_z0], p2=[sg_x1, sg_y1, sg_z1], ratio=ratio, id='subgrid1')
|
||||
scene.add(sg)
|
||||
|
||||
# half space box in main grid
|
||||
halfspace = gprMax.Box(p1=(0, 0, 0), p2=(x, y, antenna_p[2]), material_id='soil')
|
||||
scene.add(halfspace)
|
||||
|
||||
# position half space box in the subgrid. The halfspace has to be positioned
|
||||
# manually because it traverses the grid. Grid traversal requries that objects extend
|
||||
# beyond the OS. Turning off autotranslate allows you to place objects beyond the OS.
|
||||
|
||||
# PML seperation from the OS
|
||||
ps = ratio // 2 + 2
|
||||
# number of pml cells in the subgrid
|
||||
pc = 6
|
||||
# is os seperation
|
||||
isos = 3 * ratio
|
||||
|
||||
h = antenna_p[2] - sg_z0 + (ps + pc + isos) * dl_s
|
||||
|
||||
# half space box
|
||||
halfspace = gprMax.Box(p1=(0, 0, 0), p2=(411 * dl_s, 411 * dl_s, h), material_id='soil')
|
||||
# position the box using local coordinates3e8 / 400e6
|
||||
halfspace.autotranslate = False
|
||||
sg.add(halfspace)
|
||||
|
||||
# Import the antenna model and add components to subgrid
|
||||
gssi_objects = antenna_like_GSSI_400(*antenna_p, resolution=dl_s)
|
||||
for obj in gssi_objects:
|
||||
sg.add(obj)
|
||||
|
||||
# half space box
|
||||
halfspace = gprMax.Box(p1=(0, 0, 0), p2=(x, y, antenna_p[2]), material_id='soil')
|
||||
scene.add(halfspace)
|
||||
|
||||
for i in range(1, 51):
|
||||
snap = gprMax.Snapshot(p1=(0, y / 2, 0), p2=(x, y / 2 + dl, z), dl=(dl, dl, dl),
|
||||
filename=Path(*parts[:-1], parts[-1] + '_' + str(i)).name,
|
||||
time=i * tw / 50)
|
||||
scene.add(snap)
|
||||
|
||||
# create a geometry view of the main grid and the sub grid stitched together
|
||||
gv = gprMax.GeometryView(p1=(0, 0, 0),
|
||||
p2=domain.props.p1,
|
||||
dl=dl,
|
||||
filename=fn.name,
|
||||
output_type='f',
|
||||
multi_grid=True)
|
||||
|
||||
# create a geometry view of the main grid and the sub grid stitched together
|
||||
gv_normal = gprMax.GeometryView(p1=(0, 0, 0),
|
||||
p2=domain.props.p1,
|
||||
dl=dl,
|
||||
filename=Path(*parts[:-1], parts[-1] + '_voxels').name,
|
||||
output_type='n')
|
||||
# scene.add(gv)
|
||||
scene.add(gv_normal)
|
||||
|
||||
# half space material
|
||||
layer_m = gprMax.Material(er=9, se=0.397e-3, mr=1, sm=0, id='soil_2')
|
||||
scene.add(layer_m)
|
||||
|
||||
fb = gprMax.FractalBox(p1=(0, 0, 0), p2=(3, 1, 1), frac_dim=1.5, weighting=(1, 1, 1), n_materials=1, mixing_model_id='soil_2', id='fbox', seed=1)
|
||||
scene.add(fb)
|
||||
|
||||
sr = gprMax.AddSurfaceRoughness(p1=(0, 0, 1), p2=(3, 1, 1), frac_dim=1.5, weighting=(1, 1), limits=(0.4, 1.2), fractal_box_id='fbox', seed=1)
|
||||
scene.add(sr)
|
||||
|
||||
gprMax.run(scenes=[scene], n=1, geometry_only=False, outputfile=fn.parent, subgrid=True, autotranslate=True)
|
在新工单中引用
屏蔽一个用户