你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 23:14:03 +08:00
Updates to docstrings and formatting.
这个提交包含在:
@@ -29,20 +29,20 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddGrass(UserObjectGeometry):
|
||||
"""Allows you to add grass with roots to a FractalBox class in the model.
|
||||
"""Adds grass with roots to a FractalBox class in the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of a surface on a
|
||||
p1: list of the lower left (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
p2: a list of the upper right (x,y,z) coordinates of a surface on a
|
||||
p2: list of the upper right (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
frac_dim: a float for the fractal dimension which, for an orthogonal
|
||||
frac_dim:float for the fractal dimension which, for an orthogonal
|
||||
parallelepiped, should take values between zero and three.
|
||||
limits: a list to define lower and upper limits for a range over which
|
||||
limits: list to define lower and upper limits for a range over which
|
||||
the height of the blades of grass can vary.
|
||||
n_blades: an int for the number of blades of grass that should be
|
||||
n_blades:int for the number of blades of grass that should be
|
||||
applied to the surface area.
|
||||
fractal_box_id: a string identifier for the FractalBox class that the
|
||||
fractal_box_id: string identifier for the FractalBox class that the
|
||||
grass should be applied to.
|
||||
"""
|
||||
|
||||
@@ -191,7 +191,8 @@ class AddGrass(UserObjectGeometry):
|
||||
'enough for the number of grass blades/roots specified')
|
||||
raise ValueError
|
||||
|
||||
# Scale the distribution so that the summation is equal to one, i.e. a probability distribution
|
||||
# Scale the distribution so that the summation is equal to one,
|
||||
# i.e. a probability distribution
|
||||
surface.fractalsurface = surface.fractalsurface / np.sum(surface.fractalsurface)
|
||||
|
||||
# Set location of grass blades using probability distribution
|
||||
@@ -202,16 +203,23 @@ class AddGrass(UserObjectGeometry):
|
||||
R = np.random.RandomState(surface.seed)
|
||||
A = R.random_sample(n_blades)
|
||||
|
||||
# Locate the random numbers in the bins created by the 1D vector of probability values, and convert the 1D index back into a x, y index for the original surface.
|
||||
bladesindex = np.unravel_index(np.digitize(A, probability1D), (surface.fractalsurface.shape[0], surface.fractalsurface.shape[1]))
|
||||
# Locate the random numbers in the bins created by the 1D vector of
|
||||
# probability values, and convert the 1D index back into a x, y index
|
||||
# for the original surface.
|
||||
bladesindex = np.unravel_index(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
|
||||
surface.fractalrange = fractalrange
|
||||
|
||||
# Set the fractal surface using the pre-calculated spatial distribution and a random height
|
||||
surface.fractalsurface = np.zeros((surface.fractalsurface.shape[0], surface.fractalsurface.shape[1]))
|
||||
# Set the fractal surface using the pre-calculated spatial distribution
|
||||
# and a random height
|
||||
surface.fractalsurface = np.zeros((surface.fractalsurface.shape[0],
|
||||
surface.fractalsurface.shape[1]))
|
||||
for i in range(len(bladesindex[0])):
|
||||
surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint(surface.fractalrange[0], surface.fractalrange[1], size=1)
|
||||
surface.fractalsurface[bladesindex[0][i], bladesindex[1][i]] = R.randint(surface.fractalrange[0],
|
||||
surface.fractalrange[1], size=1)
|
||||
|
||||
# Create grass geometry parameters
|
||||
g = Grass(n_blades)
|
||||
|
@@ -28,20 +28,20 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddSurfaceRoughness(UserObjectGeometry):
|
||||
"""Allows you to add grass with roots to a FractalBox class in the model.
|
||||
"""Adds surface roughness to a FractalBox class in the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of a surface on a
|
||||
p1: list of the lower left (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
p2: a list of the upper right (x,y,z) coordinates of a surface on a
|
||||
p2: list of the upper right (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
frac_dim: a float for the fractal dimension which, for an orthogonal
|
||||
frac_dim: float for the fractal dimension which, for an orthogonal
|
||||
parallelepiped, should take values between zero and three.
|
||||
weighting: a list with weightings in the first and second direction of
|
||||
weighting: list with weightings in the first and second direction of
|
||||
the surface.
|
||||
limits: a list to define lower and upper limits for a range over which
|
||||
limits: ist to define lower and upper limits for a range over which
|
||||
the surface roughness can vary.
|
||||
fractal_box_id: a string identifier for the FractalBox class
|
||||
fractal_box_id: string identifier for the FractalBox class
|
||||
that the surface roughness should be applied to.
|
||||
seed: (optional) float parameter which controls the seeding of the random
|
||||
number generator used to create the fractals.
|
||||
@@ -119,7 +119,8 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(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))
|
||||
fractalrange = (round_value(limits[0] / grid.dx),
|
||||
round_value(limits[1] / grid.dx))
|
||||
# xminus surface
|
||||
if xs == volume.xs:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.xf:
|
||||
@@ -147,7 +148,8 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(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))
|
||||
fractalrange = (round_value(limits[0] / grid.dy),
|
||||
round_value(limits[1] / grid.dy))
|
||||
# yminus surface
|
||||
if ys == volume.ys:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.yf:
|
||||
@@ -175,7 +177,8 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(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))
|
||||
fractalrange = (round_value(limits[0] / grid.dz),
|
||||
round_value(limits[1] / grid.dz))
|
||||
# zminus surface
|
||||
if zs == volume.zs:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.zf:
|
||||
@@ -212,7 +215,8 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
# List of existing surfaces IDs
|
||||
existingsurfaceIDs = [x.surfaceID for x in volume.fractalsurfaces]
|
||||
if surface.surfaceID in existingsurfaceIDs:
|
||||
logger.exception(self.__str__() + f' has already been used on the {surface.surfaceID} surface')
|
||||
logger.exception(self.__str__() + f' has already been used on the ' +
|
||||
f'{surface.surfaceID} surface')
|
||||
raise ValueError
|
||||
|
||||
surface.generate_fractal_surface()
|
||||
|
@@ -28,17 +28,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddSurfaceWater(UserObjectGeometry):
|
||||
"""Allows you to add surface water to a FractalBox class in the model.
|
||||
"""Adds surface water to a FractalBox class in the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of a surface on a
|
||||
p1: list of the lower left (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
p2: a list of the upper right (x,y,z) coordinates of a surface on a
|
||||
p2: list of the upper right (x,y,z) coordinates of a surface on a
|
||||
FractalBox class.
|
||||
depth: a float that defines the depth of the water, which should be
|
||||
depth: float that defines the depth of the water, which should be
|
||||
specified relative to the dimensions of the #fractal_box that
|
||||
the surface water is being applied.
|
||||
fractal_box_id: a string identifier for the FractalBox class that the
|
||||
fractal_box_id: string identifier for the FractalBox class that the
|
||||
surface water should be applied to.
|
||||
"""
|
||||
|
||||
@@ -87,7 +87,8 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
xf, yf, zf = p2
|
||||
|
||||
if depth <= 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the depth of water')
|
||||
logger.exception(self.__str__() + ' requires a positive value for ' +
|
||||
'the depth of water')
|
||||
raise ValueError
|
||||
|
||||
# Check for valid orientations
|
||||
@@ -148,7 +149,8 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
|
||||
surface = next((x for x in volume.fractalsurfaces if x.surfaceID == requestedsurface), None)
|
||||
if not surface:
|
||||
logger.exception(self.__str__() + f' specified surface {requestedsurface} does not have a rough surface applied')
|
||||
logger.exception(self.__str__() + f' specified surface {requestedsurface} ' +
|
||||
'does not have a rough surface applied')
|
||||
raise ValueError
|
||||
|
||||
surface.filldepth = filldepthcells
|
||||
|
@@ -28,16 +28,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Box(UserObjectGeometry):
|
||||
"""Allows you to introduce an orthogonal parallelepiped with specific
|
||||
properties into the model.
|
||||
"""Introduces an orthogonal parallelepiped with specific properties into
|
||||
the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of the parallelepiped.
|
||||
p2: a list of the upper right (x,y,z) coordinates of the parallelepiped.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
p1: list of the lower left (x,y,z) coordinates of the parallelepiped.
|
||||
p2: list of the upper right (x,y,z) coordinates of the parallelepiped.
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -124,15 +124,20 @@ class Box(UserObjectGeometry):
|
||||
m = Material(numID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create dielectric-smoothed constituents for material
|
||||
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.er = np.mean((materials[0].er, materials[1].er,
|
||||
materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se,
|
||||
materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
||||
build_box(xs, xf, ys, yf, zs, zf, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_box(xs, xf, ys, yf, zs, zf, numID, numIDx, numIDy, numIDz,
|
||||
averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
dielectricsmoothing = 'on' if averaging else 'off'
|
||||
|
||||
|
@@ -45,15 +45,15 @@ class UserObjectGeometry:
|
||||
return f'{self.hash}: {s[:-1]}'
|
||||
|
||||
def create(self, grid, uip):
|
||||
"""Create object and add it to the grid."""
|
||||
"""Creates object and adds it to the grid."""
|
||||
pass
|
||||
|
||||
def rotate(self, axis, angle, origin=None):
|
||||
"""Rotate object - specialised for each object."""
|
||||
"""Rotates object - specialised for each object."""
|
||||
pass
|
||||
|
||||
def grid_name(self, grid):
|
||||
"""Return subgrid name for use with logging info. Return an empty
|
||||
"""Returns subgrid name for use with logging info. Returns an empty
|
||||
string if the grid is the main grid.
|
||||
"""
|
||||
|
||||
@@ -64,16 +64,16 @@ class UserObjectGeometry:
|
||||
|
||||
|
||||
def rotate_point(p, axis, angle, origin=(0, 0, 0)):
|
||||
"""Rotate a point.
|
||||
"""Rotates a point.
|
||||
|
||||
Args:
|
||||
p: an array of coordinates of point (x, y, z).
|
||||
axis: a string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: an int specifying the angle of rotation (degrees).
|
||||
origin: a tuple defining the point about which to perform rotation (x, y, z).
|
||||
p: array of coordinates of point (x, y, z).
|
||||
axis: string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: int specifying the angle of rotation (degrees).
|
||||
origin: tuple defining the point about which to perform rotation (x, y, z).
|
||||
|
||||
Returns:
|
||||
p: an array of coordinates of rotated point (x, y, z)
|
||||
p: array of coordinates of rotated point (x, y, z)
|
||||
"""
|
||||
|
||||
origin = np.array(origin)
|
||||
@@ -97,13 +97,13 @@ def rotate_2point_object(pts, axis, angle, origin=None):
|
||||
"""Rotate a geometry object that is defined by 2 points.
|
||||
|
||||
Args:
|
||||
pts: an array ofcoordinates of points of object to be rotated.
|
||||
axis: a string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: an int specifying the angle of rotation (degrees).
|
||||
origin: a tuple defining the point about which to perform rotation (x, y, z).
|
||||
pts: array ofcoordinates of points of object to be rotated.
|
||||
axis: string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: int specifying the angle of rotation (degrees).
|
||||
origin: tuple defining the point about which to perform rotation (x, y, z).
|
||||
|
||||
Returns:
|
||||
new_pts: an array of coordinates of points of rotated object.
|
||||
new_pts: array of coordinates of points of rotated object.
|
||||
"""
|
||||
|
||||
# Use origin at centre of object if not given
|
||||
@@ -152,18 +152,18 @@ def rotate_2point_object(pts, axis, angle, origin=None):
|
||||
|
||||
|
||||
def rotate_polarisation(p, polarisation, axis, angle, G):
|
||||
"""Rotate a geometry object that is defined by a point and polarisation.
|
||||
"""Rotates a geometry object that is defined by a point and polarisation.
|
||||
|
||||
Args:
|
||||
p: an array of coordinates of point (x, y, z).
|
||||
polarisation: a string defining the current polarisation (x, y, or z).
|
||||
axis: a string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: an int specifying the angle of rotation (degrees).
|
||||
p: array of coordinates of point (x, y, z).
|
||||
polarisation: string defining the current polarisation (x, y, or z).
|
||||
axis: string which defines the axis about which to perform rotation (x, y, or z).
|
||||
angle: int specifying the angle of rotation (degrees).
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
|
||||
Returns:
|
||||
pts: an array of coordinates of points of rotated object.
|
||||
new_polarisation: a string defining the new polarisation (x, y, or z).
|
||||
pts: array of coordinates of points of rotated object.
|
||||
new_polarisation: string defining the new polarisation (x, y, or z).
|
||||
"""
|
||||
|
||||
if polarisation.lower() == 'x':
|
||||
|
@@ -28,18 +28,18 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Cylinder(UserObjectGeometry):
|
||||
"""Allows you to introduce a circular cylinder into the model.
|
||||
"""Introduces a circular cylinder into the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the coordinates (x,y,z) of the centre of the first face
|
||||
p1: list of the coordinates (x,y,z) of the centre of the first face
|
||||
of the cylinder.
|
||||
p2: a list of the coordinates (x,y,z) of the centre of the second face
|
||||
p2: list of the coordinates (x,y,z) of the centre of the second face
|
||||
of the cylinder.
|
||||
r: float of the radius of the cylinder.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -113,10 +113,14 @@ class Cylinder(UserObjectGeometry):
|
||||
m = Material(numID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create dielectric-smoothed constituents for material
|
||||
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.er = np.mean((materials[0].er, materials[1].er,
|
||||
materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se,
|
||||
materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
@@ -28,28 +28,27 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CylindricalSector(UserObjectGeometry):
|
||||
"""Allows you to introduce a cylindrical sector (shaped like a slice of pie)
|
||||
into the model.
|
||||
"""Introduces a cylindrical sector (shaped like a slice of pie) into the model.
|
||||
|
||||
Attributes:
|
||||
normal: a string for the direction of the axis of the cylinder from which
|
||||
normal: string for the direction of the axis of the cylinder from which
|
||||
the sector is defined and can be x, y, or z.
|
||||
ctr1: a float for the first coordinate of the centre of the cylindrical
|
||||
ctr1: float for the first coordinate of the centre of the cylindrical
|
||||
sector.
|
||||
ctr2: a float for the second coordinate of the centre of the cylindrical
|
||||
ctr2: float for the second coordinate of the centre of the cylindrical
|
||||
sector.
|
||||
extent1: a float for the first thickness from the centre of the
|
||||
extent1: float for the first thickness from the centre of the
|
||||
cylindrical sector.
|
||||
extent2: a float for the second thickness from the centre of the
|
||||
extent2: float for the second thickness from the centre of the
|
||||
cylindrical sector.
|
||||
r: a float for the radius of the cylindrical sector.
|
||||
start: a float for the starting angle (in degrees) for the cylindrical
|
||||
r: float for the radius of the cylindrical sector.
|
||||
start: float for the starting angle (in degrees) for the cylindrical
|
||||
sector.
|
||||
end: a float for the angle (in degrees) swept by the cylindrical sector.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
end: float for the angle (in degrees) swept by the cylindrical sector.
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -138,10 +137,14 @@ class CylindricalSector(UserObjectGeometry):
|
||||
m = Material(numID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create dielectric-smoothed constituents for material
|
||||
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.er = np.mean((materials[0].er, materials[1].er,
|
||||
materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se,
|
||||
materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
@@ -28,12 +28,12 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Edge(UserObjectGeometry):
|
||||
"""Allows you to introduce a wire with specific properties into the model.
|
||||
"""Introduces a wire with specific properties into the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the coordinates (x,y,z) of the starting point of the edge.
|
||||
p2: a list of the coordinates (x,y,z) of the ending point of the edge.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
p1: list of the coordinates (x,y,z) of the starting point of the edge.
|
||||
p2: list of the coordinates (x,y,z) of the ending point of the edge.
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
"""
|
||||
|
||||
@@ -49,14 +49,14 @@ class Edge(UserObjectGeometry):
|
||||
self.dorotate = True
|
||||
|
||||
def __dorotate(self):
|
||||
"""Perform rotation."""
|
||||
"""Performs rotation."""
|
||||
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
|
||||
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
|
||||
self.kwargs['p1'] = tuple(rot_pts[0, :])
|
||||
self.kwargs['p2'] = tuple(rot_pts[1, :])
|
||||
|
||||
def create(self, grid, uip):
|
||||
"""Create edge and add it to the grid."""
|
||||
"""Creates edge and adds it to the grid."""
|
||||
try:
|
||||
p1 = self.kwargs['p1']
|
||||
p2 = self.kwargs['p2']
|
||||
|
@@ -27,27 +27,27 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FractalBox(UserObjectGeometry):
|
||||
"""Allows you to introduce an orthogonal parallelepiped with fractal
|
||||
distributed properties which are related to a mixing model or
|
||||
normal material into the model.
|
||||
"""Introduces an orthogonal parallelepiped with fractal distributed
|
||||
properties which are related to a mixing model or normal material into
|
||||
the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of the parallelepiped.
|
||||
p2: a list of the upper right (x,y,z) coordinates of the parallelepiped.
|
||||
frac_dim: a float for the fractal dimension which, for an orthogonal
|
||||
p1: list of the lower left (x,y,z) coordinates of the parallelepiped.
|
||||
p2: list of the upper right (x,y,z) coordinates of the parallelepiped.
|
||||
frac_dim: float for the fractal dimension which, for an orthogonal
|
||||
parallelepiped, should take values between zero and three.
|
||||
weighting: a list of the weightings in the x, y, z direction of the
|
||||
weighting: list of the weightings in the x, y, z direction of the
|
||||
parallelepiped.
|
||||
n_materials: an int of the number of materials to use for the fractal
|
||||
n_materials: int of the number of materials to use for the fractal
|
||||
distribution (defined according to the associated
|
||||
mixing model). This should be set to one if using a
|
||||
normal material instead of a mixing model.
|
||||
mixing_model_id: a string identifier for the associated mixing model or
|
||||
mixing_model_id: string identifier for the associated mixing model or
|
||||
material.
|
||||
id: a string identifier for the fractal box itself.
|
||||
seed: seed: (optional) float parameter which controls the seeding of the random
|
||||
number generator used to create the fractals.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
id: string identifier for the fractal box itself.
|
||||
seed: (optional) float parameter which controls the seeding of the
|
||||
random number generator used to create the fractals.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -62,7 +62,7 @@ class FractalBox(UserObjectGeometry):
|
||||
self.dorotate = True
|
||||
|
||||
def __dorotate(self):
|
||||
"""Perform rotation."""
|
||||
"""Performs rotation."""
|
||||
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
|
||||
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
|
||||
self.kwargs['p1'] = tuple(rot_pts[0, :])
|
||||
@@ -94,7 +94,8 @@ class FractalBox(UserObjectGeometry):
|
||||
# Go with user specified averaging
|
||||
averagefractalbox = self.kwargs['averaging']
|
||||
except KeyError:
|
||||
# If they havent specfied - default is no dielectric smoothing for a fractal box
|
||||
# If they havent specified - default is no dielectric smoothing for
|
||||
# a fractal box.
|
||||
averagefractalbox = False
|
||||
|
||||
p3 = uip.round_to_grid_static_point(p1)
|
||||
@@ -124,7 +125,8 @@ class FractalBox(UserObjectGeometry):
|
||||
'number of bins')
|
||||
raise ValueError
|
||||
|
||||
# Find materials to use to build fractal volume, either from mixing models or normal materials
|
||||
# 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)
|
||||
nbins = n_materials
|
||||
@@ -134,7 +136,8 @@ class FractalBox(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' must be used with more than ' +
|
||||
'one material from the mixing model.')
|
||||
raise ValueError
|
||||
# Create materials from mixing model as number of bins now known from fractal_box command
|
||||
# Create materials from mixing model as number of bins now known
|
||||
# from fractal_box command.
|
||||
mixingmodel.calculate_debye_properties(nbins, grid)
|
||||
elif not material:
|
||||
logger.exception(self.__str__() + f' mixing model or material with ' +
|
||||
|
@@ -124,7 +124,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add y, z coordinates to existing location
|
||||
yy = int(j - volume.ys + y)
|
||||
zz = int(k - volume.zs + z)
|
||||
# If these coordinates are outwith fractal volume stop building the blade, otherwise set the mask for grass
|
||||
# If these coordinates are outwith fractal volume stop building the blade,
|
||||
# otherwise set the mask for grass.
|
||||
if yy < 0 or yy >= volume.mask.shape[1] or zz < 0 or zz >= volume.mask.shape[2]:
|
||||
break
|
||||
else:
|
||||
@@ -146,7 +147,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add y, z coordinates to existing location
|
||||
yy = int(j - volume.ys + y)
|
||||
zz = int(k - volume.zs + z)
|
||||
# If these coordinates are outwith the fractal volume stop building the root, otherwise set the mask for grass
|
||||
# If these coordinates are outwith the fractal volume stop building the root,
|
||||
# otherwise set the mask for grass.
|
||||
if yy < 0 or yy >= volume.mask.shape[1] or zz < 0 or zz >= volume.mask.shape[2]:
|
||||
break
|
||||
else:
|
||||
@@ -192,7 +194,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add x, z coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
zz = int(k - volume.zs + z)
|
||||
# If these coordinates are outwith fractal volume stop building the blade, otherwise set the mask for grass
|
||||
# If these coordinates are outwith fractal volume stop building the blade,
|
||||
# otherwise set the mask for grass.
|
||||
if xx < 0 or xx >= volume.mask.shape[0] or zz < 0 or zz >= volume.mask.shape[2]:
|
||||
break
|
||||
else:
|
||||
@@ -214,7 +217,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add x, z coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
zz = int(k - volume.zs + z)
|
||||
# If these coordinates are outwith the fractal volume stop building the root, otherwise set the mask for grass
|
||||
# If these coordinates are outwith the fractal volume stop building the root,
|
||||
# otherwise set the mask for grass.
|
||||
if xx < 0 or xx >= volume.mask.shape[0] or zz < 0 or zz >= volume.mask.shape[2]:
|
||||
break
|
||||
else:
|
||||
@@ -260,7 +264,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add x, y coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
yy = int(j - volume.ys + y)
|
||||
# If these coordinates are outwith the fractal volume stop building the blade, otherwise set the mask for grass
|
||||
# If these coordinates are outwith the fractal volume stop building the blade,
|
||||
# otherwise set the mask for grass.
|
||||
if xx < 0 or xx >= volume.mask.shape[0] or yy < 0 or yy >= volume.mask.shape[1]:
|
||||
break
|
||||
else:
|
||||
@@ -282,7 +287,8 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
# Add x, y coordinates to existing location
|
||||
xx = int(i - volume.xs + x)
|
||||
yy = int(j - volume.ys + y)
|
||||
# If these coordinates are outwith the fractal volume stop building the root, otherwise set the mask for grass
|
||||
# If these coordinates are outwith the fractal volume stop building the root,
|
||||
# otherwise set the mask for grass.
|
||||
if xx < 0 or xx >= volume.mask.shape[0] or yy < 0 or yy >= volume.mask.shape[1]:
|
||||
break
|
||||
else:
|
||||
|
@@ -40,7 +40,7 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
pass
|
||||
|
||||
def create(self, grid, uip):
|
||||
"""Create the object and add it to the grid."""
|
||||
"""Creates the object and adds it to the grid."""
|
||||
try:
|
||||
p1 = self.kwargs['p1']
|
||||
geofile = self.kwargs['geofile']
|
||||
@@ -88,7 +88,8 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
else:
|
||||
material.type = 'imported'
|
||||
|
||||
# See if geometry object file exists at specified path and if not try input file directory
|
||||
# See if geometry object file exists at specified path and if not try
|
||||
# input file directory.
|
||||
geofile = Path(geofile)
|
||||
if not geofile.exists():
|
||||
geofile = Path(config.sim_config.input_file_path.parent, geofile)
|
||||
|
@@ -28,14 +28,14 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Plate(UserObjectGeometry):
|
||||
"""Allows you to introduce a plate with specific properties into the model.
|
||||
"""Introduces a plate with specific properties into the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the lower left (x,y,z) coordinates of the plate.
|
||||
p2: a list of the upper right (x,y,z) coordinates of the plate.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
p1: list of the lower left (x,y,z) coordinates of the plate.
|
||||
p2: list of the upper right (x,y,z) coordinates of the plate.
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -50,7 +50,7 @@ class Plate(UserObjectGeometry):
|
||||
self.dorotate = True
|
||||
|
||||
def __dorotate(self):
|
||||
"""Perform rotation."""
|
||||
"""Performs rotation."""
|
||||
pts = np.array([self.kwargs['p1'], self.kwargs['p2']])
|
||||
rot_pts = rotate_2point_object(pts, self.axis, self.angle, self.origin)
|
||||
self.kwargs['p1'] = tuple(rot_pts[0, :])
|
||||
|
@@ -28,16 +28,15 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sphere(UserObjectGeometry):
|
||||
"""Allows you to introduce a spherical object with specific parameters
|
||||
into the model.
|
||||
"""Introduces a spherical object with specific parameters into the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the coordinates (x,y,z) of the centre of the sphere.
|
||||
r: a float of radius of the sphere.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
p1: list of the coordinates (x,y,z) of the centre of the sphere.
|
||||
r: float of radius of the sphere.
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -104,15 +103,21 @@ class Sphere(UserObjectGeometry):
|
||||
m = Material(numID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create dielectric-smoothed constituents for material
|
||||
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.er = np.mean((materials[0].er, materials[1].er,
|
||||
materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se,
|
||||
materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
||||
build_sphere(xc, yc, zc, r, grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_sphere(xc, yc, zc, r, grid.dx, grid.dy, grid.dz, numID,
|
||||
numIDx, numIDy, numIDz, averaging, grid.solid,
|
||||
grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
dielectricsmoothing = 'on' if averaging else 'off'
|
||||
logger.info(self.grid_name(grid) + f"Sphere with centre {p2[0]:g}m, " +
|
||||
|
@@ -28,19 +28,19 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Triangle(UserObjectGeometry):
|
||||
"""Allows you to introduce a triangular patch or a triangular prism with
|
||||
specific properties into the model.
|
||||
"""Introduces a triangular patch or a triangular prism with specific
|
||||
properties into the model.
|
||||
|
||||
Attributes:
|
||||
p1: a list of the coordinates (x,y,z) of the first apex of the triangle.
|
||||
p2: a list of the coordinates (x,y,z) of the second apex of the triangle.
|
||||
p3: a list of the coordinates (x,y,z) of the third apex of the triangle.
|
||||
thickness: a float for the thickness of the triangular prism. If the
|
||||
p1: list of the coordinates (x,y,z) of the first apex of the triangle.
|
||||
p2: list of the coordinates (x,y,z) of the second apex of the triangle.
|
||||
p3: list of the coordinates (x,y,z) of the third apex of the triangle.
|
||||
thickness: float for the thickness of the triangular prism. If the
|
||||
thickness is zero then a triangular patch is created.
|
||||
material_id: a string for the material identifier that must correspond
|
||||
material_id: string for the material identifier that must correspond
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
averaging: a string (y or n) used to switch on and off dielectric smoothing.
|
||||
material_ids: list of material identifiers in the x, y, z directions.
|
||||
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -48,14 +48,14 @@ class Triangle(UserObjectGeometry):
|
||||
self.hash = '#triangle'
|
||||
|
||||
def rotate(self, axis, angle, origin=None):
|
||||
"""Set parameters for rotation."""
|
||||
"""Sets parameters for rotation."""
|
||||
self.axis = axis
|
||||
self.angle = angle
|
||||
self.origin = origin
|
||||
self.dorotate = True
|
||||
|
||||
def __dorotate(self):
|
||||
"""Perform rotation."""
|
||||
"""Performs rotation."""
|
||||
p1 = rotate_point(self.kwargs['p1'], self.axis, self.angle, self.origin)
|
||||
p2 = rotate_point(self.kwargs['p2'], self.axis, self.angle, self.origin)
|
||||
p3 = rotate_point(self.kwargs['p3'], self.axis, self.angle, self.origin)
|
||||
@@ -154,10 +154,14 @@ class Triangle(UserObjectGeometry):
|
||||
m = Material(numID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create dielectric-smoothed constituents for material
|
||||
m.er = np.mean((materials[0].er, materials[1].er, materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se, materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr, materials[2].mr), axis=0)
|
||||
m.er = np.mean((materials[0].er, materials[1].er,
|
||||
materials[2].er), axis=0)
|
||||
m.se = np.mean((materials[0].se, materials[1].se,
|
||||
materials[2].se), axis=0)
|
||||
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
m.sm = np.mean((materials[0].mr, materials[1].mr,
|
||||
materials[2].mr), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
@@ -57,8 +57,8 @@ cpdef void {{ item.name_a }}(
|
||||
{{ item.field_type }}[:, :, ::1] Hy,
|
||||
{{ item.field_type }}[:, :, ::1] Hz
|
||||
):
|
||||
"""This function updates the electric field components when dispersive
|
||||
materials (with multiple poles) are present.
|
||||
"""Updates the electric field components when dispersive materials
|
||||
(with multiple poles) are present.
|
||||
|
||||
Args:
|
||||
nx, ny, nz: int for grid size in cells.
|
||||
@@ -172,8 +172,8 @@ cpdef void {{ item.name_b }}(
|
||||
{{ item.field_type }}[:, :, ::1] Ey,
|
||||
{{ item.field_type }}[:, :, ::1] Ez
|
||||
):
|
||||
"""This function updates a temporary dispersive material array when
|
||||
disperisive materials (with multiple poles) are present.
|
||||
"""Updates a temporary dispersive material array when disperisive materials
|
||||
(with multiple poles) are present.
|
||||
|
||||
Args:
|
||||
nx, ny, nz: int for grid size in cells.
|
||||
@@ -246,8 +246,8 @@ cpdef void {{ item.name_a_1 }}(
|
||||
{{ item.field_type }}[:, :, ::1] Hy,
|
||||
{{ item.field_type }}[:, :, ::1] Hz
|
||||
):
|
||||
"""This function updates the electric field components when dispersive
|
||||
materials (with 1 pole) are present.
|
||||
"""Updates the electric field components when dispersive materials
|
||||
(with 1 pole) are present.
|
||||
|
||||
Args:
|
||||
nx, ny, nz: int for grid size in cells.
|
||||
@@ -353,8 +353,8 @@ cpdef void {{ item.name_b_1 }}(
|
||||
{{ item.field_type }}[:, :, ::1] Ey,
|
||||
{{ item.field_type }}[:, :, ::1] Ez
|
||||
):
|
||||
"""This function updates a temporary dispersive material array when
|
||||
disperisive materials (with 1 pole) are present.
|
||||
"""Updates a temporary dispersive material array when disperisive materials
|
||||
(with 1 pole) are present.
|
||||
|
||||
Args:
|
||||
nx, ny, nz: int for grid size in cells.
|
||||
|
@@ -46,23 +46,21 @@ cpdef void cython_update_electric_os(
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
|
||||
subgrid: (Subgrid)
|
||||
n: (String) the normal to the face to update
|
||||
nwn: (Int) number of working cell in the normal direction
|
||||
to the face
|
||||
lookup_id: (Int) id of the H component we wish to update at
|
||||
each node
|
||||
field: (Numpy array) main grid field to be updated
|
||||
inc_field: (Numpy array) incident sub_grid field
|
||||
co: (Int) Coefficient used by gprMax update equations which
|
||||
subgrid: Subgrid class instance.
|
||||
n: string for the normal to the face to update.
|
||||
nwn: int for the number of working cell in the normal direction
|
||||
to the face.
|
||||
lookup_id: int id of the H component to update at each node.
|
||||
field: nparray of main grid field to be updated.
|
||||
inc_field: nparray of incident sub_grid field.
|
||||
co: int coefficient used by gprMax update equations which
|
||||
is specific to the field component being updated.
|
||||
sign_n: (Int) 1 or -1 sign of the incident field on the near face.
|
||||
sign_f: (Int) 1 or -1 sign of the incident field on the far face.
|
||||
mid: (Bool) is the H node midway along the lower edge?
|
||||
r = self.ratio
|
||||
s = self.is_os_sep
|
||||
nb = self.n_boundary_cells
|
||||
sign_n: int 1 or -1 sign of the incident field on the near face.
|
||||
sign_f: int 1 or -1 sign of the incident field on the far face.
|
||||
mid: boolean for the H node midway along the lower edge?
|
||||
r: int for subgrid ratio.
|
||||
s: int for separation of inner and outer surfaces.
|
||||
nb: int for number of boundary cells.
|
||||
"""
|
||||
# Comments here as as per left and right face
|
||||
|
||||
@@ -70,9 +68,9 @@ cpdef void cython_update_electric_os(
|
||||
cdef int os
|
||||
cdef double inc_n, inc_f
|
||||
|
||||
# surface normal index for the subgrid near face h nodes (left i index)
|
||||
# Surface normal index for the subgrid near face h nodes (left i index)
|
||||
n_s_l = nb - s * r - r + r // 2
|
||||
# surface normal index for the subgrid far face h nodes (right i index)
|
||||
# Surface normal index for the subgrid far face h nodes (right i index)
|
||||
n_s_r = nb + nwn + s * r + r // 2
|
||||
# OS at the left face
|
||||
os = nb - r * s
|
||||
@@ -130,6 +128,7 @@ cpdef void cython_update_electric_os(
|
||||
inc_f = inc_field[i3, j3, k3] * sign_f
|
||||
field[i2, j2, k2] += updatecoeffsE[material_e_r, co] * inc_f
|
||||
|
||||
|
||||
cpdef void cython_update_magnetic_os(
|
||||
np.float64_t[:, :] updatecoeffsH,
|
||||
np.uint32_t[:, :, :, :] ID,
|
||||
@@ -154,9 +153,10 @@ cpdef void cython_update_magnetic_os(
|
||||
int nthreads
|
||||
):
|
||||
"""
|
||||
int r ratio,
|
||||
int s is_os_sep,
|
||||
int nb n_boundary_cells
|
||||
Args:
|
||||
r: int for subgrid ratio.
|
||||
s: int for separation of inner and outer surfaces.
|
||||
nb: int for number of boundary cells.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t l, m, l_s, m_s, n_s_l, n_s_r, material_e_l, material_e_r, i0, j0, k0, i1, j1, k1, i2, j2, k2, i3, j3, k3
|
||||
@@ -222,6 +222,7 @@ cpdef void cython_update_magnetic_os(
|
||||
inc_f = inc_field[i3, j3, k3] * sign_f
|
||||
field[i2, j2, k2] += updatecoeffsH[material_e_r, co] * inc_f
|
||||
|
||||
|
||||
cpdef void cython_update_is(
|
||||
int nwx,
|
||||
int nwy,
|
||||
@@ -244,9 +245,13 @@ cpdef void cython_update_is(
|
||||
int nthreads
|
||||
):
|
||||
|
||||
"""
|
||||
Args:
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t l, m, i1, j1, k1, i2, j2, k2, field_material_l, field_material_u, inc_i, inc_j
|
||||
cdef double inc_l, inc_u, f_l, f_u
|
||||
# for inner faces H nodes are 1 cell before n boundary cells
|
||||
# For inner faces H nodes are 1 cell before n boundary cells
|
||||
cdef int n_o = n + offset
|
||||
|
||||
for l in prange(n, nwl + n, nogil=True, schedule='static', num_threads=nthreads):
|
||||
|
@@ -23,9 +23,6 @@ from cython.parallel import prange
|
||||
from gprMax.config cimport float_or_double
|
||||
|
||||
|
||||
###############################################
|
||||
# Electric field updates - standard materials #
|
||||
###############################################
|
||||
cpdef void update_electric(
|
||||
int nx,
|
||||
int ny,
|
||||
@@ -40,12 +37,13 @@ cpdef void update_electric(
|
||||
float_or_double[:, :, ::1] Hy,
|
||||
float_or_double[:, :, ::1] Hz
|
||||
):
|
||||
"""This function updates the electric field components.
|
||||
"""Updates the electric field components (for standard materials).
|
||||
|
||||
Args:
|
||||
nx, ny, nz (int): Grid size in cells
|
||||
nthreads (int): Number of threads to use
|
||||
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
|
||||
nx, ny, nz: ints for grid size in cells.
|
||||
nthreads: int for number of threads to use.
|
||||
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
|
||||
ID and field component arrays
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -57,7 +55,9 @@ cpdef void update_electric(
|
||||
for j in range(1, ny):
|
||||
for k in range(1, nz):
|
||||
materialEx = ID[0, i, j, k]
|
||||
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
|
||||
Ex[i, j, k] = (updatecoeffsE[materialEx, 0] * Ex[i, j, k] +
|
||||
updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) -
|
||||
updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]))
|
||||
|
||||
# 2D - Ey component
|
||||
elif ny == 1:
|
||||
@@ -65,7 +65,9 @@ cpdef void update_electric(
|
||||
for j in range(0, ny):
|
||||
for k in range(1, nz):
|
||||
materialEy = ID[1, i, j, k]
|
||||
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
|
||||
Ey[i, j, k] = (updatecoeffsE[materialEy, 0] * Ey[i, j, k] +
|
||||
updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) -
|
||||
updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]))
|
||||
|
||||
# 2D - Ez component
|
||||
elif nz == 1:
|
||||
@@ -73,7 +75,9 @@ cpdef void update_electric(
|
||||
for j in range(1, ny):
|
||||
for k in range(0, nz):
|
||||
materialEz = ID[2, i, j, k]
|
||||
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
|
||||
Ez[i, j, k] = (updatecoeffsE[materialEz, 0] * Ez[i, j, k] +
|
||||
updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) -
|
||||
updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]))
|
||||
|
||||
# 3D
|
||||
else:
|
||||
@@ -83,32 +87,41 @@ cpdef void update_electric(
|
||||
materialEx = ID[0, i, j, k]
|
||||
materialEy = ID[1, i, j, k]
|
||||
materialEz = ID[2, i, j, k]
|
||||
Ex[i, j, k] = updatecoeffsE[materialEx, 0] * Ex[i, j, k] + updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1])
|
||||
Ey[i, j, k] = updatecoeffsE[materialEy, 0] * Ey[i, j, k] + updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k])
|
||||
Ez[i, j, k] = updatecoeffsE[materialEz, 0] * Ez[i, j, k] + updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k])
|
||||
Ex[i, j, k] = (updatecoeffsE[materialEx, 0] * Ex[i, j, k] +
|
||||
updatecoeffsE[materialEx, 2] * (Hz[i, j, k] - Hz[i, j - 1, k]) -
|
||||
updatecoeffsE[materialEx, 3] * (Hy[i, j, k] - Hy[i, j, k - 1]))
|
||||
Ey[i, j, k] = (updatecoeffsE[materialEy, 0] * Ey[i, j, k] +
|
||||
updatecoeffsE[materialEy, 3] * (Hx[i, j, k] - Hx[i, j, k - 1]) -
|
||||
updatecoeffsE[materialEy, 1] * (Hz[i, j, k] - Hz[i - 1, j, k]))
|
||||
Ez[i, j, k] = (updatecoeffsE[materialEz, 0] * Ez[i, j, k] +
|
||||
updatecoeffsE[materialEz, 1] * (Hy[i, j, k] - Hy[i - 1, j, k]) -
|
||||
updatecoeffsE[materialEz, 2] * (Hx[i, j, k] - Hx[i, j - 1, k]))
|
||||
|
||||
# Ex components at i = 0
|
||||
for j in prange(1, ny, nogil=True, schedule='static', num_threads=nthreads):
|
||||
for k in range(1, nz):
|
||||
materialEx = ID[0, 0, j, k]
|
||||
Ex[0, j, k] = updatecoeffsE[materialEx, 0] * Ex[0, j, k] + updatecoeffsE[materialEx, 2] * (Hz[0, j, k] - Hz[0, j - 1, k]) - updatecoeffsE[materialEx, 3] * (Hy[0, j, k] - Hy[0, j, k - 1])
|
||||
Ex[0, j, k] = (updatecoeffsE[materialEx, 0] * Ex[0, j, k] +
|
||||
updatecoeffsE[materialEx, 2] * (Hz[0, j, k] - Hz[0, j - 1, k]) -
|
||||
updatecoeffsE[materialEx, 3] * (Hy[0, j, k] - Hy[0, j, k - 1]))
|
||||
|
||||
# Ey components at j = 0
|
||||
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
|
||||
for k in range(1, nz):
|
||||
materialEy = ID[1, i, 0, k]
|
||||
Ey[i, 0, k] = updatecoeffsE[materialEy, 0] * Ey[i, 0, k] + updatecoeffsE[materialEy, 3] * (Hx[i, 0, k] - Hx[i, 0, k - 1]) - updatecoeffsE[materialEy, 1] * (Hz[i, 0, k] - Hz[i - 1, 0, k])
|
||||
Ey[i, 0, k] = (updatecoeffsE[materialEy, 0] * Ey[i, 0, k] +
|
||||
updatecoeffsE[materialEy, 3] * (Hx[i, 0, k] - Hx[i, 0, k - 1]) -
|
||||
updatecoeffsE[materialEy, 1] * (Hz[i, 0, k] - Hz[i - 1, 0, k]))
|
||||
|
||||
# Ez components at k = 0
|
||||
for i in prange(1, nx, nogil=True, schedule='static', num_threads=nthreads):
|
||||
for j in range(1, ny):
|
||||
materialEz = ID[2, i, j, 0]
|
||||
Ez[i, j, 0] = updatecoeffsE[materialEz, 0] * Ez[i, j, 0] + updatecoeffsE[materialEz, 1] * (Hy[i, j, 0] - Hy[i - 1, j, 0]) - updatecoeffsE[materialEz, 2] * (Hx[i, j, 0] - Hx[i, j - 1, 0])
|
||||
Ez[i, j, 0] = (updatecoeffsE[materialEz, 0] * Ez[i, j, 0] +
|
||||
updatecoeffsE[materialEz, 1] * (Hy[i, j, 0] - Hy[i - 1, j, 0]) -
|
||||
updatecoeffsE[materialEz, 2] * (Hx[i, j, 0] - Hx[i, j - 1, 0]))
|
||||
|
||||
|
||||
##########################
|
||||
# Magnetic field updates #
|
||||
##########################
|
||||
cpdef void update_magnetic(
|
||||
int nx,
|
||||
int ny,
|
||||
@@ -123,12 +136,13 @@ cpdef void update_magnetic(
|
||||
float_or_double[:, :, ::1] Hy,
|
||||
float_or_double[:, :, ::1] Hz
|
||||
):
|
||||
"""This function updates the magnetic field components.
|
||||
"""Updates the magnetic field components.
|
||||
|
||||
Args:
|
||||
nx, ny, nz (int): Grid size in cells
|
||||
nthreads (int): Number of threads to use
|
||||
updatecoeffs, ID, E, H (memoryviews): Access to update coeffients, ID and field component arrays
|
||||
nx, ny, nz: ints for grid size in cells.
|
||||
nthreads: int for number of threads to use.
|
||||
updatecoeffs, ID, E, H: memoryviews to access update coefficients,
|
||||
ID and field component arrays
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -142,7 +156,9 @@ cpdef void update_magnetic(
|
||||
for j in range(0, ny):
|
||||
for k in range(0, nz):
|
||||
materialHx = ID[3, i, j, k]
|
||||
Hx[i, j, k] = updatecoeffsH[materialHx, 0] * Hx[i, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i, j + 1, k] - Ez[i, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i, j, k + 1] - Ey[i, j, k])
|
||||
Hx[i, j, k] = (updatecoeffsH[materialHx, 0] * Hx[i, j, k] -
|
||||
updatecoeffsH[materialHx, 2] * (Ez[i, j + 1, k] - Ez[i, j, k]) +
|
||||
updatecoeffsH[materialHx, 3] * (Ey[i, j, k + 1] - Ey[i, j, k]))
|
||||
|
||||
# Hy component
|
||||
if nx == 1 or nz == 1:
|
||||
@@ -150,7 +166,9 @@ cpdef void update_magnetic(
|
||||
for j in range(1, ny):
|
||||
for k in range(0, nz):
|
||||
materialHy = ID[4, i, j, k]
|
||||
Hy[i, j, k] = updatecoeffsH[materialHy, 0] * Hy[i, j, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j, k + 1] - Ex[i, j, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j, k] - Ez[i, j, k])
|
||||
Hy[i, j, k] = (updatecoeffsH[materialHy, 0] * Hy[i, j, k] -
|
||||
updatecoeffsH[materialHy, 3] * (Ex[i, j, k + 1] - Ex[i, j, k]) +
|
||||
updatecoeffsH[materialHy, 1] * (Ez[i + 1, j, k] - Ez[i, j, k]))
|
||||
|
||||
# Hz component
|
||||
if nx == 1 or ny == 1:
|
||||
@@ -158,7 +176,9 @@ cpdef void update_magnetic(
|
||||
for j in range(0, ny):
|
||||
for k in range(1, nz):
|
||||
materialHz = ID[5, i, j, k]
|
||||
Hz[i, j, k] = updatecoeffsH[materialHz, 0] * Hz[i, j, k] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k] - Ey[i, j, k]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k] - Ex[i, j, k])
|
||||
Hz[i, j, k] = (updatecoeffsH[materialHz, 0] * Hz[i, j, k] -
|
||||
updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k] - Ey[i, j, k]) +
|
||||
updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k] - Ex[i, j, k]))
|
||||
# 3D
|
||||
else:
|
||||
for i in prange(0, nx, nogil=True, schedule='static', num_threads=nthreads):
|
||||
@@ -167,6 +187,12 @@ cpdef void update_magnetic(
|
||||
materialHx = ID[3, i + 1, j, k]
|
||||
materialHy = ID[4, i, j + 1, k]
|
||||
materialHz = ID[5, i, j, k + 1]
|
||||
Hx[i + 1, j, k] = updatecoeffsH[materialHx, 0] * Hx[i + 1, j, k] - updatecoeffsH[materialHx, 2] * (Ez[i + 1, j + 1, k] - Ez[i + 1, j, k]) + updatecoeffsH[materialHx, 3] * (Ey[i + 1, j, k + 1] - Ey[i + 1, j, k])
|
||||
Hy[i, j + 1, k] = updatecoeffsH[materialHy, 0] * Hy[i, j + 1, k] - updatecoeffsH[materialHy, 3] * (Ex[i, j + 1, k + 1] - Ex[i, j + 1, k]) + updatecoeffsH[materialHy, 1] * (Ez[i + 1, j + 1, k] - Ez[i, j + 1, k])
|
||||
Hz[i, j, k + 1] = updatecoeffsH[materialHz, 0] * Hz[i, j, k + 1] - updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k + 1] - Ey[i, j, k + 1]) + updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k + 1] - Ex[i, j, k + 1])
|
||||
Hx[i + 1, j, k] = (updatecoeffsH[materialHx, 0] * Hx[i + 1, j, k] -
|
||||
updatecoeffsH[materialHx, 2] * (Ez[i + 1, j + 1, k] - Ez[i + 1, j, k]) +
|
||||
updatecoeffsH[materialHx, 3] * (Ey[i + 1, j, k + 1] - Ey[i + 1, j, k]))
|
||||
Hy[i, j + 1, k] = (updatecoeffsH[materialHy, 0] * Hy[i, j + 1, k] -
|
||||
updatecoeffsH[materialHy, 3] * (Ex[i, j + 1, k + 1] - Ex[i, j + 1, k]) +
|
||||
updatecoeffsH[materialHy, 1] * (Ez[i + 1, j + 1, k] - Ez[i, j + 1, k]))
|
||||
Hz[i, j, k + 1] = (updatecoeffsH[materialHz, 0] * Hz[i, j, k + 1] -
|
||||
updatecoeffsH[materialHz, 1] * (Ey[i + 1, j, k + 1] - Ey[i, j, k + 1]) +
|
||||
updatecoeffsH[materialHz, 2] * (Ex[i, j + 1, k + 1] - Ex[i, j, k + 1]))
|
||||
|
@@ -23,17 +23,29 @@ from cython.parallel import prange
|
||||
from gprMax.config cimport float_or_double_complex
|
||||
|
||||
|
||||
cpdef void generate_fractal2D(int nx, int ny, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, ::1] A, float_or_double_complex[:, ::1] fractalsurface):
|
||||
"""This function generates a fractal surface for a 2D array.
|
||||
cpdef void generate_fractal2D(
|
||||
int nx,
|
||||
int ny,
|
||||
int nthreads,
|
||||
int b,
|
||||
np.float64_t[:] weighting,
|
||||
np.float64_t[:] v1,
|
||||
np.complex128_t[:, ::1] A,
|
||||
float_or_double_complex[:, ::1] fractalsurface
|
||||
):
|
||||
"""Generates a fractal surface for a 2D array.
|
||||
|
||||
Args:
|
||||
nx, ny (int): Fractal surface size in cells
|
||||
nthreads (int): Number of threads to use
|
||||
b (int): Constant related to fractal dimension
|
||||
weighting (memoryview): Access to weighting vector
|
||||
v1 (memoryview): Access to positional vector at centre of array, scaled by weighting
|
||||
A (memoryview): Access to array containing random numbers (to be convolved with fractal function)
|
||||
fractalsurface (memoryview): Access to array containing fractal surface data
|
||||
nx, ny: int for fractal surface size in cells.
|
||||
nthreads: int for number of threads to use
|
||||
b: int for constant related to fractal dimension.
|
||||
weighting: memoryview for access to weighting vector.
|
||||
v1: memoryview for access to positional vector at centre of array,
|
||||
scaled by weighting.
|
||||
A: memoryview for access to array containing random numbers
|
||||
(to be convolved with fractal function).
|
||||
fractalsurface: memoryview for access to array containing fractal
|
||||
surface data.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j
|
||||
@@ -54,17 +66,30 @@ cpdef void generate_fractal2D(int nx, int ny, int nthreads, int b, np.float64_t[
|
||||
fractalsurface[i, j] = A[i, j] / B
|
||||
|
||||
|
||||
cpdef void generate_fractal3D(int nx, int ny, int nz, int nthreads, int b, np.float64_t[:] weighting, np.float64_t[:] v1, np.complex128_t[:, :, ::1] A, float_or_double_complex[:, :, ::1] fractalvolume):
|
||||
"""This function generates a fractal volume for a 3D array.
|
||||
cpdef void generate_fractal3D(
|
||||
int nx,
|
||||
int ny,
|
||||
int nz,
|
||||
int nthreads,
|
||||
int b,
|
||||
np.float64_t[:] weighting,
|
||||
np.float64_t[:] v1,
|
||||
np.complex128_t[:, :, ::1] A,
|
||||
float_or_double_complex[:, :, ::1] fractalvolume
|
||||
):
|
||||
"""Generates a fractal volume for a 3D array.
|
||||
|
||||
Args:
|
||||
nx, ny, nz (int): Fractal volume size in cells
|
||||
nthreads (int): Number of threads to use
|
||||
b (int): Constant related to fractal dimension
|
||||
weighting (memoryview): Access to weighting vector
|
||||
v1 (memoryview): Access to positional vector at centre of array, scaled by weighting
|
||||
A (memoryview): Access to array containing random numbers (to be convolved with fractal function)
|
||||
fractalvolume (memoryview): Access to array containing fractal volume data
|
||||
nx, ny, nz: int for fractal volume size in cells.
|
||||
nthreads: int for number of threads to use
|
||||
b: int for constant related to fractal dimension.
|
||||
weighting: memoryview for access to weighting vector.
|
||||
v1: memoryview for access to positional vector at centre of array,
|
||||
scaled by weighting.
|
||||
A: memoryview for access to array containing random numbers
|
||||
(to be convolved with fractal function).
|
||||
fractalsurface: memoryview for access to array containing fractal
|
||||
volume data.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
|
@@ -20,21 +20,30 @@ import numpy as np
|
||||
cimport numpy as np
|
||||
|
||||
|
||||
cpdef write_lines(float xs, float ys, float zs, int nx, int ny, int nz,
|
||||
float dx, float dy, float dz, np.uint32_t[:, :, :, :] ID):
|
||||
"""This function generates arrays with to be written as lines (cell edges)
|
||||
to a VTK file.
|
||||
cpdef write_lines(
|
||||
float xs,
|
||||
float ys,
|
||||
float zs,
|
||||
int nx,
|
||||
int ny,
|
||||
int nz,
|
||||
float dx,
|
||||
float dy,
|
||||
float dz,
|
||||
np.uint32_t[:, :, :, :] ID
|
||||
):
|
||||
"""Generates arrays with to be written as lines (cell edges) to a VTK file.
|
||||
|
||||
Args:
|
||||
xs, ys, zs (float): Starting coordinates of geometry view in metres
|
||||
nx, ny, nz (int): Size of the volume in cells
|
||||
dx, dy, dz (float): Spatial discretisation of geometry view in metres
|
||||
ID (nparray): Sampled ID array according to geometry view spatial
|
||||
discretisation
|
||||
xs, ys, zs: float for starting coordinates of geometry view in metres.
|
||||
nx, ny, nz: int for size of the volume in cells.
|
||||
dx, dy, dz: float for spatial discretisation of geometry view in metres.
|
||||
ID: memoryview of sampled ID array according to geometry view spatial
|
||||
discretisation.
|
||||
|
||||
Returns:
|
||||
x, y, z (nparray): 1D arrays with coordinates of the vertex of the lines
|
||||
lines (nparray): array of material IDs for each line (cell edge) required
|
||||
x, y, z: 1D nparrays with coordinates of the vertex of the lines.
|
||||
lines: nparray of material IDs for each line (cell edge) required.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
|
@@ -42,7 +42,7 @@ cpdef bint are_clockwise(
|
||||
"""Find if vector 2 is clockwise relative to vector 1.
|
||||
|
||||
Args:
|
||||
v1x, v1y, v2x, v2y (float): Coordinates of vectors.
|
||||
v1x, v1y, v2x, v2y: floats of coordinates of vectors.
|
||||
|
||||
Returns:
|
||||
(boolean)
|
||||
@@ -59,8 +59,8 @@ cpdef bint is_within_radius(
|
||||
"""Check if the point is within a given radius of the centre of the circle.
|
||||
|
||||
Args:
|
||||
vx, vy (float): Coordinates of vector.
|
||||
radius (float): Radius.
|
||||
vx, vy: floats of coordinates of vector.
|
||||
radius: float for radius.
|
||||
|
||||
Returns:
|
||||
(boolean)
|
||||
@@ -86,11 +86,11 @@ cpdef bint is_inside_sector(
|
||||
i.e. sector defined in an anti-clockwise direction
|
||||
|
||||
Args:
|
||||
px, py (float): Coordinates of point.
|
||||
ctrx, ctry (float): Coordinates of centre of circle.
|
||||
sectorstartangle (float): Angle (in radians) of start of sector.
|
||||
sectorangle (float): Angle (in radians) that sector makes.
|
||||
radius (float): Radius.
|
||||
px, py: floats for coordinates of point.
|
||||
ctrx, ctry: floats for coordinates of centre of circle.
|
||||
sectorstartangle: float for angle (in radians) of start of sector.
|
||||
sectorangle: float for angle (in radians) that sector makes.
|
||||
radius: float for radius.
|
||||
|
||||
Returns:
|
||||
(boolean)
|
||||
@@ -118,11 +118,11 @@ cpdef bint point_in_polygon(
|
||||
"""Calculates, using a ray casting algorithm, whether a point lies within a polygon.
|
||||
|
||||
Args:
|
||||
px, py (float): Coordinates of point to test.
|
||||
polycoords (list): x, y tuples of coordinates that define the polygon.
|
||||
px, py: float for coordinates of point to test.
|
||||
polycoords: list of x, y tuples of coordinates that define the polygon.
|
||||
|
||||
Returns:
|
||||
inside (boolean)
|
||||
inside: boolean
|
||||
"""
|
||||
|
||||
cdef int i
|
||||
@@ -175,9 +175,9 @@ cpdef void build_edge_x(
|
||||
"""Set x-orientated edges in the rigid and ID arrays for a Yee voxel.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of edge.
|
||||
numIDz (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of edge.
|
||||
numIDx: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ex(i, j, k, rigidE)
|
||||
@@ -196,9 +196,9 @@ cpdef void build_edge_y(
|
||||
"""Set y-orientated edges in the rigid and ID arrays for a Yee voxel.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of edge.
|
||||
numIDz (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of edge.
|
||||
numIDy: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ey(i, j, k, rigidE)
|
||||
@@ -217,9 +217,9 @@ cpdef void build_edge_z(
|
||||
"""Set z-orientated edges in the rigid and ID arrays for a Yee voxel.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of edge.
|
||||
numIDz (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of edge.
|
||||
numIDz: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ez(i, j, k, rigidE)
|
||||
@@ -239,9 +239,9 @@ cpdef void build_face_yz(
|
||||
"""Set the edges of the yz-plane face of a Yell cell in the rigid and ID arrays.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of the face.
|
||||
numIDx, numIDy (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of the face.
|
||||
numIDy, numIDz: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ey(i, j, k, rigidE)
|
||||
@@ -267,9 +267,9 @@ cpdef void build_face_xz(
|
||||
"""Set the edges of the xz-plane face of a Yell cell in the rigid and ID arrays.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of the face.
|
||||
numIDx, numIDy (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of the face.
|
||||
numIDx, numIDz: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ex(i, j, k, rigidE)
|
||||
@@ -295,9 +295,9 @@ cpdef void build_face_xy(
|
||||
"""Set the edges of the xy-plane face of a Yell cell in the rigid and ID arrays.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of the face.
|
||||
numIDx, numIDy (int): Numeric ID of material.
|
||||
rigidE, rigidH, ID (memoryviews): Access to rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of the face.
|
||||
numIDx, numIDy: int for numeric ID of material.
|
||||
rigidE, rigidH, ID: memoryviews to access rigid and ID arrays.
|
||||
"""
|
||||
|
||||
set_rigid_Ex(i, j, k, rigidE)
|
||||
@@ -327,10 +327,11 @@ cpdef void build_voxel(
|
||||
"""Set values in the solid, rigid and ID arrays for a Yee voxel.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates of voxel.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
i, j, k: ints for cell coordinates of voxel.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
if averaging:
|
||||
@@ -400,18 +401,19 @@ cpdef void build_triangle(
|
||||
np.uint32_t[:, :, :, ::1] ID
|
||||
):
|
||||
"""
|
||||
Builds #triangle and #triangular_prism commands which sets values in the
|
||||
solid, rigid and ID arrays for a Yee voxel.
|
||||
Builds triangles and triangular prisms which sets values in the solid,
|
||||
rigid and ID arrays for a Yee voxel.
|
||||
|
||||
Args:
|
||||
x1, y1, z1, x2, y2, z2, x3, y3, z3 (float): Coordinates of the vertices
|
||||
x1, y1, z1, x2, y2, z2, x3, y3, z3: floats of coordinates of the vertices
|
||||
of the triangular prism.
|
||||
normal (char): Normal direction to the plane of the triangular prism.
|
||||
thickness (float): Thickness of the triangular prism.
|
||||
dx, dy, dz (float): Spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
normal: string for normal direction to the plane of the triangular prism.
|
||||
thickness: float for thickness of the triangular prism.
|
||||
dx, dy, dz: floats for spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -449,7 +451,8 @@ cpdef void build_triangle(
|
||||
for i in range(i1, i2):
|
||||
for j in range(j1, j2):
|
||||
|
||||
# Calculate the areas of the 3 triangles defined by the 3 vertices of the main triangle and the point under test
|
||||
# Calculate the areas of the 3 triangles defined by the 3 vertices
|
||||
# of the main triangle and the point under test.
|
||||
if normal == 'x':
|
||||
ir = (i + 0.5) * dy
|
||||
jr = (j + 0.5) * dz
|
||||
@@ -470,19 +473,25 @@ cpdef void build_triangle(
|
||||
if s > 0 and t > 0 and (s + t) < 2 * area * sign:
|
||||
if thicknesscells == 0:
|
||||
if normal == 'x':
|
||||
build_face_yz(level, i, j, numIDy, numIDz, rigidE, rigidH, ID)
|
||||
build_face_yz(level, i, j, numIDy, numIDz,
|
||||
rigidE, rigidH, ID)
|
||||
elif normal == 'y':
|
||||
build_face_xz(i, level, j, numIDx, numIDz, rigidE, rigidH, ID)
|
||||
build_face_xz(i, level, j, numIDx, numIDz,
|
||||
rigidE, rigidH, ID)
|
||||
elif normal == 'z':
|
||||
build_face_xy(i, j, level, numIDx, numIDy, rigidE, rigidH, ID)
|
||||
build_face_xy(i, j, level, numIDx, numIDy,
|
||||
rigidE, rigidH, ID)
|
||||
else:
|
||||
for k in range(level, level + thicknesscells):
|
||||
if normal == 'x':
|
||||
build_voxel(k, i, j, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(k, i, j, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
elif normal == 'y':
|
||||
build_voxel(i, k, j, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, k, j, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
elif normal == 'z':
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
|
||||
cpdef void build_cylindrical_sector(
|
||||
@@ -508,32 +517,34 @@ cpdef void build_cylindrical_sector(
|
||||
np.uint32_t[:, :, :, ::1] ID
|
||||
):
|
||||
"""
|
||||
Builds #cylindrical_sector commands which sets values in the solid, rigid
|
||||
and ID arrays for a Yee voxel. It defines a sector of cylinder given by the
|
||||
direction of the axis of the coordinates of the cylinder face centre, depth
|
||||
coordinates, sector start point, sector angle, and sector radius. N.B
|
||||
Assumes sector start is always clockwise from sector end, i.e. sector
|
||||
defined in an anti-clockwise direction.
|
||||
Builds cylindrical sectors which sets values in the solid, rigid and ID
|
||||
arrays for a Yee voxel. It defines a sector of cylinder given by the
|
||||
direction of the axis of the coordinates of the cylinder face centre,
|
||||
depth coordinates, sector start point, sector angle, and sector radius.
|
||||
N.B Assumes sector start is always clockwise from sector end,
|
||||
i.e. sector defined in an anti-clockwise direction.
|
||||
|
||||
Args:
|
||||
ctr1, ctr2 (float): Coordinates of centre of circle.
|
||||
level (int): Third dimensional coordinate.
|
||||
sectorstartangle (float): Angle (in radians) of start of sector.
|
||||
sectorangle (float): Angle (in radians) that sector makes.
|
||||
radius (float): Radius of the cylindrical sector.
|
||||
normal (char): Normal direction to the plane of the cylindrical sector.
|
||||
thickness (float): Thickness of the cylindrical sector.
|
||||
dx, dy, dz (float): Spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
ctr1, ctr2: floats for coordinates of centre of circle.
|
||||
level: int for the third dimensional coordinate.
|
||||
sectorstartangle: float for angle (in radians) of start of sector.
|
||||
sectorangle: float for angle (in radians) that sector makes.
|
||||
radius: float for radius of the cylindrical sector.
|
||||
normal: string for normal direction to the plane of the triangular prism.
|
||||
thickness: float for thickness of the triangular prism.
|
||||
dx, dy, dz: floats for spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t x, y, z
|
||||
cdef int x1, x2, y1, y2, z1, z2, thicknesscells
|
||||
|
||||
if normal == 'x':
|
||||
# Angles are defined from zero degrees on the positive y-axis going towards positive z-axis
|
||||
# Angles are defined from zero degrees on the positive y-axis going
|
||||
# towards positive z-axis.
|
||||
y1 = round_value((ctr1 - radius)/dy)
|
||||
y2 = round_value((ctr1 + radius)/dy)
|
||||
z1 = round_value((ctr2 - radius)/dz)
|
||||
@@ -552,15 +563,19 @@ cpdef void build_cylindrical_sector(
|
||||
|
||||
for y in range(y1, y2):
|
||||
for z in range(z1, z2):
|
||||
if is_inside_sector(y * dy + 0.5 * dy, z * dz + 0.5 * dz, ctr1, ctr2, sectorstartangle, sectorangle, radius):
|
||||
if is_inside_sector(y * dy + 0.5 * dy, z * dz + 0.5 * dz, ctr1,
|
||||
ctr2, sectorstartangle, sectorangle, radius):
|
||||
if thicknesscells == 0:
|
||||
build_face_yz(level, y, z, numIDy, numIDz, rigidE, rigidH, ID)
|
||||
build_face_yz(level, y, z, numIDy, numIDz,
|
||||
rigidE, rigidH, ID)
|
||||
else:
|
||||
for x in range(level, level + thicknesscells):
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
elif normal == 'y':
|
||||
# Angles are defined from zero degrees on the positive x-axis going towards positive z-axis
|
||||
# Angles are defined from zero degrees on the positive x-axis going
|
||||
# towards positive z-axis.
|
||||
x1 = round_value((ctr1 - radius)/dx)
|
||||
x2 = round_value((ctr1 + radius)/dx)
|
||||
z1 = round_value((ctr2 - radius)/dz)
|
||||
@@ -579,15 +594,19 @@ cpdef void build_cylindrical_sector(
|
||||
|
||||
for x in range(x1, x2):
|
||||
for z in range(z1, z2):
|
||||
if is_inside_sector(x * dx + 0.5 * dx, z * dz + 0.5 * dz, ctr1, ctr2, sectorstartangle, sectorangle, radius):
|
||||
if is_inside_sector(x * dx + 0.5 * dx, z * dz + 0.5 * dz, ctr1,
|
||||
ctr2, sectorstartangle, sectorangle, radius):
|
||||
if thicknesscells == 0:
|
||||
build_face_xz(x, level, z, numIDx, numIDz, rigidE, rigidH, ID)
|
||||
build_face_xz(x, level, z, numIDx, numIDz,
|
||||
rigidE, rigidH, ID)
|
||||
else:
|
||||
for y in range(level, level + thicknesscells):
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
elif normal == 'z':
|
||||
# Angles are defined from zero degrees on the positive x-axis going towards positive y-axis
|
||||
# Angles are defined from zero degrees on the positive x-axis going
|
||||
# towards positive y-axis.
|
||||
x1 = round_value((ctr1 - radius)/dx)
|
||||
x2 = round_value((ctr1 + radius)/dx)
|
||||
y1 = round_value((ctr2 - radius)/dy)
|
||||
@@ -606,12 +625,15 @@ cpdef void build_cylindrical_sector(
|
||||
|
||||
for x in range(x1, x2):
|
||||
for y in range(y1, y2):
|
||||
if is_inside_sector(x * dx + 0.5 * dx, y * dy + 0.5 * dy, ctr1, ctr2, sectorstartangle, sectorangle, radius):
|
||||
if is_inside_sector(x * dx + 0.5 * dx, y * dy + 0.5 * dy, ctr1,
|
||||
ctr2, sectorstartangle, sectorangle, radius):
|
||||
if thicknesscells == 0:
|
||||
build_face_xy(x, y, level, numIDx, numIDy, rigidE, rigidH, ID)
|
||||
build_face_xy(x, y, level, numIDx, numIDy,
|
||||
rigidE, rigidH, ID)
|
||||
else:
|
||||
for z in range(level, level + thicknesscells):
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(x, y, z, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
|
||||
cpdef void build_box(
|
||||
@@ -631,13 +653,14 @@ cpdef void build_box(
|
||||
np.int8_t[:, :, :, ::1] rigidH,
|
||||
np.uint32_t[:, :, :, ::1] ID
|
||||
):
|
||||
"""Builds #box commands which sets values in the solid, rigid and ID arrays.
|
||||
"""Builds boxes which sets values in the solid, rigid and ID arrays.
|
||||
|
||||
Args:
|
||||
xs, xf, ys, yf, zs, zf (int): Cell coordinates of entire box.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
xs, xf, ys, yf, zs, zf: ints for cell coordinates of entire box.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -709,15 +732,18 @@ cpdef void build_cylinder(
|
||||
np.int8_t[:, :, :, ::1] rigidH,
|
||||
np.uint32_t[:, :, :, ::1] ID
|
||||
):
|
||||
"""Builds #cylinder commands which sets values in the solid, rigid and ID arrays for a Yee voxel.
|
||||
"""Builds cylinders which sets values in the solid, rigid and ID arrays for
|
||||
a Yee voxel.
|
||||
|
||||
Args:
|
||||
x1, y1, z1, x2, y2, z2 (float): Coordinates of the centres of cylinder faces.
|
||||
r (float): Radius of the cylinder.
|
||||
dx, dy, dz (float): Spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
x1, y1, z1, x2, y2, z2: floats for coordinates of the centres of cylinder
|
||||
faces.
|
||||
r: float for radius of the cylinder.
|
||||
dx, dy, dz: floats for spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -729,15 +755,18 @@ cpdef void build_cylinder(
|
||||
# Check if cylinder is aligned with an axis
|
||||
x_align = y_align = z_align = 0
|
||||
# x-aligned
|
||||
if round_value(y1 / dy) == round_value(y2 / dy) and round_value(z1 / dz) == round_value(z2 / dz):
|
||||
if (round_value(y1 / dy) == round_value(y2 / dy) and
|
||||
round_value(z1 / dz) == round_value(z2 / dz)):
|
||||
x_align = 1
|
||||
|
||||
# y-aligned
|
||||
elif round_value(x1 / dx) == round_value(x2 / dx) and round_value(z1 / dz) == round_value(z2 / dz):
|
||||
elif (round_value(x1 / dx) == round_value(x2 / dx) and
|
||||
round_value(z1 / dz) == round_value(z2 / dz)):
|
||||
y_align = 1
|
||||
|
||||
# z-aligned
|
||||
elif round_value(x1 / dx) == round_value(x2 / dx) and round_value(y1 / dy) == round_value(y2 / dy):
|
||||
elif (round_value(x1 / dx) == round_value(x2 / dx) and
|
||||
round_value(y1 / dy) == round_value(y2 / dy):)
|
||||
z_align = 1
|
||||
|
||||
# Calculate a bounding box for the cylinder
|
||||
@@ -804,21 +833,24 @@ cpdef void build_cylinder(
|
||||
for k in range(zs, zf):
|
||||
if np.sqrt((j * dy + 0.5 * dy - y1)**2 + (k * dz + 0.5 * dz - z1)**2) <= r:
|
||||
for i in range(xs, xf):
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
# y-aligned cylinder
|
||||
elif y_align:
|
||||
for i in range(xs, xf):
|
||||
for k in range(zs, zf):
|
||||
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (k * dz + 0.5 * dz - z1)**2) <= r:
|
||||
for j in range(ys, yf):
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
# z-aligned cylinder
|
||||
elif z_align:
|
||||
for i in range(xs, xf):
|
||||
for j in range(ys, yf):
|
||||
if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (j * dy + 0.5 * dy - y1)**2) <= r:
|
||||
for k in range(zs, zf):
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
# Not aligned with any axis
|
||||
else:
|
||||
@@ -836,9 +868,13 @@ cpdef void build_cylinder(
|
||||
# Build flag - default false, set to True if point is in cylinder
|
||||
build = 0
|
||||
# Vector from centre of first cylinder face to test point
|
||||
f1pt = np.array([i * dx + 0.5 * dx - x1, j * dy + 0.5 * dy - y1, k * dz + 0.5 * dz - z1], dtype=np.float32)
|
||||
f1pt = np.array([i * dx + 0.5 * dx - x1,
|
||||
j * dy + 0.5 * dy - y1,
|
||||
k * dz + 0.5 * dz - z1], dtype=np.float32)
|
||||
# Vector from centre of second cylinder face to test point
|
||||
f2pt = np.array([i * dx + 0.5 * dx - x2, j * dy + 0.5 * dy - y2, k * dz + 0.5 * dz - z2], dtype=np.float32)
|
||||
f2pt = np.array([i * dx + 0.5 * dx - x2,
|
||||
j * dy + 0.5 * dy - y2,
|
||||
k * dz + 0.5 * dz - z2], dtype=np.float32)
|
||||
# Magnitudes
|
||||
f1ptmag = np.sqrt((f1pt*f1pt).sum(axis=0))
|
||||
f2ptmag = np.sqrt((f2pt*f2pt).sum(axis=0))
|
||||
@@ -862,11 +898,13 @@ cpdef void build_cylinder(
|
||||
theta2 = 0
|
||||
distance1 = f1ptmag * np.sin(theta1)
|
||||
distance2 = f2ptmag * np.sin(theta2)
|
||||
if (distance1 <= r or distance2 <= r) and theta1 <= np.pi/2 and theta2 <= np.pi/2:
|
||||
if ((distance1 <= r or distance2 <= r) and
|
||||
theta1 <= np.pi/2 and theta2 <= np.pi/2):
|
||||
build = 1
|
||||
|
||||
if build:
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
|
||||
cpdef void build_sphere(
|
||||
@@ -887,15 +925,17 @@ cpdef void build_sphere(
|
||||
np.int8_t[:, :, :, ::1] rigidH,
|
||||
np.uint32_t[:, :, :, ::1] ID
|
||||
):
|
||||
"""Builds #sphere commands which sets values in the solid, rigid and ID arrays for a Yee voxel.
|
||||
"""Builds spheres which sets values in the solid, rigid and ID arrays for
|
||||
a Yee voxel.
|
||||
|
||||
Args:
|
||||
xc, yc, zc (int): Cell coordinates of the centre of the sphere.
|
||||
r (float): Radius of the sphere.
|
||||
dx, dy, dz (float): Spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz (int): Numeric ID of material.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
xc, yc, zc: ints for cell coordinates of the centre of the sphere.
|
||||
r: float for radius of the sphere.
|
||||
dx, dy, dz: floats for spatial discretisation.
|
||||
numID, numIDx, numIDy, numIDz: ints for numeric ID of material.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -926,8 +966,11 @@ cpdef void build_sphere(
|
||||
for i in range(xs, xf):
|
||||
for j in range(ys, yf):
|
||||
for k in range(zs, zf):
|
||||
if np.sqrt((i + 0.5 - xc)**2 * dx**2 + (j + 0.5 - yc)**2 * dy**2 + (k + 0.5 - zc)**2 * dz**2) <= r:
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
if (np.sqrt((i + 0.5 - xc)**2 * dx**2 +
|
||||
(j + 0.5 - yc)**2 * dy**2 +
|
||||
(k + 0.5 - zc)**2 * dz**2) <= r):
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
||||
|
||||
cpdef void build_voxels_from_array(
|
||||
@@ -945,11 +988,14 @@ cpdef void build_voxels_from_array(
|
||||
"""Builds Yee voxels by reading integers from an array.
|
||||
|
||||
Args:
|
||||
xs, ys, zs (int): Cell coordinates of position of start of array in domain.
|
||||
numexistmaterials (int): Number of existing materials in model prior to building voxels.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
data (memoryview): Access to array containing numeric IDs of voxels to create.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
xs, ys, zs: ints for cell coordinates of position of start of array in
|
||||
domain.
|
||||
numexistmaterials: int for number of existing materials in model prior
|
||||
to building voxels.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
data: memoryview to access array containing numeric IDs of voxels to create.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -1003,12 +1049,13 @@ cpdef void build_voxels_from_array_mask(
|
||||
"""Builds Yee voxels by reading integers from an array.
|
||||
|
||||
Args:
|
||||
xs, ys, zs (int): Cell coordinates of position of start of array in domain.
|
||||
waternumID, grassnumID (int): Numeric ID of water and grass materials.
|
||||
averaging (bint): Whether material property averaging will occur for the object.
|
||||
data (memoryview): Access to array containing numeric IDs of voxels to create.
|
||||
mask (memoryview): Access to array containing a mask of voxels to create.
|
||||
solid, rigidE, rigidH, ID (memoryviews): Access to solid, rigid and ID arrays.
|
||||
xs, ys, zs: ints for cell coordinates of position of start of array in domain.
|
||||
waternumID, grassnumID: ints for numeric ID of water and grass materials.
|
||||
averaging: bint for whether material property averaging will occur for
|
||||
the object.
|
||||
data: memoryview to access array containing numeric IDs of voxels to create.
|
||||
mask: memoryview to access to array containing a mask of voxels to create.
|
||||
solid, rigidE, rigidH, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -1024,10 +1071,13 @@ cpdef void build_voxels_from_array_mask(
|
||||
for k in range(zs, zf):
|
||||
if mask[i - xs, j - ys, k - zs] == 1:
|
||||
numID = numIDx = numIDy = numIDz = data[i - xs, j - ys, k - zs]
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
elif mask[i - xs, j - ys, k - zs] == 2:
|
||||
numID = numIDx = numIDy = numIDz = waternumID
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
elif mask[i - xs, j - ys, k - zs] == 3:
|
||||
numID = numIDx = numIDy = numIDz = grassnumID
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID)
|
||||
build_voxel(i, j, k, numID, numIDx, numIDy, numIDz,
|
||||
averaging, solid, rigidE, rigidH, ID)
|
||||
|
@@ -36,15 +36,13 @@ cpdef void calculate_snapshot_fields(
|
||||
float_or_double[:, :, ::1] snapHy,
|
||||
float_or_double[:, :, ::1] snapHz
|
||||
):
|
||||
"""This function calculates electric and magnetic values at points from
|
||||
averaging values in cells.
|
||||
"""Calculates electric and magnetic values at points from averaging values
|
||||
in cells.
|
||||
|
||||
Args:
|
||||
nx, ny, nz (int): Size of snapshot array
|
||||
sliceEx, sliceEy, sliceEz,
|
||||
sliceHx, sliceHy, sliceHz (memoryview): Access to slices of field arrays
|
||||
snapEx, snapEy, snapEz,
|
||||
snapHx, snapHy, snapHz (memoryview): Access to snapshot arrays
|
||||
nx, ny, nz: ints for size of snapshot array.
|
||||
slice: memoryviews to access slices of field arrays.
|
||||
snap: memoryviews to access snapshot arrays.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
|
@@ -28,18 +28,30 @@ from gprMax.cython.yee_cell_setget_rigid cimport get_rigid_Hz
|
||||
from gprMax.materials import Material
|
||||
|
||||
|
||||
cpdef void create_electric_average(int i, int j, int k, int numID1, int numID2, int numID3, int numID4, int componentID, G):
|
||||
"""This function creates a new material by averaging the dielectric properties of the surrounding cells.
|
||||
cpdef void create_electric_average(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
int numID1,
|
||||
int numID2,
|
||||
int numID3,
|
||||
int numID4,
|
||||
int componentID,
|
||||
G
|
||||
):
|
||||
"""Creates a new material by averaging the dielectric properties of the
|
||||
surrounding cells.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates.
|
||||
numID1, numID2, numID3, numID4 (int): Numeric IDs for materials in surrounding cells.
|
||||
componentID (int): Numeric ID for electric field component.
|
||||
G (class): Grid class instance - holds essential parameters describing the model.
|
||||
i, j, k: ints for cell coordinates.
|
||||
numID: ints for numeric IDs for materials in surrounding cells.
|
||||
componentID: int for numeric ID for electric field component.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
# Make an ID composed of the names of the four materials that will be averaged
|
||||
requiredID = G.materials[numID1].ID + '+' + G.materials[numID2].ID + '+' + G.materials[numID3].ID + '+' + G.materials[numID4].ID
|
||||
requiredID = (G.materials[numID1].ID + '+' + G.materials[numID2].ID + '+' +
|
||||
G.materials[numID3].ID + '+' + G.materials[numID4].ID)
|
||||
|
||||
# Check if this material already exists
|
||||
tmp = requiredID.split('+')
|
||||
@@ -57,10 +69,14 @@ cpdef void create_electric_average(int i, int j, int k, int numID1, int numID2,
|
||||
m = Material(newNumID, requiredID)
|
||||
m.type = 'dielectric-smoothed'
|
||||
# Create averaged constituents for material
|
||||
m.er = np.mean((G.materials[numID1].er, G.materials[numID2].er, G.materials[numID3].er, G.materials[numID4].er), axis=0)
|
||||
m.se = np.mean((G.materials[numID1].se, G.materials[numID2].se, G.materials[numID3].se, G.materials[numID4].se), axis=0)
|
||||
m.mr = np.mean((G.materials[numID1].mr, G.materials[numID2].mr, G.materials[numID3].mr, G.materials[numID4].mr), axis=0)
|
||||
m.sm = np.mean((G.materials[numID1].sm, G.materials[numID2].sm, G.materials[numID3].sm, G.materials[numID4].sm), axis=0)
|
||||
m.er = np.mean((G.materials[numID1].er, G.materials[numID2].er,
|
||||
G.materials[numID3].er, G.materials[numID4].er), axis=0)
|
||||
m.se = np.mean((G.materials[numID1].se, G.materials[numID2].se,
|
||||
G.materials[numID3].se, G.materials[numID4].se), axis=0)
|
||||
m.mr = np.mean((G.materials[numID1].mr, G.materials[numID2].mr,
|
||||
G.materials[numID3].mr, G.materials[numID4].mr), axis=0)
|
||||
m.sm = np.mean((G.materials[numID1].sm, G.materials[numID2].sm,
|
||||
G.materials[numID3].sm, G.materials[numID4].sm), axis=0)
|
||||
|
||||
# Append the new material object to the materials list
|
||||
G.materials.append(m)
|
||||
@@ -68,14 +84,23 @@ cpdef void create_electric_average(int i, int j, int k, int numID1, int numID2,
|
||||
G.ID[componentID, i, j, k] = newNumID
|
||||
|
||||
|
||||
cpdef void create_magnetic_average(int i, int j, int k, int numID1, int numID2, int componentID, G):
|
||||
"""This function creates a new material by averaging the dielectric properties of the surrounding cells.
|
||||
cpdef void create_magnetic_average(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
int numID1,
|
||||
int numID2,
|
||||
int componentID,
|
||||
G
|
||||
):
|
||||
"""Creates a new material by averaging the dielectric properties of the
|
||||
surrounding cells.
|
||||
|
||||
Args:
|
||||
i, j, k (int): Cell coordinates.
|
||||
numID1, numID2 (int): Numeric IDs for materials in surrounding cells.
|
||||
componentID (int): Numeric ID for electric field component.
|
||||
G (class): Grid class instance - holds essential parameters describing the model.
|
||||
i, j, k: ints for cell coordinates.
|
||||
numID: ints for numeric IDs for materials in surrounding cells.
|
||||
componentID: int for numeric ID for magnetic field component.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
# Make an ID composed of the names of the two materials that will be averaged
|
||||
@@ -107,12 +132,17 @@ cpdef void create_magnetic_average(int i, int j, int k, int numID1, int numID2,
|
||||
G.ID[componentID, i, j, k] = newNumID
|
||||
|
||||
|
||||
cpdef void build_electric_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:, :, :, ::1] rigidE, np.uint32_t[:, :, :, ::1] ID, G):
|
||||
"""This function builds the electric field components in the ID array.
|
||||
cpdef void build_electric_components(
|
||||
np.uint32_t[:, :, ::1] solid,
|
||||
np.int8_t[:, :, :, ::1] rigidE,
|
||||
np.uint32_t[:, :, :, ::1] ID,
|
||||
G
|
||||
):
|
||||
"""Builds the electric field components in the ID array.
|
||||
|
||||
Args:
|
||||
solid, rigid, ID (memoryviews): Access to solid, rigid and ID arrays
|
||||
G (class): Grid class instance - holds essential parameters describing the model.
|
||||
solid, rigid, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -138,7 +168,8 @@ cpdef void build_electric_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[componentID, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_electric_average(i, j, k, numID1, numID2, numID3, numID4, componentID, G)
|
||||
create_electric_average(i, j, k, numID1, numID2,
|
||||
numID3, numID4, componentID, G)
|
||||
|
||||
# Ey component
|
||||
componentID = G.IDlookup['Ey']
|
||||
@@ -160,7 +191,8 @@ cpdef void build_electric_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[componentID, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_electric_average(i, j, k, numID1, numID2, numID3, numID4, componentID, G)
|
||||
create_electric_average(i, j, k, numID1, numID2,
|
||||
numID3, numID4, componentID, G)
|
||||
|
||||
# Ez component
|
||||
componentID = G.IDlookup['Ez']
|
||||
@@ -182,15 +214,21 @@ cpdef void build_electric_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[componentID, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_electric_average(i, j, k, numID1, numID2, numID3, numID4, componentID, G)
|
||||
create_electric_average(i, j, k, numID1, numID2,
|
||||
numID3, numID4, componentID, G)
|
||||
|
||||
|
||||
cpdef void build_magnetic_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:, :, :, ::1] rigidH, np.uint32_t[:, :, :, ::1] ID, G):
|
||||
"""This function builds the magnetic field components in the ID array.
|
||||
cpdef void build_magnetic_components(
|
||||
np.uint32_t[:, :, ::1] solid,
|
||||
np.int8_t[:, :, :, ::1] rigidH,
|
||||
np.uint32_t[:, :, :, ::1] ID,
|
||||
G
|
||||
):
|
||||
"""Builds the magnetic field components in the ID array.
|
||||
|
||||
Args:
|
||||
solid, rigid, ID (memoryviews): Access to solid, rigid and ID arrays
|
||||
G (class): Grid class instance - holds essential parameters describing the model.
|
||||
solid, rigid, ID: memoryviews to access solid, rigid and ID arrays.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
cdef Py_ssize_t i, j, k
|
||||
@@ -214,7 +252,8 @@ cpdef void build_magnetic_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[componentID, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_magnetic_average(i, j, k, numID1, numID2, componentID, G)
|
||||
create_magnetic_average(i, j, k, numID1, numID2,
|
||||
componentID, G)
|
||||
|
||||
# Hy component
|
||||
componentID = G.IDlookup['Hy']
|
||||
@@ -234,7 +273,8 @@ cpdef void build_magnetic_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[4, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_magnetic_average(i, j, k, numID1, numID2, componentID, G)
|
||||
create_magnetic_average(i, j, k, numID1, numID2,
|
||||
componentID, G)
|
||||
|
||||
# Hz component
|
||||
componentID = G.IDlookup['Hz']
|
||||
@@ -254,4 +294,5 @@ cpdef void build_magnetic_components(np.uint32_t[:, :, ::1] solid, np.int8_t[:,
|
||||
ID[5, i, j, k] = numID1
|
||||
else:
|
||||
# Averaging is required
|
||||
create_magnetic_average(i, j, k, numID1, numID2, componentID, G)
|
||||
create_magnetic_average(i, j, k, numID1, numID2,
|
||||
componentID, G)
|
||||
|
@@ -23,7 +23,13 @@ cimport numpy as np
|
||||
# Get and set functions for the rigid electric component array. The rigid array
|
||||
# is 4D with the 1st dimension holding the 12 electric edge components of a
|
||||
# cell - Ex1, Ex2, Ex3, Ex4, Ey1, Ey2, Ey3, Ey4, Ez1, Ez2, Ez3, Ez4
|
||||
cdef bint get_rigid_Ex(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
cdef bint get_rigid_Ex(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidE[0, i, j, k]:
|
||||
@@ -39,7 +45,13 @@ cdef bint get_rigid_Ex(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef bint get_rigid_Ey(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef bint get_rigid_Ey(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidE[4, i, j, k]:
|
||||
@@ -55,7 +67,13 @@ cdef bint get_rigid_Ey(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef bint get_rigid_Ez(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef bint get_rigid_Ez(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidE[8, i, j, k]:
|
||||
@@ -71,7 +89,13 @@ cdef bint get_rigid_Ez(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef void set_rigid_Ex(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef void set_rigid_Ex(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
rigidE[0, i, j, k] = True
|
||||
if j != 0:
|
||||
rigidE[1, i, j - 1, k] = True
|
||||
@@ -80,7 +104,13 @@ cdef void set_rigid_Ex(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
if j != 0 and k != 0:
|
||||
rigidE[2, i, j - 1, k - 1] = True
|
||||
|
||||
cdef void set_rigid_Ey(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef void set_rigid_Ey(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
rigidE[4, i, j, k] = True
|
||||
if i != 0:
|
||||
rigidE[7, i - 1, j, k] = True
|
||||
@@ -89,7 +119,13 @@ cdef void set_rigid_Ey(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
if i != 0 and k != 0:
|
||||
rigidE[6, i - 1, j, k - 1] = True
|
||||
|
||||
cdef void set_rigid_Ez(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef void set_rigid_Ez(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
rigidE[8, i, j, k] = True
|
||||
if i != 0:
|
||||
rigidE[9, i - 1, j, k] = True
|
||||
@@ -98,16 +134,33 @@ cdef void set_rigid_Ez(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
if i != 0 and j != 0:
|
||||
rigidE[10, i - 1, j - 1, k] = True
|
||||
|
||||
cdef void set_rigid_E(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef void set_rigid_E(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
rigidE[:, i, j, k] = True
|
||||
|
||||
cdef void unset_rigid_E(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidE):
|
||||
|
||||
cdef void unset_rigid_E(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidE
|
||||
):
|
||||
rigidE[:, i, j, k] = False
|
||||
|
||||
# Get and set functions for the rigid magnetic component array. The rigid array
|
||||
# is 4D with the 1st dimension holding the 6 magnetic edge components - Hx1,
|
||||
# Hx2, Hy1, Hy2, Hz1, Hz2
|
||||
cdef bint get_rigid_Hx(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
cdef bint get_rigid_Hx(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidH[0, i, j, k]:
|
||||
@@ -117,7 +170,13 @@ cdef bint get_rigid_Hx(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef bint get_rigid_Hy(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef bint get_rigid_Hy(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidH[2, i, j, k]:
|
||||
@@ -127,7 +186,13 @@ cdef bint get_rigid_Hy(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef bint get_rigid_Hz(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef bint get_rigid_Hz(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
cdef bint result
|
||||
result = False
|
||||
if rigidH[4, i, j, k]:
|
||||
@@ -137,23 +202,53 @@ cdef bint get_rigid_Hz(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
result = True
|
||||
return result
|
||||
|
||||
cdef void set_rigid_Hx(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef void set_rigid_Hx(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
rigidH[0, i, j, k] = True
|
||||
if i != 0:
|
||||
rigidH[1, i - 1, j, k] = True
|
||||
|
||||
cdef void set_rigid_Hy(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef void set_rigid_Hy(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
rigidH[2, i, j, k] = True
|
||||
if j != 0:
|
||||
rigidH[3, i, j - 1, k] = True
|
||||
|
||||
cdef void set_rigid_Hz(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef void set_rigid_Hz(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
rigidH[4, i, j, k] = True
|
||||
if k != 0:
|
||||
rigidH[5, i, j, k - 1] = True
|
||||
|
||||
cdef void set_rigid_H(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef void set_rigid_H(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
rigidH[:, i, j, k] = True
|
||||
|
||||
cdef void unset_rigid_H(int i, int j, int k, np.int8_t[:, :, :, ::1] rigidH):
|
||||
|
||||
cdef void unset_rigid_H(
|
||||
int i,
|
||||
int j,
|
||||
int k,
|
||||
np.int8_t[:, :, :, ::1] rigidH
|
||||
):
|
||||
rigidH[:, i, j, k] = False
|
||||
|
@@ -17,7 +17,6 @@
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import numpy as np
|
||||
|
||||
from ..grid import FDTDGrid
|
||||
|
||||
@@ -57,7 +56,7 @@ class SubGridBase(FDTDGrid):
|
||||
|
||||
# Number of sub cells to extend the sub grid beyond the IS boundary
|
||||
d_to_pml = self.s_is_os_sep + self.pml_separation
|
||||
# index of the is
|
||||
# Index of the is
|
||||
self.n_boundary_cells = d_to_pml + self.pmlthickness['x0']
|
||||
self.n_boundary_cells_x = d_to_pml + self.pmlthickness['x0']
|
||||
self.n_boundary_cells_y = d_to_pml + self.pmlthickness['y0']
|
||||
|
@@ -34,14 +34,14 @@ class ReferenceRx(Rx):
|
||||
logger.debug('ReferenceRx has no offset member.')
|
||||
|
||||
def get_field(self, str_id, field):
|
||||
"""Return the field value at the equivalent coarse yee cell.
|
||||
"""Field value at the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
str_id (str): 'Ex' etc...
|
||||
field (nparray): Numpy array of grid.Ez
|
||||
str_id: string of 'Ex' etc...
|
||||
field: nparray of grid.Ez
|
||||
|
||||
Returns:
|
||||
e (float): Field value.
|
||||
e: float of field value.
|
||||
"""
|
||||
|
||||
d = {
|
||||
@@ -58,13 +58,13 @@ class ReferenceRx(Rx):
|
||||
return e
|
||||
|
||||
def get_Ex_from_field(self, Ex):
|
||||
"""Return the Ex field value from the equivalent coarse yee cell.
|
||||
"""Ex field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Ex (nparray): Numpy array of Ex field.
|
||||
Ex: nparray of Ex field.
|
||||
|
||||
Returns:
|
||||
e (float): Ex field value.
|
||||
e: float of Ex field value.
|
||||
"""
|
||||
|
||||
# offset = ratio // 2
|
||||
@@ -72,62 +72,62 @@ class ReferenceRx(Rx):
|
||||
return e
|
||||
|
||||
def get_Ey_from_field(self, Ey):
|
||||
"""Return the Ey field value from the equivalent coarse yee cell.
|
||||
"""Ey field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Ey (nparray): Numpy array of Ey field.
|
||||
Ey: nparray of Ey field.
|
||||
|
||||
Returns:
|
||||
e (float): Ey field value.
|
||||
e: float of Ey field value.
|
||||
"""
|
||||
e = Ey[self.xcoord, self.ycoord + self.offset, self.zcoord]
|
||||
return e
|
||||
|
||||
def get_Ez_from_field(self, Ez):
|
||||
"""Return the Ez field value from the equivalent coarse yee cell.
|
||||
"""Ez field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Ez (nparray): Numpy array of Ez field.
|
||||
Ez: nparray of Ez field.
|
||||
|
||||
Returns:
|
||||
e (float): Ez field value.
|
||||
e: float of Ez field value.
|
||||
"""
|
||||
|
||||
e = Ez[self.xcoord, self.ycoord, self.zcoord + self.offset]
|
||||
return e
|
||||
|
||||
def get_Hx_from_field(self, Hx):
|
||||
"""Return the Hx field value from the equivalent coarse yee cell.
|
||||
"""Hx field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Hx (nparray): Numpy array of Hx field.
|
||||
Hx: nparray of Hx field.
|
||||
|
||||
Returns:
|
||||
e (float): Hx field value.
|
||||
e: float of Hx field value.
|
||||
"""
|
||||
e = Hx[self.xcoord, self.ycoord + self.offset, self.zcoord + self.offset]
|
||||
return e
|
||||
|
||||
def get_Hy_from_field(self, Hy):
|
||||
"""Return the Hy field value from the equivalent coarse yee cell.
|
||||
"""Hy field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Hy (nparray): Numpy array of Hy field.
|
||||
Hy: nparray of Hy field.
|
||||
|
||||
Returns:
|
||||
e (float): Hy field value.
|
||||
e: float of Hy field value.
|
||||
"""
|
||||
e = Hy[self.xcoord + self.offset, self.ycoord, self.zcoord + self.offset]
|
||||
return e
|
||||
|
||||
def get_Hz_from_field(self, Hz):
|
||||
"""Return the Hz field value from the equivalent coarse yee cell.
|
||||
"""Hz field value from the equivalent coarse yee cell.
|
||||
|
||||
Args:
|
||||
Hz (nparray): Numpy array of Hz field.
|
||||
Hz: nparray of Hz field.
|
||||
|
||||
Returns:
|
||||
e (float): Hz field value.
|
||||
e: float of Hz field value.
|
||||
"""
|
||||
e = Hz[self.xcoord + self.offset, self.ycoord + self.offset, self.zcoord]
|
||||
return e
|
@@ -180,9 +180,8 @@ class PrecursorNodesBase:
|
||||
setattr(self, f, val)
|
||||
|
||||
def calc_exact_field(self, field_names):
|
||||
"""Function to set the fields used in update calculations to the
|
||||
values at the current main time step.
|
||||
i.e. ey_left = copy.ey_left_1
|
||||
"""Sets the fields used in update calculations to the values at the
|
||||
current main time step, i.e. ey_left = copy.ey_left_1
|
||||
"""
|
||||
for f in field_names:
|
||||
val = np.copy(getattr(self, f + '_1'))
|
||||
|
@@ -36,7 +36,7 @@ class SubGridHSG(SubGridBase):
|
||||
self.gridtype = SubGridHSG.gridtype
|
||||
|
||||
def update_magnetic_is(self, precursors):
|
||||
"""Update the subgrid nodes at the IS with the currents derived
|
||||
"""Updates the subgrid nodes at the IS with the currents derived
|
||||
from the main grid.
|
||||
|
||||
Args:
|
||||
@@ -59,7 +59,7 @@ class SubGridHSG(SubGridBase):
|
||||
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx + 1, self.nwz, self.nwy, 3, self.Hx, precursors.ez_front, precursors.ez_back, self.IDlookup['Hx'], 1, -1, 2, config.get_model_config().ompthreads)
|
||||
|
||||
def update_electric_is(self, precursors):
|
||||
"""Update the subgrid nodes at the IS with the currents derived
|
||||
"""Updates the subgrid nodes at the IS with the currents derived
|
||||
from the main grid.
|
||||
|
||||
Args:
|
||||
@@ -142,7 +142,7 @@ class SubGridHSG(SubGridBase):
|
||||
cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 1, i_l, i_u + 1, j_l, j_u, k_l - 1, k_u, self.nwz, main_grid.IDlookup['Hx'], main_grid.Hx, self.Ey, 3, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
|
||||
|
||||
def print_info(self):
|
||||
"""Print information about the subgrid."""
|
||||
"""Prints information about the subgrid."""
|
||||
|
||||
logger.info('')
|
||||
logger.info(f'[{self.name}] Type: {self.gridtype}')
|
||||
|
@@ -47,37 +47,37 @@ def create_updates(G):
|
||||
|
||||
|
||||
class SubgridUpdates(CPUUpdates):
|
||||
"""Provides update functions for the Sub gridding simulation."""
|
||||
"""Update functions for the Sub gridding simulation."""
|
||||
|
||||
def __init__(self, G, updaters):
|
||||
super().__init__(G)
|
||||
self.updaters = updaters
|
||||
|
||||
def hsg_1(self):
|
||||
"""Method to update the subgrids over the first phase."""
|
||||
# updaters update each subgrid
|
||||
"""Updates the subgrids over the first phase."""
|
||||
for sg_updater in self.updaters:
|
||||
sg_updater.hsg_1()
|
||||
|
||||
def hsg_2(self):
|
||||
"""Method to update the subgrids over the second phase."""
|
||||
"""Updates the subgrids over the second phase."""
|
||||
for sg_updater in self.updaters:
|
||||
sg_updater.hsg_2()
|
||||
|
||||
|
||||
class SubgridUpdater(CPUUpdates):
|
||||
"""Class to handle updating the electric and magnetic fields of an HSG
|
||||
subgrid. The IS, OS, subgrid region and the electric/magnetic sources
|
||||
are updated using the precursor regions.
|
||||
"""Handles updating the electric and magnetic fields of an HSG subgrid.
|
||||
The IS, OS, subgrid region and the electric/magnetic sources are updated
|
||||
using the precursor regions.
|
||||
"""
|
||||
|
||||
def __init__(self, subgrid, precursors, G):
|
||||
"""
|
||||
Args:
|
||||
subgrid (SubGrid3d): Subgrid to be updated.
|
||||
precursors (PrecursorNodes): Precursor nodes associated with
|
||||
the subgrid - contain interpolated fields.
|
||||
G (FDTDGrid): Parameters describing a grid in a model.
|
||||
subgrid: SubGrid3d instance to be updated.
|
||||
precursors (PrecursorNodes): PrecursorNodes instance nodes associated
|
||||
with the subgrid - contain interpolated
|
||||
fields.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
super().__init__(subgrid)
|
||||
self.precursors = precursors
|
||||
@@ -85,8 +85,8 @@ class SubgridUpdater(CPUUpdates):
|
||||
self.source_iteration = 0
|
||||
|
||||
def hsg_1(self):
|
||||
"""This is the first half of the subgrid update. Takes the time step
|
||||
up to the main grid magnetic update.
|
||||
"""First half of the subgrid update. Takes the time step up to the main
|
||||
grid magnetic update.
|
||||
"""
|
||||
|
||||
G = self.G
|
||||
@@ -126,8 +126,8 @@ class SubgridUpdater(CPUUpdates):
|
||||
sub_grid.update_electric_os(G)
|
||||
|
||||
def hsg_2(self):
|
||||
"""This is the first half of the subgrid update. Takes the time step
|
||||
up to the main grid electric update.
|
||||
"""Second half of the subgrid update. Takes the time step up to the main
|
||||
grid electric update.
|
||||
"""
|
||||
|
||||
G = self.G
|
||||
|
@@ -30,18 +30,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SubGridBase(UserObjectMulti):
|
||||
"""Class to allow UserObjectMulti and UserObjectGeometry to be nested
|
||||
in SubGrid type user objects.
|
||||
"""Allows UserObjectMulti and UserObjectGeometry to be nested in SubGrid
|
||||
type user objects.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Constructor."""
|
||||
super().__init__(**kwargs)
|
||||
self.children_multiple = []
|
||||
self.children_geometry = []
|
||||
|
||||
def add(self, node):
|
||||
"""Function to add other user objects. Geometry and multi only."""
|
||||
"""Adds other user objects. Geometry and multi only."""
|
||||
if isinstance(node, UserObjectMulti):
|
||||
self.children_multiple.append(node)
|
||||
elif isinstance(node, UserObjectGeometry):
|
||||
@@ -51,14 +50,13 @@ class SubGridBase(UserObjectMulti):
|
||||
raise ValueError
|
||||
|
||||
def set_discretisation(self, sg, grid):
|
||||
"""Set the spatial discretisation."""
|
||||
sg.dx = grid.dx / sg.ratio
|
||||
sg.dy = grid.dy / sg.ratio
|
||||
sg.dz = grid.dz / sg.ratio
|
||||
sg.dl = np.array([sg.dx, sg.dy, sg.dz])
|
||||
|
||||
def set_main_grid_indices(self, sg, grid, uip, p1, p2):
|
||||
"""Set subgrid indices related to main grid placement."""
|
||||
"""Sets subgrid indices related to main grid placement."""
|
||||
# location of the IS
|
||||
sg.i0, sg.j0, sg.k0 = p1
|
||||
sg.i1, sg.j1, sg.k1 = p2
|
||||
@@ -82,7 +80,7 @@ class SubGridBase(UserObjectMulti):
|
||||
sg.nz = 2 * sg.n_boundary_cells_z + sg.nwz
|
||||
|
||||
def set_iterations(self, sg, main):
|
||||
"""Set number of iterations that will take place in the subgrid."""
|
||||
"""Sets number of iterations that will take place in the subgrid."""
|
||||
sg.iterations = main.iterations * sg.ratio
|
||||
|
||||
def setup(self, sg, grid, uip):
|
||||
@@ -97,7 +95,7 @@ class SubGridBase(UserObjectMulti):
|
||||
# Set the temporal discretisation
|
||||
sg.calculate_dt()
|
||||
|
||||
# set the indices related to the subgrids main grid placement
|
||||
# Set the indices related to the subgrids main grid placement
|
||||
self.set_main_grid_indices(sg, grid, uip, p1, p2)
|
||||
|
||||
"""
|
||||
@@ -121,8 +119,8 @@ class SubGridBase(UserObjectMulti):
|
||||
|
||||
sg.timewindow = grid.timewindow
|
||||
|
||||
# Copy a subgrid reference to self so that children.create(grid, uip) can access
|
||||
# the correct grid
|
||||
# Copy a subgrid reference to self so that children.create(grid, uip)
|
||||
# can access the correct grid.
|
||||
self.subgrid = sg
|
||||
|
||||
# Copy over built in materials
|
||||
@@ -141,25 +139,25 @@ class SubGridBase(UserObjectMulti):
|
||||
class SubGridHSG(SubGridBase):
|
||||
"""Huygens Surface subgridding (HSG) user object.
|
||||
|
||||
:param p1: Position of the lower left corner of the Inner Surface (x, y, z) in the main grid.
|
||||
:type p1: list, non-optional
|
||||
:param p2: Position of the upper right corner of the Inner Surface (x, y, z) in the main grid.
|
||||
:type p2: list, non-optional
|
||||
:param ratio: Ratio of the main grid spatial step to the sub-grid spatial step. Must be an odd integer.
|
||||
:type ratio: int, non-optional
|
||||
:param id: Identifier for the sub-grid.
|
||||
:type id: str, non-optional
|
||||
:param is_os_sep: Number of main grid cells between the Inner Surface and the Outer Surface. Defaults to 3.
|
||||
:type is_os_sep: str, optional
|
||||
:param pml_separation: Number of sub-grid cells between the Outer Surface and the PML. Defaults to ratio // 2 + 2
|
||||
:type pml_separation: int, optional
|
||||
:param subgrid_pml_thickness: Thickness of the PML on each of the 6 sides of the sub-grid. Defaults to 6.
|
||||
:type subgrid_pml_thickness: int, optional
|
||||
:param interpolation: Degree of the interpolation scheme used for spatial interpolation of the fields at the Inner Surface. Defaults to Linear
|
||||
:type interpolation: str, optional
|
||||
:param filter: Turn on the 3-pole filter. Increases numerical stability. Defaults to True
|
||||
:type filter: bool, optional
|
||||
|
||||
Attributes:
|
||||
p1: list of the position of the lower left corner of the Inner Surface
|
||||
(x, y, z) in the main grid.
|
||||
p2: list of the position of the upper right corner of the Inner Surface
|
||||
(x, y, z) in the main grid.
|
||||
ratio: int of the ratio of the main grid spatial step to the sub-grid
|
||||
spatial step. Must be an odd integer.
|
||||
id: string identifier for the sub-grid.
|
||||
is_os_sep: int for the number of main grid cells between the Inner
|
||||
Surface and the Outer Surface. Defaults to 3.
|
||||
pml_separation: int for the number of sub-grid cells between the Outer
|
||||
Surface and the PML. Defaults to ratio // 2 + 2
|
||||
subgrid_pml_thickness: int for the thickness of the PML on each of the
|
||||
6 sides of the sub-grid. Defaults to 6.
|
||||
interpolation: string for the degree of the interpolation scheme used
|
||||
for spatial interpolation of the fields at the Inner
|
||||
Surface. Defaults to Linear.
|
||||
filter: boolean to turn on the 3-pole filter. Increases numerical
|
||||
stability. Defaults to True.
|
||||
"""
|
||||
def __init__(self,
|
||||
p1=None,
|
||||
@@ -175,7 +173,7 @@ class SubGridHSG(SubGridBase):
|
||||
|
||||
pml_separation = ratio // 2 + 2
|
||||
|
||||
# copy over the optional parameters
|
||||
# Copy over the optional parameters
|
||||
kwargs['p1'] = p1
|
||||
kwargs['p2'] = p2
|
||||
kwargs['ratio'] = ratio
|
||||
|
在新工单中引用
屏蔽一个用户