你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 15:10:13 +08:00

Introduced object primitives #ellipsoid and #cone. The #ellipsoid works with regular semi-axes along x, y, and z. The #cone works in a similar way to the cylinder and can be truncated with circular faces of different radii. If one radius is zero then it is a normal cone. Introduced two new mixing models for using with a fractal box, #material_range and #material_list The #material_range allows materials to be constructed using ranges of permittivity, conductivity, magnetic permeability and magnetic loss. Ranges can be increasing or decreasing as needed. The #material_list creates a list of predefined materials that can be used with a fractal box. The order of the listed materials reflects the order of the bins they are allocated to in a fractal box. The fractal box and associated mixing models have been updated to use a list of material IDs and do not rely on the assumption that are generated sequentially. This gives greater flexibility and adds little computation burden on the creation of the fractal volume. Bug fixes for mixing anisotropic volumetric materials where "mr" was used instead of "ms". Bug fixes on objects that use integer coordinates for centres but where passed floats instead.
148 行
6.1 KiB
Python
148 行
6.1 KiB
Python
# Copyright (C) 2015-2023: The University of Edinburgh, United Kingdom
|
|
# Authors: Craig Warren, Antonis Giannopoulos, and John Hartley
|
|
#
|
|
# This file is part of gprMax.
|
|
#
|
|
# gprMax is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# gprMax is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
import logging
|
|
|
|
import numpy as np
|
|
|
|
from ..cython.geometry_primitives import build_cone
|
|
from ..materials import Material
|
|
from .cmds_geometry import UserObjectGeometry
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Cone(UserObjectGeometry):
|
|
"""Introduces a circular cone into the model. The difference with the cylinder is that the faces of the cone
|
|
can have different radii and one of them can be zero.
|
|
|
|
Attributes:
|
|
p1: list of the coordinates (x,y,z) of the centre of the first face
|
|
of the cone.
|
|
p2: list of the coordinates (x,y,z) of the centre of the second face
|
|
of the cone.
|
|
r1: float of the radius of the first face of the cone.
|
|
r2: float of the radius of the second face of the cone.
|
|
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.
|
|
averaging: string (y or n) used to switch on and off dielectric smoothing.
|
|
"""
|
|
|
|
def __init__(self, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.hash = '#cylinder'
|
|
|
|
def create(self, grid, uip):
|
|
try:
|
|
p1 = self.kwargs['p1']
|
|
p2 = self.kwargs['p2']
|
|
r1 = self.kwargs['r1']
|
|
r2 = self.kwargs['r2']
|
|
except KeyError:
|
|
logger.exception(self.__str__() + ' please specify 2 points and two radii')
|
|
raise
|
|
|
|
# Check averaging
|
|
try:
|
|
# Try user-specified averaging
|
|
averagecylinder = self.kwargs['averaging']
|
|
except KeyError:
|
|
# Otherwise go with the grid default
|
|
averagecylinder = grid.averagevolumeobjects
|
|
|
|
# Check materials have been specified
|
|
# Isotropic case
|
|
try:
|
|
materialsrequested = [self.kwargs['material_id']]
|
|
except KeyError:
|
|
# Anisotropic case
|
|
try:
|
|
materialsrequested = self.kwargs['material_ids']
|
|
except KeyError:
|
|
logger.exception(self.__str__() + ' no materials have been specified')
|
|
raise
|
|
|
|
p3 = uip.round_to_grid_static_point(p1)
|
|
p4 = uip.round_to_grid_static_point(p2)
|
|
|
|
x1, y1, z1 = uip.round_to_grid(p1)
|
|
x2, y2, z2 = uip.round_to_grid(p2)
|
|
|
|
if r1 < 0:
|
|
logger.exception(self.__str__() + f' the radius of the first face {r1:g} should be a positive value.')
|
|
raise ValueError
|
|
|
|
if r2 < 0:
|
|
logger.exception(self.__str__() + f' the radius of the second face {r2:g} should be a positive value.')
|
|
raise ValueError
|
|
|
|
if r1 == 0 and r2 == 0:
|
|
logger.exception(self.__str__() + f' not both radii can be zero.')
|
|
raise ValueError
|
|
|
|
# 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]
|
|
|
|
if len(materials) != len(materialsrequested):
|
|
notfound = [x for x in materialsrequested if x not in materials]
|
|
logger.exception(self.__str__() + f' material(s) {notfound} do not exist')
|
|
raise ValueError
|
|
|
|
# Isotropic case
|
|
if len(materials) == 1:
|
|
averaging = materials[0].averagable and averagecylinder
|
|
numID = numIDx = numIDy = numIDz = materials[0].numID
|
|
|
|
# Uniaxial anisotropic case
|
|
elif len(materials) == 3:
|
|
averaging = False
|
|
numIDx = materials[0].numID
|
|
numIDy = materials[1].numID
|
|
numIDz = materials[2].numID
|
|
requiredID = materials[0].ID + '+' + materials[1].ID + '+' + materials[2].ID
|
|
averagedmaterial = [x for x in grid.materials if x.ID == requiredID]
|
|
if averagedmaterial:
|
|
numID = averagedmaterial.numID
|
|
else:
|
|
numID = len(grid.materials)
|
|
m = Material(numID, requiredID)
|
|
m.type = 'dielectric-smoothed'
|
|
# Create dielectric-smoothed constituents for material
|
|
m.er = np.mean((materials[0].er, materials[1].er,
|
|
materials[2].er), axis=0)
|
|
m.se = np.mean((materials[0].se, materials[1].se,
|
|
materials[2].se), axis=0)
|
|
m.mr = np.mean((materials[0].mr, materials[1].mr,
|
|
materials[2].mr), axis=0)
|
|
m.sm = np.mean((materials[0].sm, materials[1].sm,
|
|
materials[2].sm), axis=0)
|
|
|
|
# Append the new material object to the materials list
|
|
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)
|
|
|
|
dielectricsmoothing = 'on' if averaging else 'off'
|
|
logger.info(self.grid_name(grid) + f"Cone 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 radii {r1:g}m and {r2:g}, of material(s) {', '.join(materialsrequested)} " +
|
|
f"created, dielectric smoothing is {dielectricsmoothing}.")
|