Refactor AddGress UserObject build process

这个提交包含在:
nmannall
2024-05-17 14:05:14 +01:00
父节点 07052347de
当前提交 1d7b5ff0f9
共有 4 个文件被更改,包括 67 次插入26 次删除

查看文件

@@ -64,7 +64,7 @@ class AddGrass(UserObjectGeometry):
self.kwargs["p1"] = tuple(rot_pts[0, :]) self.kwargs["p1"] = tuple(rot_pts[0, :])
self.kwargs["p2"] = tuple(rot_pts[1, :]) self.kwargs["p2"] = tuple(rot_pts[1, :])
def build(self, grid, uip): def build(self, model, uip):
"""Add Grass to fractal box.""" """Add Grass to fractal box."""
try: try:
p1 = self.kwargs["p1"] p1 = self.kwargs["p1"]
@@ -91,7 +91,7 @@ class AddGrass(UserObjectGeometry):
self._do_rotate() self._do_rotate()
# Get the correct fractal volume # 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]
try: try:
volume = volumes[0] volume = volumes[0]
except NameError: except NameError:
@@ -103,7 +103,9 @@ class AddGrass(UserObjectGeometry):
xf, yf, zf = p2 xf, yf, zf = p2
if frac_dim < 0: 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 raise ValueError
if limits[0] < 0 or limits[1] < 0: if limits[0] < 0 or limits[1] < 0:
logger.exception( logger.exception(
@@ -112,12 +114,15 @@ class AddGrass(UserObjectGeometry):
raise ValueError raise ValueError
# Check for valid orientations # Check for valid orientations
grid = uip.grid
if xs == xf: if xs == xf:
if ys == yf or zs == zf: if ys == yf or zs == zf:
logger.exception(f"{self.__str__()} dimensions are not specified correctly") logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError raise ValueError
if xs not in [volume.xs, volume.xf]: if xs not in [volume.xs, volume.xf]:
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box") logger.exception(
f"{self.__str__()} must specify external surfaces on a fractal box"
)
raise ValueError raise ValueError
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx)) fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface # xminus surface
@@ -142,7 +147,9 @@ class AddGrass(UserObjectGeometry):
logger.exception(f"{self.__str__()} dimensions are not specified correctly") logger.exception(f"{self.__str__()} dimensions are not specified correctly")
raise ValueError raise ValueError
if ys not in [volume.ys, volume.yf]: if ys not in [volume.ys, volume.yf]:
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box") logger.exception(
f"{self.__str__()} must specify external surfaces on a fractal box"
)
raise ValueError raise ValueError
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy)) fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface # yminus surface
@@ -164,7 +171,9 @@ class AddGrass(UserObjectGeometry):
elif zs == zf: elif zs == zf:
if zs not in [volume.zs, volume.zf]: if zs not in [volume.zs, volume.zf]:
logger.exception(f"{self.__str__()} must specify external surfaces on a fractal box") logger.exception(
f"{self.__str__()} must specify external surfaces on a fractal box"
)
raise ValueError raise ValueError
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz)) fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface # zminus surface
@@ -219,7 +228,8 @@ class AddGrass(UserObjectGeometry):
# probability values, and convert the 1D index back into a x, y index # probability values, and convert the 1D index back into a x, y index
# for the original surface. # for the original surface.
bladesindex = np.unravel_index( bladesindex = np.unravel_index(
np.digitize(A, probability1D), (surface.fractalsurface.shape[0], surface.fractalsurface.shape[1]) np.digitize(A, probability1D),
(surface.fractalsurface.shape[0], surface.fractalsurface.shape[1]),
) )
# Set the fractal range to minimum and maximum heights of the grass blades # Set the fractal range to minimum and maximum heights of the grass blades
@@ -227,7 +237,9 @@ class AddGrass(UserObjectGeometry):
# Set the fractal surface using the pre-calculated spatial distribution # Set the fractal surface using the pre-calculated spatial distribution
# and a random height # and a random height
surface.fractalsurface = np.zeros((surface.fractalsurface.shape[0], surface.fractalsurface.shape[1])) surface.fractalsurface = np.zeros(
(surface.fractalsurface.shape[0], surface.fractalsurface.shape[1])
)
for i in range(len(bladesindex[0])): for i in range(len(bladesindex[0])):
surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint( surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint(
surface.fractalrange[0], surface.fractalrange[1], size=1 surface.fractalrange[0], surface.fractalrange[1], size=1
@@ -238,11 +250,11 @@ class AddGrass(UserObjectGeometry):
surface.grass.append(g) surface.grass.append(g)
# Check to see if grass has been already defined as a material # Check to see if grass has been already defined as a material
if not any(x.ID == "grass" for x in grid.materials): if not any(x.ID == "grass" for x in model.materials):
create_grass(grid) create_grass(model)
# Check if time step for model is suitable for using grass # Check if time step for model is suitable for using grass
grass = next((x for x in grid.materials if x.ID == "grass")) grass = next((x for x in model.materials if x.ID == "grass"))
testgrass = next((x for x in grass.tau if x < grid.dt), None) testgrass = next((x for x in grass.tau if x < grid.dt), None)
if testgrass: if testgrass:
logger.exception( logger.exception(

查看文件

@@ -16,6 +16,8 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>. # along with gprMax. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional, Tuple
import numpy as np import numpy as np
from scipy import fftpack from scipy import fftpack
@@ -32,7 +34,17 @@ class FractalSurface:
surfaceIDs = ["xminus", "xplus", "yminus", "yplus", "zminus", "zplus"] surfaceIDs = ["xminus", "xplus", "yminus", "yplus", "zminus", "zplus"]
def __init__(self, xs, xf, ys, yf, zs, zf, dimension, seed): def __init__(
self,
xs: float,
xf: float,
ys: float,
yf: float,
zs: float,
zf: float,
dimension: float,
seed: Optional[int] = None,
):
""" """
Args: Args:
xs, xf, ys, yf, zs, zf: floats for the extent of the fractal surface xs, xf, ys, yf, zs, zf: floats for the extent of the fractal surface
@@ -43,8 +55,9 @@ class FractalSurface:
seed: int for seed value for random number generator. seed: int for seed value for random number generator.
""" """
self.ID = None self.ID: str
self.surfaceID = None self.surfaceID: str
self.operatingonID: str
self.xs = xs self.xs = xs
self.xf = xf self.xf = xf
self.ys = ys self.ys = ys
@@ -56,9 +69,11 @@ class FractalSurface:
self.nz = zf - zs self.nz = zf - zs
self.dtype = np.dtype(np.complex128) self.dtype = np.dtype(np.complex128)
self.seed = seed self.seed = seed
self.dimension = dimension # Fractal dimension from: http://dx.doi.org/10.1017/CBO9781139174695 self.dimension = (
dimension # Fractal dimension from: http://dx.doi.org/10.1017/CBO9781139174695
)
self.weighting = np.array([1, 1], dtype=np.float64) self.weighting = np.array([1, 1], dtype=np.float64)
self.fractalrange = (0, 0) self.fractalrange: Tuple[int, int] = (0, 0)
self.filldepth = 0 self.filldepth = 0
self.grass = [] self.grass = []
@@ -82,7 +97,9 @@ class FractalSurface:
self.fractalsurface = np.zeros(surfacedims, dtype=self.dtype) self.fractalsurface = np.zeros(surfacedims, dtype=self.dtype)
# Positional vector at centre of array, scaled by weighting # Positional vector at centre of array, scaled by weighting
v1 = np.array([self.weighting[0] * (surfacedims[0]) / 2, self.weighting[1] * (surfacedims[1]) / 2]) v1 = np.array(
[self.weighting[0] * (surfacedims[0]) / 2, self.weighting[1] * (surfacedims[1]) / 2]
)
# 2D array of random numbers to be convolved with the fractal function # 2D array of random numbers to be convolved with the fractal function
rng = np.random.default_rng(seed=self.seed) rng = np.random.default_rng(seed=self.seed)
@@ -137,8 +154,8 @@ class FractalVolume:
seed: int for seed value for random number generator. seed: int for seed value for random number generator.
""" """
self.ID = None self.ID: str
self.operatingonID = None self.operatingonID: str
self.xs = xs self.xs = xs
self.xf = xf self.xf = xf
self.ys = ys self.ys = ys
@@ -157,7 +174,9 @@ class FractalVolume:
self.averaging = False self.averaging = False
self.dtype = np.dtype(np.complex128) self.dtype = np.dtype(np.complex128)
self.seed = seed self.seed = seed
self.dimension = dimension # Fractal dimension from: http://dx.doi.org/10.1017/CBO9781139174695 self.dimension = (
dimension # Fractal dimension from: http://dx.doi.org/10.1017/CBO9781139174695
)
self.weighting = np.array([1, 1, 1], dtype=np.float64) self.weighting = np.array([1, 1, 1], dtype=np.float64)
self.nbins = 0 self.nbins = 0
self.fractalsurfaces = [] self.fractalsurfaces = []
@@ -176,7 +195,9 @@ class FractalVolume:
filterscaling = np.amin(np.array([self.nx, self.ny])) / np.array([self.nx, self.ny]) filterscaling = np.amin(np.array([self.nx, self.ny])) / np.array([self.nx, self.ny])
filterscaling = np.insert(filterscaling, 2, 1) filterscaling = np.insert(filterscaling, 2, 1)
else: else:
filterscaling = np.amin(np.array([self.nx, self.ny, self.nz])) / np.array([self.nx, self.ny, self.nz]) filterscaling = np.amin(np.array([self.nx, self.ny, self.nz])) / np.array(
[self.nx, self.ny, self.nz]
)
# Adjust weighting to account for filter scaling # Adjust weighting to account for filter scaling
self.weighting = np.multiply(self.weighting, filterscaling) self.weighting = np.multiply(self.weighting, filterscaling)
@@ -185,7 +206,11 @@ class FractalVolume:
# Positional vector at centre of array, scaled by weighting # Positional vector at centre of array, scaled by weighting
v1 = np.array( v1 = np.array(
[self.weighting[0] * self.nx / 2, self.weighting[1] * self.ny / 2, self.weighting[2] * self.nz / 2] [
self.weighting[0] * self.nx / 2,
self.weighting[1] * self.ny / 2,
self.weighting[2] * self.nz / 2,
]
) )
# 3D array of random numbers to be convolved with the fractal function # 3D array of random numbers to be convolved with the fractal function
@@ -225,7 +250,9 @@ class FractalVolume:
bins = np.linspace(np.amin(self.fractalvolume), np.amax(self.fractalvolume), self.nbins) bins = np.linspace(np.amin(self.fractalvolume), np.amax(self.fractalvolume), self.nbins)
for j in range(self.ny): for j in range(self.ny):
for k in range(self.nz): for k in range(self.nz):
self.fractalvolume[:, j, k] = np.digitize(self.fractalvolume[:, j, k], bins, right=True) self.fractalvolume[:, j, k] = np.digitize(
self.fractalvolume[:, j, k], bins, right=True
)
def generate_volume_mask(self): def generate_volume_mask(self):
"""Generate a 3D volume to use as a mask for adding rough surfaces, """Generate a 3D volume to use as a mask for adding rough surfaces,
@@ -254,7 +281,9 @@ class Grass:
""" """
self.numblades = numblades self.numblades = numblades
self.geometryparams = np.zeros((self.numblades, 6), dtype=config.sim_config.dtypes["float_or_double"]) self.geometryparams = np.zeros(
(self.numblades, 6), dtype=config.sim_config.dtypes["float_or_double"]
)
self.seed = seed self.seed = seed
self.set_geometry_parameters() self.set_geometry_parameters()

查看文件

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

查看文件

@@ -26,6 +26,7 @@ import numpy as np
import psutil import psutil
from colorama import Fore, Style, init from colorama import Fore, Style, init
from gprMax.fractals import FractalVolume
from gprMax.grid.cuda_grid import CUDAGrid from gprMax.grid.cuda_grid import CUDAGrid
from gprMax.grid.opencl_grid import OpenCLGrid from gprMax.grid.opencl_grid import OpenCLGrid
from gprMax.materials import ListMaterial, Material, PeplinskiSoil, RangeMaterial from gprMax.materials import ListMaterial, Material, PeplinskiSoil, RangeMaterial
@@ -67,6 +68,7 @@ class Model:
self.subgrids: List[SubGridBaseGrid] = [] self.subgrids: List[SubGridBaseGrid] = []
self.materials: List[Material] = [] self.materials: List[Material] = []
self.mixingmodels: List[Union[PeplinskiSoil, RangeMaterial, ListMaterial]] = [] self.mixingmodels: List[Union[PeplinskiSoil, RangeMaterial, ListMaterial]] = []
self.fractalvolumes: List[FractalVolume] = []
self.geometryviews: List[GeometryView] = [] self.geometryviews: List[GeometryView] = []
self.geometryobjects: List[GeometryObjects] = [] self.geometryobjects: List[GeometryObjects] = []