diff --git a/gprMax/cmds_geometry/add_grass.py b/gprMax/cmds_geometry/add_grass.py index a1f14c61..1650c2db 100644 --- a/gprMax/cmds_geometry/add_grass.py +++ b/gprMax/cmds_geometry/add_grass.py @@ -22,7 +22,7 @@ import gprMax.config as config import numpy as np from ..fractals import FractalSurface, Grass -from ..materials import DispersiveMaterial +from ..materials import create_grass from ..utilities import round_value from .cmds_geometry import UserObjectGeometry, rotate_2point_object @@ -197,15 +197,7 @@ class AddGrass(UserObjectGeometry): # Check to see if grass has been already defined as a material if not any(x.ID == 'grass' for x in grid.materials): - m = DispersiveMaterial(len(grid.materials), 'grass') - m.averagable = False - m.type = 'builtin, debye' - m.er = DispersiveMaterial.grasseri - m.deltaer.append(DispersiveMaterial.grassdeltaer) - m.tau.append(DispersiveMaterial.grasstau) - grid.materials.append(m) - if config.get_model_config().materials['maxpoles'] == 0: - config.get_model_config().materials['maxpoles'] = 1 + create_grass(grid) # Check if time step for model is suitable for using grass grass = next((x for x in grid.materials if x.ID == 'grass')) @@ -216,4 +208,4 @@ class AddGrass(UserObjectGeometry): volume.fractalsurfaces.append(surface) - logger.info(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 {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}.') diff --git a/gprMax/cmds_geometry/add_surface_roughness.py b/gprMax/cmds_geometry/add_surface_roughness.py index af7cab5c..447550e0 100644 --- a/gprMax/cmds_geometry/add_surface_roughness.py +++ b/gprMax/cmds_geometry/add_surface_roughness.py @@ -180,4 +180,4 @@ class AddSurfaceRoughness(UserObjectGeometry): surface.generate_fractal_surface(grid) volume.fractalsurfaces.append(surface) - logger.info(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, {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}.') diff --git a/gprMax/cmds_geometry/add_surface_water.py b/gprMax/cmds_geometry/add_surface_water.py index 74846432..1563e809 100644 --- a/gprMax/cmds_geometry/add_surface_water.py +++ b/gprMax/cmds_geometry/add_surface_water.py @@ -21,7 +21,7 @@ import logging import gprMax.config as config import numpy as np -from ..materials import DispersiveMaterial +from ..materials import create_water from ..utilities import round_value from .cmds_geometry import UserObjectGeometry, rotate_2point_object @@ -145,15 +145,7 @@ class AddSurfaceWater(UserObjectGeometry): # Check to see if water has been already defined as a material if not any(x.ID == 'water' for x in grid.materials): - m = DispersiveMaterial(len(grid.materials), 'water') - m.averagable = False - m.type = 'builtin, debye' - m.er = DispersiveMaterial.watereri - m.deltaer.append(DispersiveMaterial.waterdeltaer) - m.tau.append(DispersiveMaterial.watertau) - grid.materials.append(m) - if config.get_model_config().materials['maxpoles'] == 0: - config.get_model_config().materials['maxpoles'] = 1 + create_water(grid) # Check if time step for model is suitable for using water water = next((x for x in grid.materials if x.ID == 'water')) @@ -162,4 +154,4 @@ class AddSurfaceWater(UserObjectGeometry): 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(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, {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}.') diff --git a/gprMax/cmds_geometry/box.py b/gprMax/cmds_geometry/box.py index 105e3e2f..431852a9 100644 --- a/gprMax/cmds_geometry/box.py +++ b/gprMax/cmds_geometry/box.py @@ -123,4 +123,4 @@ class Box(UserObjectGeometry): build_box(xs, xf, ys, yf, zs, zf, numID, numIDx, numIDy, numIDz, averaging, grid.solid, grid.rigidE, grid.rigidH, grid.ID) dielectricsmoothing = 'on' if averaging else 'off' - logger.info(f"Box 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 of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.") + logger.info(self.grid_name(grid) + f"Box 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 of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.") diff --git a/gprMax/cmds_geometry/cmds_geometry.py b/gprMax/cmds_geometry/cmds_geometry.py index 93f1b096..1c44b81b 100644 --- a/gprMax/cmds_geometry/cmds_geometry.py +++ b/gprMax/cmds_geometry/cmds_geometry.py @@ -51,6 +51,16 @@ class UserObjectGeometry: """Rotate object - specialised for each object.""" pass + def grid_name(self, grid): + """Return subgrid name for use with logging info. Return an empty + string if the grid is the main grid. + """ + + if config.sim_config.general['subgrid'] and grid.name != 'main_grid': + return f'[{grid.name}] ' + else: + return '' + def rotate_point(p, axis, angle, origin=(0, 0, 0)): """Rotate a point. diff --git a/gprMax/cmds_geometry/cylinder.py b/gprMax/cmds_geometry/cylinder.py index 37dd23d3..bfdf8e31 100644 --- a/gprMax/cmds_geometry/cylinder.py +++ b/gprMax/cmds_geometry/cylinder.py @@ -123,4 +123,4 @@ class Cylinder(UserObjectGeometry): 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(f"Cylinder with face centres {x1:g}m, {y1:g}m, {z1:g}m and {x2:g}m, {y2:g}m, {z2: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 {x1:g}m, {y1:g}m, {z1:g}m and {x2:g}m, {y2:g}m, {z2:g}m, with radius {r:g}m, of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.") diff --git a/gprMax/cmds_geometry/cylindrical_sector.py b/gprMax/cmds_geometry/cylindrical_sector.py index abd185dc..d33eb320 100644 --- a/gprMax/cmds_geometry/cylindrical_sector.py +++ b/gprMax/cmds_geometry/cylindrical_sector.py @@ -178,6 +178,6 @@ class CylindricalSector(UserObjectGeometry): if thickness > 0: dielectricsmoothing = 'on' if averaging else 'off' - logger.info(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 {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}.") else: - logger.info(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 {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.") diff --git a/gprMax/cmds_geometry/edge.py b/gprMax/cmds_geometry/edge.py index 10e893b1..62e18bba 100644 --- a/gprMax/cmds_geometry/edge.py +++ b/gprMax/cmds_geometry/edge.py @@ -96,4 +96,4 @@ 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(f'Edge 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 of material {material_id} created.') + logger.info(self.grid_name(grid) + f'Edge 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 of material {material_id} created.') diff --git a/gprMax/cmds_geometry/fractal_box.py b/gprMax/cmds_geometry/fractal_box.py index 8be92ab9..da065519 100644 --- a/gprMax/cmds_geometry/fractal_box.py +++ b/gprMax/cmds_geometry/fractal_box.py @@ -132,6 +132,6 @@ class FractalBox(UserObjectGeometry): volume.mixingmodel = mixingmodel dielectricsmoothing = 'on' if volume.averaging else 'off' - logger.info(f'Fractal box {volume.ID} 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 {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 {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 {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}.') grid.fractalvolumes.append(volume) diff --git a/gprMax/cmds_geometry/geometry_objects_read.py b/gprMax/cmds_geometry/geometry_objects_read.py index 7abd9f82..11eec30f 100644 --- a/gprMax/cmds_geometry/geometry_objects_read.py +++ b/gprMax/cmds_geometry/geometry_objects_read.py @@ -117,8 +117,8 @@ class GeometryObjectsRead(UserObjectGeometry): G.rigidE[:, xs:xs + rigidE.shape[1], ys:ys + rigidE.shape[2], zs:zs + rigidE.shape[3]] = rigidE G.rigidH[:, xs:xs + rigidH.shape[1], ys:ys + rigidH.shape[2], zs:zs + rigidH.shape[3]] = rigidH G.ID[:, xs:xs + ID.shape[1], ys:ys + ID.shape[2], zs:zs + ID.shape[3]] = ID + numexistmaterials - logger.info(f'Geometry objects from file {geofile} inserted at {xs * G.dx:g}m, {ys * G.dy:g}m, {zs * G.dz:g}m, with corresponding materials file {matfile}.') + logger.info(self.grid_name(grid) + f'Geometry objects from file {geofile} inserted at {xs * G.dx:g}m, {ys * G.dy:g}m, {zs * G.dz:g}m, with corresponding materials file {matfile}.') except KeyError: averaging = False build_voxels_from_array(xs, ys, zs, numexistmaterials, averaging, data, G.solid, G.rigidE, G.rigidH, G.ID) - logger.info(f'Geometry objects from file (voxels only){geofile} inserted at {xs * G.dx:g}m, {ys * G.dy:g}m, {zs * G.dz:g}m, with corresponding materials file {matfile}.') + logger.info(self.grid_name(grid) + f'Geometry objects from file (voxels only){geofile} inserted at {xs * G.dx:g}m, {ys * G.dy:g}m, {zs * G.dz:g}m, with corresponding materials file {matfile}.') diff --git a/gprMax/cmds_geometry/plate.py b/gprMax/cmds_geometry/plate.py index 95eb2c1f..cd1868fa 100644 --- a/gprMax/cmds_geometry/plate.py +++ b/gprMax/cmds_geometry/plate.py @@ -146,4 +146,4 @@ class Plate(UserObjectGeometry): for j in range(ys, yf): build_face_xy(i, j, zs, numIDx, numIDy, grid.rigidE, grid.rigidH, grid.ID) - logger.info(f"Plate 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 of material(s) {', '.join(materialsrequested)} created.") + logger.info(self.grid_name(grid) + f"Plate 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 of material(s) {', '.join(materialsrequested)} created.") diff --git a/gprMax/cmds_geometry/sphere.py b/gprMax/cmds_geometry/sphere.py index 7a126a11..f6ba2142 100644 --- a/gprMax/cmds_geometry/sphere.py +++ b/gprMax/cmds_geometry/sphere.py @@ -116,4 +116,4 @@ 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(f"Sphere with centre {xc * grid.dx:g}m, {yc * grid.dy:g}m, {zc * grid.dz: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 {xc * grid.dx:g}m, {yc * grid.dy:g}m, {zc * grid.dz:g}m, radius {r:g}m, of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.") diff --git a/gprMax/cmds_geometry/triangle.py b/gprMax/cmds_geometry/triangle.py index 61a199f5..085cfd0d 100644 --- a/gprMax/cmds_geometry/triangle.py +++ b/gprMax/cmds_geometry/triangle.py @@ -167,6 +167,6 @@ class Triangle(UserObjectGeometry): if thickness > 0: dielectricsmoothing = 'on' if averaging else 'off' - logger.info(f"Triangle with coordinates {x1:g}m {y1:g}m {z1:g}m, {x2:g}m {y2:g}m {z2:g}m, {x3:g}m {y3:g}m {z3: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 {x1:g}m {y1:g}m {z1:g}m, {x2:g}m {y2:g}m {z2:g}m, {x3:g}m {y3:g}m {z3:g}m and thickness {thickness:g}m of material(s) {', '.join(materialsrequested)} created, dielectric smoothing is {dielectricsmoothing}.") else: - logger.info(f"Triangle with coordinates {x1:g}m {y1:g}m {z1:g}m, {x2:g}m {y2:g}m {z2:g}m, {x3:g}m {y3:g}m {z3:g}m of material(s) {', '.join(materialsrequested)} created.") + logger.info(self.grid_name(grid) + f"Triangle with coordinates {x1:g}m {y1:g}m {z1:g}m, {x2:g}m {y2:g}m {z2:g}m, {x3:g}m {y3:g}m {z3:g}m of material(s) {', '.join(materialsrequested)} created.") diff --git a/gprMax/cmds_multiuse.py b/gprMax/cmds_multiuse.py index 35f57191..c56d26ce 100644 --- a/gprMax/cmds_multiuse.py +++ b/gprMax/cmds_multiuse.py @@ -74,6 +74,16 @@ class UserObjectMulti: """Readable string of parameters given to object.""" return self.hash + ': ' + str(self.kwargs) + def grid_name(self, grid): + """Return subgrid name for use with logging info. Return an empty + string if the grid is the main grid. + """ + + if config.sim_config.general['subgrid'] and grid.name != 'main_grid': + return f'[{grid.name}] ' + else: + return '' + class Waveform(UserObjectMulti): """Allows you to specify waveforms to use with sources in the model. @@ -117,7 +127,7 @@ class Waveform(UserObjectMulti): w.amp = amp w.freq = freq - logger.info(f'Waveform {w.ID} of type {w.type} with maximum amplitude scaling {w.amp:g}, frequency {w.freq:g}Hz created.') + logger.info(self.grid_name(grid) + f'Waveform {w.ID} of type {w.type} with maximum amplitude scaling {w.amp:g}, frequency {w.freq:g}Hz created.') grid.waveforms.append(w) @@ -219,7 +229,7 @@ class VoltageSource(UserObjectMulti): v.calculate_waveform_values(grid) - logger.info(f'Voltage source with polarity {v.polarisation} at {v.xcoord * grid.dx:g}m, {v.ycoord * grid.dy:g}m, {v.zcoord * grid.dz:g}m, resistance {v.resistance:.1f} Ohms,' + startstop + f'using waveform {v.waveformID} created.') + logger.info(self.grid_name(grid) + f'Voltage source with polarity {v.polarisation} at {v.xcoord * grid.dx:g}m, {v.ycoord * grid.dy:g}m, {v.zcoord * grid.dz:g}m, resistance {v.resistance:.1f} Ohms,' + startstop + f'using waveform {v.waveformID} created.') grid.voltagesources.append(v) @@ -327,9 +337,9 @@ class HertzianDipole(UserObjectMulti): h.calculate_waveform_values(grid) if config.get_model_config().mode == '2D': - logger.info(f'Hertzian dipole is a line source in 2D with polarity {h.polarisation} at {h.xcoord * grid.dx:g}m, {h.ycoord * grid.dy:g}m, {h.zcoord * grid.dz:g}m,' + startstop + f'using waveform {h.waveformID} created.') + logger.info(self.grid_name(grid) + f'Hertzian dipole is a line source in 2D with polarity {h.polarisation} at {h.xcoord * grid.dx:g}m, {h.ycoord * grid.dy:g}m, {h.zcoord * grid.dz:g}m,' + startstop + f'using waveform {h.waveformID} created.') else: - logger.info(f'Hertzian dipole with polarity {h.polarisation} at {h.xcoord * grid.dx:g}m, {h.ycoord * grid.dy:g}m, {h.zcoord * grid.dz:g}m,' + startstop + f'using waveform {h.waveformID} created.') + logger.info(self.grid_name(grid) + f'Hertzian dipole with polarity {h.polarisation} at {h.xcoord * grid.dx:g}m, {h.ycoord * grid.dy:g}m, {h.zcoord * grid.dz:g}m,' + startstop + f'using waveform {h.waveformID} created.') grid.hertziandipoles.append(h) @@ -427,7 +437,7 @@ class MagneticDipole(UserObjectMulti): m.calculate_waveform_values(grid) - logger.info(f'Magnetic dipole with polarity {m.polarisation} at {m.xcoord * grid.dx:g}m, {m.ycoord * grid.dy:g}m, {m.zcoord * grid.dz:g}m,' + startstop + f'using waveform {m.waveformID} created.') + logger.info(self.grid_name(grid) + f'Magnetic dipole with polarity {m.polarisation} at {m.xcoord * grid.dx:g}m, {m.ycoord * grid.dy:g}m, {m.zcoord * grid.dz:g}m,' + startstop + f'using waveform {m.waveformID} created.') grid.magneticdipoles.append(m) @@ -536,7 +546,7 @@ class TransmissionLine(UserObjectMulti): t.calculate_waveform_values(grid) t.calculate_incident_V_I(grid) - logger.info(f'Transmission line with polarity {t.polarisation} at {t.xcoord * grid.dx:g}m, {t.ycoord * grid.dy:g}m, {t.zcoord * grid.dz:g}m, resistance {t.resistance:.1f} Ohms,' + startstop + f'using waveform {t.waveformID} created.') + logger.info(self.grid_name(grid) + f'Transmission line with polarity {t.polarisation} at {t.xcoord * grid.dx:g}m, {t.ycoord * grid.dy:g}m, {t.zcoord * grid.dz:g}m, resistance {t.resistance:.1f} Ohms,' + startstop + f'using waveform {t.waveformID} created.') grid.transmissionlines.append(t) @@ -587,6 +597,8 @@ class Rx(UserObjectMulti): raise p = uip.check_src_rx_point(p1, self.params_str()) + print(p1) + print(p) r = self.constructor() r.xcoord, r.ycoord, r.zcoord = p @@ -612,7 +624,7 @@ class Rx(UserObjectMulti): logger.exception(self.params_str() + f' contains an output type that is not allowable. Allowable outputs in current context are {allowableoutputs}') raise ValueError - logger.info(f"Receiver at {r.xcoord * grid.dx:g}m, {r.ycoord * grid.dy:g}m, {r.zcoord * grid.dz:g}m with output component(s) {', '.join(r.outputs)} created.") + logger.info(self.grid_name(grid) + f"Receiver at {r.xcoord * grid.dx:g}m, {r.ycoord * grid.dy:g}m, {r.zcoord * grid.dz:g}m with output component(s) {', '.join(r.outputs)} created.") grid.rxs.append(r) @@ -673,7 +685,7 @@ class RxArray(UserObjectMulti): logger.exception(self.params_str() + ' the step size should not be less than the spatial discretisation') raise ValueError - logger.info(f'Receiver array {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 steps {dx * grid.dx:g}m, {dy * grid.dy:g}m, {dz * grid.dz:g}m') + logger.info(self.grid_name(grid) + f'Receiver array {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 steps {dx * grid.dx:g}m, {dy * grid.dy:g}m, {dz * grid.dz:g}m') for x in range(xs, xf + 1, dx): for y in range(ys, yf + 1, dy): @@ -832,7 +844,7 @@ class Material(UserObjectMulti): if m.se == float('inf'): m.averagable = False - logger.info(f'Material {m.ID} with eps_r={m.er:g}, sigma={m.se:g} S/m; mu_r={m.mr:g}, sigma*={m.sm:g} Ohm/m created.') + logger.info(self.grid_name(grid) + f'Material {m.ID} with eps_r={m.er:g}, sigma={m.se:g} S/m; mu_r={m.mr:g}, sigma*={m.sm:g} Ohm/m created.') # Append the new material object to the materials list grid.materials.append(m) @@ -901,7 +913,7 @@ class AddDebyeDispersion(UserObjectMulti): # Replace original material with newly created DispersiveMaterial grid.materials = [disp_material if mat.numID==material.numID else mat for mat in grid.materials] - logger.info(f"Debye disperion added to {disp_material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in disp_material.deltaer)}, and tau={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs created.") + logger.info(self.grid_name(grid) + f"Debye disperion added to {disp_material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in disp_material.deltaer)}, and tau={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs created.") class AddLorentzDispersion(UserObjectMulti): @@ -970,7 +982,7 @@ class AddLorentzDispersion(UserObjectMulti): # Replace original material with newly created DispersiveMaterial grid.materials = [disp_material if mat.numID==material.numID else mat for mat in grid.materials] - logger.info(f"Lorentz disperion added to {disp_material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in disp_material.deltaer)}, omega={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs, and gamma={', '.join('%4.3e' % alpha for alpha in disp_material.alpha)} created.") + logger.info(self.grid_name(grid) + f"Lorentz disperion added to {disp_material.ID} with delta_eps_r={', '.join('%4.2f' % deltaer for deltaer in disp_material.deltaer)}, omega={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs, and gamma={', '.join('%4.3e' % alpha for alpha in disp_material.alpha)} created.") class AddDrudeDispersion(UserObjectMulti): @@ -1035,7 +1047,7 @@ class AddDrudeDispersion(UserObjectMulti): # Replace original material with newly created DispersiveMaterial grid.materials = [disp_material if mat.numID==material.numID else mat for mat in grid.materials] - logger.info(f"Drude disperion added to {disp_material.ID} with omega={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs, and gamma={', '.join('%4.3e' % alpha for alpha in disp_material.alpha)} secs created.") + logger.info(self.grid_name(grid) + f"Drude disperion added to {disp_material.ID} with omega={', '.join('%4.3e' % tau for tau in disp_material.tau)} secs, and gamma={', '.join('%4.3e' % alpha for alpha in disp_material.alpha)} secs created.") class SoilPeplinski(UserObjectMulti): @@ -1098,7 +1110,7 @@ class SoilPeplinski(UserObjectMulti): # Create a new instance of the Material class material (start index after pec & free_space) s = PeplinskiSoilUser(ID, sand_fraction, clay_fraction, bulk_density, sand_density, (water_fraction_lower, water_fraction_upper)) - logger.info(f'Mixing model (Peplinski) used to create {s.ID} with sand fraction {s.S:g}, clay fraction {s.C:g}, bulk density {s.rb:g}g/cm3, sand particle density {s.rs:g}g/cm3, and water volumetric fraction {s.mu[0]:g} to {s.mu[1]:g} created.') + logger.info(self.grid_name(grid) + f'Mixing model (Peplinski) used to create {s.ID} with sand fraction {s.S:g}, clay fraction {s.C:g}, bulk density {s.rb:g}g/cm3, sand particle density {s.rs:g}g/cm3, and water volumetric fraction {s.mu[0]:g} to {s.mu[1]:g} created.') # Append the new material object to the materials list grid.mixingmodels.append(s) diff --git a/gprMax/model_build_run.py b/gprMax/model_build_run.py index aad12e8c..1587f6ce 100644 --- a/gprMax/model_build_run.py +++ b/gprMax/model_build_run.py @@ -143,7 +143,7 @@ class ModelBuildRun: # Print info on any subgrids for grid in G.subgrids: - logger.info(grid) + grid.print_info() # Combine available grids grids = [G] + G.subgrids diff --git a/gprMax/subgrids/subgrid_hsg.py b/gprMax/subgrids/subgrid_hsg.py index ef2fa84e..82faacaa 100644 --- a/gprMax/subgrids/subgrid_hsg.py +++ b/gprMax/subgrids/subgrid_hsg.py @@ -16,12 +16,16 @@ # You should have received a copy of the GNU General Public License # along with gprMax. If not, see . +import logging + import gprMax.config as config from ..cython.fields_updates_hsg import (cython_update_electric_os, cython_update_is, cython_update_magnetic_os) from .base import SubGridBase +logger = logging.getLogger(__name__) + class SubGridHSG(SubGridBase): @@ -137,28 +141,22 @@ class SubGridHSG(SubGridBase): cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 1, i_l, i_u, j_l, j_u + 1, k_l - 1, k_u, self.nwz, main_grid.IDlookup['Hy'], main_grid.Hy, self.Ex, 3, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads) cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 1, i_l, i_u + 1, j_l, j_u, k_l - 1, k_u, self.nwz, main_grid.IDlookup['Hx'], main_grid.Hx, self.Ey, 3, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads) - def __str__(self): - - s = '\n' - s += f' Name: {self.name}\n' - s += f' Type: {self.gridtype}\n' - s += f' Ratio: 1:{self.ratio}\n' - s += f' Spatial discretisation: {self.dx:g} x {self.dy:g} x {self.dz:g}m\n' - s += f' Time step (at CFL limit): {self.dt:g} secs\n' - # s += f' Extent from {self.i0 * self.dx * self.ratio}m, {self.j0 * self.dy * self.ratio}m, {self.k0 * self.dz * self.ratio}m to {self.i1 * self.dx * self.ratio}m, {self.j1 * self.dy * self.ratio}m, {self.k1 * self.dz * self.ratio}m\n' - s += f' Extent from {self.i0}, {self.j0}, {self.k0} to {self.i1}, {self.j1}, {self.k1} cells (main grid)\n' - s += f' Total cells: {self.nx:d} x {self.ny:d} x {self.nz:d} = {(self.nx * self.ny * self.nz):g} cells\n' - s += f' Working region cells: {self.nwx} x {self.nwy} x {self.nwz}\n' - - for h in self.hertziandipoles: - s += f' Hertzian dipole at {h.xcoord} {h.ycoord} {h.zcoord}\n' - s += ' ' + str([x for x in self.waveforms - if x.ID == h.waveformID][0]) + '\n' - for r in self.rxs: - s += f' Receiver at {r.xcoord} {r.ycoord} {r.zcoord}\n' - - for tl in self.transmissionlines: - s += f' Transmission line: {tl.xcoord} {tl.ycoord} {tl.zcoord}\n' - s += ' ' + str([x for x in self.waveforms - if x.ID == tl.waveformID][0]) + '\n' - return s + def print_info(self): + """Print information about the subgrid.""" + + logger.info('') + logger.info(f'[{self.name}] Type: {self.gridtype}') + logger.info(f'[{self.name}] Ratio: 1:{self.ratio}') + logger.info(f'[{self.name}] Spatial discretisation: {self.dx:g} x {self.dy:g} x {self.dz:g}m') + logger.info(f'[{self.name}] Extent: {self.i0 * self.dx * self.ratio}m, {self.j0 * self.dy * self.ratio}m, {self.k0 * self.dz * self.ratio}m to {self.i1 * self.dx * self.ratio}m, {self.j1 * self.dy * self.ratio}m, {self.k1 * self.dz * self.ratio}m') + logger.debug(f'[{self.name}] Working region: {self.nwx} x {self.nwy} x {self.nwz} cells') + logger.debug(f'[{self.name}] Total region: {self.nx:d} x {self.ny:d} x {self.nz:d} = {(self.nx * self.ny * self.nz):g} cells') + # Total region = working region + 2 * (is_os_sep * pml_separation * pml_thickness) + # is_os_sep - number of main grid cells between the Inner Surface and + # the Outer Surface. Defaults to 3. Multiply by ratio to + # get sub-grid cells. + # pml_separation - number of sub-grid cells between the Outer Surface + # and the PML. Defaults to ratio // 2 + 2. + # pml_thickness - number of PML cells on each of the 6 sides of the + # sub-grid. Defaults to 6. + logger.info(f'[{self.name}] Time step (at CFL limit): {self.dt:g} secs') \ No newline at end of file