Refactor remaining UserObjectGeometry build processes

这个提交包含在:
nmannall
2024-05-17 14:57:58 +01:00
父节点 1d7b5ff0f9
当前提交 444f2a6a7f
共有 15 个文件被更改,包括 294 次插入130 次删除

查看文件

@@ -65,7 +65,7 @@ class AddSurfaceRoughness(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -91,7 +91,7 @@ class AddSurfaceRoughness(UserObjectGeometry):
self._do_rotate()
# Get the correct fractal volume
volumes = [volume for volume in grid.fractalvolumes if volume.ID == fractal_box_id]
volumes = [volume for volume in model.fractalvolumes if volume.ID == fractal_box_id]
if volumes:
volume = volumes[0]
else:
@@ -103,7 +103,9 @@ class AddSurfaceRoughness(UserObjectGeometry):
xf, yf, zf = p2
if frac_dim < 0:
logger.exception(f"{self.__str__()} requires a positive value for the " + "fractal dimension")
logger.exception(
f"{self.__str__()} requires a positive value for the " + "fractal dimension"
)
raise ValueError
if weighting[0] < 0:
logger.exception(
@@ -119,12 +121,15 @@ class AddSurfaceRoughness(UserObjectGeometry):
raise ValueError
# Check for valid orientations
grid = uip.grid
if xs == xf:
if ys == yf or zs == zf:
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if xs not in [volume.xs, volume.xf]:
logger.exception(f"{self.__str__()} can only be used on the external surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external surfaces of a fractal box"
)
raise ValueError
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface
@@ -155,7 +160,10 @@ class AddSurfaceRoughness(UserObjectGeometry):
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if ys not in [volume.ys, volume.yf]:
logger.exception(f"{self.__str__()} can only be used on the external " + "surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external "
+ "surfaces of a fractal box"
)
raise ValueError
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface
@@ -183,7 +191,10 @@ class AddSurfaceRoughness(UserObjectGeometry):
elif zs == zf:
if zs not in [volume.zs, volume.zf]:
logger.exception(f"{self.__str__()} can only be used on the external " + "surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external "
+ "surfaces of a fractal box"
)
raise ValueError
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface
@@ -222,7 +233,9 @@ class AddSurfaceRoughness(UserObjectGeometry):
# List of existing surfaces IDs
existingsurfaceIDs = [x.surfaceID for x in volume.fractalsurfaces]
if surface.surfaceID in existingsurfaceIDs:
logger.exception(f"{self.__str__()} has already been used on the {surface.surfaceID} surface")
logger.exception(
f"{self.__str__()} has already been used on the {surface.surfaceID} surface"
)
raise ValueError
surface.generate_fractal_surface()

查看文件

@@ -60,7 +60,7 @@ class AddSurfaceWater(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip):
def build(self, model, uip):
""" "Create surface water on fractal box."""
try:
p1 = self.kwargs["p1"]
@@ -74,7 +74,7 @@ class AddSurfaceWater(UserObjectGeometry):
if self.do_rotate:
self._do_rotate()
if volumes := [volume for volume in grid.fractalvolumes if volume.ID == fractal_box_id]:
if volumes := [volume for volume in model.fractalvolumes if volume.ID == fractal_box_id]:
volume = volumes[0]
else:
logger.exception(f"{self.__str__()} cannot find FractalBox {fractal_box_id}")
@@ -89,12 +89,15 @@ class AddSurfaceWater(UserObjectGeometry):
raise ValueError
# Check for valid orientations
grid = uip.grid
if xs == xf:
if ys == yf or zs == zf:
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if xs not in [volume.xs, volume.xf]:
logger.exception(f"{self.__str__()} can only be used on the external surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external surfaces of a fractal box"
)
raise ValueError
# xminus surface
if xs == volume.xs:
@@ -110,7 +113,9 @@ class AddSurfaceWater(UserObjectGeometry):
logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError
if ys not in [volume.ys, volume.yf]:
logger.exception(f"{self.__str__()} can only be used on the external surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external surfaces of a fractal box"
)
raise ValueError
# yminus surface
if ys == volume.ys:
@@ -123,7 +128,9 @@ class AddSurfaceWater(UserObjectGeometry):
elif zs == zf:
if zs not in [volume.zs, volume.zf]:
logger.exception(f"{self.__str__()} can only be used on the external surfaces of a fractal box")
logger.exception(
f"{self.__str__()} can only be used on the external surfaces of a fractal box"
)
raise ValueError
# zminus surface
if zs == volume.zs:
@@ -148,7 +155,10 @@ class AddSurfaceWater(UserObjectGeometry):
surface.filldepth = filldepthcells
# Check that requested fill depth falls within range of surface roughness
if surface.filldepth < surface.fractalrange[0] or surface.filldepth > surface.fractalrange[1]:
if (
surface.filldepth < surface.fractalrange[0]
or surface.filldepth > surface.fractalrange[1]
):
logger.exception(
f"{self.__str__()} requires a value for the depth of water that lies with the "
f"range of the requested surface roughness"
@@ -156,11 +166,11 @@ class AddSurfaceWater(UserObjectGeometry):
raise ValueError
# Check to see if water has been already defined as a material
if not any(x.ID == "water" for x in grid.materials):
create_water(grid)
if not any(x.ID == "water" for x in model.materials):
create_water(model)
# Check if time step for model is suitable for using water
water = next((x for x in grid.materials if x.ID == "water"))
water = next((x for x in model.materials if x.ID == "water"))
if testwater := next((x for x in water.tau if x < grid.dt), None):
logger.exception(
f"{self.__str__()} requires the time step for the model "

查看文件

@@ -60,7 +60,7 @@ class Box(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -89,7 +89,7 @@ class Box(UserObjectGeometry):
averagebox = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagebox = grid.averagevolumeobjects
averagebox = model.averagevolumeobjects
p3, p4 = uip.check_box_points(p1, p2, self.__str__())
# Find nearest point on grid without translation
@@ -99,7 +99,7 @@ class Box(UserObjectGeometry):
xf, yf, zf = p4
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -118,11 +118,11 @@ class Box(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -132,8 +132,9 @@ class Box(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
grid = uip.grid
build_box(
xs,
xf,

查看文件

@@ -48,7 +48,7 @@ class Cone(UserObjectGeometry):
super().__init__(**kwargs)
self.hash = "#cone"
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -64,7 +64,7 @@ class Cone(UserObjectGeometry):
averagecylinder = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylinder = grid.averagevolumeobjects
averagecylinder = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -85,11 +85,15 @@ class Cone(UserObjectGeometry):
x2, y2, z2 = uip.round_to_grid(p2)
if r1 < 0:
logger.exception(f"{self.__str__()} the radius of the first face {r1:g} should be a positive value.")
logger.exception(
f"{self.__str__()} the radius of the first face {r1:g} should be a positive value."
)
raise ValueError
if r2 < 0:
logger.exception(f"{self.__str__()} the radius of the second face {r2:g} should be a positive value.")
logger.exception(
f"{self.__str__()} the radius of the second face {r2:g} should be a positive value."
)
raise ValueError
if r1 == 0 and r2 == 0:
@@ -97,7 +101,7 @@ class Cone(UserObjectGeometry):
raise ValueError
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -116,11 +120,11 @@ class Cone(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -130,8 +134,9 @@ class Cone(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
grid = uip.grid
build_cone(
x1,
y1,

查看文件

@@ -46,7 +46,7 @@ class Cylinder(UserObjectGeometry):
super().__init__(**kwargs)
self.hash = "#cylinder"
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -61,7 +61,7 @@ class Cylinder(UserObjectGeometry):
averagecylinder = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylinder = grid.averagevolumeobjects
averagecylinder = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -86,7 +86,7 @@ class Cylinder(UserObjectGeometry):
raise ValueError
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -105,11 +105,11 @@ class Cylinder(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -119,8 +119,9 @@ class Cylinder(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
grid = uip.grid
build_cylinder(
x1,
y1,

查看文件

@@ -55,7 +55,7 @@ class CylindricalSector(UserObjectGeometry):
super().__init__(**kwargs)
self.hash = "#cylindrical_sector"
def build(self, grid, uip):
def build(self, model, uip):
try:
normal = self.kwargs["normal"].lower()
ctr1 = self.kwargs["ctr1"]
@@ -76,7 +76,7 @@ class CylindricalSector(UserObjectGeometry):
averagecylindricalsector = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagecylindricalsector = grid.averagevolumeobjects
averagecylindricalsector = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -99,14 +99,18 @@ class CylindricalSector(UserObjectGeometry):
if r <= 0:
logger.exception(f"{self.__str__()} the radius {r:g} should be a positive value.")
if sectorstartangle < 0 or sectorangle <= 0:
logger.exception(f"{self.__str__()} the starting angle and sector angle should be a positive values.")
logger.exception(
f"{self.__str__()} the starting angle and sector angle should be a positive values."
)
raise ValueError
if sectorstartangle >= 2 * np.pi or sectorangle >= 2 * np.pi:
logger.exception(f"{self.__str__()} the starting angle and sector angle must be less than 360 degrees.")
logger.exception(
f"{self.__str__()} the starting angle and sector angle must be less than 360 degrees."
)
raise ValueError
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -125,11 +129,11 @@ class CylindricalSector(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = f"{materials[0].ID}+{materials[1].ID}+{materials[2].ID}"
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -139,7 +143,7 @@ class CylindricalSector(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
else:
averaging = False
# Isotropic case
@@ -166,6 +170,7 @@ class CylindricalSector(UserObjectGeometry):
elif normal == "z":
ctr1, ctr2, level = uip.round_to_grid((ctr1, ctr2, extent1))
grid = uip.grid
build_cylindrical_sector(
ctr1,
ctr2,

查看文件

@@ -54,7 +54,7 @@ class Edge(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip):
def build(self, model, uip):
"""Creates edge and adds it to the grid."""
try:
p1 = self.kwargs["p1"]
@@ -74,12 +74,13 @@ class Edge(UserObjectGeometry):
xs, ys, zs = p1
xf, yf, zf = p2
material = next((x for x in grid.materials if x.ID == material_id), None)
material = next((x for x in model.materials if x.ID == material_id), None)
if not material:
logger.exception(f"Material with ID {material_id} does not exist")
raise ValueError
grid = uip.grid
# Check for valid orientations
# x-orientated edge
if (

查看文件

@@ -45,7 +45,7 @@ class Ellipsoid(UserObjectGeometry):
super().__init__(**kwargs)
self.hash = "#ellipsoid"
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
xr = self.kwargs["xr"]
@@ -62,7 +62,7 @@ class Ellipsoid(UserObjectGeometry):
averageellipsoid = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averageellipsoid = grid.averagevolumeobjects
averageellipsoid = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -81,7 +81,7 @@ class Ellipsoid(UserObjectGeometry):
xc, yc, zc = uip.discretise_point(p1)
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -100,11 +100,11 @@ class Ellipsoid(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -114,8 +114,9 @@ class Ellipsoid(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
grid = uip.grid
build_ellipsoid(
xc,
yc,

查看文件

@@ -24,6 +24,8 @@ import gprMax.config as config
from gprMax.cmds_geometry.cmds_geometry import UserObjectGeometry, rotate_2point_object
from gprMax.fractals import FractalVolume
from gprMax.materials import ListMaterial
from gprMax.model import Model
from gprMax.user_inputs import MainGridUserInput
from ..cython.geometry_primitives import build_voxels_from_array, build_voxels_from_array_mask
@@ -73,7 +75,7 @@ class FractalBox(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def pre_build(self, grid, uip):
def pre_build(self, model: Model, uip: MainGridUserInput):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -116,40 +118,55 @@ class FractalBox(UserObjectGeometry):
xf, yf, zf = p2
if frac_dim < 0:
logger.exception(f"{self.__str__()} requires a positive value for the fractal dimension")
logger.exception(
f"{self.__str__()} requires a positive value for the fractal dimension"
)
raise ValueError
if weighting[0] < 0:
logger.exception(f"{self.__str__()} requires a positive value for the fractal weighting in the x direction")
logger.exception(
f"{self.__str__()} requires a positive value for the fractal weighting in the x direction"
)
raise ValueError
if weighting[1] < 0:
logger.exception(f"{self.__str__()} requires a positive value for the fractal weighting in the y direction")
logger.exception(
f"{self.__str__()} requires a positive value for the fractal weighting in the y direction"
)
raise ValueError
if weighting[2] < 0:
logger.exception(f"{self.__str__()} requires a positive value for the fractal weighting in the z direction")
logger.exception(
f"{self.__str__()} requires a positive value for the fractal weighting in the z direction"
)
if n_materials < 0:
logger.exception(f"{self.__str__()} requires a positive value for the number of bins")
raise ValueError
# Find materials to use to build fractal volume, either from mixing
# models or normal materials.
mixingmodel = next((x for x in grid.mixingmodels if x.ID == mixing_model_id), None)
material = next((x for x in grid.materials if x.ID == mixing_model_id), None)
mixingmodel = next((x for x in model.mixingmodels if x.ID == mixing_model_id), None)
material = next((x for x in model.materials if x.ID == mixing_model_id), None)
nbins = n_materials
if mixingmodel:
if nbins == 1:
logger.exception(f"{self.__str__()} must be used with more than one material from the mixing model.")
logger.exception(
f"{self.__str__()} must be used with more than one material from the mixing model."
)
raise ValueError
if isinstance(mixingmodel, ListMaterial) and nbins > len(mixingmodel.mat):
logger.exception(
f"{self.__str__()} too many materials/bins " "requested compared to materials in " "mixing model."
f"{self.__str__()} too many materials/bins "
"requested compared to materials in "
"mixing model."
)
raise ValueError
# Create materials from mixing model as number of bins now known
# from fractal_box command.
mixingmodel.calculate_properties(nbins, grid)
mixingmodel.calculate_properties(nbins, model)
elif not material:
logger.exception(f"{self.__str__()} mixing model or material with " + "ID {mixing_model_id} does not exist")
logger.exception(
f"{self.__str__()} mixing model or material with "
+ "ID {mixing_model_id} does not exist"
)
raise ValueError
self.volume = FractalVolume(xs, xf, ys, yf, zs, zf, frac_dim, seed)
@@ -162,7 +179,7 @@ class FractalBox(UserObjectGeometry):
dielectricsmoothing = "on" if self.volume.averaging else "off"
logger.info(
f"{self.grid_name(grid)}Fractal box {self.volume.ID} from "
f"{self.grid_name(uip.grid)}Fractal box {self.volume.ID} from "
f"{p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, "
f"{p4[1]:g}m, {p4[2]:g}m with {self.volume.operatingonID}, "
f"fractal dimension {self.volume.dimension:g}, fractal weightings "
@@ -171,13 +188,14 @@ class FractalBox(UserObjectGeometry):
f"with {self.volume.nbins} material(s) created, dielectric smoothing "
f"is {dielectricsmoothing}."
)
grid.fractalvolumes.append(self.volume)
model.fractalvolumes.append(self.volume)
def build(self, grid, uip):
def build(self, model, uip):
if self.do_pre_build:
self.pre_build(grid, uip)
self.pre_build(model, uip)
self.do_pre_build = False
else:
grid = uip.grid
if self.volume.fractalsurfaces:
self.volume.originalxs = self.volume.xs
self.volume.originalxf = self.volume.xf
@@ -221,7 +239,9 @@ class FractalBox(UserObjectGeometry):
(self.volume.nx, self.volume.ny, self.volume.nz),
dtype=config.sim_config.dtypes["float_or_double"],
)
materialnumID = next(x.numID for x in grid.materials if x.ID == self.volume.operatingonID)
materialnumID = next(
x.numID for x in model.materials if x.ID == self.volume.operatingonID
)
self.volume.fractalvolume *= materialnumID
else:
self.volume.generate_fractal_volume()
@@ -229,7 +249,9 @@ class FractalBox(UserObjectGeometry):
for j in range(0, self.volume.ny):
for k in range(0, self.volume.nz):
numberinbin = self.volume.fractalvolume[i, j, k]
self.volume.fractalvolume[i, j, k] = self.volume.mixingmodel.matID[int(numberinbin)]
self.volume.fractalvolume[i, j, k] = self.volume.mixingmodel.matID[
int(numberinbin)
]
self.volume.generate_volume_mask()
@@ -242,28 +264,49 @@ class FractalBox(UserObjectGeometry):
for j in range(surface.ys, surface.yf):
for k in range(surface.zs, surface.zf):
if i > surface.fractalsurface[j - surface.ys, k - surface.zs]:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 1
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and i > surface.filldepth:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 2
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 0
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.surfaceID == "xplus":
if not surface.ID:
for i in range(surface.fractalrange[0], surface.fractalrange[1]):
for j in range(surface.ys, surface.yf):
for k in range(surface.zs, surface.zf):
if i < surface.fractalsurface[j - surface.ys, k - surface.zs]:
if (
i
< surface.fractalsurface[j - surface.ys, k - surface.zs]
):
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and i < surface.filldepth:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.ID == "grass":
g = surface.grass[0]
@@ -275,9 +318,14 @@ class FractalBox(UserObjectGeometry):
height = 0
for i in range(self.volume.xs, surface.fractalrange[1]):
if (
i < surface.fractalsurface[j - surface.ys, k - surface.zs]
i
< surface.fractalsurface[
j - surface.ys, k - surface.zs
]
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
!= 1
):
@@ -311,11 +359,15 @@ class FractalBox(UserObjectGeometry):
i
> self.volume.originalxf
- (
surface.fractalsurface[j - surface.ys, k - surface.zs]
surface.fractalsurface[
j - surface.ys, k - surface.zs
]
- self.volume.originalxf
)
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
== 1
):
@@ -343,28 +395,49 @@ class FractalBox(UserObjectGeometry):
for j in range(surface.fractalrange[0], surface.fractalrange[1]):
for k in range(surface.zs, surface.zf):
if j > surface.fractalsurface[i - surface.xs, k - surface.zs]:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 1
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and j > surface.filldepth:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 2
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 0
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.surfaceID == "yplus":
if not surface.ID:
for i in range(surface.xs, surface.xf):
for j in range(surface.fractalrange[0], surface.fractalrange[1]):
for k in range(surface.zs, surface.zf):
if j < surface.fractalsurface[i - surface.xs, k - surface.zs]:
if (
j
< surface.fractalsurface[i - surface.xs, k - surface.zs]
):
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and j < surface.filldepth:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.ID == "grass":
g = surface.grass[0]
@@ -376,9 +449,14 @@ class FractalBox(UserObjectGeometry):
height = 0
for j in range(self.volume.ys, surface.fractalrange[1]):
if (
j < surface.fractalsurface[i - surface.xs, k - surface.zs]
j
< surface.fractalsurface[
i - surface.xs, k - surface.zs
]
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
!= 1
):
@@ -412,11 +490,15 @@ class FractalBox(UserObjectGeometry):
j
> self.volume.originalyf
- (
surface.fractalsurface[i - surface.xs, k - surface.zs]
surface.fractalsurface[
i - surface.xs, k - surface.zs
]
- self.volume.originalyf
)
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
== 1
):
@@ -444,28 +526,51 @@ class FractalBox(UserObjectGeometry):
for j in range(surface.ys, surface.yf):
for k in range(surface.fractalrange[0], surface.fractalrange[1]):
if k > surface.fractalsurface[i - surface.xs, j - surface.ys]:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 1
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and k > surface.filldepth:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 2
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[i - self.volume.xs, j - self.volume.ys, k - self.volume.zs] = 0
self.volume.mask[
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.surfaceID == "zplus":
if not surface.ID:
for i in range(surface.xs, surface.xf):
for j in range(surface.ys, surface.yf):
for k in range(surface.fractalrange[0], surface.fractalrange[1]):
if k < surface.fractalsurface[i - surface.xs, j - surface.ys]:
for k in range(
surface.fractalrange[0], surface.fractalrange[1]
):
if (
k
< surface.fractalsurface[i - surface.xs, j - surface.ys]
):
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 1
elif surface.filldepth > 0 and k < surface.filldepth:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 2
else:
self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
] = 0
elif surface.ID == "grass":
g = surface.grass[0]
@@ -477,9 +582,14 @@ class FractalBox(UserObjectGeometry):
height = 0
for k in range(self.volume.zs, surface.fractalrange[1]):
if (
k < surface.fractalsurface[i - surface.xs, j - surface.ys]
k
< surface.fractalsurface[
i - surface.xs, j - surface.ys
]
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
!= 1
):
@@ -513,11 +623,15 @@ class FractalBox(UserObjectGeometry):
k
> self.volume.originalzf
- (
surface.fractalsurface[i - surface.xs, j - surface.ys]
surface.fractalsurface[
i - surface.xs, j - surface.ys
]
- self.volume.originalzf
)
and self.volume.mask[
i - self.volume.xs, j - self.volume.ys, k - self.volume.zs
i - self.volume.xs,
j - self.volume.ys,
k - self.volume.zs,
]
== 1
):
@@ -541,8 +655,8 @@ class FractalBox(UserObjectGeometry):
root += 1
# Build voxels from any true values of the 3D mask array
waternumID = next((x.numID for x in grid.materials if x.ID == "water"), 0)
grassnumID = next((x.numID for x in grid.materials if x.ID == "grass"), 0)
waternumID = next((x.numID for x in model.materials if x.ID == "water"), 0)
grassnumID = next((x.numID for x in model.materials if x.ID == "grass"), 0)
data = self.volume.fractalvolume.astype("int16", order="C")
mask = self.volume.mask.copy(order="C")
build_voxels_from_array_mask(
@@ -575,7 +689,9 @@ class FractalBox(UserObjectGeometry):
for j in range(0, self.volume.ny):
for k in range(0, self.volume.nz):
numberinbin = self.volume.fractalvolume[i, j, k]
self.volume.fractalvolume[i, j, k] = self.volume.mixingmodel.matID[int(numberinbin)]
self.volume.fractalvolume[i, j, k] = self.volume.mixingmodel.matID[
int(numberinbin)
]
data = self.volume.fractalvolume.astype("int16", order="C")
build_voxels_from_array(

查看文件

@@ -39,7 +39,7 @@ class GeometryObjectsRead(UserObjectGeometry):
def rotate(self, axis, angle, origin=None):
pass
def build(self, grid, uip):
def build(self, model, uip):
"""Creates the object and adds it to the grid."""
try:
p1 = self.kwargs["p1"]
@@ -62,7 +62,7 @@ class GeometryObjectsRead(UserObjectGeometry):
matfile = Path(config.sim_config.input_file_path.parent, matfile)
matstr = matfile.with_suffix("").name
numexistmaterials = len(grid.materials)
numexistmaterials = len(model.materials)
# Read materials from file
with open(matfile, "r") as f:
@@ -82,10 +82,10 @@ class GeometryObjectsRead(UserObjectGeometry):
scene.add(material_obj)
# Creates the internal simulation objects
scene.process_cmds(material_objs, grid)
scene.process_cmds(material_objs, model)
# Update material type
for material in grid.materials:
for material in model.materials:
if material.numID >= numexistmaterials:
if material.type:
material.type += ",\nimported"
@@ -101,6 +101,7 @@ class GeometryObjectsRead(UserObjectGeometry):
# Open geometry object file and read/check spatial resolution attribute
f = h5py.File(geofile, "r")
dx_dy_dz = f.attrs["dx_dy_dz"]
grid = uip.grid
if round_value(
(dx_dy_dz[0] / grid.dx) != 1
or round_value(dx_dy_dz[1] / grid.dy) != 1
@@ -126,12 +127,18 @@ class GeometryObjectsRead(UserObjectGeometry):
rigidE = f["/rigidE"][:]
rigidH = f["/rigidH"][:]
ID = f["/ID"][:]
grid.solid[xs : xs + data.shape[0], ys : ys + data.shape[1], zs : zs + data.shape[2]] = (
data + numexistmaterials
grid.solid[
xs : xs + data.shape[0], ys : ys + data.shape[1], zs : zs + data.shape[2]
] = (data + numexistmaterials)
grid.rigidE[
:, xs : xs + rigidE.shape[1], ys : ys + rigidE.shape[2], zs : zs + rigidE.shape[3]
] = rigidE
grid.rigidH[
:, xs : xs + rigidH.shape[1], ys : ys + rigidH.shape[2], zs : zs + rigidH.shape[3]
] = rigidH
grid.ID[:, xs : xs + ID.shape[1], ys : ys + ID.shape[2], zs : zs + ID.shape[3]] = (
ID + numexistmaterials
)
grid.rigidE[:, xs : xs + rigidE.shape[1], ys : ys + rigidE.shape[2], zs : zs + rigidE.shape[3]] = rigidE
grid.rigidH[:, xs : xs + rigidH.shape[1], ys : ys + rigidH.shape[2], zs : zs + rigidH.shape[3]] = rigidH
grid.ID[:, xs : xs + ID.shape[1], ys : ys + ID.shape[2], zs : zs + ID.shape[3]] = ID + numexistmaterials
logger.info(
f"{self.grid_name(grid)}Geometry objects from file {geofile} "
f"inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, "

查看文件

@@ -55,7 +55,7 @@ class Plate(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
p2 = self.kwargs["p2"]
@@ -94,13 +94,14 @@ class Plate(UserObjectGeometry):
raise ValueError
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
logger.exception(f"{self.__str__()} material(s) {notfound} do not exist")
raise ValueError
grid = uip.grid
# yz-plane plate
if xs == xf:
# Isotropic case

查看文件

@@ -43,7 +43,7 @@ class Sphere(UserObjectGeometry):
super().__init__(**kwargs)
self.hash = "#sphere"
def build(self, grid, uip):
def build(self, model, uip):
try:
p1 = self.kwargs["p1"]
r = self.kwargs["r"]
@@ -57,7 +57,7 @@ class Sphere(UserObjectGeometry):
averagesphere = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagesphere = grid.averagevolumeobjects
averagesphere = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -76,7 +76,7 @@ class Sphere(UserObjectGeometry):
xc, yc, zc = uip.discretise_point(p1)
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -95,11 +95,11 @@ class Sphere(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -109,8 +109,9 @@ class Sphere(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
grid = uip.grid
build_sphere(
xc,
yc,

查看文件

@@ -63,7 +63,7 @@ class Triangle(UserObjectGeometry):
self.kwargs["p2"] = tuple(p2)
self.kwargs["p3"] = tuple(p3)
def build(self, grid, uip):
def build(self, model, uip):
try:
up1 = self.kwargs["p1"]
up2 = self.kwargs["p2"]
@@ -82,7 +82,7 @@ class Triangle(UserObjectGeometry):
averagetriangularprism = self.kwargs["averaging"]
except KeyError:
# Otherwise go with the grid default
averagetriangularprism = grid.averagevolumeobjects
averagetriangularprism = model.averagevolumeobjects
# Check materials have been specified
# Isotropic case
@@ -126,7 +126,7 @@ class Triangle(UserObjectGeometry):
raise ValueError
# Look up requested materials in existing list of material instances
materials = [y for x in materialsrequested for y in grid.materials if y.ID == x]
materials = [y for x in materialsrequested for y in model.materials if y.ID == x]
if len(materials) != len(materialsrequested):
notfound = [x for x in materialsrequested if x not in materials]
@@ -146,11 +146,11 @@ class Triangle(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
requiredID = materials[0].ID + "+" + materials[1].ID + "+" + materials[2].ID
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
averagedmaterial = [x for x in model.materials if x.ID == requiredID]
if averagedmaterial:
numID = averagedmaterial.numID
else:
numID = len(grid.materials)
numID = len(model.materials)
m = Material(numID, requiredID)
m.type = "dielectric-smoothed"
# Create dielectric-smoothed constituents for material
@@ -160,7 +160,7 @@ class Triangle(UserObjectGeometry):
m.sm = np.mean((materials[0].sm, materials[1].sm, materials[2].sm), axis=0)
# Append the new material object to the materials list
grid.materials.append(m)
model.materials.append(m)
else:
averaging = False
# Isotropic case
@@ -175,6 +175,7 @@ class Triangle(UserObjectGeometry):
numIDy = materials[1].numID
numIDz = materials[2].numID
grid = uip.grid
build_triangle(
x1,
y1,

查看文件

@@ -73,7 +73,6 @@ class FDTDGrid:
# corrections will be different.
self.pmls["thickness"] = OrderedDict((key, 10) for key in PML.boundaryIDs)
self.averagevolumeobjects = True
self.waveforms: List[Waveform] = []
self.voltagesources: List[VoltageSource] = []
self.hertziandipoles: List[HertzianDipole] = []

查看文件

@@ -66,9 +66,11 @@ class Model:
self.G = self._create_grid()
self.subgrids: List[SubGridBaseGrid] = []
self.materials: List[Material] = []
self.mixingmodels: List[Union[PeplinskiSoil, RangeMaterial, ListMaterial]] = []
self.fractalvolumes: List[FractalVolume] = []
self.averagevolumeobjects = True
self.geometryviews: List[GeometryView] = []
self.geometryobjects: List[GeometryObjects] = []