Updates docstrings and line lengths

这个提交包含在:
Craig Warren
2022-11-03 21:16:39 +00:00
父节点 64250b01f4
当前提交 6b793f0d7d
共有 14 个文件被更改,包括 359 次插入245 次删除

查看文件

@@ -29,20 +29,21 @@ logger = logging.getLogger(__name__)
class AddGrass(UserObjectGeometry): 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` Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of a surface on a
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` FractalBox class.
:type p2: list, non-optional p2: a list of the upper right (x,y,z) coordinates of a surface on a
:param frac_dim: is the fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three. FractalBox class.
:type frac_dim: float, non-optional frac_dim: a float for the fractal dimension which, for an orthogonal
:param limits: Define lower and upper limits for a range over which the height of the blades of grass can vary. parallelepiped, should take values between zero and three.
:type limits: list, non-optional limits: a list to define lower and upper limits for a range over which
:param n_blades: The number of blades of grass that should be applied to the surface area. the height of the blades of grass can vary.
:type n_blades: int, non-optional n_blades: an int for the number of blades of grass that should be
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the grass should be applied to applied to the surface area.
:type fractal_box_id: list, non-optional fractal_box_id: a string identifier for the FractalBox class that the
grass should be applied to.
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -97,10 +98,12 @@ class AddGrass(UserObjectGeometry):
xf, yf, zf = p2 xf, yf, zf = p2
if frac_dim < 0: 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 raise ValueError
if limits[0] < 0 or limits[1] < 0: 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 raise ValueError
# Check for valid orientations # Check for valid orientations
@@ -114,12 +117,15 @@ class AddGrass(UserObjectGeometry):
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx)) fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface # xminus surface
if xs == volume.xs: 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 raise ValueError
# xplus surface # xplus surface
elif xf == volume.xf: elif xf == volume.xf:
if fractalrange[1] > grid.nx: 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 raise ValueError
requestedsurface = 'xplus' requestedsurface = 'xplus'
@@ -133,12 +139,15 @@ class AddGrass(UserObjectGeometry):
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy)) fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface # yminus surface
if ys == volume.ys: 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 raise ValueError
# yplus surface # yplus surface
elif yf == volume.yf: elif yf == volume.yf:
if fractalrange[1] > grid.ny: 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 raise ValueError
requestedsurface = 'yplus' requestedsurface = 'yplus'
@@ -152,12 +161,15 @@ class AddGrass(UserObjectGeometry):
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz)) fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface # zminus surface
if zs == volume.zs: 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 raise ValueError
# zplus surface # zplus surface
elif zf == volume.zf: elif zf == volume.zf:
if fractalrange[1] > grid.nz: 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 raise ValueError
requestedsurface = 'zplus' requestedsurface = 'zplus'
@@ -175,7 +187,8 @@ class AddGrass(UserObjectGeometry):
surface.operatingonID = volume.ID surface.operatingonID = volume.ID
surface.generate_fractal_surface() surface.generate_fractal_surface()
if n_blades > surface.fractalsurface.shape[0] * surface.fractalsurface.shape[1]: 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 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
@@ -213,9 +226,15 @@ class AddGrass(UserObjectGeometry):
grass = next((x for x in grid.materials if x.ID == 'grass')) 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) testgrass = next((x for x in grass.tau if x < grid.dt), None)
if testgrass: 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 raise ValueError
volume.fractalsurfaces.append(surface) 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): 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` Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of a surface on a
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` FractalBox class.
:type p2: list, non-optional p2: a list of the upper right (x,y,z) coordinates of a surface on a
:param frac_dim: is the fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three. FractalBox class.
:type frac_dim: float, non-optional frac_dim: a float for the fractal dimension which, for an orthogonal
:param weighting: Weightings in the first and second direction of the surface. parallelepiped, should take values between zero and three.
:type weighting: list, non-optional weighting: a list with weightings in the first and second direction of
:param limits: Define lower and upper limits for a range over which the roughness can vary. the surface.
:type limits: list, non-optional limits: a list to define lower and upper limits for a range over which
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the roughness should be applied to the surface roughness can vary.
:type fractal_box_id: list, non-optional fractal_box_id: a string identifier for the FractalBox class
:param seed: Is an optional parameter which controls the seeding of the random number generator used to create the fractals. that the surface roughness should be applied to.
:type seed: int, optional seed: (optional) float parameter which controls the seeding of the random
number generator used to create the fractals.
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -65,7 +66,6 @@ class AddSurfaceRoughness(UserObjectGeometry):
self.kwargs['p2'] = tuple(rot_pts[1, :]) self.kwargs['p2'] = tuple(rot_pts[1, :])
def create(self, grid, uip): def create(self, grid, uip):
try: try:
p1 = self.kwargs['p1'] p1 = self.kwargs['p1']
p2 = self.kwargs['p2'] p2 = self.kwargs['p2']
@@ -98,13 +98,16 @@ class AddSurfaceRoughness(UserObjectGeometry):
xf, yf, zf = p2 xf, yf, zf = p2
if frac_dim < 0: 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 raise ValueError
if weighting[0] < 0: 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 raise ValueError
if weighting[1] < 0: 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 raise ValueError
# Check for valid orientations # Check for valid orientations
@@ -113,19 +116,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if xs != volume.xs and xs != volume.xf: 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 raise ValueError
fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx)) fractalrange = (round_value(limits[0] / grid.dx), round_value(limits[1] / grid.dx))
# xminus surface # xminus surface
if xs == volume.xs: if xs == volume.xs:
if fractalrange[0] < 0 or fractalrange[1] > volume.xf: 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 raise ValueError
requestedsurface = 'xminus' requestedsurface = 'xminus'
# xplus surface # xplus surface
elif xf == volume.xf: elif xf == volume.xf:
if fractalrange[0] < volume.xs or fractalrange[1] > grid.nx: 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 raise ValueError
requestedsurface = 'xplus' requestedsurface = 'xplus'
@@ -134,19 +144,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if ys != volume.ys and ys != volume.yf: 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 raise ValueError
fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy)) fractalrange = (round_value(limits[0] / grid.dy), round_value(limits[1] / grid.dy))
# yminus surface # yminus surface
if ys == volume.ys: if ys == volume.ys:
if fractalrange[0] < 0 or fractalrange[1] > volume.yf: 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 raise ValueError
requestedsurface = 'yminus' requestedsurface = 'yminus'
# yplus surface # yplus surface
elif yf == volume.yf: elif yf == volume.yf:
if fractalrange[0] < volume.ys or fractalrange[1] > grid.ny: 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 raise ValueError
requestedsurface = 'yplus' requestedsurface = 'yplus'
@@ -155,19 +172,26 @@ class AddSurfaceRoughness(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if zs != volume.zs and zs != volume.zf: 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 raise ValueError
fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz)) fractalrange = (round_value(limits[0] / grid.dz), round_value(limits[1] / grid.dz))
# zminus surface # zminus surface
if zs == volume.zs: if zs == volume.zs:
if fractalrange[0] < 0 or fractalrange[1] > volume.zf: 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 raise ValueError
requestedsurface = 'zminus' requestedsurface = 'zminus'
# zplus surface # zplus surface
elif zf == volume.zf: elif zf == volume.zf:
if fractalrange[0] < volume.zs or fractalrange[1] > grid.nz: 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 raise ValueError
requestedsurface = 'zplus' requestedsurface = 'zplus'
@@ -194,4 +218,10 @@ class AddSurfaceRoughness(UserObjectGeometry):
surface.generate_fractal_surface() surface.generate_fractal_surface()
volume.fractalsurfaces.append(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): 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` Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of a surface on a
:param p2: The lower left (x,y,z) coordinates of a surface on a :class:`gprMax.cmds_geometry.fractal_box.FractalBox` FractalBox class.
:type p2: list, non-optional p2: a list of the upper right (x,y,z) coordinates of a surface on a
: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. FractalBox class.
:type depth: float, non-optional depth: a float that defines the depth of the water, which should be
:param fractal_box_id: An identifier for the :class:`gprMax.cmds_geometry.fractal_box.FractalBox` that the water should be applied to specified relative to the dimensions of the #fractal_box that
:type fractal_box_id: list, non-optional 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): def __init__(self, **kwargs):
@@ -94,7 +96,8 @@ class AddSurfaceWater(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if xs != volume.xs and xs != volume.xf: 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 raise ValueError
# xminus surface # xminus surface
if xs == volume.xs: if xs == volume.xs:
@@ -110,7 +113,8 @@ class AddSurfaceWater(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if ys != volume.ys and ys != volume.yf: 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 raise ValueError
# yminus surface # yminus surface
if ys == volume.ys: if ys == volume.ys:
@@ -126,7 +130,8 @@ class AddSurfaceWater(UserObjectGeometry):
logger.exception(self.__str__() + ' dimensions are not specified correctly') logger.exception(self.__str__() + ' dimensions are not specified correctly')
raise ValueError raise ValueError
if zs != volume.zs and zs != volume.zf: 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 raise ValueError
# zminus surface # zminus surface
if zs == volume.zs: if zs == volume.zs:
@@ -150,7 +155,9 @@ class AddSurfaceWater(UserObjectGeometry):
# Check that requested fill depth falls within range of surface roughness # Check that requested fill depth falls within range of surface roughness
if surface.filldepth < surface.fractalrange[0] or surface.filldepth > surface.fractalrange[1]: if surface.filldepth < surface.fractalrange[0] or surface.filldepth > surface.fractalrange[1]:
logger.exception(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 raise ValueError
# Check to see if water has been already defined as a material # 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')) 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) testwater = next((x for x in water.tau if x < grid.dt), None)
if testwater: 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 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): 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. Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of the parallelepiped.
:param p2: The lower left (x,y,z) coordinates of the box. p2: a list of the upper right (x,y,z) coordinates of the parallelepiped.
:type p2: list, non-optional material_id: a string for the material identifier that must correspond
:param material_id: Material identifier that must correspond to material that has already been defined. to material that has already been defined.
:type material_id: str, non-optional material_ids: a list of material identifiers in the x, y, z directions.
:param material_ids: Material identifiers in the x, y, z directions. averaging: a string (y or n) used to switch on and off dielectric smoothing.
:type material_ids: list, non-optional
:param averaging: y or n, used to switch on and off dielectric smoothing.
:type averaging: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -71,8 +69,8 @@ class Box(UserObjectGeometry):
if self.dorotate: if self.dorotate:
self.__dorotate() self.__dorotate()
# check materials have been specified # Check materials have been specified
# isotropic case # Isotropic case
try: try:
materialsrequested = [self.kwargs['material_id']] materialsrequested = [self.kwargs['material_id']]
except KeyError: except KeyError:
@@ -92,7 +90,7 @@ class Box(UserObjectGeometry):
averagebox = grid.averagevolumeobjects averagebox = grid.averagevolumeobjects
p3, p4 = uip.check_box_points(p1, p2, self.__str__()) 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) p5 = uip.round_to_grid_static_point(p1)
p6 = uip.round_to_grid_static_point(p2) p6 = uip.round_to_grid_static_point(p2)
xs, ys, zs = p3 xs, ys, zs = p3
@@ -138,4 +136,7 @@ class Box(UserObjectGeometry):
dielectricsmoothing = 'on' if averaging else 'off' 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. """Rotate a point.
Args: Args:
p (array): coordinates of point (x, y, z) p: an array of coordinates of point (x, y, z).
axis (str): axis about which to perform rotation (x, y, or z) axis: a string which defines the axis about which to perform rotation (x, y, or z).
angle (int): angle of rotation (degrees) angle: an int specifying the angle of rotation (degrees).
origin (tuple): point about which to perform rotation (x, y, z) origin: a tuple defining the point about which to perform rotation (x, y, z).
Returns: 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) 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. """Rotate a geometry object that is defined by 2 points.
Args: Args:
pts (array): coordinates of points of object to be rotated pts: an array ofcoordinates of points of object to be rotated.
axis (str): axis about which to perform rotation (x, y, or z) axis: a string which defines the axis about which to perform rotation (x, y, or z).
angle (int): angle of rotation (degrees) angle: an int specifying the angle of rotation (degrees).
origin (tuple): point about which to perform rotation (x, y, z) origin: a tuple defining the point about which to perform rotation (x, y, z).
Returns: 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 # 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. """Rotate a geometry object that is defined by a point and polarisation.
Args: Args:
p (array): coordinates of point (x, y, z) p: an array of coordinates of point (x, y, z).
polarisation (str): current polarisation (x, y, or z) polarisation: a string defining the current polarisation (x, y, or z).
axis (str): axis about which to perform rotation (x, y, or z) axis: a string which defines the axis about which to perform rotation (x, y, or z).
angle (int): angle of rotation (degrees) angle: an int specifying the angle of rotation (degrees).
G (class): Grid class instance - holds essential parameters G: FDTDGrid class describing a grid in a model.
describing the model.
Returns: Returns:
pts (array): coordinates of points of rotated object pts: an array of coordinates of points of rotated object.
new_polarisation (str): new polarisation (x, y, or z) new_polarisation: a string defining the new polarisation (x, y, or z).
""" """
if polarisation.lower() == 'x': if polarisation.lower() == 'x':

查看文件

@@ -30,18 +30,16 @@ logger = logging.getLogger(__name__)
class Cylinder(UserObjectGeometry): class Cylinder(UserObjectGeometry):
"""Allows you to introduce a circular cylinder into the model. """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. Attributes:
:type p1: list, non-optional p1: a list of the coordinates (x,y,z) of the centre of the first face
:param p2: The coordinates (x,y,z) of the centre of the second face of the cylinder. of the cylinder.
:type p2: list, non-optional p2: a list of the coordinates (x,y,z) of the centre of the second face
:param r: is the radius of the cylinder. of the cylinder.
:type r: float, non-optional r: float of the radius of the cylinder.
:param material_id: Material identifier that must correspond to material that has already been defined. material_id: a string for the material identifier that must correspond
:type material_id: str, non-optional to material that has already been defined.
:param material_ids: Material identifiers in the x, y, z directions. material_ids: a list of material identifiers in the x, y, z directions.
:type material_ids: list, non-optional averaging: a string (y or n) used to switch on and off dielectric smoothing.
:param averaging: y or n, used to switch on and off dielectric smoothing.
:type averaging: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -65,8 +63,8 @@ class Cylinder(UserObjectGeometry):
# Otherwise go with the grid default # Otherwise go with the grid default
averagecylinder = grid.averagevolumeobjects averagecylinder = grid.averagevolumeobjects
# check materials have been specified # Check materials have been specified
# isotropic case # Isotropic case
try: try:
materialsrequested = [self.kwargs['material_id']] materialsrequested = [self.kwargs['material_id']]
except KeyError: except KeyError:
@@ -123,7 +121,12 @@ class Cylinder(UserObjectGeometry):
# Append the new material object to the materials list # Append the new material object to the materials list
grid.materials.append(m) 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' 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): 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.. Attributes:
:type normal: str, non-optional normal: a string for the direction of the axis of the cylinder from which
:param ctr1: First coordinate of the centre of the cylindrical sector. the sector is defined and can be x, y, or z.
:type ctr1: float, non-optional ctr1: a float for the first coordinate of the centre of the cylindrical
:param ctr2: Second coordinate of the centre of the cylindrical sector. sector.
:type ctr2: Float, non-optional ctr2: a float for the second coordinate of the centre of the cylindrical
:param extent1: First thickness from the centre of the cylindrical sector. sector.
:type extent1: float, non-optional extent1: a float for the first thickness from the centre of the
:param extent2: Second thickness from the centre of the cylindrical sector. cylindrical sector.
:type extent2: float, non-optional extent2: a float for the second thickness from the centre of the
:param r: is the radius of the cylindrical sector. cylindrical sector.
:type r: float, non-optional r: a float for the radius of the cylindrical sector.
:param start: The starting angle (in degrees) for the cylindrical sector. start: a float for the starting angle (in degrees) for the cylindrical
:type start: float, non-optional sector.
:param end: The angle (in degrees) swept by the cylindrical sector end: a float for the angle (in degrees) swept by the cylindrical sector.
:type end: float, non-optional material_id: a string for the material identifier that must correspond
:param material_id: Material identifier that must correspond to material that has already been defined. to material that has already been defined.
:type material_id: str, non-optional material_ids: a list of material identifiers in the x, y, z directions.
:param material_ids: Material identifiers in the x, y, z directions. averaging: a string (y or n) used to switch on and off dielectric smoothing.
:type material_ids: list, non-optional
:param averaging: y or n, used to switch on and off dielectric smoothing.
:type averaging: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -82,8 +80,8 @@ class CylindricalSector(UserObjectGeometry):
# Otherwise go with the grid default # Otherwise go with the grid default
averagecylindricalsector = grid.averagevolumeobjects averagecylindricalsector = grid.averagevolumeobjects
# check materials have been specified # Check materials have been specified
# isotropic case # Isotropic case
try: try:
materialsrequested = [self.kwargs['material_id']] materialsrequested = [self.kwargs['material_id']]
except KeyError: except KeyError:
@@ -103,10 +101,12 @@ class CylindricalSector(UserObjectGeometry):
if r <= 0: if r <= 0:
logger.exception(self.__str__() + f' the radius {r:g} should be a positive value.') logger.exception(self.__str__() + f' the radius {r:g} should be a positive value.')
if sectorstartangle < 0 or sectorangle <= 0: 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 raise ValueError
if sectorstartangle >= 2 * np.pi or sectorangle >= 2 * np.pi: 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 raise ValueError
# Look up requested materials in existing list of material instances # Look up requested materials in existing list of material instances
@@ -171,10 +171,23 @@ class CylindricalSector(UserObjectGeometry):
elif normal == 'z': elif normal == 'z':
ctr1, ctr2, level = uip.round_to_grid((ctr1, ctr2, extent1)) 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: if thickness > 0:
dielectricsmoothing = 'on' if averaging else 'off' 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: 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): class Edge(UserObjectGeometry):
"""Allows you to introduce a wire with specific properties into the model. """Allows you to introduce a wire with specific properties into the model.
:param p1: Starting point of the edge. Attributes:
:type p1: list, non-optional p1: a list of the coordinates (x,y,z) of the starting point of the edge.
:param p2: Ending point of the edge. p2: a list of the coordinates (x,y,z) of the ending point of the edge.
:type p2: list, non-optional material_id: a string for the material identifier that must correspond
:param material_id: Material identifier that must correspond to material that has already been defined. to material that has already been defined.
:type material_id: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -83,7 +82,7 @@ class Edge(UserObjectGeometry):
raise ValueError raise ValueError
# Check for valid orientations # Check for valid orientations
# x-orientated wire # x-orientated edge
if xs != xf: if xs != xf:
if ys != yf or zs != zf: if ys != yf or zs != zf:
logger.exception(self.__str__() + ' the edge is not specified correctly') logger.exception(self.__str__() + ' the edge is not specified correctly')
@@ -92,7 +91,7 @@ class Edge(UserObjectGeometry):
for i in range(xs, xf): for i in range(xs, xf):
build_edge_x(i, ys, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID) build_edge_x(i, ys, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID)
# y-orientated wire # y-orientated edge
elif ys != yf: elif ys != yf:
if xs != xf or zs != zf: if xs != xf or zs != zf:
logger.exception(self.__str__() + ' the edge is not specified correctly') logger.exception(self.__str__() + ' the edge is not specified correctly')
@@ -101,7 +100,7 @@ class Edge(UserObjectGeometry):
for j in range(ys, yf): for j in range(ys, yf):
build_edge_y(xs, j, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID) build_edge_y(xs, j, zs, material.numID, grid.rigidE, grid.rigidH, grid.ID)
# z-orientated wire # z-orientated edge
elif zs != zf: elif zs != zf:
if xs != xf or ys != yf: if xs != xf or ys != yf:
logger.exception(self.__str__() + ' the edge is not specified correctly') logger.exception(self.__str__() + ' the edge is not specified correctly')
@@ -110,4 +109,6 @@ class Edge(UserObjectGeometry):
for k in range(zs, zf): for k in range(zs, zf):
build_edge_z(xs, ys, k, material.numID, grid.rigidE, grid.rigidH, grid.ID) 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): 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 Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of the parallelepiped.
:param p2: The upper right (x,y,z) coordinates of the parallelepiped p2: a list of the upper right (x,y,z) coordinates of the parallelepiped.
:type p2: list, non-optional frac_dim: a float for the fractal dimension which, for an orthogonal
:param frac_dim: The fractal dimension which, for an orthogonal parallelepiped, should take values between zero and three. parallelepiped, should take values between zero and three.
:type frac_dim: float, non-optional weighting: a list of the weightings in the x, y, z direction of the
:param weighting: Weightings in the x, y, z direction of the surface. parallelepiped.
:type weighting: list, non-optional n_materials: an int of the number of materials to use for the fractal
: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. distribution (defined according to the associated
:type n_materials: list, non-optional mixing model). This should be set to one if using a
:param mixing_model_id: Is an identifier for the associated mixing model or material. normal material instead of a mixing model.
:type mixing_model_id: list, non-optional mixing_model_id: a string identifier for the associated mixing model or
:param id: Identifier for the fractal box itself. material.
:type id: list, non-optional id: a string identifier for the fractal box itself.
:param seed: Controls the seeding of the random number generator used to create the fractals.. seed: seed: (optional) float parameter which controls the seeding of the random
:type seed: float, non-optional number generator used to create the fractals.
:param averaging: y or n, used to switch on and off dielectric smoothing. averaging: a string (y or n) used to switch on and off dielectric smoothing.
:type averaging: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -88,15 +89,12 @@ class FractalBox(UserObjectGeometry):
if self.dorotate: if self.dorotate:
self.__dorotate() self.__dorotate()
# Default is no dielectric smoothing for a fractal box # Check averaging
averagefractalbox = False
# check averaging
try: try:
# go with user specified averaging # Go with user specified averaging
averagefractalbox = self.kwargs['averaging'] averagefractalbox = self.kwargs['averaging']
except KeyError: 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 averagefractalbox = False
p3 = uip.round_to_grid_static_point(p1) p3 = uip.round_to_grid_static_point(p1)
@@ -107,18 +105,23 @@ class FractalBox(UserObjectGeometry):
xf, yf, zf = p2 xf, yf, zf = p2
if frac_dim < 0: 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 raise ValueError
if weighting[0] < 0: 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 raise ValueError
if weighting[1] < 0: 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 raise ValueError
if weighting[2] < 0: 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: 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 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
@@ -128,12 +131,14 @@ class FractalBox(UserObjectGeometry):
if mixingmodel: if mixingmodel:
if nbins == 1: 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 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) mixingmodel.calculate_debye_properties(nbins, grid)
elif not material: 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 raise ValueError
volume = FractalVolume(xs, xf, ys, yf, zs, zf, frac_dim) volume = FractalVolume(xs, xf, ys, yf, zs, zf, frac_dim)
@@ -149,6 +154,13 @@ class FractalBox(UserObjectGeometry):
volume.mixingmodel = mixingmodel volume.mixingmodel = mixingmodel
dielectricsmoothing = 'on' if volume.averaging else 'off' 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) grid.fractalvolumes.append(volume)

查看文件

@@ -30,7 +30,7 @@ logger = logging.getLogger(__name__)
class FractalBoxBuilder(UserObjectGeometry): class FractalBoxBuilder(UserObjectGeometry):
"""Internal class for fractal box modifications. This class should be used """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): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
@@ -303,7 +303,9 @@ class FractalBoxBuilder(UserObjectGeometry):
else: else:
if volume.nbins == 1: 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 raise ValueError
else: else:
volume.generate_fractal_volume() volume.generate_fractal_volume()

查看文件

@@ -49,7 +49,7 @@ class GeometryObjectsRead(UserObjectGeometry):
logger.exception(self.__str__() + 'requires exactly five parameters') logger.exception(self.__str__() + 'requires exactly five parameters')
raise 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 # depending on the type of uip object. So we can use it for
# the main grid or the subgrid. # the main grid or the subgrid.
xs, ys, zs = uip.discretise_point(p1) xs, ys, zs = uip.discretise_point(p1)
@@ -70,7 +70,7 @@ class GeometryObjectsRead(UserObjectGeometry):
# characters and comments that must begin with double hashes. # 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'))] 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 # API for multiple scenes / model runs
scene = config.get_model_config().get_scene() scene = config.get_model_config().get_scene()
material_objs = get_user_objects(materials, check=False) 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 # Open geometry object file and read/check spatial resolution attribute
f = h5py.File(geofile, 'r') f = h5py.File(geofile, 'r')
dx_dy_dz = f.attrs['dx_dy_dz'] 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: if round_value((dx_dy_dz[0] / grid.dx) != 1 or
logger.exception(self.__str__() + ' requires the spatial resolution of the geometry objects file to match the spatial resolution of the model') 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 raise ValueError
data = f['/data'][:] 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.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.rigidH[:, xs:xs + rigidH.shape[1], ys:ys + rigidH.shape[2], zs:zs + rigidH.shape[3]] = rigidH
grid.ID[:, xs:xs + ID.shape[1], ys:ys + ID.shape[2], zs:zs + ID.shape[3]] = ID + numexistmaterials grid.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: except KeyError:
averaging = False averaging = False
build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging, data, grid.solid, grid.rigidE, grid.rigidH, grid.ID) build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging,
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}.') 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): class Plate(UserObjectGeometry):
"""Allows you to introduce a plate with specific properties into the model. """Allows you to introduce a plate with specific properties into the model.
:param p1: The lower left (x,y,z) coordinates of the plate. Attributes:
:type p1: list, non-optional p1: a list of the lower left (x,y,z) coordinates of the plate.
:param p2: The upper right (x,y,z) coordinates of the plate. p2: a list of the upper right (x,y,z) coordinates of the plate.
:type p2: list, non-optional material_id: a string for the material identifier that must correspond
:param material_id: Material identifier that must correspond to material that has already been defined. to material that has already been defined.
:type material_id: str, non-optional material_ids: a list of material identifiers in the x, y, z directions.
:param material_ids: Material identifiers in the x, y, z directions.
:type material_ids: list, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -128,7 +126,8 @@ class Plate(UserObjectGeometry):
for j in range(ys, yf): for j in range(ys, yf):
for k in range(zs, zf): 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 # xz-plane plate
elif ys == yf: elif ys == yf:
@@ -143,7 +142,8 @@ class Plate(UserObjectGeometry):
for i in range(xs, xf): for i in range(xs, xf):
for k in range(zs, zf): 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 # xy-plane plate
elif zs == zf: elif zs == zf:
@@ -158,6 +158,9 @@ class Plate(UserObjectGeometry):
for i in range(xs, xf): for i in range(xs, xf):
for j in range(ys, yf): 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): 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. Attributes:
:type p1: list, non-optional p1: a list of the coordinates (x,y,z) of the centre of the sphere.
:param r: The coordinates (x,y,z) of the centre of the sphere. r: a float of radius of the sphere.
:type r: float, non-optional material_id: a string for the material identifier that must correspond
:param material_id: Material identifier that must correspond to material that has already been defined. to material that has already been defined.
:type material_id: str, non-optional material_ids: a list of material identifiers in the x, y, z directions.
:param material_ids: Material identifiers in the x, y, z directions. averaging: a string (y or n) used to switch on and off dielectric smoothing.
:type material_ids: list, non-optional
:param averaging: y or n, used to switch on and off dielectric smoothing.
:type averaging: str, non-optional
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -62,8 +60,8 @@ class Sphere(UserObjectGeometry):
# Otherwise go with the grid default # Otherwise go with the grid default
averagesphere = grid.averagevolumeobjects averagesphere = grid.averagevolumeobjects
# check materials have been specified # Check materials have been specified
# isotropic case # Isotropic case
try: try:
materialsrequested = [self.kwargs['material_id']] materialsrequested = [self.kwargs['material_id']]
except KeyError: 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) 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' 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): 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. Attributes:
:type p1: list, non-optional p1: a list of the coordinates (x,y,z) of the first apex of the triangle.
:param p2: the coordinates (x,y,z) of the second apex of the triangle p2: a list of the coordinates (x,y,z) of the second apex of the triangle.
:type p2: list, non-optional p3: a list of the coordinates (x,y,z) of the third apex of the triangle.
:param p3: the coordinates (x,y,z) of the third apex of the triangle. thickness: a float for the thickness of the triangular prism. If the
:type p3: list, non-optional thickness is zero then a triangular patch is created.
:param thickness: 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
:type thickness: float, non-optional to material that has already been defined.
:param material_id: 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.
:type material_id: str, non-optional averaging: a string (y or n) used to switch on and off dielectric smoothing.
: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
""" """
def __init__(self, **kwargs): def __init__(self, **kwargs):
@@ -87,8 +84,8 @@ class Triangle(UserObjectGeometry):
# Otherwise go with the grid default # Otherwise go with the grid default
averagetriangularprism = grid.averagevolumeobjects averagetriangularprism = grid.averagevolumeobjects
# check materials have been specified # Check materials have been specified
# isotropic case # Isotropic case
try: try:
materialsrequested = [self.kwargs['material_id']] materialsrequested = [self.kwargs['material_id']]
except KeyError: except KeyError:
@@ -178,10 +175,19 @@ class Triangle(UserObjectGeometry):
numIDy = materials[1].numID numIDy = materials[1].numID
numIDz = materials[2].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: if thickness > 0:
dielectricsmoothing = 'on' if averaging else 'off' 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: 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.")