Work on memory estimate, dispersive materials & GPU, and sub-gridding.

这个提交包含在:
Craig Warren
2019-12-09 17:09:52 +00:00
父节点 2c5afad69b
当前提交 342613a781
共有 13 个文件被更改,包括 140 次插入117 次删除

查看文件

@@ -93,7 +93,7 @@ class GeometryObjectsRead(UserObjectGeometry):
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] / G.dx) != 1 or round_value(dx_dy_dz[1] / G.dy) != 1 or round_value(dx_dy_dz[2] / G.dz) != 1: if round_value(dx_dy_dz[0] / G.dx) != 1 or round_value(dx_dy_dz[1] / G.dy) != 1 or round_value(dx_dy_dz[2] / G.dz) != 1:
raise CmdInputError("'" + ' '.join(tmp) + "'" + ' requires the spatial resolution of the geometry objects file to match the spatial resolution of the model') raise CmdInputError(self.__str__() + ' requires the spatial resolution of the geometry objects file to match the spatial resolution of the model')
data = f['/data'][:] data = f['/data'][:]

查看文件

@@ -40,7 +40,7 @@ log = logging.getLogger(__name__)
# Single instance of SimConfig to hold simulation configuration parameters. # Single instance of SimConfig to hold simulation configuration parameters.
sim_config = None sim_config = None
# Instance of ModelConfig that hold model configuration parameters. # Instances of ModelConfig that hold model configuration parameters.
model_configs = [] model_configs = []
# Each model in a simulation is given a unique number when the instance of # Each model in a simulation is given a unique number when the instance of
@@ -74,24 +74,21 @@ class ModelConfig:
'snapsgpu2cpu': False} 'snapsgpu2cpu': False}
# Total memory usage for all grids in the model. Starts with 50MB overhead. # Total memory usage for all grids in the model. Starts with 50MB overhead.
self.mem_use = 50e6 self.mem_overhead = 50e6
self.mem_use = self.mem_overhead
self.reuse_geometry = False self.reuse_geometry = False
# String to print at start of each model run # String to print at start of each model run
inputfilestr = f'\n--- Model {model_num + 1}/{sim_config.model_end}, input file: {sim_config.input_file_path}' s = f'\n--- Model {model_num + 1}/{sim_config.model_end}, input file: {sim_config.input_file_path}'
self.set_inputfilestr(inputfilestr) self.inputfilestr = Fore.GREEN + f"{s} {'-' * (get_terminal_width() - 1 - len(s))}\n" + Style.RESET_ALL
if not sim_config.single_model: # Output file path and name for specific model
self.appendmodelnumber = str(model_num + 1) # Indexed from 1 self.appendmodelnumber = '' if sim_config.single_model else str(model_num + 1) # Indexed from 1
else:
self.appendmodelnumber = ''
# Output file path for specific model
self.set_output_file_path() self.set_output_file_path()
# Specify a snapshot directory # Specify a snapshot directory
self.set_snapshots_file_path() self.set_snapshots_dir()
# Numerical dispersion analysis parameters # Numerical dispersion analysis parameters
# highestfreqthres: threshold (dB) down from maximum power (0dB) of main frequency used # highestfreqthres: threshold (dB) down from maximum power (0dB) of main frequency used
@@ -124,13 +121,18 @@ class ModelConfig:
'current_model_run': model_num + 1, 'current_model_run': model_num + 1,
'inputfile': sim_config.input_file_path.resolve()} 'inputfile': sim_config.input_file_path.resolve()}
def set_inputfilestr(self, inputfilestr): def set_dispersive_material_types(self):
"""Set string describing model. """Set data type for disperive materials. Complex if Drude or Lorentz
materials are present. Real if Debye materials.
Args:
inputfilestr (str): Description of model.
""" """
self.inputfilestr = Fore.GREEN + f"{inputfilestr} {'-' * (get_terminal_width() - 1 - len(inputfilestr))}\n" + Style.RESET_ALL if self.materials['drudelorentz']:
self.materials['cuda_real_func'] = '.real()'
self.materials['dispersivedtype'] = sim_config.dtypes['complex']
self.materials['dispersiveCdtype'] = sim_config.dtypes['C_complex']
else:
self.materials['cuda_real_func'] = ''
self.materials['dispersivedtype'] = sim_config.dtypes['float_or_double']
self.materials['dispersiveCdtype'] = sim_config.dtypes['C_float_or_double']
def set_output_file_path(self, outputdir=None): def set_output_file_path(self, outputdir=None):
"""Output file path can be provided by the user via the API or an input file """Output file path can be provided by the user via the API or an input file
@@ -156,10 +158,11 @@ class ModelConfig:
self.output_file_path = Path(*parts[:-1], parts[-1] + self.appendmodelnumber) self.output_file_path = Path(*parts[:-1], parts[-1] + self.appendmodelnumber)
self.output_file_path_ext = self.output_file_path.with_suffix('.out') self.output_file_path_ext = self.output_file_path.with_suffix('.out')
def set_snapshots_file_path(self): def set_snapshots_dir(self):
"""Set directory to store any snapshots.""" """Set directory to store any snapshots."""
parts = self.output_file_path.with_suffix('').parts parts = self.output_file_path.with_suffix('').parts
self.snapshot_file_path = Path(*parts[:-1], parts[-1] + '_snaps') self.snapshot_dir = Path(*parts[:-1], parts[-1] + '_snaps')
class SimulationConfig: class SimulationConfig:
"""Configuration parameters for a standard simulation. """Configuration parameters for a standard simulation.
@@ -188,7 +191,7 @@ class SimulationConfig:
'cuda': False, 'cuda': False,
'opencl': False, 'opencl': False,
'subgrid': False, 'subgrid': False,
'precision': 'double'} 'precision': 'single'}
self.em_consts = {'c': c, # Speed of light in free space (m/s) self.em_consts = {'c': c, # Speed of light in free space (m/s)
'e0': e0, # Permittivity of free space (F/m) 'e0': e0, # Permittivity of free space (F/m)
@@ -203,12 +206,14 @@ class SimulationConfig:
self.general['cuda'] = True self.general['cuda'] = True
self.general['cpu'] = False self.general['cpu'] = False
self.general['opencl'] = False self.general['opencl'] = False
# Both single and double precision are possible on GPUs, but single
# provides best performance.
self.general['precision'] = 'single' self.general['precision'] = 'single'
self.cuda = {'gpus': [], # gpus: list of GPU objects self.cuda = {'gpus': [], # gpus: list of GPU objects
'gpus_str': [], # gpus_str: list of strings describing GPU(s) 'gpus_str': [], # gpus_str: list of strings describing GPU(s)
'nvcc_opts': None} # nvcc_opts: nvcc compiler options 'nvcc_opts': None} # nvcc_opts: nvcc compiler options
# Suppress nvcc warnings on Microsoft Windows # Suppress nvcc warnings on Microsoft Windows
if sys.platform == 'win32': self.cuda['nvcc_opts'] = '-w' if sys.platform == 'win32': self.cuda['nvcc_opts'] = ['-w']
# Flatten a list of lists # Flatten a list of lists
if any(isinstance(element, list) for element in self.args.gpu): if any(isinstance(element, list) for element in self.args.gpu):
@@ -302,7 +307,7 @@ class SimulationConfig:
# API # API
if self.args.inputfile is None: if self.args.inputfile is None:
self.input_file_path = Path(self.args.outputfile) self.input_file_path = Path(self.args.outputfile)
# CLI # API/CLI
else: else:
self.input_file_path = Path(self.args.inputfile) self.input_file_path = Path(self.args.inputfile)

查看文件

@@ -72,13 +72,8 @@ class Context:
def print_time_report(self): def print_time_report(self):
"""Print the total simulation time based on context.""" """Print the total simulation time based on context."""
s = self.make_time_report()
log.info(s)
def make_time_report(self):
"""Generate a string for the total simulation time."""
s = f"\n=== Simulation on {config.sim_config.hostinfo['hostname']} completed in [HH:MM:SS]: {datetime.timedelta(seconds=self.tsimend - self.tsimstart)}" s = f"\n=== Simulation on {config.sim_config.hostinfo['hostname']} completed in [HH:MM:SS]: {datetime.timedelta(seconds=self.tsimend - self.tsimstart)}"
return f"{s} {'=' * (get_terminal_width() - 1 - len(s))}\n" log.info(f"{s} {'=' * (get_terminal_width() - 1 - len(s))}\n")
class NoMPIContext(Context): class NoMPIContext(Context):

查看文件

@@ -160,7 +160,7 @@ __global__ void update_electric_dispersive_A(int NX, int NY, int NZ, int MAXPOLE
int materialEx = ID[INDEX4D_ID(0,i_ID,j_ID,k_ID)]; int materialEx = ID[INDEX4D_ID(0,i_ID,j_ID,k_ID)];
$REAL phi = 0; $REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) { for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,pole*3)].real() * Tx[INDEX4D_T(pole,i_T,j_T,k_T)].real(); phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,pole*3)]$REALFUNC * Tx[INDEX4D_T(pole,i_T,j_T,k_T)]$REALFUNC;
Tx[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,1+(pole*3))] * Tx[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,2+(pole*3))] * Ex[INDEX3D_FIELDS(i,j,k)]; Tx[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,1+(pole*3))] * Tx[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEx,2+(pole*3))] * Ex[INDEX3D_FIELDS(i,j,k)];
} }
Ex[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEx,0)] * Ex[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEx,2)] * (Hz[INDEX3D_FIELDS(i,j,k)] - Hz[INDEX3D_FIELDS(i,j-1,k)]) - updatecoeffsE[INDEX2D_MAT(materialEx,3)] * (Hy[INDEX3D_FIELDS(i,j,k)] - Hy[INDEX3D_FIELDS(i,j,k-1)]) - updatecoeffsE[INDEX2D_MAT(materialEx,4)] * phi; Ex[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEx,0)] * Ex[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEx,2)] * (Hz[INDEX3D_FIELDS(i,j,k)] - Hz[INDEX3D_FIELDS(i,j-1,k)]) - updatecoeffsE[INDEX2D_MAT(materialEx,3)] * (Hy[INDEX3D_FIELDS(i,j,k)] - Hy[INDEX3D_FIELDS(i,j,k-1)]) - updatecoeffsE[INDEX2D_MAT(materialEx,4)] * phi;
@@ -171,7 +171,7 @@ __global__ void update_electric_dispersive_A(int NX, int NY, int NZ, int MAXPOLE
int materialEy = ID[INDEX4D_ID(1,i_ID,j_ID,k_ID)]; int materialEy = ID[INDEX4D_ID(1,i_ID,j_ID,k_ID)];
$REAL phi = 0; $REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) { for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,pole*3)].real() * Ty[INDEX4D_T(pole,i_T,j_T,k_T)].real(); phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,pole*3)]$REALFUNC * Ty[INDEX4D_T(pole,i_T,j_T,k_T)]$REALFUNC;
Ty[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,1+(pole*3))] * Ty[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,2+(pole*3))] * Ey[INDEX3D_FIELDS(i,j,k)]; Ty[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,1+(pole*3))] * Ty[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEy,2+(pole*3))] * Ey[INDEX3D_FIELDS(i,j,k)];
} }
Ey[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEy,0)] * Ey[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEy,3)] * (Hx[INDEX3D_FIELDS(i,j,k)] - Hx[INDEX3D_FIELDS(i,j,k-1)]) - updatecoeffsE[INDEX2D_MAT(materialEy,1)] * (Hz[INDEX3D_FIELDS(i,j,k)] - Hz[INDEX3D_FIELDS(i-1,j,k)]) - updatecoeffsE[INDEX2D_MAT(materialEy,4)] * phi; Ey[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEy,0)] * Ey[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEy,3)] * (Hx[INDEX3D_FIELDS(i,j,k)] - Hx[INDEX3D_FIELDS(i,j,k-1)]) - updatecoeffsE[INDEX2D_MAT(materialEy,1)] * (Hz[INDEX3D_FIELDS(i,j,k)] - Hz[INDEX3D_FIELDS(i-1,j,k)]) - updatecoeffsE[INDEX2D_MAT(materialEy,4)] * phi;
@@ -182,7 +182,7 @@ __global__ void update_electric_dispersive_A(int NX, int NY, int NZ, int MAXPOLE
int materialEz = ID[INDEX4D_ID(2,i_ID,j_ID,k_ID)]; int materialEz = ID[INDEX4D_ID(2,i_ID,j_ID,k_ID)];
$REAL phi = 0; $REAL phi = 0;
for (int pole = 0; pole < MAXPOLES; pole++) { for (int pole = 0; pole < MAXPOLES; pole++) {
phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,pole*3)].real() * Tz[INDEX4D_T(pole,i_T,j_T,k_T)].real(); phi = phi + updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,pole*3)]$REALFUNC * Tz[INDEX4D_T(pole,i_T,j_T,k_T)]$REALFUNC;
Tz[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,1+(pole*3))] * Tz[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,2+(pole*3))] * Ez[INDEX3D_FIELDS(i,j,k)]; Tz[INDEX4D_T(pole,i_T,j_T,k_T)] = updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,1+(pole*3))] * Tz[INDEX4D_T(pole,i_T,j_T,k_T)] + updatecoeffsdispersive[INDEX2D_MATDISP(materialEz,2+(pole*3))] * Ez[INDEX3D_FIELDS(i,j,k)];
} }
Ez[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEz,0)] * Ez[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEz,1)] * (Hy[INDEX3D_FIELDS(i,j,k)] - Hy[INDEX3D_FIELDS(i-1,j,k)]) - updatecoeffsE[INDEX2D_MAT(materialEz,2)] * (Hx[INDEX3D_FIELDS(i,j,k)] - Hx[INDEX3D_FIELDS(i,j-1,k)]) - updatecoeffsE[INDEX2D_MAT(materialEz,4)] * phi; Ez[INDEX3D_FIELDS(i,j,k)] = updatecoeffsE[INDEX2D_MAT(materialEz,0)] * Ez[INDEX3D_FIELDS(i,j,k)] + updatecoeffsE[INDEX2D_MAT(materialEz,1)] * (Hy[INDEX3D_FIELDS(i,j,k)] - Hy[INDEX3D_FIELDS(i-1,j,k)]) - updatecoeffsE[INDEX2D_MAT(materialEz,2)] * (Hx[INDEX3D_FIELDS(i,j,k)] - Hx[INDEX3D_FIELDS(i,j-1,k)]) - updatecoeffsE[INDEX2D_MAT(materialEz,4)] * phi;

查看文件

@@ -76,7 +76,7 @@ class ModelBuildRun:
self.p = psutil.Process() self.p = psutil.Process()
# Normal model reading/building process; bypassed if geometry information to be reused # Normal model reading/building process; bypassed if geometry information to be reused
self.reuse_geometry() if config.get_model_config().reuse_geometry else self.build_geometry() self.build_geometry() if not config.get_model_config().reuse_geometry else self.reuse_geometry()
log.info(f'\nOutput directory: {config.get_model_config().output_file_path.parent.resolve()}') log.info(f'\nOutput directory: {config.get_model_config().output_file_path.parent.resolve()}')
@@ -136,10 +136,21 @@ class ModelBuildRun:
scene = self.build_scene() scene = self.build_scene()
# Combine available grids and check memory requirements # Combine available grids
grids = [G] + G.subgrids grids = [G] + G.subgrids
total_mem = mem_check_all(grids)
log.info(f'\nMemory (RAM) required: ~{human_size(total_mem)}') # Check for dispersive materials and specific type
for grid in grids:
if config.get_model_config().materials['maxpoles'] != 0:
config.get_model_config().materials['drudelorentz'] = any([m for m in grid.materials if 'drude' in m.type or 'lorentz' in m.type])
# Set data type if any dispersive materials (must be done before memory checks)
if config.get_model_config().materials['maxpoles'] != 0:
config.get_model_config().set_dispersive_material_types()
# Check memory requirements
total_mem, mem_strs = mem_check_all(grids)
log.info(f'\nMemory required: {" + ".join(mem_strs)} + ~{human_size(config.get_model_config().mem_overhead)} overhead = {human_size(total_mem)}')
# Build grids # Build grids
gridbuilders = [GridBuilder(grid) for grid in grids] gridbuilders = [GridBuilder(grid) for grid in grids]
@@ -172,7 +183,7 @@ class ModelBuildRun:
def reuse_geometry(self): def reuse_geometry(self):
# Reset iteration number # Reset iteration number
self.G.iteration = 0 self.G.iteration = 0
config.get_model_config().set_inputfilestr(f'\n--- Model {config.get_model_config().appendmodelnumber}/{config.sim_config.model_end}, input file (not re-processed, i.e. geometry fixed): {config.sim_config.input_file_path}') config.get_model_config().inputfilestr = f'\n--- Model {config.get_model_config().appendmodelnumber}/{config.sim_config.model_end}, input file (not re-processed, i.e. geometry fixed): {config.sim_config.input_file_path}'
log.info(config.get_model_config().inputfilestr) log.info(config.get_model_config().inputfilestr)
for grid in [self.G] + self.G.subgrids: for grid in [self.G] + self.G.subgrids:
grid.reset_fields() grid.reset_fields()
@@ -225,11 +236,11 @@ class ModelBuildRun:
memsolve (float): Memory (RAM) used on GPU. memsolve (float): Memory (RAM) used on GPU.
""" """
memGPU_str = '' mem_str = ''
if config.sim_config.general['cuda']: if config.sim_config.general['cuda']:
memGPU_str = f' host + ~{human_size(memsolve)} GPU' mem_str = f' host + ~{human_size(memsolve)} GPU'
log.info(f'\nMemory (RAM) used: ~{human_size(self.p.memory_full_info().uss)}{memGPU_str}') log.info(f'\nMemory used: ~{human_size(self.p.memory_full_info().uss)}{mem_str}')
log.info(f'Solving time [HH:MM:SS]: {datetime.timedelta(seconds=tsolve)}') log.info(f'Solving time [HH:MM:SS]: {datetime.timedelta(seconds=tsolve)}')
def solve(self, solver): def solve(self, solver):

查看文件

@@ -66,7 +66,6 @@ def create_solver(G):
updates = CUDAUpdates(G) updates = CUDAUpdates(G)
solver = Solver(updates) solver = Solver(updates)
return solver return solver

查看文件

@@ -25,7 +25,7 @@ from ..grid import FDTDGrid
class SubGridBase(FDTDGrid): class SubGridBase(FDTDGrid):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(args[0]) super().__init__()
self.mode = '3D' self.mode = '3D'
self.ratio = kwargs['ratio'] self.ratio = kwargs['ratio']

查看文件

@@ -16,7 +16,9 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>. # along with gprMax. If not, see <http://www.gnu.org/licenses/>.
from colorama import init, Fore, Style from colorama import init
from colorama import Fore
from colorama import Style
init() init()
import gprMax.config as config import gprMax.config as config
@@ -24,40 +26,43 @@ from .base import SubGridBase
from ..cython.fields_updates_hsg import cython_update_is from ..cython.fields_updates_hsg import cython_update_is
from ..cython.fields_updates_hsg import cython_update_magnetic_os from ..cython.fields_updates_hsg import cython_update_magnetic_os
from ..cython.fields_updates_hsg import cython_update_electric_os from ..cython.fields_updates_hsg import cython_update_electric_os
from ..utilities import human_size
class SubGridHSG(SubGridBase): class SubGridHSG(SubGridBase):
gridtype = '3DSUBGRID' gridtype = '3DSUBGRID'
def __init__(self, model_num, **kwargs): def __init__(self, **kwargs):
super().__init__(model_num, **kwargs) super().__init__(**kwargs)
self.gridtype = SubGridHSG.gridtype self.gridtype = SubGridHSG.gridtype
def update_magnetic_is(self, precursors): def update_magnetic_is(self, precursors):
"""Update the subgrid nodes at the IS with the currents derived """Update the subgrid nodes at the IS with the currents derived
from the main grid. from the main grid.
Args:
nwl, nwm, nwn, face, field, inc_field, lookup_id, sign, mod, co Args:
nwl, nwm, nwn, face, field, inc_field, lookup_id, sign, mod, co
""" """
# Hz = c0Hz - c1Ey + c2Ex # Hz = c0Hz - c1Ey + c2Ex
# Hy = c0Hy - c3Ex + c1Ez # Hy = c0Hy - c3Ex + c1Ez
# Hx = c0Hx - c2Ez + c3Ey # Hx = c0Hx - c2Ez + c3Ey
# bottom and top # bottom and top
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx, self.nwy + 1, self.nwz, 1, self.Hy, precursors.ex_bottom, precursors.ex_top, self.IDlookup['Hy'], 1, -1, 3, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx, self.nwy + 1, self.nwz, 1, self.Hy, precursors.ex_bottom, precursors.ex_top, self.IDlookup['Hy'], 1, -1, 3, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx + 1, self.nwy, self.nwz, 1, self.Hx, precursors.ey_bottom, precursors.ey_top, self.IDlookup['Hx'], -1, 1, 3, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx + 1, self.nwy, self.nwz, 1, self.Hx, precursors.ey_bottom, precursors.ey_top, self.IDlookup['Hx'], -1, 1, 3, config.get_model_config().ompthreads)
# left and right # left and right
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwy, self.nwz + 1, self.nwx, 2, self.Hz, precursors.ey_left, precursors.ey_right, self.IDlookup['Hz'], 1, -1, 1, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwy, self.nwz + 1, self.nwx, 2, self.Hz, precursors.ey_left, precursors.ey_right, self.IDlookup['Hz'], 1, -1, 1, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwy + 1, self.nwz, self.nwx, 2, self.Hy, precursors.ez_left, precursors.ez_right, self.IDlookup['Hy'], -1, 1, 1, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwy + 1, self.nwz, self.nwx, 2, self.Hy, precursors.ez_left, precursors.ez_right, self.IDlookup['Hy'], -1, 1, 1, config.get_model_config().ompthreads)
# front and back # front and back
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx, self.nwz + 1, self.nwy, 3, self.Hz, precursors.ex_front, precursors.ex_back, self.IDlookup['Hz'], -1, 1, 2, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx, self.nwz + 1, self.nwy, 3, self.Hz, precursors.ex_front, precursors.ex_back, self.IDlookup['Hz'], -1, 1, 2, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx + 1, self.nwz, self.nwy, 3, self.Hx, precursors.ez_front, precursors.ez_back, self.IDlookup['Hx'], 1, -1, 2, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsH, self.ID, self.n_boundary_cells, -1, self.nwx + 1, self.nwz, self.nwy, 3, self.Hx, precursors.ez_front, precursors.ez_back, self.IDlookup['Hx'], 1, -1, 2, config.get_model_config().ompthreads)
def update_electric_is(self, precursors): def update_electric_is(self, precursors):
"""
"""
# Args: nwl, nwm, nwn, face, field, inc_field, lookup_id, sign, mod, co # Args: nwl, nwm, nwn, face, field, inc_field, lookup_id, sign, mod, co
# Ex = c0(Ex) + c2(dHz) - c3(dHy) # Ex = c0(Ex) + c2(dHz) - c3(dHy)
@@ -65,18 +70,21 @@ class SubGridHSG(SubGridBase):
# Ez = c0(Ez) + c1(dHy) - c2(dHx) # Ez = c0(Ez) + c1(dHy) - c2(dHx)
# bottom and top # bottom and top
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx, self.nwy + 1, self.nwz, 1, self.Ex, precursors.hy_bottom, precursors.hy_top, self.IDlookup['Ex'], 1, -1, 3, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx, self.nwy + 1, self.nwz, 1, self.Ex, precursors.hy_bottom, precursors.hy_top, self.IDlookup['Ex'], 1, -1, 3, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx + 1, self.nwy, self.nwz, 1, self.Ey, precursors.hx_bottom, precursors.hx_top, self.IDlookup['Ey'], -1, 1, 3, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx + 1, self.nwy, self.nwz, 1, self.Ey, precursors.hx_bottom, precursors.hx_top, self.IDlookup['Ey'], -1, 1, 3, config.get_model_config().ompthreads)
# left and right # left and right
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwy, self.nwz + 1, self.nwx, 2, self.Ey, precursors.hz_left, precursors.hz_right, self.IDlookup['Ey'], 1, -1, 1, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwy, self.nwz + 1, self.nwx, 2, self.Ey, precursors.hz_left, precursors.hz_right, self.IDlookup['Ey'], 1, -1, 1, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwy + 1, self.nwz, self.nwx, 2, self.Ez, precursors.hy_left, precursors.hy_right, self.IDlookup['Ez'], -1, 1, 1, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwy + 1, self.nwz, self.nwx, 2, self.Ez, precursors.hy_left, precursors.hy_right, self.IDlookup['Ez'], -1, 1, 1, config.get_model_config().ompthreads)
# front and back # front and back
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx, self.nwz + 1, self.nwy, 3, self.Ex, precursors.hz_front, precursors.hz_back, self.IDlookup['Ex'], -1, 1, 2, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx, self.nwz + 1, self.nwy, 3, self.Ex, precursors.hz_front, precursors.hz_back, self.IDlookup['Ex'], -1, 1, 2, config.get_model_config().ompthreads)
cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx + 1, self.nwz, self.nwy, 3, self.Ez, precursors.hx_front, precursors.hx_back, self.IDlookup['Ez'], 1, -1, 2, config.get_model().ompthreads) cython_update_is(self.nwx, self.nwy, self.nwz, self.updatecoeffsE, self.ID, self.n_boundary_cells, 0, self.nwx + 1, self.nwz, self.nwy, 3, self.Ez, precursors.hx_front, precursors.hx_back, self.IDlookup['Ez'], 1, -1, 2, config.get_model_config().ompthreads)
def update_electric_os(self, main_grid): def update_electric_os(self, main_grid):
"""
"""
i_l = self.i0 - self.is_os_sep i_l = self.i0 - self.is_os_sep
i_u = self.i1 + self.is_os_sep i_u = self.i1 + self.is_os_sep
j_l = self.j0 - self.is_os_sep j_l = self.j0 - self.is_os_sep
@@ -91,19 +99,21 @@ class SubGridHSG(SubGridBase):
# Ey = c0(Ey) + c3(dHx) - c1(dHz) # Ey = c0(Ey) + c3(dHx) - c1(dHz)
# Ez = c0(Ez) + c1(dHy) - c2(dHx) # Ez = c0(Ez) + c1(dHy) - c2(dHx)
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 3, i_l, i_u, k_l, k_u + 1, j_l, j_u, self.nwy, main_grid.IDlookup['Ex'], main_grid.Ex, self.Hz, 2, 1, -1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 3, i_l, i_u, k_l, k_u + 1, j_l, j_u, self.nwy, main_grid.IDlookup['Ex'], main_grid.Ex, self.Hz, 2, 1, -1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 3, i_l, i_u + 1, k_l, k_u, j_l, j_u, self.nwy, main_grid.IDlookup['Ez'], main_grid.Ez, self.Hx, 2, -1, 1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 3, i_l, i_u + 1, k_l, k_u, j_l, j_u, self.nwy, main_grid.IDlookup['Ez'], main_grid.Ez, self.Hx, 2, -1, 1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
# Left and Right # Left and Right
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 2, j_l, j_u, k_l, k_u + 1, i_l, i_u, self.nwx, main_grid.IDlookup['Ey'], main_grid.Ey, self.Hz, 1, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 2, j_l, j_u, k_l, k_u + 1, i_l, i_u, self.nwx, main_grid.IDlookup['Ey'], main_grid.Ey, self.Hz, 1, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 2, j_l, j_u + 1, k_l, k_u, i_l, i_u, self.nwx, main_grid.IDlookup['Ez'], main_grid.Ez, self.Hy, 1, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 2, j_l, j_u + 1, k_l, k_u, i_l, i_u, self.nwx, main_grid.IDlookup['Ez'], main_grid.Ez, self.Hy, 1, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
# Bottom and Top # Bottom and Top
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 1, i_l, i_u, j_l, j_u + 1, k_l, k_u, self.nwz, main_grid.IDlookup['Ex'], main_grid.Ex, self.Hy, 3, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 1, i_l, i_u, j_l, j_u + 1, k_l, k_u, self.nwz, main_grid.IDlookup['Ex'], main_grid.Ex, self.Hy, 3, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 1, i_l, i_u + 1, j_l, j_u, k_l, k_u, self.nwz, main_grid.IDlookup['Ey'], main_grid.Ey, self.Hx, 3, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_electric_os(main_grid.updatecoeffsE, main_grid.ID, 1, i_l, i_u + 1, j_l, j_u, k_l, k_u, self.nwz, main_grid.IDlookup['Ey'], main_grid.Ey, self.Hx, 3, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
def update_magnetic_os(self, main_grid): def update_magnetic_os(self, main_grid):
"""
"""
i_l = self.i0 - self.is_os_sep i_l = self.i0 - self.is_os_sep
i_u = self.i1 + self.is_os_sep i_u = self.i1 + self.is_os_sep
j_l = self.j0 - self.is_os_sep j_l = self.j0 - self.is_os_sep
@@ -119,28 +129,25 @@ class SubGridHSG(SubGridBase):
# Args: sub_grid, normal, l_l, l_u, m_l, m_u, n_l, n_u, nwn, lookup_id, field, inc_field, co, sign_n, sign_f): # Args: sub_grid, normal, l_l, l_u, m_l, m_u, n_l, n_u, nwn, lookup_id, field, inc_field, co, sign_n, sign_f):
# Front and back # Front and back
cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 3, i_l, i_u, k_l, k_u + 1, j_l - 1, j_u, self.nwy, main_grid.IDlookup['Hz'], main_grid.Hz, self.Ex, 2, 1, -1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 3, i_l, i_u, k_l, k_u + 1, j_l - 1, j_u, self.nwy, main_grid.IDlookup['Hz'], main_grid.Hz, self.Ex, 2, 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, 3, i_l, i_u + 1, k_l, k_u, j_l - 1, j_u, self.nwy, main_grid.IDlookup['Hx'], main_grid.Hx, self.Ez, 2, -1, 1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 3, i_l, i_u + 1, k_l, k_u, j_l - 1, j_u, self.nwy, main_grid.IDlookup['Hx'], main_grid.Hx, self.Ez, 2, -1, 1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
# Left and Right # Left and Right
cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 2, j_l, j_u, k_l, k_u + 1, i_l - 1, i_u, self.nwx, main_grid.IDlookup['Hz'], main_grid.Hz, self.Ey, 1, -1, 1, 1, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 2, j_l, j_u, k_l, k_u + 1, i_l - 1, i_u, self.nwx, main_grid.IDlookup['Hz'], main_grid.Hz, self.Ey, 1, -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, 2, j_l, j_u + 1, k_l, k_u, i_l - 1, i_u, self.nwx, main_grid.IDlookup['Hy'], main_grid.Hy, self.Ez, 1, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model().ompthreads) cython_update_magnetic_os(main_grid.updatecoeffsH, main_grid.ID, 2, j_l, j_u + 1, k_l, k_u, i_l - 1, i_u, self.nwx, main_grid.IDlookup['Hy'], main_grid.Hy, self.Ez, 1, 1, -1, 0, self.ratio, self.is_os_sep, self.n_boundary_cells, config.get_model_config().ompthreads)
# bottom and top # bottom and top
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().ompthreads) 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().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): def __str__(self):
mem_use = self.mem_est_basic()
s = '\n' s = '\n'
s += Fore.CYAN s += Fore.CYAN
s += 'Sub Grid HSG\n' s += 'Sub Grid HSG\n'
s += f'Name: {self.name}\n' s += f'Name: {self.name}\n'
s += f'dx, dy, dz: {self.dx}m {self.dy}m {self.dz}m\n' s += f'Spatial discretisation: {self.dx:g} x {self.dy:g} x {self.dz:g}m\n'
s += f'dt: {self.dt}s\n' s += f'Time step (at CFL limit): {self.dt:g} secs\n'
s += f'Memory Estimate: {human_size(mem_use)}\n'
s += f'Position: ({self.x1}m, {self.y1}m, {self.z1}m), ({self.x2}m, {self.y2}m, {self.z2}m)\n' s += f'Position: ({self.x1}m, {self.y1}m, {self.z1}m), ({self.x2}m, {self.y2}m, {self.z2}m)\n'
s += f'Main Grid Indices: lower left({self.i0}, {self.j0}, {self.k0}), upper right({self.i1}, {self.j1}, {self.k1})\n' s += f'Main Grid Indices: lower left({self.i0}, {self.j0}, {self.k0}), upper right({self.i1}, {self.j1}, {self.k1})\n'
s += f'Total Cells: {self.nx} {self.ny} {self.nz}\n' s += f'Total Cells: {self.nx} {self.ny} {self.nz}\n'

查看文件

@@ -16,19 +16,23 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with gprMax. If not, see <http://www.gnu.org/licenses/>. # along with gprMax. If not, see <http://www.gnu.org/licenses/>.
import logging
from ..exceptions import GeneralError from ..exceptions import GeneralError
from .precursor_nodes import PrecursorNodes from .precursor_nodes import PrecursorNodes
from .precursor_nodes import PrecursorNodesFiltered from .precursor_nodes import PrecursorNodesFiltered
from .subgrid_hsg import SubGridHSG from .subgrid_hsg import SubGridHSG
from ..updates import CPUUpdates from ..updates import CPUUpdates
log = logging.getLogger(__name__)
def create_updates(G): def create_updates(G):
"""Return the solver for the given subgrids.""" """Return the solver for the given subgrids."""
updaters = [] updaters = []
for sg in G.subgrids: for sg in G.subgrids:
print(sg) log.info(sg)
sg_type = type(sg) sg_type = type(sg)
if sg_type == SubGridHSG and sg.filter: if sg_type == SubGridHSG and sg.filter:
precursors = PrecursorNodesFiltered(G, sg) precursors = PrecursorNodesFiltered(G, sg)

查看文件

@@ -169,7 +169,6 @@ class SubGridHSG(SubGridBase):
interpolation=1, interpolation=1,
filter=True, filter=True,
**kwargs): **kwargs):
"""Constructor."""
pml_separation = ratio // 2 + 2 pml_separation = ratio // 2 + 2
@@ -189,7 +188,7 @@ class SubGridHSG(SubGridBase):
self.hash = '#subgrid_hsg' self.hash = '#subgrid_hsg'
def create(self, grid, uip): def create(self, grid, uip):
sg = SubGridHSGUser(grid.model_num, **self.kwargs) sg = SubGridHSGUser(**self.kwargs)
self.setup(sg, grid, uip) self.setup(sg, grid, uip)
return sg return sg

查看文件

@@ -279,7 +279,8 @@ class CUDAUpdates:
if config.get_model_config().materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
kernels_fields = self.source_module(kernel_template_fields.substitute( kernels_fields = self.source_module(kernel_template_fields.substitute(
REAL=config.sim_config.dtypes['C_float_or_double'], REAL=config.sim_config.dtypes['C_float_or_double'],
COMPLEX=config.sim_config.dtypes['C_complex'], REALFUNC=config.get_model_config().materials['cuda_real_func'],
COMPLEX=config.get_model_config().materials['dispersiveCdtype'],
N_updatecoeffsE=self.grid.updatecoeffsE.size, N_updatecoeffsE=self.grid.updatecoeffsE.size,
N_updatecoeffsH=self.grid.updatecoeffsH.size, N_updatecoeffsH=self.grid.updatecoeffsH.size,
NY_MATCOEFFS=self.grid.updatecoeffsE.shape[1], NY_MATCOEFFS=self.grid.updatecoeffsE.shape[1],
@@ -294,9 +295,11 @@ class CUDAUpdates:
NY_T=self.grid.Tx.shape[2], NY_T=self.grid.Tx.shape[2],
NZ_T=self.grid.Tx.shape[3]), NZ_T=self.grid.Tx.shape[3]),
options=config.sim_config.cuda['nvcc_opts']) options=config.sim_config.cuda['nvcc_opts'])
else: # Set to one any substitutions for dispersive materials else: # Set to one any substitutions for dispersive materials.
# Value of COMPLEX is not relevant.
kernels_fields = self.source_module(kernel_template_fields.substitute( kernels_fields = self.source_module(kernel_template_fields.substitute(
REAL=config.sim_config.dtypes['C_float_or_double'], REAL=config.sim_config.dtypes['C_float_or_double'],
REALFUNC=config.get_model_config().materials['cuda_real_func'],
COMPLEX=config.sim_config.dtypes['C_complex'], COMPLEX=config.sim_config.dtypes['C_complex'],
N_updatecoeffsE=self.grid.updatecoeffsE.size, N_updatecoeffsE=self.grid.updatecoeffsE.size,
N_updatecoeffsH=self.grid.updatecoeffsH.size, N_updatecoeffsH=self.grid.updatecoeffsH.size,

查看文件

@@ -73,11 +73,9 @@ class UserInput:
# Incorrect index # Incorrect index
i = p[v.index(err.args[0])] i = p[v.index(err.args[0])]
if name: if name:
s = f"'{cmd_str}' the {err.args[0]} {name}-coordinate {i * dl:g} \ s = f"'{cmd_str}' the {err.args[0]} {name}-coordinate {i * dl:g} is not within the model domain"
is not within the model domain"
else: else:
s = f"'{cmd_str}' {err.args[0]}-coordinate {i * dl:g} is not \ s = f"'{cmd_str}' {err.args[0]}-coordinate {i * dl:g} is not within the model domain"
within the model domain"
raise CmdInputError(log.exception(s)) raise CmdInputError(log.exception(s))
def discretise_point(self, p): def discretise_point(self, p):
@@ -106,8 +104,7 @@ class MainGridUserInput(UserInput):
p = self.check_point(p, cmd_str, name) p = self.check_point(p, cmd_str, name)
if self.grid.within_pml(p): if self.grid.within_pml(p):
log.warning(Fore.RED + f"'{cmd_str}' sources and receivers should \ log.warning(Fore.RED + f"'{cmd_str}' sources and receivers should not normally be positioned within the PML." + Style.RESET_ALL)
not normally be positioned within the PML." + Style.RESET_ALL)
return p return p
@@ -116,8 +113,7 @@ class MainGridUserInput(UserInput):
p2 = self.check_point(p2, cmd_str, name='upper') p2 = self.check_point(p2, cmd_str, name='upper')
if np.greater(p1, p2).any(): if np.greater(p1, p2).any():
raise CmdInputError(log.exception(f"'{cmd_str}' the lower coordinates \ raise CmdInputError(log.exception(f"'{cmd_str}' the lower coordinates should be less than the upper coordinates."))
should be less than the upper coordinates."))
return p1, p2 return p1, p2
@@ -139,10 +135,9 @@ class SubgridUserInput(MainGridUserInput):
super().__init__(grid) super().__init__(grid)
# Defines the region exposed to the user # Defines the region exposed to the user
self.inner_bound = np.array([ self.inner_bound = np.array([grid.n_boundary_cells_x,
grid.n_boundary_cells_x, grid.n_boundary_cells_y,
grid.n_boundary_cells_y, grid.n_boundary_cells_z])
grid.n_boundary_cells_z])
self.outer_bound = np.subtract([grid.nx, grid.ny, grid.nz], self.outer_bound = np.subtract([grid.nx, grid.ny, grid.nz],
self.inner_bound) self.inner_bound)
@@ -180,6 +175,5 @@ class SubgridUserInput(MainGridUserInput):
# the OS non-working region. # the OS non-working region.
if (np.less(p_t, self.inner_bound).any() or if (np.less(p_t, self.inner_bound).any() or
np.greater(p_t, self.outer_bound).any()): np.greater(p_t, self.outer_bound).any()):
log.warning(Fore.RED + f"'{cmd_str}' this object traverses the \ log.warning(Fore.RED + f"'{cmd_str}' this object traverses the Outer Surface. This is an advanced feature." + Style.RESET_ALL)
Outer Surface. This is an advanced feature." + Style.RESET_ALL)
return p_t return p_t

查看文件

@@ -28,7 +28,12 @@ import subprocess
from shutil import get_terminal_size from shutil import get_terminal_size
import sys import sys
import textwrap import textwrap
from time import perf_counter
try:
from time import thread_time as timer_fn
except ImportError:
from time import perf_counter as timer_fn
from colorama import init from colorama import init
from colorama import Fore from colorama import Fore
@@ -301,7 +306,7 @@ def get_host_info():
cpuIDinfo = subprocess.check_output("cat /proc/cpuinfo", shell=True, stderr=subprocess.STDOUT, env=myenv).decode('utf-8').strip() cpuIDinfo = subprocess.check_output("cat /proc/cpuinfo", shell=True, stderr=subprocess.STDOUT, env=myenv).decode('utf-8').strip()
for line in cpuIDinfo.split('\n'): for line in cpuIDinfo.split('\n'):
if re.search('model name', line): if re.search('model name', line):
cpuID = re.sub('.*model name.*:', '', line, 1).strip() cpuID = re.sub('.*model name.*:', '', line, 1).strip()
allcpuinfo = subprocess.check_output("lscpu", shell=True, stderr=subprocess.STDOUT, env=myenv).decode('utf-8').strip() allcpuinfo = subprocess.check_output("lscpu", shell=True, stderr=subprocess.STDOUT, env=myenv).decode('utf-8').strip()
for line in allcpuinfo.split('\n'): for line in allcpuinfo.split('\n'):
if 'Socket(s)' in line: if 'Socket(s)' in line:
@@ -420,44 +425,44 @@ def mem_check_all(grids):
Returns: Returns:
total_mem (int): Total memory required for all grids. total_mem (int): Total memory required for all grids.
mem_strs (list): Strings containing text of memory requirements for
each grid.
""" """
total_mem = 0
total_snaps_mem = 0 total_snaps_mem = 0
mem_strs = []
for grid in grids: for grid in grids:
# Memory required for main grid arrays
config.get_model_config().mem_use += grid.mem_est_basic() config.get_model_config().mem_use += grid.mem_est_basic()
grid.mem_use += grid.mem_est_basic()
# Set datatype for dispersive arrays if there are any dispersive materials. # Additional memory required if there are any dispersive materials.
if config.get_model_config().materials['maxpoles'] != 0: if config.get_model_config().materials['maxpoles'] != 0:
drudelorentz = any([m for m in grid.materials if 'drude' in m.type or 'lorentz' in m.type])
if drudelorentz:
config.get_model_config().materials['dispersivedtype'] = config.sim_config.dtypes['complex']
config.get_model_config().materials['dispersiveCdtype'] = config.sim_config.dtypes['C_complex']
else:
config.get_model_config().materials['dispersivedtype'] = config.sim_config.dtypes['float_or_double']
config.get_model_config().materials['dispersiveCdtype'] = config.sim_config.dtypes['C_float_or_double']
# Update estimated memory (RAM) usage
config.get_model_config().mem_use += grid.mem_est_dispersive() config.get_model_config().mem_use += grid.mem_est_dispersive()
grid.mem_use += grid.mem_est_dispersive()
# Calculate snapshot memory # Additional memory required if there are any snapshots
if grid.snapshots: if grid.snapshots:
for snap in grid.snapshots: for snap in grid.snapshots:
# 2 x required to account for electric and magnetic fields # 2 x required to account for electric and magnetic fields
config.get_model_config().mem_use += int(2 * snap.datasizefield) snap_mem = int(2 * snap.datasizefield)
total_snaps_mem += int(2 * snap.datasizefield) config.get_model_config().mem_use += snap_mem
total_snaps_mem += snap_mem
grid.mem_use += snap_mem
total_mem += config.get_model_config().mem_use mem_strs.append(f'~{human_size(grid.mem_use)} ({grid.name})')
total_mem = config.get_model_config().mem_use
# Check if there is sufficient memory on host # Check if there is sufficient memory on host
mem_check_host(total_mem) mem_check_host(total_mem)
# Check if there is sufficient memory for any snapshots on GPU # Check if there is sufficient memory for any snapshots on GPU
if config.sim_config.general['cuda']: if total_snaps_mem > 0 and config.sim_config.general['cuda']:
mem_check_gpu_snaps(total_mem, total_snaps_mem) mem_check_gpu_snaps(total_mem, total_snaps_mem)
return total_mem return total_mem, mem_strs
class GPU: class GPU:
@@ -535,5 +540,6 @@ def detect_check_gpus(deviceIDs):
def timer(): def timer():
"""Function to return the current process wide time in fractional seconds.""" """Function to return time in fractional seconds."""
return perf_counter() log.debug('Review "thread_time" not currently available in macOS and bug (https://bugs.python.org/issue36205) with "process_time"')
return timer_fn()