你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 04:56:51 +08:00
Updates docstrings and line lengths
这个提交包含在:
@@ -29,20 +29,21 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddGrass(UserObjectGeometry):
|
||||
"""Allows you to add grass with roots to a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` in the model.
|
||||
"""Allows you to add grass with roots to a FractalBox class in the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p1: list, non-optional
|
||||
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p2: list, non-optional
|
||||
:param frac_dim: is the fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three.
|
||||
:type frac_dim: float, non-optional
|
||||
:param limits: Define lower and upper limits for a range over which the height of the blades of grass can vary.
|
||||
:type limits: list, non-optional
|
||||
:param n_blades: The number of blades of grass that should be applied to the surface area.
|
||||
:type n_blades: int, non-optional
|
||||
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the grass should be applied to
|
||||
:type fractal_box_id: list, non-optional
|
||||
Attributes:
|
||||
p1: a 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
|
||||
FractalBox class.
|
||||
frac_dim: a 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
|
||||
the height of the blades of grass can vary.
|
||||
n_blades: an 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
|
||||
grass should be applied to.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -97,10 +98,12 @@ class AddGrass(UserObjectGeometry):
|
||||
xf, yf, zf = p2
|
||||
|
||||
if frac_dim < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal dimension')
|
||||
logger.exception(self.__str__() + ' requires a positive value for ' +
|
||||
'the fractal dimension')
|
||||
raise ValueError
|
||||
if limits[0] < 0 or limits[1] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the minimum and maximum heights for grass blades')
|
||||
logger.exception(self.__str__() + ' requires a positive value for ' +
|
||||
'the minimum and maximum heights for grass blades')
|
||||
raise ValueError
|
||||
|
||||
# Check for valid orientations
|
||||
@@ -114,12 +117,15 @@ class AddGrass(UserObjectGeometry):
|
||||
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
|
||||
# xminus surface
|
||||
if xs == volume.xs:
|
||||
logger.exception(self.__str__() + ' grass can only be specified on surfaces in the positive axis direction')
|
||||
logger.exception(self.__str__() + ' grass can only be specified ' +
|
||||
'on surfaces in the positive axis direction')
|
||||
raise ValueError
|
||||
# xplus surface
|
||||
elif xf == volume.xf:
|
||||
if fractalrange[1] > grid.nx:
|
||||
logger.exception(self.__str__() + ' cannot apply grass to fractal box as it would exceed the domain size in the x direction')
|
||||
logger.exception(self.__str__() + ' cannot apply grass to ' +
|
||||
'fractal box as it would exceed the domain ' +
|
||||
'size in the x direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'xplus'
|
||||
|
||||
@@ -133,12 +139,15 @@ class AddGrass(UserObjectGeometry):
|
||||
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
|
||||
# yminus surface
|
||||
if ys == volume.ys:
|
||||
logger.exception(self.__str__() + ' grass can only be specified on surfaces in the positive axis direction')
|
||||
logger.exception(self.__str__() + ' grass can only be specified ' +
|
||||
'on surfaces in the positive axis direction')
|
||||
raise ValueError
|
||||
# yplus surface
|
||||
elif yf == volume.yf:
|
||||
if fractalrange[1] > grid.ny:
|
||||
logger.exception(self.__str__() + ' cannot apply grass to fractal box as it would exceed the domain size in the y direction')
|
||||
logger.exception(self.__str__() + ' cannot apply grass to ' +
|
||||
'fractal box as it would exceed the domain ' +
|
||||
'size in the y direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'yplus'
|
||||
|
||||
@@ -152,12 +161,15 @@ class AddGrass(UserObjectGeometry):
|
||||
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
|
||||
# zminus surface
|
||||
if zs == volume.zs:
|
||||
logger.exception(self.__str__() + ' grass can only be specified on surfaces in the positive axis direction')
|
||||
logger.exception(self.__str__() + ' grass can only be specified ' +
|
||||
'on surfaces in the positive axis direction')
|
||||
raise ValueError
|
||||
# zplus surface
|
||||
elif zf == volume.zf:
|
||||
if fractalrange[1] > grid.nz:
|
||||
logger.exception(self.__str__() + ' cannot apply grass to fractal box as it would exceed the domain size in the z direction')
|
||||
logger.exception(self.__str__() + ' cannot apply grass to ' +
|
||||
'fractal box as it would exceed the domain ' +
|
||||
'size in the z direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'zplus'
|
||||
|
||||
@@ -175,7 +187,8 @@ class AddGrass(UserObjectGeometry):
|
||||
surface.operatingonID = volume.ID
|
||||
surface.generate_fractal_surface()
|
||||
if n_blades > surface.fractalsurface.shape[0] * surface.fractalsurface.shape[1]:
|
||||
logger.exception(self.__str__() + ' the specified surface is not large enough for the number of grass blades/roots specified')
|
||||
logger.exception(self.__str__() + ' the specified surface is not large ' +
|
||||
'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
|
||||
@@ -213,9 +226,15 @@ class AddGrass(UserObjectGeometry):
|
||||
grass = next((x for x in grid.materials if x.ID == 'grass'))
|
||||
testgrass = next((x for x in grass.tau if x < grid.dt), None)
|
||||
if testgrass:
|
||||
logger.exception(self.__str__() + ' requires the time step for the model to be less than the relaxation time required to model grass.')
|
||||
logger.exception(self.__str__() + ' requires the time step for the ' +
|
||||
'model to be less than the relaxation time required to model grass.')
|
||||
raise ValueError
|
||||
|
||||
volume.fractalsurfaces.append(surface)
|
||||
|
||||
logger.info(self.grid_name(grid) + f'{n_blades} blades of grass on surface from {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m with fractal dimension {surface.dimension:g}, fractal seeding {surface.seed}, and range {limits[0]:g}m to {limits[1]:g}m, added to {surface.operatingonID}.')
|
||||
logger.info(self.grid_name(grid) + f'{n_blades} blades of grass on surface from ' +
|
||||
f'{xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, ' +
|
||||
f'to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m ' +
|
||||
f'with fractal dimension {surface.dimension:g}, fractal seeding ' +
|
||||
f'{surface.seed}, and range {limits[0]:g}m to {limits[1]:g}m, ' +
|
||||
f'added to {surface.operatingonID}.')
|
||||
|
@@ -28,22 +28,23 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddSurfaceRoughness(UserObjectGeometry):
|
||||
"""Allows you to add grass with roots to a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` in the model.
|
||||
"""Allows you to add grass with roots to a FractalBox class in the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p1: list, non-optional
|
||||
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p2: list, non-optional
|
||||
:param frac_dim: is the fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three.
|
||||
:type frac_dim: float, non-optional
|
||||
:param weighting: Weightings in the first and second direction of the surface.
|
||||
:type weighting: list, non-optional
|
||||
:param limits: Define lower and upper limits for a range over which the roughness can vary.
|
||||
:type limits: list, non-optional
|
||||
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the roughness should be applied to
|
||||
:type fractal_box_id: list, non-optional
|
||||
:param seed: Is an optional parameter which controls the seeding of the random number generator used to create the fractals.
|
||||
:type seed: int, optional
|
||||
Attributes:
|
||||
p1: a 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
|
||||
FractalBox class.
|
||||
frac_dim: a 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
|
||||
the surface.
|
||||
limits: a list 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
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -65,7 +66,6 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
self.kwargs['p2'] = tuple(rot_pts[1, :])
|
||||
|
||||
def create(self, grid, uip):
|
||||
|
||||
try:
|
||||
p1 = self.kwargs['p1']
|
||||
p2 = self.kwargs['p2']
|
||||
@@ -98,13 +98,16 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
xf, yf, zf = p2
|
||||
|
||||
if frac_dim < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal dimension')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal dimension')
|
||||
raise ValueError
|
||||
if weighting[0] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal weighting in the first direction of the surface')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal weighting in the first direction of the surface')
|
||||
raise ValueError
|
||||
if weighting[1] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal weighting in the second direction of the surface')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal weighting in the second direction of the surface')
|
||||
raise ValueError
|
||||
|
||||
# Check for valid orientations
|
||||
@@ -113,19 +116,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if xs != volume.xs and xs != volume.xf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
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))
|
||||
# xminus surface
|
||||
if xs == volume.xs:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.xf:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the upper coordinates of the fractal box or the domain in the x direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'upper coordinates of the fractal box or the ' +
|
||||
'domain in the x direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'xminus'
|
||||
# xplus surface
|
||||
elif xf == volume.xf:
|
||||
if fractalrange[0] < volume.xs or fractalrange[1] > grid.nx:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the lower coordinates of the fractal box or the domain in the x direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'lower coordinates of the fractal box or the ' +
|
||||
'domain in the x direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'xplus'
|
||||
|
||||
@@ -134,19 +144,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if ys != volume.ys and ys != volume.yf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
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))
|
||||
# yminus surface
|
||||
if ys == volume.ys:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.yf:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the upper coordinates of the fractal box or the domain in the y direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'upper coordinates of the fractal box or the ' +
|
||||
'domain in the y direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'yminus'
|
||||
# yplus surface
|
||||
elif yf == volume.yf:
|
||||
if fractalrange[0] < volume.ys or fractalrange[1] > grid.ny:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the lower coordinates of the fractal box or the domain in the y direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'lower coordinates of the fractal box or the ' +
|
||||
'domain in the y direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'yplus'
|
||||
|
||||
@@ -155,19 +172,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if zs != volume.zs and zs != volume.zf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
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))
|
||||
# zminus surface
|
||||
if zs == volume.zs:
|
||||
if fractalrange[0] < 0 or fractalrange[1] > volume.zf:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the upper coordinates of the fractal box or the domain in the x direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'upper coordinates of the fractal box or the ' +
|
||||
'domain in the x direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'zminus'
|
||||
# zplus surface
|
||||
elif zf == volume.zf:
|
||||
if fractalrange[0] < volume.zs or fractalrange[1] > grid.nz:
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface to fractal box as it would exceed either the lower coordinates of the fractal box or the domain in the z direction')
|
||||
logger.exception(self.__str__() + ' cannot apply fractal surface ' +
|
||||
'to fractal box as it would exceed either the ' +
|
||||
'lower coordinates of the fractal box or the ' +
|
||||
'domain in the z direction')
|
||||
raise ValueError
|
||||
requestedsurface = 'zplus'
|
||||
|
||||
@@ -194,4 +218,10 @@ class AddSurfaceRoughness(UserObjectGeometry):
|
||||
surface.generate_fractal_surface()
|
||||
volume.fractalsurfaces.append(surface)
|
||||
|
||||
logger.info(self.grid_name(grid) + f'Fractal surface from {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m with fractal dimension {surface.dimension:g}, fractal weightings {surface.weighting[0]:g}, {surface.weighting[1]:g}, fractal seeding {surface.seed}, and range {limits[0]:g}m to {limits[1]:g}m, added to {surface.operatingonID}.')
|
||||
logger.info(self.grid_name(grid) + f'Fractal surface from {xs * grid.dx:g}m, ' +
|
||||
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, ' +
|
||||
f'{yf * grid.dy:g}m, {zf * grid.dz:g}m with fractal dimension ' +
|
||||
f'{surface.dimension:g}, fractal weightings {surface.weighting[0]:g}, ' +
|
||||
f'{surface.weighting[1]:g}, fractal seeding {surface.seed}, ' +
|
||||
f'and range {limits[0]:g}m to {limits[1]:g}m, added to ' +
|
||||
f'{surface.operatingonID}.')
|
||||
|
@@ -28,16 +28,18 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AddSurfaceWater(UserObjectGeometry):
|
||||
"""Allows you to add surface water to a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` in the model.
|
||||
"""Allows you to add surface water to a FractalBox class in the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p1: list, non-optional
|
||||
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox`
|
||||
:type p2: list, non-optional
|
||||
:param depth: 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.
|
||||
:type depth: float, non-optional
|
||||
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the water should be applied to
|
||||
:type fractal_box_id: list, non-optional
|
||||
Attributes:
|
||||
p1: a 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
|
||||
FractalBox class.
|
||||
depth: a 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
|
||||
surface water should be applied to.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -94,7 +96,8 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if xs != volume.xs and xs != volume.xf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
logger.exception(self.__str__() + ' can only be used on the ' +
|
||||
'external surfaces of a fractal box')
|
||||
raise ValueError
|
||||
# xminus surface
|
||||
if xs == volume.xs:
|
||||
@@ -110,7 +113,8 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if ys != volume.ys and ys != volume.yf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
logger.exception(self.__str__() + ' can only be used on the ' +
|
||||
'external surfaces of a fractal box')
|
||||
raise ValueError
|
||||
# yminus surface
|
||||
if ys == volume.ys:
|
||||
@@ -126,7 +130,8 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + ' dimensions are not specified correctly')
|
||||
raise ValueError
|
||||
if zs != volume.zs and zs != volume.zf:
|
||||
logger.exception(self.__str__() + ' can only be used on the external surfaces of a fractal box')
|
||||
logger.exception(self.__str__() + ' can only be used on the ' +
|
||||
'external surfaces of a fractal box')
|
||||
raise ValueError
|
||||
# zminus surface
|
||||
if zs == volume.zs:
|
||||
@@ -150,7 +155,9 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
|
||||
# Check that requested fill depth falls within range of surface roughness
|
||||
if surface.filldepth < surface.fractalrange[0] or surface.filldepth > surface.fractalrange[1]:
|
||||
logger.exception(self.__str__() + ' requires a value for the depth of water that lies with the range of the requested surface roughness')
|
||||
logger.exception(self.__str__() + ' requires a value for the depth ' +
|
||||
'of water that lies with the range of the requested ' +
|
||||
'surface roughness')
|
||||
raise ValueError
|
||||
|
||||
# Check to see if water has been already defined as a material
|
||||
@@ -161,7 +168,12 @@ class AddSurfaceWater(UserObjectGeometry):
|
||||
water = next((x for x in grid.materials if x.ID == 'water'))
|
||||
testwater = next((x for x in water.tau if x < grid.dt), None)
|
||||
if testwater:
|
||||
logger.exception(self.__str__() + ' requires the time step for the model to be less than the relaxation time required to model water.')
|
||||
logger.exception(self.__str__() + ' requires the time step for the ' +
|
||||
'model to be less than the relaxation time required ' +
|
||||
'to model water.')
|
||||
raise ValueError
|
||||
|
||||
logger.info(self.grid_name(grid) + f'Water on surface from {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, {yf * grid.dy:g}m, {zf * grid.dz:g}m with depth {filldepth:g}m, added to {surface.operatingonID}.')
|
||||
logger.info(self.grid_name(grid) + f'Water on surface from {xs * grid.dx:g}m, ' +
|
||||
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, to {xf * grid.dx:g}m, ' +
|
||||
f'{yf * grid.dy:g}m, {zf * grid.dz:g}m with depth {filldepth:g}m, ' +
|
||||
f'added to {surface.operatingonID}.')
|
||||
|
@@ -28,18 +28,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Box(UserObjectGeometry):
|
||||
"""Allows you to introduce an orthogonal parallelepiped with specific properties into the model.
|
||||
"""Allows you to introduce an orthogonal parallelepiped with specific
|
||||
properties into the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of a the box.
|
||||
:type p1: list, non-optional
|
||||
:param p2: The lower left (x,y,z) coordinates of the box.
|
||||
:type p2: list, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
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
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -71,8 +69,8 @@ class Box(UserObjectGeometry):
|
||||
if self.dorotate:
|
||||
self.__dorotate()
|
||||
|
||||
# check materials have been specified
|
||||
# isotropic case
|
||||
# Check materials have been specified
|
||||
# Isotropic case
|
||||
try:
|
||||
materialsrequested = [self.kwargs['material_id']]
|
||||
except KeyError:
|
||||
@@ -92,7 +90,7 @@ class Box(UserObjectGeometry):
|
||||
averagebox = grid.averagevolumeobjects
|
||||
|
||||
p3, p4 = uip.check_box_points(p1, p2, self.__str__())
|
||||
# find nearest point on grid without translation
|
||||
# Find nearest point on grid without translation
|
||||
p5 = uip.round_to_grid_static_point(p1)
|
||||
p6 = uip.round_to_grid_static_point(p2)
|
||||
xs, ys, zs = p3
|
||||
@@ -138,4 +136,7 @@ class Box(UserObjectGeometry):
|
||||
|
||||
dielectricsmoothing = 'on' if averaging else 'off'
|
||||
|
||||
logger.info(self.grid_name(grid) + f"Box from {p5[0]:g}m, {p5[1]:g}m, {p5[2]:g}m, to {p6[0]:g}m, {p6[1]:g}m, {p6[2]:g}m of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
logger.info(self.grid_name(grid) + f"Box from {p5[0]:g}m, {p5[1]:g}m, " +
|
||||
f"{p5[2]:g}m, to {p6[0]:g}m, {p6[1]:g}m, {p6[2]:g}m of " +
|
||||
f"material(s) {', '.join(materialsrequested)} created, " +
|
||||
f"dielectric smoothing is {dielectricsmoothing}.")
|
||||
|
@@ -67,13 +67,13 @@ def rotate_point(p, axis, angle, origin=(0, 0, 0)):
|
||||
"""Rotate a point.
|
||||
|
||||
Args:
|
||||
p (array): coordinates of point (x, y, z)
|
||||
axis (str): axis about which to perform rotation (x, y, or z)
|
||||
angle (int): angle of rotation (degrees)
|
||||
origin (tuple): point about which to perform rotation (x, y, z)
|
||||
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).
|
||||
|
||||
Returns:
|
||||
p (array): coordinates of rotated point (x, y, z)
|
||||
p: an 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 (array): coordinates of points of object to be rotated
|
||||
axis (str): axis about which to perform rotation (x, y, or z)
|
||||
angle (int): angle of rotation (degrees)
|
||||
origin (tuple): point about which to perform rotation (x, y, z)
|
||||
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).
|
||||
|
||||
Returns:
|
||||
new_pts (array): coordinates of points of rotated object
|
||||
new_pts: an array of coordinates of points of rotated object.
|
||||
"""
|
||||
|
||||
# Use origin at centre of object if not given
|
||||
@@ -155,16 +155,15 @@ def rotate_polarisation(p, polarisation, axis, angle, G):
|
||||
"""Rotate a geometry object that is defined by a point and polarisation.
|
||||
|
||||
Args:
|
||||
p (array): coordinates of point (x, y, z)
|
||||
polarisation (str): current polarisation (x, y, or z)
|
||||
axis (str): axis about which to perform rotation (x, y, or z)
|
||||
angle (int): angle of rotation (degrees)
|
||||
G (class): Grid class instance - holds essential parameters
|
||||
describing the model.
|
||||
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).
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
|
||||
Returns:
|
||||
pts (array): coordinates of points of rotated object
|
||||
new_polarisation (str): new polarisation (x, y, or z)
|
||||
pts: an array of coordinates of points of rotated object.
|
||||
new_polarisation: a string defining the new polarisation (x, y, or z).
|
||||
"""
|
||||
|
||||
if polarisation.lower() == 'x':
|
||||
|
@@ -30,18 +30,16 @@ logger = logging.getLogger(__name__)
|
||||
class Cylinder(UserObjectGeometry):
|
||||
"""Allows you to introduce a circular cylinder into the model.
|
||||
|
||||
:param p1: The coordinates (x,y,z) of the centre of the first face of the cylinder.
|
||||
:type p1: list, non-optional
|
||||
:param p2: The coordinates (x,y,z) of the centre of the second face of the cylinder.
|
||||
:type p2: list, non-optional
|
||||
:param r: is the radius of the cylinder.
|
||||
:type r: float, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
Attributes:
|
||||
p1: a 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
|
||||
of the cylinder.
|
||||
r: float of the radius of the cylinder.
|
||||
material_id: a 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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -65,8 +63,8 @@ class Cylinder(UserObjectGeometry):
|
||||
# Otherwise go with the grid default
|
||||
averagecylinder = grid.averagevolumeobjects
|
||||
|
||||
# check materials have been specified
|
||||
# isotropic case
|
||||
# Check materials have been specified
|
||||
# Isotropic case
|
||||
try:
|
||||
materialsrequested = [self.kwargs['material_id']]
|
||||
except KeyError:
|
||||
@@ -123,7 +121,12 @@ class Cylinder(UserObjectGeometry):
|
||||
# Append the new material object to the materials list
|
||||
grid.materials.append(m)
|
||||
|
||||
build_cylinder(x1, y1, z1, x2, y2, z2, r, grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_cylinder(x1, y1, z1, x2, y2, z2, 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"Cylinder with face centres {p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, with radius {r:g}m, of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
logger.info(self.grid_name(grid) + f"Cylinder with face centres {p3[0]:g}m, " +
|
||||
f"{p3[1]:g}m, {p3[2]:g}m and {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, " +
|
||||
f"with radius {r:g}m, of material(s) {', '.join(materialsrequested)} " +
|
||||
f"created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
|
@@ -28,30 +28,28 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CylindricalSector(UserObjectGeometry):
|
||||
"""Allows you to introduce a cylindrical sector (shaped like a slice of pie) into the model.
|
||||
"""Allows you to introduce a cylindrical sector (shaped like a slice of pie)
|
||||
into the model.
|
||||
|
||||
:param normal: Direction of the axis of the cylinder from which the sector is defined and can be x, y, or z..
|
||||
:type normal: str, non-optional
|
||||
:param ctr1: First coordinate of the centre of the cylindrical sector.
|
||||
:type ctr1: float, non-optional
|
||||
:param ctr2: Second coordinate of the centre of the cylindrical sector.
|
||||
:type ctr2: Float, non-optional
|
||||
:param extent1: First thickness from the centre of the cylindrical sector.
|
||||
:type extent1: float, non-optional
|
||||
:param extent2: Second thickness from the centre of the cylindrical sector.
|
||||
:type extent2: float, non-optional
|
||||
:param r: is the radius of the cylindrical sector.
|
||||
:type r: float, non-optional
|
||||
:param start: The starting angle (in degrees) for the cylindrical sector.
|
||||
:type start: float, non-optional
|
||||
:param end: The angle (in degrees) swept by the cylindrical sector
|
||||
:type end: float, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
Attributes:
|
||||
normal: a 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
|
||||
sector.
|
||||
ctr2: a float for the second coordinate of the centre of the cylindrical
|
||||
sector.
|
||||
extent1: a float for the first thickness from the centre of the
|
||||
cylindrical sector.
|
||||
extent2: a 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
|
||||
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
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -82,8 +80,8 @@ class CylindricalSector(UserObjectGeometry):
|
||||
# Otherwise go with the grid default
|
||||
averagecylindricalsector = grid.averagevolumeobjects
|
||||
|
||||
# check materials have been specified
|
||||
# isotropic case
|
||||
# Check materials have been specified
|
||||
# Isotropic case
|
||||
try:
|
||||
materialsrequested = [self.kwargs['material_id']]
|
||||
except KeyError:
|
||||
@@ -103,10 +101,12 @@ class CylindricalSector(UserObjectGeometry):
|
||||
if r <= 0:
|
||||
logger.exception(self.__str__() + f' the radius {r:g} should be a positive value.')
|
||||
if sectorstartangle < 0 or sectorangle <= 0:
|
||||
logger.exception(self.__str__() + ' the starting angle and sector angle should be a positive values.')
|
||||
logger.exception(self.__str__() + ' the starting angle and sector ' +
|
||||
'angle should be a positive values.')
|
||||
raise ValueError
|
||||
if sectorstartangle >= 2 * np.pi or sectorangle >= 2 * np.pi:
|
||||
logger.exception(self.__str__() + ' the starting angle and sector angle must be less than 360 degrees.')
|
||||
logger.exception(self.__str__() + ' the starting angle and sector ' +
|
||||
'angle must be less than 360 degrees.')
|
||||
raise ValueError
|
||||
|
||||
# Look up requested materials in existing list of material instances
|
||||
@@ -171,10 +171,23 @@ class CylindricalSector(UserObjectGeometry):
|
||||
elif normal == 'z':
|
||||
ctr1, ctr2, level = uip.round_to_grid((ctr1, ctr2, extent1))
|
||||
|
||||
build_cylindrical_sector(ctr1, ctr2, level, sectorstartangle, sectorangle, r, normal, thickness, grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_cylindrical_sector(ctr1, ctr2, level, sectorstartangle, sectorangle,
|
||||
r, normal, thickness, grid.dx, grid.dy, grid.dz,
|
||||
numID, numIDx, numIDy, numIDz, averaging,
|
||||
grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
if thickness > 0:
|
||||
dielectricsmoothing = 'on' if averaging else 'off'
|
||||
logger.info(self.grid_name(grid) + f"Cylindrical sector with centre {ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle {(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} degrees, thickness {thickness:g}m, of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
logger.info(self.grid_name(grid) + f"Cylindrical sector with centre " +
|
||||
f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle " +
|
||||
f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, " +
|
||||
f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} degrees, " +
|
||||
f"thickness {thickness:g}m, of material(s) {', '.join(materialsrequested)} " +
|
||||
f"created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
else:
|
||||
logger.info(self.grid_name(grid) + f"Cylindrical sector with centre {ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle {(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} degrees, of material(s) {', '.join(materialsrequested)} created.")
|
||||
logger.info(self.grid_name(grid) + f"Cylindrical sector with centre " +
|
||||
f"{ctr1:g}m, {ctr2:g}m, radius {r:g}m, starting angle " +
|
||||
f"{(sectorstartangle / (2 * np.pi)) * 360:.1f} degrees, " +
|
||||
f"sector angle {(sectorangle / (2 * np.pi)) * 360:.1f} " +
|
||||
f"degrees, of material(s) {', '.join(materialsrequested)} " +
|
||||
f"created.")
|
||||
|
@@ -30,12 +30,11 @@ logger = logging.getLogger(__name__)
|
||||
class Edge(UserObjectGeometry):
|
||||
"""Allows you to introduce a wire with specific properties into the model.
|
||||
|
||||
:param p1: Starting point of the edge.
|
||||
:type p1: list, non-optional
|
||||
:param p2: Ending point of the edge.
|
||||
:type p2: list, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
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
|
||||
to material that has already been defined.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -83,7 +82,7 @@ class Edge(UserObjectGeometry):
|
||||
raise ValueError
|
||||
|
||||
# Check for valid orientations
|
||||
# x-orientated wire
|
||||
# x-orientated edge
|
||||
if xs != xf:
|
||||
if ys != yf or zs != zf:
|
||||
logger.exception(self.__str__() + ' the edge is not specified correctly')
|
||||
@@ -92,7 +91,7 @@ class Edge(UserObjectGeometry):
|
||||
for i in range(xs, xf):
|
||||
build_edge_x(i, ys, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
# y-orientated wire
|
||||
# y-orientated edge
|
||||
elif ys != yf:
|
||||
if xs != xf or zs != zf:
|
||||
logger.exception(self.__str__() + ' the edge is not specified correctly')
|
||||
@@ -101,7 +100,7 @@ class Edge(UserObjectGeometry):
|
||||
for j in range(ys, yf):
|
||||
build_edge_y(xs, j, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
# z-orientated wire
|
||||
# z-orientated edge
|
||||
elif zs != zf:
|
||||
if xs != xf or ys != yf:
|
||||
logger.exception(self.__str__() + ' the edge is not specified correctly')
|
||||
@@ -110,4 +109,6 @@ class Edge(UserObjectGeometry):
|
||||
for k in range(zs, zf):
|
||||
build_edge_z(xs, ys, k, material.numID, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
logger.info(self.grid_name(grid) + f'Edge from {p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of material {material_id} created.')
|
||||
logger.info(self.grid_name(grid) + f'Edge from {p3[0]:g}m, {p3[1]:g}m, ' +
|
||||
f'{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of ' +
|
||||
f'material {material_id} created.')
|
||||
|
@@ -27,26 +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.
|
||||
"""Allows you to introduce an orthogonal parallelepiped with fractal
|
||||
distributed properties which are related to a mixing model or
|
||||
normal material into the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of the parallelepiped
|
||||
:type p1: list, non-optional
|
||||
:param p2: The upper right (x,y,z) coordinates of the parallelepiped
|
||||
:type p2: list, non-optional
|
||||
:param frac_dim: The fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three.
|
||||
:type frac_dim: float, non-optional
|
||||
:param weighting: Weightings in the x, y, z direction of the surface.
|
||||
:type weighting: list, non-optional
|
||||
:param n_materials: 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.
|
||||
:type n_materials: list, non-optional
|
||||
:param mixing_model_id: Is an identifier for the associated mixing model or material.
|
||||
:type mixing_model_id: list, non-optional
|
||||
:param id: Identifier for the fractal box itself.
|
||||
:type id: list, non-optional
|
||||
:param seed: Controls the seeding of the random number generator used to create the fractals..
|
||||
:type seed: float, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
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
|
||||
parallelepiped, should take values between zero and three.
|
||||
weighting: a 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
|
||||
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
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -88,15 +89,12 @@ class FractalBox(UserObjectGeometry):
|
||||
if self.dorotate:
|
||||
self.__dorotate()
|
||||
|
||||
# Default is no dielectric smoothing for a fractal box
|
||||
averagefractalbox = False
|
||||
|
||||
# check averaging
|
||||
# Check averaging
|
||||
try:
|
||||
# go with user specified averaging
|
||||
# Go with user specified averaging
|
||||
averagefractalbox = self.kwargs['averaging']
|
||||
except KeyError:
|
||||
# if they havent specfied - go with the grid default
|
||||
# If they havent specfied - default is no dielectric smoothing for a fractal box
|
||||
averagefractalbox = False
|
||||
|
||||
p3 = uip.round_to_grid_static_point(p1)
|
||||
@@ -107,18 +105,23 @@ class FractalBox(UserObjectGeometry):
|
||||
xf, yf, zf = p2
|
||||
|
||||
if frac_dim < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal dimension')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal dimension')
|
||||
raise ValueError
|
||||
if weighting[0] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal weighting in the x direction')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal weighting in the x direction')
|
||||
raise ValueError
|
||||
if weighting[1] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal weighting in the y direction')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal weighting in the y direction')
|
||||
raise ValueError
|
||||
if weighting[2] < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the fractal weighting in the z direction')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'fractal weighting in the z direction')
|
||||
if n_materials < 0:
|
||||
logger.exception(self.__str__() + ' requires a positive value for the number of bins')
|
||||
logger.exception(self.__str__() + ' requires a positive value for the ' +
|
||||
'number of bins')
|
||||
raise ValueError
|
||||
|
||||
# Find materials to use to build fractal volume, either from mixing models or normal materials
|
||||
@@ -128,12 +131,14 @@ class FractalBox(UserObjectGeometry):
|
||||
|
||||
if mixingmodel:
|
||||
if nbins == 1:
|
||||
logger.exception(self.__str__() + ' must be used with more than one material from the mixing model.')
|
||||
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
|
||||
mixingmodel.calculate_debye_properties(nbins, grid)
|
||||
elif not material:
|
||||
logger.exception(self.__str__() + f' mixing model or material with ID {mixing_model_id} does not exist')
|
||||
logger.exception(self.__str__() + f' mixing model or material with ' +
|
||||
'ID {mixing_model_id} does not exist')
|
||||
raise ValueError
|
||||
|
||||
volume = FractalVolume(xs, xf, ys, yf, zs, zf, frac_dim)
|
||||
@@ -149,6 +154,13 @@ class FractalBox(UserObjectGeometry):
|
||||
volume.mixingmodel = mixingmodel
|
||||
|
||||
dielectricsmoothing = 'on' if volume.averaging else 'off'
|
||||
logger.info(self.grid_name(grid) + f'Fractal box {volume.ID} from {p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m with {volume.operatingonID}, fractal dimension {volume.dimension:g}, fractal weightings {volume.weighting[0]:g}, {volume.weighting[1]:g}, {volume.weighting[2]:g}, fractal seeding {volume.seed}, with {volume.nbins} material(s) created, dielectric smoothing is {dielectricsmoothing}.')
|
||||
logger.info(self.grid_name(grid) + f'Fractal box {volume.ID} from ' +
|
||||
f'{p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, ' +
|
||||
f'{p4[1]:g}m, {p4[2]:g}m with {volume.operatingonID}, ' +
|
||||
f'fractal dimension {volume.dimension:g}, fractal weightings ' +
|
||||
f'{volume.weighting[0]:g}, {volume.weighting[1]:g}, ' +
|
||||
f'{volume.weighting[2]:g}, fractal seeding {volume.seed}, ' +
|
||||
f'with {volume.nbins} material(s) created, dielectric smoothing ' +
|
||||
f'is {dielectricsmoothing}.')
|
||||
|
||||
grid.fractalvolumes.append(volume)
|
||||
|
@@ -30,7 +30,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
class FractalBoxBuilder(UserObjectGeometry):
|
||||
"""Internal class for fractal box modifications. This class should be used
|
||||
internally only when surface modification have been made to a fractal box"""
|
||||
internally only when surface modification have been made to a fractal box."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
@@ -303,7 +303,9 @@ class FractalBoxBuilder(UserObjectGeometry):
|
||||
|
||||
else:
|
||||
if volume.nbins == 1:
|
||||
logger.exception(self.__str__() + ' is being used with a single material and no modifications, therefore please use a #box command instead.')
|
||||
logger.exception(self.__str__() + ' is being used with a ' +
|
||||
'single material and no modifications, ' +
|
||||
'therefore please use a #box command instead.')
|
||||
raise ValueError
|
||||
else:
|
||||
volume.generate_fractal_volume()
|
||||
|
@@ -49,7 +49,7 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
logger.exception(self.__str__() + 'requires exactly five parameters')
|
||||
raise
|
||||
|
||||
# discretise the point using uip object. This has different behaviour
|
||||
# Discretise the point using uip object. This has different behaviour
|
||||
# depending on the type of uip object. So we can use it for
|
||||
# the main grid or the subgrid.
|
||||
xs, ys, zs = uip.discretise_point(p1)
|
||||
@@ -70,7 +70,7 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
# characters and comments that must begin with double hashes.
|
||||
materials = [line.rstrip() + '{' + matstr + '}\n' for line in f if(line.startswith('#') and not line.startswith('##') and line.rstrip('\n'))]
|
||||
|
||||
# build scene
|
||||
# Build scene
|
||||
# API for multiple scenes / model runs
|
||||
scene = config.get_model_config().get_scene()
|
||||
material_objs = get_user_objects(materials, check=False)
|
||||
@@ -96,8 +96,12 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
# Open geometry object file and read/check spatial resolution attribute
|
||||
f = h5py.File(geofile, 'r')
|
||||
dx_dy_dz = f.attrs['dx_dy_dz']
|
||||
if round_value(dx_dy_dz[0] / grid.dx) != 1 or round_value(dx_dy_dz[1] / grid.dy) != 1 or round_value(dx_dy_dz[2] / grid.dz) != 1:
|
||||
logger.exception(self.__str__() + ' requires the spatial resolution of the geometry objects file to match the spatial resolution of the model')
|
||||
if round_value((dx_dy_dz[0] / grid.dx) != 1 or
|
||||
round_value(dx_dy_dz[1] / grid.dy) != 1 or
|
||||
round_value(dx_dy_dz[2] / grid.dz) != 1):
|
||||
logger.exception(self.__str__() + ' requires the spatial resolution ' +
|
||||
'of the geometry objects file to match the spatial ' +
|
||||
'resolution of the model')
|
||||
raise ValueError
|
||||
|
||||
data = f['/data'][:]
|
||||
@@ -117,8 +121,16 @@ class GeometryObjectsRead(UserObjectGeometry):
|
||||
grid.rigidE[:, xs:xs + rigidE.shape[1], ys:ys + rigidE.shape[2], zs:zs + rigidE.shape[3]] = rigidE
|
||||
grid.rigidH[:, xs:xs + rigidH.shape[1], ys:ys + rigidH.shape[2], zs:zs + rigidH.shape[3]] = rigidH
|
||||
grid.ID[:, xs:xs + ID.shape[1], ys:ys + ID.shape[2], zs:zs + ID.shape[3]] = ID + numexistmaterials
|
||||
logger.info(self.grid_name(grid) + f'Geometry objects from file {geofile} inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, with corresponding materials file {matfile}.')
|
||||
logger.info(self.grid_name(grid) + f'Geometry objects from file {geofile} ' +
|
||||
f'inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, ' +
|
||||
f'{zs * grid.dz:g}m, with corresponding materials file ' +
|
||||
f'{matfile}.')
|
||||
except KeyError:
|
||||
averaging = False
|
||||
build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging, data, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
logger.info(self.grid_name(grid) + f'Geometry objects from file (voxels only){geofile} inserted at {xs * grid.dx:g}m, {ys * grid.dy:g}m, {zs * grid.dz:g}m, with corresponding materials file {matfile}.')
|
||||
build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging,
|
||||
data, grid.solid, grid.rigidE, grid.rigidH,
|
||||
grid.ID)
|
||||
logger.info(self.grid_name(grid) + f'Geometry objects from file ' +
|
||||
f'(voxels only){geofile} inserted at {xs * grid.dx:g}m, ' +
|
||||
f'{ys * grid.dy:g}m, {zs * grid.dz:g}m, with corresponding ' +
|
||||
f'materials file {matfile}.')
|
||||
|
@@ -30,14 +30,12 @@ logger = logging.getLogger(__name__)
|
||||
class Plate(UserObjectGeometry):
|
||||
"""Allows you to introduce a plate with specific properties into the model.
|
||||
|
||||
:param p1: The lower left (x,y,z) coordinates of the plate.
|
||||
:type p1: list, non-optional
|
||||
:param p2: The upper right (x,y,z) coordinates of the plate.
|
||||
:type p2: list, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
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
|
||||
to material that has already been defined.
|
||||
material_ids: a list of material identifiers in the x, y, z directions.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -128,7 +126,8 @@ class Plate(UserObjectGeometry):
|
||||
|
||||
for j in range(ys, yf):
|
||||
for k in range(zs, zf):
|
||||
build_face_yz(xs, j, k, numIDy, numIDz, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_face_yz(xs, j, k, numIDy, numIDz, grid.rigidE,
|
||||
grid.rigidH, grid.ID)
|
||||
|
||||
# xz-plane plate
|
||||
elif ys == yf:
|
||||
@@ -143,7 +142,8 @@ class Plate(UserObjectGeometry):
|
||||
|
||||
for i in range(xs, xf):
|
||||
for k in range(zs, zf):
|
||||
build_face_xz(i, ys, k, numIDx, numIDz, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_face_xz(i, ys, k, numIDx, numIDz, grid.rigidE,
|
||||
grid.rigidH, grid.ID)
|
||||
|
||||
# xy-plane plate
|
||||
elif zs == zf:
|
||||
@@ -158,6 +158,9 @@ class Plate(UserObjectGeometry):
|
||||
|
||||
for i in range(xs, xf):
|
||||
for j in range(ys, yf):
|
||||
build_face_xy(i, j, zs, numIDx, numIDy, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_face_xy(i, j, zs, numIDx, numIDy, grid.rigidE,
|
||||
grid.rigidH, grid.ID)
|
||||
|
||||
logger.info(self.grid_name(grid) + f"Plate from {p3[0]:g}m, {p3[1]:g}m, {p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of material(s) {', '.join(materialsrequested)} created.")
|
||||
logger.info(self.grid_name(grid) + f"Plate from {p3[0]:g}m, {p3[1]:g}m, " +
|
||||
f"{p3[2]:g}m, to {p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m of " +
|
||||
f"material(s) {', '.join(materialsrequested)} created.")
|
||||
|
@@ -28,18 +28,16 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sphere(UserObjectGeometry):
|
||||
"""Allows you to introduce a spherical object with specific parameters into the model.
|
||||
"""Allows you to introduce a spherical object with specific parameters
|
||||
into the model.
|
||||
|
||||
:param p1: the coordinates (x,y,z) of the centre of the sphere.
|
||||
:type p1: list, non-optional
|
||||
:param r: The coordinates (x,y,z) of the centre of the sphere.
|
||||
:type r: float, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
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
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -62,8 +60,8 @@ class Sphere(UserObjectGeometry):
|
||||
# Otherwise go with the grid default
|
||||
averagesphere = grid.averagevolumeobjects
|
||||
|
||||
# check materials have been specified
|
||||
# isotropic case
|
||||
# Check materials have been specified
|
||||
# Isotropic case
|
||||
try:
|
||||
materialsrequested = [self.kwargs['material_id']]
|
||||
except KeyError:
|
||||
@@ -117,4 +115,7 @@ class Sphere(UserObjectGeometry):
|
||||
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, {p2[1]:g}m, {p2[2]:g}m, radius {r:g}m, of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
logger.info(self.grid_name(grid) + f"Sphere with centre {p2[0]:g}m, " +
|
||||
f"{p2[1]:g}m, {p2[2]:g}m, radius {r:g}m, of material(s) " +
|
||||
f"{', '.join(materialsrequested)} created, dielectric " +
|
||||
f"smoothing is {dielectricsmoothing}.")
|
||||
|
@@ -28,22 +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.
|
||||
"""Allows you to introduce a triangular patch or a triangular prism with
|
||||
specific properties into the model.
|
||||
|
||||
:param p1: the coordinates (x,y,z) of the first apex of the triangle.
|
||||
:type p1: list, non-optional
|
||||
:param p2: the coordinates (x,y,z) of the second apex of the triangle
|
||||
:type p2: list, non-optional
|
||||
:param p3: the coordinates (x,y,z) of the third apex of the triangle.
|
||||
:type p3: list, non-optional
|
||||
:param thickness: The thickness of the triangular prism. If the thickness is zero then a triangular patch is created.
|
||||
:type thickness: float, non-optional
|
||||
:param material_id: Material identifier that must correspond to material that has already been defined.
|
||||
:type material_id: str, non-optional
|
||||
:param material_ids: Material identifiers in the x, y, z directions.
|
||||
:type material_ids: list, non-optional
|
||||
:param averaging: y or n, used to switch on and off dielectric smoothing.
|
||||
:type averaging: str, non-optional
|
||||
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
|
||||
thickness is zero then a triangular patch is created.
|
||||
material_id: a 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.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@@ -87,8 +84,8 @@ class Triangle(UserObjectGeometry):
|
||||
# Otherwise go with the grid default
|
||||
averagetriangularprism = grid.averagevolumeobjects
|
||||
|
||||
# check materials have been specified
|
||||
# isotropic case
|
||||
# Check materials have been specified
|
||||
# Isotropic case
|
||||
try:
|
||||
materialsrequested = [self.kwargs['material_id']]
|
||||
except KeyError:
|
||||
@@ -178,10 +175,19 @@ class Triangle(UserObjectGeometry):
|
||||
numIDy = materials[1].numID
|
||||
numIDz = materials[2].numID
|
||||
|
||||
build_triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3, normal, thickness, grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
build_triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3, normal, thickness,
|
||||
grid.dx, grid.dy, grid.dz, numID, numIDx, numIDy, numIDz,
|
||||
averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID)
|
||||
|
||||
if thickness > 0:
|
||||
dielectricsmoothing = 'on' if averaging else 'off'
|
||||
logger.info(self.grid_name(grid) + f"Triangle with coordinates {p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m {p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m and thickness {thickness:g}m of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
logger.info(self.grid_name(grid) + f"Triangle with coordinates " +
|
||||
f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m " +
|
||||
f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m and thickness " +
|
||||
f"{thickness:g}m of material(s) {', '.join(materialsrequested)} " +
|
||||
f"created, dielectric smoothing is {dielectricsmoothing}.")
|
||||
else:
|
||||
logger.info(self.grid_name(grid) + f"Triangle with coordinates {p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m {p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m of material(s) {', '.join(materialsrequested)} created.")
|
||||
logger.info(self.grid_name(grid) + f"Triangle with coordinates " +
|
||||
f"{p4[0]:g}m {p4[1]:g}m {p4[2]:g}m, {p5[0]:g}m {p5[1]:g}m " +
|
||||
f"{p5[2]:g}m, {p6[0]:g}m {p6[1]:g}m {p6[2]:g}m of material(s) " +
|
||||
f"{', '.join(materialsrequested)} created.")
|
||||
|
在新工单中引用
屏蔽一个用户