diff --git a/docs/source/input_api.rst b/docs/source/input_api.rst index 60757538..f450798a 100644 --- a/docs/source/input_api.rst +++ b/docs/source/input_api.rst @@ -135,6 +135,10 @@ Box --- .. autoclass:: gprMax.cmds_geometry.box.Box +Cone +---- +.. autoclass:: gprMax.cmds_geometry.cone.Cone + Cylinder -------- .. autoclass:: gprMax.cmds_geometry.cylinder.Cylinder @@ -147,18 +151,22 @@ Edge ---- .. autoclass:: gprMax.cmds_geometry.edge.Edge +Ellipsoid +--------- +.. autoclass:: gprMax.cmds_geometry.ellipsoid.Ellipsoid + Plate ----- .. autoclass:: gprMax.cmds_geometry.plate.Plate -Triangle --------- -.. autoclass:: gprMax.cmds_geometry.triangle.Triangle - Sphere ------ .. autoclass:: gprMax.cmds_geometry.sphere.Sphere +Triangle +-------- +.. autoclass:: gprMax.cmds_geometry.triangle.Triangle + Fractal Box ----------- .. autoclass:: gprMax.cmds_geometry.fractal_box.FractalBox diff --git a/docs/source/input_hash_cmds.rst b/docs/source/input_hash_cmds.rst index 11b8e7c6..417c639b 100644 --- a/docs/source/input_hash_cmds.rst +++ b/docs/source/input_hash_cmds.rst @@ -407,7 +407,7 @@ Allows you to introduce a wire with specific properties into the model. A wire i #edge: f1 f2 f3 f4 f5 f6 str1 * ``f1 f2 f3`` are the starting (x,y,z) coordinates of the edge, and ``f4 f5 f6`` are the ending (x,y,z) coordinates of the edge. The coordinates should define a single line. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. For example to specify a x-directed wire that is a perfect electric conductor, use: ``#edge: 0.5 0.5 0.5 0.7 0.5 0.5 pec``. Note that the y and z coordinates are identical. @@ -421,7 +421,7 @@ Allows you to introduce a plate with specific properties into the model. A plate #plate: f1 f2 f3 f4 f5 f6 str1 * ``f1 f2 f3`` are the lower left (x,y,z) coordinates of the plate, and ``f4 f5 f6`` are the upper right (x,y,z) coordinates of the plate. The coordinates should define a surface and not a 3D object like the ``#box`` command. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. For example to specify a xy oriented plate that is a perfect electric conductor, use: ``#plate: 0.5 0.5 0.5 0.7 0.8 0.5 pec``. Note that the z coordinates are identical. @@ -436,7 +436,7 @@ Allows you to introduce a triangular patch or a triangular prism with specific p * ``f1 f2 f3`` are the coordinates (x,y,z) of the first apex of the triangle, ``f4 f5 f6`` the coordinates (x,y,z) of the second apex, and ``f7 f8 f9`` the coordinates (x,y,z) of the third apex. * ``f10`` is the thickness of the triangular prism. If the thickness is zero then a triangular patch is created. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. * ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. For use only when creating a triangular prism, not a triangular patch. For example, to specify a xy orientated triangular patch that is a perfect electric conductor, use: ``#triangle: 0.5 0.5 0.5 0.6 0.4 0.5 0.7 0.9 0.5 0.0 pec``. Note that the z coordinates are identical and the thickness is zero. @@ -451,7 +451,7 @@ Allows you to introduce an orthogonal parallelepiped with specific properties in #box: f1 f2 f3 f4 f5 f6 str1 [c1] * ``f1 f2 f3`` are the lower left (x,y,z) coordinates of the parallelepiped, and ``f4 f5 f6`` are the upper right (x,y,z) coordinates of the parallelepiped. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. * ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. #sphere: @@ -465,7 +465,7 @@ Allows you to introduce a spherical object with specific parameters into the mod * ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of the sphere. * ``f4`` is its radius. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. * ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. For example, to specify a sphere with centre at (0.5, 0.5, 0.5), radius 100 mm, and with constitutive parameters of ``my_sand``, use: ``#sphere: 0.5 0.5 0.5 0.1 my_sand``. @@ -485,7 +485,7 @@ Allows you to introduce a circular cylinder into the model. The orientation of t * ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of one face of the cylinder, and ``f4 f5 f6`` are the coordinates (x,y,z) of the centre of the other face. * ``f7`` is the radius of the cylinder. -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. * ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. For example, to specify a cylinder with its axis in the y direction, a length of 0.7 m, a radius of 100 mm, and that is a perfect electric conductor, use: ``#cylinder: 0.5 0.1 0.5 0.5 0.8 0.5 0.1 pec``. @@ -510,7 +510,7 @@ Allows you to introduce a cylindrical sector (shaped like a slice of pie) into t * ``f5`` is the radius of the cylindrical sector. * ``f6`` is the starting angle (in degrees) for the cylindrical sector (with zero degrees defined on the positive first axis of the plane of the cylindrical sector). * ``f7`` is the angle (in degrees) swept by the cylindrical sector (the finishing angle of the sector is always anti-clockwise from the starting angle). -* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials ``pec`` or ``free_space``. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. * ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. For example, to specify a cylindrical sector with its axis in the z direction, radius of 0.25 m, thickness of 2 mm, a starting angle of 330 :math:`^\circ`, a sector angle of 60 :math:`^\circ`, and that is a perfect electric conductor, use: ``#cylindrical_sector: z 0.34 0.24 0.500 0.502 0.25 330 60 pec``. @@ -519,6 +519,46 @@ For example, to specify a cylindrical sector with its axis in the z direction, r * Cylindrical sector objects are permitted to extend outwith the model domain if desired, however, only parts of object inside the domain will be created. +#cone: +------ + +Allows you to introduce a cone into the model. The orientation of the cylinder axis can be arbitrary, i.e. it does not have align with one of the Cartesian axes of the model. The syntax of the command is: + +.. code-block:: none + + #cone: f1 f2 f3 f4 f5 f6 f7 f8 str1 [c1] + +* ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of the first face of the cone, and ``f4 f5 f6`` are the coordinates (x,y,z) of the centre of the other face. +* ``f7`` is the radius of the first face of the cone, and ``f8`` is the radius of the other face of the cone. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. +* ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. + +For example, to specify a cone... + +.. note:: + + * Cone objects are permitted to extend outwith the model domain if desired, however, only parts of object inside the domain will be created. + +#ellipsoid: +----------- + +Allows you to introduce an ellipsoid into the model. The syntax of the command is: + +.. code-block:: none + + #ellipsoid: f1 f2 f3 f4 f5 f6 str1 [c1] + +* ``f1 f2 f3`` are the coordinates (x,y,z) of the centre of the ellipsoid. +* ``f4 f5 f6`` are the coordinates (x,y,z) of the semi-axes of the ellipsoid. +* ``str1`` is a material identifier that must correspond to material that has already been defined in the input file, or is one of the builtin materials. +* ``c1`` is an optional parameter which can be ``y`` or ``n``, used to switch on and off dielectric smoothing. + +For example, to specify a ellipsoid.... + +.. note:: + + * Ellipsoidal objects are permitted to extend outwith the model domain if desired, however, only parts of object inside the domain will be created. + .. _fractals: #fractal_box: diff --git a/gprMax/cmds_geometry/cone.py b/gprMax/cmds_geometry/cone.py index 609505a1..96cbc7ef 100644 --- a/gprMax/cmds_geometry/cone.py +++ b/gprMax/cmds_geometry/cone.py @@ -46,7 +46,7 @@ class Cone(UserObjectGeometry): def __init__(self, **kwargs): super().__init__(**kwargs) - self.hash = '#cylinder' + self.hash = '#cone' def create(self, grid, uip): try: @@ -55,7 +55,7 @@ class Cone(UserObjectGeometry): r1 = self.kwargs['r1'] r2 = self.kwargs['r2'] except KeyError: - logger.exception(f'{self.__str__()} please specify 2 points and two radii') + logger.exception(f'{self.__str__()} please specify two points and two radii') raise # Check averaging @@ -85,15 +85,17 @@ class Cone(UserObjectGeometry): x2, y2, z2 = uip.round_to_grid(p2) if r1 < 0: - logger.exception(f'{self.__str__()} the radius of the first face {r1:g} should be a positive value.') + logger.exception(f'{self.__str__()} the radius of the first face ' + + f'{r1:g} should be a positive value.') raise ValueError if r2 < 0: - logger.exception(f'{self.__str__()} the radius of the second face {r2:g} should be a positive value.') + logger.exception(f'{self.__str__()} the radius of the second face ' + + f'{r2:g} should be a positive value.') raise ValueError if r1 == 0 and r2 == 0: - logger.exception(f'{self.__str__()} not both radii can be zero.') + logger.exception(f'{self.__str__()} both radii cannot be zero.') raise ValueError # Look up requested materials in existing list of material instances @@ -137,8 +139,8 @@ class Cone(UserObjectGeometry): grid.materials.append(m) build_cone(x1, y1, z1, x2, y2, z2, r1, r2, grid.dx, grid.dy, grid.dz, - numID, numIDx, numIDy, numIDz, averaging, grid.solid, - grid.rigidE, grid.rigidH, grid.ID) + numID, numIDx, numIDy, numIDz, averaging, grid.solid, + grid.rigidE, grid.rigidH, grid.ID) dielectricsmoothing = 'on' if averaging else 'off' logger.info(f"{self.grid_name(grid)}Cone with face centres {p3[0]:g}m, " + diff --git a/gprMax/cmds_geometry/ellipsoid.py b/gprMax/cmds_geometry/ellipsoid.py index ba5e7264..24060607 100644 --- a/gprMax/cmds_geometry/ellipsoid.py +++ b/gprMax/cmds_geometry/ellipsoid.py @@ -32,9 +32,9 @@ class Ellipsoid(UserObjectGeometry): Attributes: p1: list of the coordinates (x,y,z) of the centre of the ellipsoid. - xr: float of x semiaxis of the ellipsoid. - xy: float of y semiaxis of the ellipsoid. - xz: float of z semiaxis of the ellipsoid. + xr: float for x-semiaxis of the elliposid. + xy: float for y-semiaxis of the ellipsoid. + xz: float for z-semiaxis of the ellipsoid. material_id: string for the material identifier that must correspond to material that has already been defined. material_ids: list of material identifiers in the x, y, z directions. @@ -53,7 +53,8 @@ class Ellipsoid(UserObjectGeometry): zr = self.kwargs['zr'] except KeyError: - logger.exception(f'{self.__str__()} please specify a point and the three semiaxes.') + logger.exception(f'{self.__str__()} please specify a point and ' + + f'the three semiaxes.') raise # Check averaging @@ -76,9 +77,8 @@ class Ellipsoid(UserObjectGeometry): logger.exception(f'{self.__str__()} no materials have been specified') raise - # Centre of sphere + # Centre of ellipsoid p2 = uip.round_to_grid_static_point(p1) - #xc, yc, zc = uip.round_to_grid(p1) xc, yc, zc = uip.discretise_point(p1) # Look up requested materials in existing list of material instances @@ -122,11 +122,12 @@ class Ellipsoid(UserObjectGeometry): grid.materials.append(m) build_ellipsoid(xc, yc, zc, xr, yr, zr, grid.dx, grid.dy, grid.dz, numID, - numIDx, numIDy, numIDz, averaging, grid.solid, - grid.rigidE, grid.rigidH, grid.ID) + numIDx, numIDy, numIDz, averaging, grid.solid, + grid.rigidE, grid.rigidH, grid.ID) dielectricsmoothing = 'on' if averaging else 'off' logger.info(f"{self.grid_name(grid)}Ellipsoid with centre {p2[0]:g}m, " + - f"{p2[1]:g}m, {p2[2]:g}m, x-semiaxis {xr:g}m, y-semiaxis {yr:g}m and z-semiaxis {zr:g}m of material(s) " + + f"{p2[1]:g}m, {p2[2]:g}m, x-semiaxis {xr:g}m, " + + f"y-semiaxis {yr:g}m and z-semiaxis {zr:g}m of material(s) " + f"{', '.join(materialsrequested)} created, dielectric " + f"smoothing is {dielectricsmoothing}.") diff --git a/gprMax/cmds_geometry/sphere.py b/gprMax/cmds_geometry/sphere.py index 31e7c465..2679aaaa 100644 --- a/gprMax/cmds_geometry/sphere.py +++ b/gprMax/cmds_geometry/sphere.py @@ -70,16 +70,11 @@ class Sphere(UserObjectGeometry): except KeyError: logger.exception(f'{self.__str__()} no materials have been specified') raise - + # Centre of sphere - p2 = uip.round_to_grid_static_point(p1) - #xc, yc, zc = uip.round_to_grid(p1) xc, yc, zc = uip.discretise_point(p1) - - - # Look up requested materials in existing list of material instances materials = [y for x in materialsrequested for y in grid.materials if y.ID == x] diff --git a/gprMax/cython/geometry_primitives.pyx b/gprMax/cython/geometry_primitives.pyx index 7c359bc7..fa37554e 100644 --- a/gprMax/cython/geometry_primitives.pyx +++ b/gprMax/cython/geometry_primitives.pyx @@ -917,7 +917,6 @@ cpdef void build_cylinder( averaging, solid, rigidE, rigidH, ID) - cpdef void build_cone( float x1, float y1, @@ -966,7 +965,7 @@ cpdef void build_cone( Rmax = np.amax([r1, r2]) - # Check if cylinder is aligned with an axis + # Check if cone is aligned with an axis x_align = y_align = z_align = 0 # x-aligned if (round_value(y1 / dy) == round_value(y2 / dy) and @@ -983,7 +982,7 @@ cpdef void build_cone( round_value(y1 / dy) == round_value(y2 / dy)): z_align = 1 - # Calculate a bounding box for the cylinder + # Calculate a bounding box for the cone if x1 < x2: if x_align: xs = round_value(x1 / dx) @@ -1041,7 +1040,7 @@ cpdef void build_cone( if zf > solid.shape[2]: zf = solid.shape[2] - # x-aligned cylinder + # x-aligned cone if x_align: for j in range(ys, yf): for k in range(zs, zf): @@ -1049,7 +1048,7 @@ cpdef void build_cone( if np.sqrt((j * dy + 0.5 * dy - y1)**2 + (k * dz + 0.5 * dz - z1)**2) <= ((i-xs)/(xf-xs))*(r2-r1) + r1: build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID) - # y-aligned cylinder + # y-aligned cone elif y_align: for i in range(xs, xf): for k in range(zs, zf): @@ -1057,7 +1056,7 @@ cpdef void build_cone( if np.sqrt((i * dx + 0.5 * dx - x1)**2 + (k * dz + 0.5 * dz - z1)**2) <= ((j-ys)/(yf-ys))*(r2-r1) + r1: build_voxel(i, j, k, numID, numIDx, numIDy, numIDz, averaging, solid, rigidE, rigidH, ID) - # z-aligned cylinder + # z-aligned cone elif z_align: for i in range(xs, xf): for j in range(ys, yf): @@ -1068,7 +1067,7 @@ cpdef void build_cone( # Not aligned with any axis else: - # Vectors between centres of cylinder faces + # Vectors between centres of cone faces f1f2 = np.array([x2 - x1, y2 - y1, z2 - z1], dtype=np.float32) f2f1 = np.array([x1 - x2, y1 - y2, z1 - z2], dtype=np.float32) @@ -1078,17 +1077,16 @@ cpdef void build_cone( height = f1f2mag - for i in range(xs, xf): for j in range(ys, yf): for k in range(zs, zf): - # Build flag - default false, set to True if point is in cylinder + # Build flag - default false, set to True if point is in cone build = 0 - # Vector from centre of first cylinder face to test point + # Vector from centre of first cone face to test point f1pt = np.array([i * dx + 0.5 * dx - x1, j * dy + 0.5 * dy - y1, k * dz + 0.5 * dz - z1], dtype=np.float32) - # Vector from centre of second cylinder face to test point + # Vector from centre of second cone face to test point f2pt = np.array([i * dx + 0.5 * dx - x2, j * dy + 0.5 * dy - y2, k * dz + 0.5 * dz - z2], dtype=np.float32) @@ -1129,10 +1127,6 @@ cpdef void build_cone( averaging, solid, rigidE, rigidH, ID) - - - - cpdef void build_sphere( int xc, int yc, @@ -1269,7 +1263,6 @@ cpdef void build_ellipsoid( averaging, solid, rigidE, rigidH, ID) - cpdef void build_voxels_from_array( int xs, int ys,