你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 15:10:13 +08:00
Work to select field outputs in snapshots
这个提交包含在:
@@ -1020,20 +1020,21 @@ class Snapshot(UserObjectMulti):
|
||||
fileext = SnapshotUser.fileexts[0]
|
||||
|
||||
try:
|
||||
outputs = self.kwargs['outputs']
|
||||
tmp = self.kwargs['outputs']
|
||||
outputs = dict.fromkeys(SnapshotUser.allowableoutputs, False)
|
||||
# Check and set output names
|
||||
for output in tmp:
|
||||
if output not in SnapshotUser.allowableoutputs.keys():
|
||||
logger.exception(self.params_str() + " contains an "
|
||||
"output type that is not allowable. "
|
||||
"Allowable outputs in current context are "
|
||||
f"{', '.join(SnapshotUser.allowableoutputs.keys())}.")
|
||||
raise ValueError
|
||||
else:
|
||||
outputs[output] = True
|
||||
except KeyError:
|
||||
# If outputs are not specified, use default
|
||||
outputs = SnapshotUser.allowableoutputs
|
||||
|
||||
outputs.sort()
|
||||
# Check and add field output names
|
||||
for output in outputs:
|
||||
if output not in SnapshotUser.allowableoutputs:
|
||||
logger.exception(self.params_str() + ' contains an '
|
||||
'output type that is not allowable. '
|
||||
'Allowable outputs in current context are '
|
||||
f'{SnapshotUser.allowableoutputs}.')
|
||||
raise ValueError
|
||||
outputs = dict.fromkeys(SnapshotUser.allowableoutputs, True)
|
||||
|
||||
if dx < 0 or dy < 0 or dz < 0:
|
||||
logger.exception(self.params_str() + ' the step size should not '
|
||||
@@ -1054,8 +1055,8 @@ class Snapshot(UserObjectMulti):
|
||||
f"{p4[0]:g}m, {p4[1]:g}m, {p4[2]:g}m, discretisation "
|
||||
f"{dx * grid.dx:g}m, {dy * grid.dy:g}m, {dz * grid.dz:g}m, "
|
||||
f"at {s.time * grid.dt:g} secs with field outputs "
|
||||
f"{', '.join(outputs)} and filename {s.filename}{s.fileext} "
|
||||
f"will be created.")
|
||||
f"{', '.join([k for k, v in outputs.items() if v])} and "
|
||||
f"filename {s.filename}{s.fileext} will be created.")
|
||||
|
||||
grid.snapshots.append(s)
|
||||
|
||||
|
@@ -26,18 +26,24 @@ cpdef void calculate_snapshot_fields(
|
||||
int ny,
|
||||
int nz,
|
||||
int nthreads,
|
||||
float_or_double[:, :, ::1] sliceEx,
|
||||
float_or_double[:, :, ::1] sliceEy,
|
||||
float_or_double[:, :, ::1] sliceEz,
|
||||
float_or_double[:, :, ::1] sliceHx,
|
||||
float_or_double[:, :, ::1] sliceHy,
|
||||
float_or_double[:, :, ::1] sliceHz,
|
||||
float_or_double[:, :, ::1] snapEx,
|
||||
float_or_double[:, :, ::1] snapEy,
|
||||
float_or_double[:, :, ::1] snapEz,
|
||||
float_or_double[:, :, ::1] snapHx,
|
||||
float_or_double[:, :, ::1] snapHy,
|
||||
float_or_double[:, :, ::1] snapHz
|
||||
bint Ex,
|
||||
bint Ey,
|
||||
bint Ez,
|
||||
bint Hx,
|
||||
bint Hy,
|
||||
bint Hz,
|
||||
float_or_double[:, :, ::1] Exslice,
|
||||
float_or_double[:, :, ::1] Eyslice,
|
||||
float_or_double[:, :, ::1] Ezslice,
|
||||
float_or_double[:, :, ::1] Hxslice,
|
||||
float_or_double[:, :, ::1] Hyslice,
|
||||
float_or_double[:, :, ::1] Hzslice,
|
||||
float_or_double[:, :, ::1] Exsnap,
|
||||
float_or_double[:, :, ::1] Eysnap,
|
||||
float_or_double[:, :, ::1] Ezsnap,
|
||||
float_or_double[:, :, ::1] Hxsnap,
|
||||
float_or_double[:, :, ::1] Hysnap,
|
||||
float_or_double[:, :, ::1] Hzsnap
|
||||
):
|
||||
"""Calculates electric and magnetic values at points from averaging values
|
||||
in cells.
|
||||
@@ -56,16 +62,31 @@ cpdef void calculate_snapshot_fields(
|
||||
for k in range(nz):
|
||||
# The electric field component value at a point comes from the
|
||||
# average of the 4 electric field component values in that cell.
|
||||
snapEx[i, j, k] = (sliceEx[i, j, k] + sliceEx[i, j + 1, k] +
|
||||
sliceEx[i, j, k + 1] + sliceEx[i, j + 1, k + 1]) / 4
|
||||
snapEy[i, j, k] = (sliceEy[i, j, k] + sliceEy[i + 1, j, k] +
|
||||
sliceEy[i, j, k + 1] + sliceEy[i + 1, j, k + 1]) / 4
|
||||
snapEz[i, j, k] = (sliceEz[i, j, k] + sliceEz[i + 1, j, k] +
|
||||
sliceEz[i, j + 1, k] + sliceEz[i + 1, j + 1, k]) / 4
|
||||
if Ex:
|
||||
Exsnap[i, j, k] = (Exslice[i, j, k] +
|
||||
Exslice[i, j + 1, k] +
|
||||
Exslice[i, j, k + 1] +
|
||||
Exslice[i, j + 1, k + 1]) / 4
|
||||
if Ey:
|
||||
Eysnap[i, j, k] = (Eyslice[i, j, k] +
|
||||
Eyslice[i + 1, j, k] +
|
||||
Eyslice[i, j, k + 1] +
|
||||
Eyslice[i + 1, j, k + 1]) / 4
|
||||
if Ez:
|
||||
Ezsnap[i, j, k] = (Ezslice[i, j, k] +
|
||||
Ezslice[i + 1, j, k] +
|
||||
Ezslice[i, j + 1, k] +
|
||||
Ezslice[i + 1, j + 1, k]) / 4
|
||||
|
||||
# The magnetic field component value at a point comes from
|
||||
# average of 2 magnetic field component values in that cell and
|
||||
# the neighbouring cell.
|
||||
snapHx[i, j, k] = (sliceHx[i, j, k] + sliceHx[i + 1, j, k]) / 2
|
||||
snapHy[i, j, k] = (sliceHy[i, j, k] + sliceHy[i, j + 1, k]) / 2
|
||||
snapHz[i, j, k] = (sliceHz[i, j, k] + sliceHz[i, j, k + 1]) / 2
|
||||
if Hx:
|
||||
Hxsnap[i, j, k] = (Hxslice[i, j, k] +
|
||||
Hxslice[i + 1, j, k]) / 2
|
||||
if Hy:
|
||||
Hysnap[i, j, k] = (Hyslice[i, j, k] +
|
||||
Hyslice[i, j + 1, k]) / 2
|
||||
if Hz:
|
||||
Hzsnap[i, j, k] = (Hzslice[i, j, k] +
|
||||
Hzslice[i, j, k + 1]) / 2
|
||||
|
@@ -77,7 +77,7 @@ def save_geometry_views(gvs):
|
||||
ncols=get_terminal_width() - 1, file=sys.stdout,
|
||||
disable=not config.sim_config.general['progressbars'])
|
||||
gv.write_vtk(vtk_data)
|
||||
pbar.update(vtk_data['nbytes'])
|
||||
pbar.update(gv.nbytes)
|
||||
pbar.close()
|
||||
|
||||
# Write a Paraview data file (.pvd) if there is more than one GeometryView
|
||||
@@ -96,7 +96,7 @@ class GeometryView():
|
||||
xs, xf, ys, yf, zs, zf: ints for extent of geometry view in cells.
|
||||
dx, dy, dz: ints for spatial discretisation of geometry view in cells.
|
||||
filename: string for filename.
|
||||
grid: FDTDgrid class for parameters describing a grid in a model.
|
||||
grid: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
self.xs = xs
|
||||
@@ -113,6 +113,7 @@ class GeometryView():
|
||||
self.dz = dz
|
||||
self.filename = filename
|
||||
self.grid = grid
|
||||
self.nbytes = None
|
||||
|
||||
def set_filename(self):
|
||||
"""Constructs filename from user-supplied name and model run number."""
|
||||
@@ -175,11 +176,10 @@ class GeometryViewLines(GeometryView):
|
||||
dtype = 'int32').nbytes
|
||||
connect_size = len(x) * np.dtype('int32').itemsize
|
||||
cell_type_size = len(x) * np.dtype('uint8').itemsize
|
||||
nbytes = (x.nbytes + y.nbytes + z.nbytes + lines.nbytes + offsets_size
|
||||
self.nbytes = (x.nbytes + y.nbytes + z.nbytes + lines.nbytes + offsets_size
|
||||
+ connect_size + cell_type_size)
|
||||
|
||||
vtk_data = {'x': x, 'y': y, 'z': z, 'data': lines, 'comments': comments,
|
||||
'nbytes': nbytes}
|
||||
vtk_data = {'x': x, 'y': y, 'z': z, 'data': lines, 'comments': comments}
|
||||
|
||||
return vtk_data
|
||||
|
||||
@@ -223,17 +223,19 @@ class GeometryViewVoxels(GeometryView):
|
||||
# This array is contiguous by design
|
||||
solid = self.grid.solid
|
||||
|
||||
# Get information about pml, sources, receivers
|
||||
# Write information about any PMLs, sources, receivers
|
||||
comments = Comments(self.grid, self)
|
||||
info = comments.get_gprmax_info()
|
||||
comments = json.dumps(info)
|
||||
|
||||
vtk_data = {'data': solid, 'comments': comments, 'nbytes': solid.nbytes}
|
||||
self.nbytes = solid.nbytes
|
||||
|
||||
vtk_data = {'data': solid, 'comments': comments}
|
||||
|
||||
return vtk_data
|
||||
|
||||
def write_vtk(self, vtk_data):
|
||||
"""Write geometry information to a VTK file.
|
||||
"""Writes geometry information to a VTK file.
|
||||
|
||||
Args:
|
||||
vtk_data: dict of data and comments for VTK file.
|
||||
@@ -378,23 +380,28 @@ class GeometryObjects:
|
||||
self.filename_materials = self.filename_materials.with_suffix('.txt')
|
||||
|
||||
# Sizes of arrays to write necessary to update progress bar
|
||||
self.solidsize = (self.nx + 1) * (self.ny + 1) * \
|
||||
(self.nz + 1) * np.dtype(np.uint32).itemsize
|
||||
self.rigidsize = 18 * (self.nx + 1) * (self.ny + 1) * \
|
||||
(self.nz + 1) * np.dtype(np.int8).itemsize
|
||||
self.IDsize = 6 * (self.nx + 1) * (self.ny + 1) * \
|
||||
(self.nz + 1) * np.dtype(np.uint32).itemsize
|
||||
self.solidsize = ((self.nx + 1) *
|
||||
(self.ny + 1) *
|
||||
(self.nz + 1) *
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.rigidsize = (18 * (self.nx + 1) *
|
||||
(self.ny + 1) *
|
||||
(self.nz + 1) *
|
||||
np.dtype(np.int8).itemsize)
|
||||
self.IDsize = (6 * (self.nx + 1) *
|
||||
(self.ny + 1) *
|
||||
(self.nz + 1) *
|
||||
np.dtype(np.uint32).itemsize)
|
||||
self.datawritesize = self.solidsize + self.rigidsize + self.IDsize
|
||||
|
||||
def write_hdf5(self, G, pbar):
|
||||
"""Write a geometry objects file in HDF5 format.
|
||||
"""Writes a geometry objects file in HDF5 format.
|
||||
|
||||
Args:
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
pbar: Progress bar class instance.
|
||||
"""
|
||||
|
||||
# Write the geometry objects to a HDF5 file
|
||||
with h5py.File(self.filename_hdf5, 'w') as fdata:
|
||||
fdata.attrs['gprMax'] = __version__
|
||||
fdata.attrs['Title'] = G.title
|
||||
|
@@ -20,7 +20,6 @@ import datetime
|
||||
import itertools
|
||||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import psutil
|
||||
@@ -41,6 +40,7 @@ from .hash_cmds_file import parse_hash_commands
|
||||
from .materials import process_materials
|
||||
from .pml import build_pml, print_pml_info, set_pml_defaults
|
||||
from .scene import Scene
|
||||
from .snapshots import save_snapshots
|
||||
from .utilities.host_info import mem_check_all, set_omp_threads
|
||||
from .utilities.utilities import get_terminal_width, human_size
|
||||
|
||||
@@ -228,36 +228,18 @@ class ModelBuildRun:
|
||||
return scene
|
||||
|
||||
def write_output_data(self):
|
||||
"""Write output data, i.e. field data for receivers and snapshots
|
||||
"""Writes output data, i.e. field data for receivers and snapshots
|
||||
to file(s).
|
||||
"""
|
||||
|
||||
# Write an output file in HDF5 format
|
||||
write_hdf5_outputfile(config.get_model_config().output_file_path_ext, self.G)
|
||||
|
||||
# Write any snapshots to file
|
||||
if self.G.snapshots:
|
||||
# Create directory for snapshots
|
||||
snapshotdir = config.get_model_config().set_snapshots_dir()
|
||||
snapshotdir.mkdir(exist_ok=True)
|
||||
logger.info('')
|
||||
logger.info(f'Snapshot directory: {snapshotdir.resolve()}')
|
||||
|
||||
for i, snap in enumerate(self.G.snapshots):
|
||||
fn = snapshotdir / Path(snap.filename)
|
||||
snap.filename = fn.with_suffix(snap.fileext)
|
||||
pbar = tqdm(total=snap.vtkdatawritesize, leave=True, unit='byte',
|
||||
unit_scale=True, desc=f'Writing snapshot file {i + 1} '
|
||||
f'of {len(self.G.snapshots)}, '
|
||||
f'{snap.filename.name}',
|
||||
ncols=get_terminal_width() - 1, file=sys.stdout,
|
||||
disable=not config.sim_config.general['progressbars'])
|
||||
snap.write_file(pbar, self.G)
|
||||
pbar.close()
|
||||
logger.info('')
|
||||
save_snapshots(self.G)
|
||||
|
||||
|
||||
def print_resource_info(self, tsolve, memsolve):
|
||||
"""Print resource information on runtime and memory usage.
|
||||
"""Prints resource information on runtime and memory usage.
|
||||
|
||||
Args:
|
||||
tsolve: float of time taken to execute solving (seconds).
|
||||
|
@@ -16,22 +16,55 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from struct import pack
|
||||
import logging
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
from evtk.hl import imageToVTK
|
||||
from tqdm import tqdm
|
||||
|
||||
import gprMax.config as config
|
||||
|
||||
from ._version import __version__
|
||||
from .cython.snapshots import calculate_snapshot_fields
|
||||
from .utilities.utilities import round_value
|
||||
from .utilities.utilities import get_terminal_width, round_value
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def save_snapshots(grid):
|
||||
"""Saves snapshots to file(s).
|
||||
|
||||
Args:
|
||||
grid: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
# Create directory for snapshots
|
||||
snapshotdir = config.get_model_config().set_snapshots_dir()
|
||||
snapshotdir.mkdir(exist_ok=True)
|
||||
logger.info('')
|
||||
logger.info(f'Snapshot directory: {snapshotdir.resolve()}')
|
||||
|
||||
for i, snap in enumerate(grid.snapshots):
|
||||
fn = snapshotdir / Path(snap.filename)
|
||||
snap.filename = fn.with_suffix(snap.fileext)
|
||||
pbar = tqdm(total=snap.nbytes, leave=True, unit='byte',
|
||||
unit_scale=True, desc=f'Writing snapshot file {i + 1} '
|
||||
f'of {len(grid.snapshots)}, '
|
||||
f'{snap.filename.name}',
|
||||
ncols=get_terminal_width() - 1, file=sys.stdout,
|
||||
disable=not config.sim_config.general['progressbars'])
|
||||
snap.write_file(pbar, grid)
|
||||
pbar.close()
|
||||
logger.info('')
|
||||
|
||||
class Snapshot:
|
||||
"""Snapshots of the electric and magnetic field values."""
|
||||
|
||||
allowableoutputs = ['Ex', 'Ey', 'Ez', 'Hx', 'Hy', 'Hz']
|
||||
allowableoutputs = {'Ex': None, 'Ey': None, 'Ez': None,
|
||||
'Hx': None, 'Hy': None, 'Hz': None}
|
||||
|
||||
# Snapshots can be output as VTK ImageData (.vti) format or
|
||||
# HDF5 format (.h5) files
|
||||
@@ -64,10 +97,7 @@ class Snapshot:
|
||||
self.fileext = fileext
|
||||
self.filename = filename
|
||||
self.time = time
|
||||
# Select a set of field outputs - electric (Ex, Ey, Ez)
|
||||
# and/or magnetic (Hx, Hy, Hz). Only affects field outputs written to
|
||||
# file, i.e. ALL field outputs are still stored in memory
|
||||
self.fieldoutputs = {'electric': True, 'magnetic': True}
|
||||
self.outputs = outputs
|
||||
self.xs = xs
|
||||
self.ys = ys
|
||||
self.zs = zs
|
||||
@@ -83,13 +113,8 @@ class Snapshot:
|
||||
self.sx = slice(self.xs, self.xf + self.dx, self.dx)
|
||||
self.sy = slice(self.ys, self.yf + self.dy, self.dy)
|
||||
self.sz = slice(self.zs, self.zf + self.dz, self.dz)
|
||||
self.ncells = self.nx * self.ny * self.nz
|
||||
self.datasizefield = (3 * np.dtype(config.sim_config.dtypes['float_or_double']).itemsize
|
||||
* self.ncells)
|
||||
self.vtkdatawritesize = ((self.fieldoutputs['electric'] +
|
||||
self.fieldoutputs['magnetic']) *
|
||||
self.datasizefield + (self.fieldoutputs['electric'] +
|
||||
self.fieldoutputs['magnetic']) * np.dtype(np.uint32).itemsize)
|
||||
self.nbytes = (6 * self.nx * self.ny * self.nz *
|
||||
np.dtype(config.sim_config.dtypes['float_or_double']).itemsize)
|
||||
|
||||
def store(self, G):
|
||||
"""Store (in memory) electric and magnetic field values for snapshot.
|
||||
@@ -107,18 +132,31 @@ class Snapshot:
|
||||
Hzslice = np.ascontiguousarray(G.Hz[self.sx, self.sy, self.sz])
|
||||
|
||||
# Create arrays to hold the field data for snapshot
|
||||
self.Exsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Eysnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Ezsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hxsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hysnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hzsnap = np.zeros((self.nx, self.ny, self.nz), dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Exsnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Eysnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Ezsnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hxsnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hysnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
self.Hzsnap = np.zeros((self.nx, self.ny, self.nz),
|
||||
dtype=config.sim_config.dtypes['float_or_double'])
|
||||
|
||||
# Calculate field values at points (comes from averaging field components in cells)
|
||||
calculate_snapshot_fields(
|
||||
self.nx,
|
||||
self.ny,
|
||||
self.nz,
|
||||
config.get_model_config().ompthreads,
|
||||
self.outputs['Ex'],
|
||||
self.outputs['Ey'],
|
||||
self.outputs['Ez'],
|
||||
self.outputs['Hx'],
|
||||
self.outputs['Hy'],
|
||||
self.outputs['Hz'],
|
||||
Exslice,
|
||||
Eyslice,
|
||||
Ezslice,
|
||||
@@ -130,10 +168,11 @@ class Snapshot:
|
||||
self.Ezsnap,
|
||||
self.Hxsnap,
|
||||
self.Hysnap,
|
||||
self.Hzsnap)
|
||||
self.Hzsnap
|
||||
)
|
||||
|
||||
def write_file(self, pbar, G):
|
||||
"""Write snapshot file either as VTK ImageData (.vti) format
|
||||
"""Writes snapshot file either as VTK ImageData (.vti) format
|
||||
or HDF5 format (.h5) files
|
||||
|
||||
Args:
|
||||
@@ -142,65 +181,50 @@ class Snapshot:
|
||||
"""
|
||||
|
||||
if self.fileext == '.vti':
|
||||
self.write_vtk_imagedata(pbar, G)
|
||||
self.write_vtk(pbar, G)
|
||||
elif self.fileext == '.h5':
|
||||
self.write_hdf5(pbar, G)
|
||||
|
||||
def write_vtk_imagedata(self, pbar, G):
|
||||
"""Write snapshot file in VTK ImageData (.vti) format.
|
||||
|
||||
N.B. No Python 3 support for VTK at time of writing (03/2015)
|
||||
def write_vtk(self, pbar, G):
|
||||
"""Writes snapshot file in VTK ImageData (.vti) format.
|
||||
|
||||
Args:
|
||||
pbar: Progress bar class instance.
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
"""
|
||||
|
||||
celldata = {}
|
||||
|
||||
hfield_offset = (3 * np.dtype(config.sim_config.dtypes['float_or_double']).itemsize
|
||||
* self.ncells + np.dtype(np.uint32).itemsize)
|
||||
for k, v in self.outputs.items():
|
||||
if v:
|
||||
if k == 'Ex':
|
||||
celldata[k] = self.Exsnap
|
||||
if k == 'Ey':
|
||||
celldata[k] = self.Eysnap
|
||||
if k == 'Ez':
|
||||
celldata[k] = self.Ezsnap
|
||||
if k == 'Hx':
|
||||
celldata[k] = self.Hxsnap
|
||||
if k == 'Hy':
|
||||
celldata[k] = self.Hysnap
|
||||
if k == 'Hz':
|
||||
celldata[k] = self.Hzsnap
|
||||
|
||||
f = open(self.filename, 'wb')
|
||||
f.write('<?xml version="1.0"?>\n'.encode('utf-8'))
|
||||
f.write(f'<VTKFile type="ImageData" version="1.0" byte_order="{config.sim_config.vtk_byteorder}">\n'.encode('utf-8'))
|
||||
f.write(f'<ImageData WholeExtent="{self.xs} {round_value(self.xf / self.dx)} {self.ys} {round_value(self.yf / self.dy)} {self.zs} {round_value(self.zf / self.dz)}" Origin="0 0 0" Spacing="{self.dx * G.dx:.3} {self.dy * G.dy:.3} {self.dz * G.dz:.3}">\n'.encode('utf-8'))
|
||||
f.write(f'<Piece Extent="{self.xs} {round_value(self.xf / self.dx)} {self.ys} {round_value(self.yf / self.dy)} {self.zs} {round_value(self.zf / self.dz)}">\n'.encode('utf-8'))
|
||||
imageToVTK(str(self.filename.with_suffix('')),
|
||||
origin=((self.xs * self.dx * G.dx),
|
||||
(self.ys * self.dy * G.dy),
|
||||
(self.zs * self.dz * G.dz)),
|
||||
spacing=((self.dx * G.dx),
|
||||
(self.dy * G.dy),
|
||||
(self.dz * G.dz)),
|
||||
cellData=celldata)
|
||||
|
||||
pbar.update(n=len(celldata) * self.nx * self.ny * self.nz *
|
||||
np.dtype(config.sim_config.dtypes['float_or_double']).itemsize)
|
||||
|
||||
if self.fieldoutputs['electric'] and self.fieldoutputs['magnetic']:
|
||||
f.write('<CellData Vectors="E-field H-field">\n'.encode('utf-8'))
|
||||
f.write(f"""<DataArray type="{config.sim_config.dtypes['vtk_float']}" Name="E-field" NumberOfComponents="3" format="appended" offset="0" />\n""".encode('utf-8'))
|
||||
f.write(f"""<DataArray type="{config.sim_config.dtypes['vtk_float']}" Name="H-field" NumberOfComponents="3" format="appended" offset="{hfield_offset}" />\n""".encode('utf-8'))
|
||||
elif self.fieldoutputs['electric']:
|
||||
f.write('<CellData Vectors="E-field">\n'.encode('utf-8'))
|
||||
f.write(f"""<DataArray type="{config.sim_config.dtypes['vtk_float']}" Name="E-field" NumberOfComponents="3" format="appended" offset="0" />\n""".encode('utf-8'))
|
||||
elif self.fieldoutputs['magnetic']:
|
||||
f.write('<CellData Vectors="H-field">\n'.encode('utf-8'))
|
||||
f.write(f"""<DataArray type="{config.sim_config.dtypes['vtk_float']}" Name="H-field" NumberOfComponents="3" format="appended" offset="0" />\n""".encode('utf-8'))
|
||||
|
||||
f.write('</CellData>\n</Piece>\n</ImageData>\n<AppendedData encoding="raw">\n_'.encode('utf-8'))
|
||||
|
||||
if self.fieldoutputs['electric']:
|
||||
# Write number of bytes of appended data as UInt32
|
||||
f.write(pack('I', self.datasizefield))
|
||||
pbar.update(n=4)
|
||||
# Convert to format for Paraview
|
||||
electric = np.stack((self.Exsnap, self.Eysnap, self.Ezsnap)).reshape(-1, order='F')
|
||||
electric.tofile(f)
|
||||
pbar.update(n=self.datasizefield)
|
||||
|
||||
if self.fieldoutputs['magnetic']:
|
||||
# Write number of bytes of appended data as UInt32
|
||||
f.write(pack('I', self.datasizefield))
|
||||
pbar.update(n=4)
|
||||
magnetic = np.stack((self.Hxsnap, self.Hysnap, self.Hzsnap)).reshape(-1, order='F')
|
||||
magnetic.tofile(f)
|
||||
pbar.update(n=self.datasizefield)
|
||||
|
||||
f.write('\n</AppendedData>\n</VTKFile>'.encode('utf-8'))
|
||||
f.close()
|
||||
|
||||
def write_hdf5(self, pbar, G):
|
||||
"""Write snapshot file in HDF5 (.h5) format.
|
||||
"""Writes snapshot file in HDF5 (.h5) format.
|
||||
|
||||
Args:
|
||||
pbar: Progress bar class instance.
|
||||
@@ -214,23 +238,30 @@ class Snapshot:
|
||||
f.attrs['dx_dy_dz'] = (self.dx * G.dx, self.dy * G.dy, self.dz * G.dz)
|
||||
f.attrs['time'] = self.time * G.dt
|
||||
|
||||
if self.fieldoutputs['electric']:
|
||||
if self.outputs['Ex']:
|
||||
f['Ex'] = self.Exsnap
|
||||
pbar.update(n=self.Exsnap.nbytes)
|
||||
if self.outputs['Ey']:
|
||||
f['Ey'] = self.Eysnap
|
||||
pbar.update(n=self.Eysnap.nbytes)
|
||||
if self.outputs['Ez']:
|
||||
f['Ez'] = self.Ezsnap
|
||||
pbar.update(n=self.datasizefield)
|
||||
|
||||
if self.fieldoutputs['magnetic']:
|
||||
pbar.update(n=self.Ezsnap.nbytes)
|
||||
if self.outputs['Hx']:
|
||||
f['Hx'] = self.Hxsnap
|
||||
pbar.update(n=self.Hxsnap.nbytes)
|
||||
if self.outputs['Hy']:
|
||||
f['Hy'] = self.Hysnap
|
||||
pbar.update(n=self.Hysnap.nbytes)
|
||||
if self.outputs['Hz']:
|
||||
f['Hz'] = self.Hzsnap
|
||||
pbar.update(n=self.datasizefield)
|
||||
pbar.update(n=self.Hzsnap.nbytes)
|
||||
|
||||
f.close()
|
||||
|
||||
|
||||
def htod_snapshot_array(G, queue=None):
|
||||
"""Initialise array on compute device for to store field data for snapshots.
|
||||
"""Initialises arrays on compute device to store field data for snapshots.
|
||||
|
||||
Args:
|
||||
G: FDTDGrid class describing a grid in a model.
|
||||
@@ -300,7 +331,7 @@ def htod_snapshot_array(G, queue=None):
|
||||
|
||||
|
||||
def dtoh_snapshot_array(snapEx_dev, snapEy_dev, snapEz_dev, snapHx_dev, snapHy_dev, snapHz_dev, i, snap):
|
||||
"""Copy snapshot array used on compute device back to snapshot objects and
|
||||
"""Copies snapshot array used on compute device back to snapshot objects and
|
||||
store in format for Paraview.
|
||||
|
||||
Args:
|
||||
|
@@ -179,21 +179,14 @@ class CPUUpdates:
|
||||
"""Set properties for disperive materials.
|
||||
|
||||
Returns:
|
||||
props (Props): Dispersive material properties.
|
||||
props: dict of dispersive material properties.
|
||||
"""
|
||||
|
||||
poles = 'multi' if config.get_model_config().materials['maxpoles'] > 1 else '1'
|
||||
|
||||
type = 'float' if config.sim_config.general['precision'] == 'single' else 'double'
|
||||
|
||||
precision = 'float' if config.sim_config.general['precision'] == 'single' else 'double'
|
||||
dispersion = 'complex' if config.get_model_config().materials['dispersivedtype'] == config.sim_config.dtypes['complex'] else 'real'
|
||||
|
||||
class Props():
|
||||
pass
|
||||
|
||||
props = Props()
|
||||
props.poles = poles
|
||||
props.precision = type
|
||||
props.dispersion_type = dispersion
|
||||
props = {'poles': poles, 'precision': precision, 'dispersion_type': dispersion}
|
||||
|
||||
return props
|
||||
|
||||
@@ -201,11 +194,11 @@ class CPUUpdates:
|
||||
"""Set dispersive update functions.
|
||||
|
||||
Args:
|
||||
props: dispersive material properties.
|
||||
props: dict of dispersive material properties.
|
||||
"""
|
||||
update_f = 'update_electric_dispersive_{}pole_{}_{}_{}'
|
||||
disp_a = update_f.format(props.poles, 'A', props.precision, props.dispersion_type)
|
||||
disp_b = update_f.format(props.poles, 'B', props.precision, props.dispersion_type)
|
||||
disp_a = update_f.format(props['poles'], 'A', props['precision'], props['dispersion_type'])
|
||||
disp_b = update_f.format(props['poles'], 'B', props['precision'], props['dispersion_type'])
|
||||
|
||||
disp_a_f = getattr(import_module('gprMax.cython.fields_updates_dispersive'), disp_a)
|
||||
disp_b_f = getattr(import_module('gprMax.cython.fields_updates_dispersive'), disp_b)
|
||||
|
@@ -334,11 +334,9 @@ def mem_check_all(grids):
|
||||
# Additional memory required if there are any snapshots
|
||||
if grid.snapshots:
|
||||
for snap in grid.snapshots:
|
||||
# 2 x required to account for electric and magnetic fields
|
||||
snap_mem = int(2 * snap.datasizefield)
|
||||
config.get_model_config().mem_use += snap_mem
|
||||
total_snaps_mem += snap_mem
|
||||
grid.mem_use += snap_mem
|
||||
config.get_model_config().mem_use += snap.nbytes
|
||||
total_snaps_mem += snap.nbytes
|
||||
grid.mem_use += snap.nbytes
|
||||
|
||||
mem_strs.append(f'~{human_size(grid.mem_use)} [{grid.name}]')
|
||||
|
||||
|
在新工单中引用
屏蔽一个用户