Further work to prepare sub-gridding.

这个提交包含在:
Craig Warren
2019-11-18 14:02:32 +00:00
父节点 df0c3cf205
当前提交 2c450a63af
共有 19 个文件被更改,包括 206 次插入216 次删除

查看文件

@@ -35,7 +35,7 @@ class UserObjectGeometry:
self.autotranslate = True self.autotranslate = True
def __str__(self): def __str__(self):
"""Readble user string as per hash commands.""" """Readable string of parameters given to object."""
s = '' s = ''
for k, v in self.kwargs.items(): for k, v in self.kwargs.items():
if isinstance(v, tuple) or isinstance(v, list): if isinstance(v, tuple) or isinstance(v, list):
@@ -45,7 +45,7 @@ class UserObjectGeometry:
return f'{self.hash}: {s[:-1]}' return f'{self.hash}: {s[:-1]}'
def params_str(self): def params_str(self):
"""Readble string of parameters given to object.""" """Readable user string as per hash commands."""
return self.hash + ': ' + str(self.kwargs) return self.hash + ': ' + str(self.kwargs)
def create(self, grid, uip): def create(self, grid, uip):

查看文件

@@ -25,8 +25,7 @@ import gprMax.config as config
from .cmds_geometry import UserObjectGeometry from .cmds_geometry import UserObjectGeometry
from ..cython.geometry_primitives import build_voxels_from_array from ..cython.geometry_primitives import build_voxels_from_array
from ..exceptions import CmdInputError from ..exceptions import CmdInputError
# from ..hash_cmds_file import check_cmd_names from ..hash_cmds_file import get_user_objects
# from ..hash_cmds_multiuse import process_multicmds
from ..utilities import round_value from ..utilities import round_value
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -69,11 +68,15 @@ class GeometryObjectsRead(UserObjectGeometry):
# Strip out any newline characters and comments that must begin with double hashes # Strip out any newline characters and comments that must begin with double hashes
materials = [line.rstrip() + '{' + matstr + '}\n' for line in f if(not line.startswith('##') and line.rstrip('\n'))] materials = [line.rstrip() + '{' + matstr + '}\n' for line in f if(not line.startswith('##') and line.rstrip('\n'))]
# Check validity of command names # build scene
singlecmdsimport, multicmdsimport, geometryimport = check_cmd_names(materials, checkessential=False) # API for multiple scenes / model runs
scene = config.get_model_config().get_scene()
user_objs = get_user_objects(materials, check=False)
for user_obj in user_objs:
scene.add(user_obj)
# Process parameters for commands that can occur multiple times in the model # Creates the internal simulation objects
process_multicmds(multicmdsimport) # scene.create_internal_objects(self.G)
# Update material type # Update material type
for material in G.materials: for material in G.materials:

查看文件

@@ -272,9 +272,9 @@ class NumThreads(UserObjectSingle):
def __str__(self): def __str__(self):
try: try:
return '#n_threads: {}'.format(self.kwargs['n']) return f"#num_threads: {self.kwargs['n']}"
except KeyError: except KeyError:
return '#n_threads:' return '#num_threads:'
def create(self, G, uip): def create(self, G, uip):
try: try:
@@ -284,7 +284,7 @@ class NumThreads(UserObjectSingle):
if n < 1: if n < 1:
raise CmdInputError(self.__str__() + ' requires the value to be an integer not less than one') raise CmdInputError(self.__str__() + ' requires the value to be an integer not less than one')
config.model_configs[G.model_num].ompthreads = set_omp_threads(n) config.get_model_config().ompthreads = set_omp_threads(n)
class TimeStepStabilityFactor(UserObjectSingle): class TimeStepStabilityFactor(UserObjectSingle):
@@ -386,9 +386,7 @@ class SrcSteps(UserObjectSingle):
except KeyError: except KeyError:
raise CmdInputError('#src_steps: requires exactly three parameters') raise CmdInputError('#src_steps: requires exactly three parameters')
log.info(f'Simple sources will step {G.srcsteps[0] * G.dx:g}m, \ log.info(f'Simple sources will step {G.srcsteps[0] * G.dx:g}m, {G.srcsteps[1] * G.dy:g}m, {G.srcsteps[2] * G.dz:g}m for each model run.')
{G.srcsteps[1] * G.dy:g}m, {G.srcsteps[2] * G.dz:g}m \
for each model run.')
class RxSteps(UserObjectSingle): class RxSteps(UserObjectSingle):
@@ -409,9 +407,7 @@ class RxSteps(UserObjectSingle):
except KeyError: except KeyError:
raise CmdInputError('#rx_steps: requires exactly three parameters') raise CmdInputError('#rx_steps: requires exactly three parameters')
log.info(f'All receivers will step {G.rxsteps[0] * G.dx:g}m, \ log.info(f'All receivers will step {G.rxsteps[0] * G.dx:g}m, {G.rxsteps[1] * G.dy:g}m, {G.rxsteps[2] * G.dz:g}m for each model run.')
{G.rxsteps[1] * G.dy:g}m, {G.rxsteps[2] * G.dz:g}m \
for each model run.')
class ExcitationFile(UserObjectSingle): class ExcitationFile(UserObjectSingle):
@@ -509,7 +505,7 @@ class OutputDir(UserObjectSingle):
self.order = 12 self.order = 12
def create(self, grid, uip): def create(self, grid, uip):
config.model_configs[grid.model_num].set_output_file_path(self.kwargs['dir']) config.get_model_config().set_output_file_path(self.kwargs['dir'])
class NumberOfModelRuns(UserObjectSingle): class NumberOfModelRuns(UserObjectSingle):

查看文件

@@ -43,18 +43,22 @@ sim_config = None
# Instance of ModelConfig that hold model configuration parameters. # Instance 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
# ModelConfig is created
model_num = 0
def get_model_config():
"""Return ModelConfig instace for specific model."""
return model_configs[model_num]
class ModelConfig: class ModelConfig:
"""Configuration parameters for a model. """Configuration parameters for a model.
N.B. Multiple models can exist within a simulation N.B. Multiple models can exist within a simulation
""" """
def __init__(self, model_num): def __init__(self):
"""
Args:
model_num (int): Model number.
"""
self.i = model_num # Indexed from 0
self.mode = '3D' self.mode = '3D'
self.grids = [] self.grids = []
self.ompthreads = None # Number of OpenMP threads self.ompthreads = None # Number of OpenMP threads
@@ -75,11 +79,11 @@ class ModelConfig:
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 {self.i + 1}/{sim_config.model_end}, input file: {sim_config.input_file_path}' inputfilestr = f'\n--- Model {model_num + 1}/{sim_config.model_end}, input file: {sim_config.input_file_path}'
self.set_inputfilestr(inputfilestr) self.set_inputfilestr(inputfilestr)
if not sim_config.single_model: if not sim_config.single_model:
self.appendmodelnumber = str(self.i + 1) # Indexed from 1 self.appendmodelnumber = str(model_num + 1) # Indexed from 1
else: else:
self.appendmodelnumber = '' self.appendmodelnumber = ''
@@ -108,7 +112,7 @@ class ModelConfig:
def get_scene(self): def get_scene(self):
if sim_config.scenes: if sim_config.scenes:
return sim_config.scenes[self.i] return sim_config.scenes[model_num]
else: return None else: return None
def get_usernamespace(self): def get_usernamespace(self):
@@ -116,8 +120,8 @@ class ModelConfig:
'e0': e0, # Permittivity of free space (F/m) 'e0': e0, # Permittivity of free space (F/m)
'm0': m0, # Permeability of free space (H/m) 'm0': m0, # Permeability of free space (H/m)
'z0': np.sqrt(m0 / e0), # Impedance of free space (Ohms) 'z0': np.sqrt(m0 / e0), # Impedance of free space (Ohms)
'number_model_runs': sim_config.model_end + 1, 'number_model_runs': sim_config.model_end,
'current_model_run': self.i + 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_inputfilestr(self, inputfilestr):
@@ -169,7 +173,6 @@ class SimulationConfig:
""" """
self.args = args self.args = args
log.debug('Fix parsing args')
# General settings for the simulation # General settings for the simulation
# inputfilepath: path to inputfile location # inputfilepath: path to inputfile location
@@ -177,17 +180,15 @@ class SimulationConfig:
# messages: whether to print all messages as output to stdout or not # messages: whether to print all messages as output to stdout or not
# progressbars: whether to show progress bars on stdoout or not # progressbars: whether to show progress bars on stdoout or not
# cpu, cuda, opencl: solver type # cpu, cuda, opencl: solver type
# subgrid: whether the simulation uses sub-grids
# precision: data type for electromagnetic field output (single/double) # precision: data type for electromagnetic field output (single/double)
# autotranslate: auto translate objects with main grid coordinates
# to their equivalent local grid coordinate within the subgrid.
# If this option is off users must specify sub-grid object point
# within the global subgrid space.
self.general = {'messages': True, self.general = {'messages': True,
'progressbars': True, 'progressbars': True,
'cpu': True, 'cpu': True,
'cuda': False, 'cuda': False,
'opencl': False, 'opencl': False,
'precision': 'single'} 'subgrid': False,
'precision': 'double'}
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)
@@ -217,9 +218,9 @@ class SimulationConfig:
# Subgrid parameter may not exist if user enters via CLI # Subgrid parameter may not exist if user enters via CLI
try: try:
self.subgrid = args.subgrid self.general['subgrid'] = self.args.subgrid
except AttributeError: except AttributeError:
self.subgrid = False self.general['subgrid'] = False
# Scenes parameter may not exist if user enters via CLI # Scenes parameter may not exist if user enters via CLI
try: try:

查看文件

@@ -34,14 +34,11 @@ def write_simulation_config(args):
config.sim_config = config.SimulationConfig(args) config.sim_config = config.SimulationConfig(args)
def write_model_config(model_num): def write_model_config():
"""Write model level configuration parameters to config module. As there can """Write model level configuration parameters to config module. As there can
only be one instance of the config module objects are always found via only be one instance of the config module objects are always found via
'import gprMax.config' 'import gprMax.config'
Args:
model_num (int): Model number.
""" """
model_config = config.ModelConfig(model_num) model_config = config.ModelConfig()
config.model_configs.append(model_config) config.model_configs.append(model_config)

查看文件

@@ -35,7 +35,7 @@ log = logging.getLogger(__name__)
class Context: class Context:
"""Generic context for the model to run in. Sub-class with specific contexts """Generic context for the model to run in. Sub-class with specific contexts
e.g. an MPI context. e.g. an MPI context.
""" """
def __init__(self): def __init__(self):
@@ -90,16 +90,17 @@ class NoMPIContext(Context):
"""Specialise how the models are farmed out.""" """Specialise how the models are farmed out."""
for i in self.model_range: for i in self.model_range:
write_model_config(i) config.model_num = i
write_model_config()
# Always create a solver for the first model. # Always create a solver for the first model.
# The next model to run only gets a new solver if the # The next model to run only gets a new solver if the
# geometry is not re-used. # geometry is not re-used.
if i != 0 and config.sim_config.args.geometry_fixed: if i != 0 and config.sim_config.args.geometry_fixed:
config.model_configs[i].reuse_geometry = True config.get_model_config().reuse_geometry = True
# Ensure re-used G is associated correctly with model # Ensure re-used G is associated correctly with model
G.model_num = i # G.model_num = i
else: else:
G = create_G(i) G = create_G()
model = ModelBuildRun(G) model = ModelBuildRun(G)
model.build() model.build()

查看文件

@@ -98,9 +98,12 @@ __global__ void store_outputs(int NRX, int iteration, const int* __restrict__ rx
""") """)
def write_hdf5_outputfile(outputfile, G): def write_hdf5_outputfiles(outputfile, G):
write_hdf5_main_grid_outputfile(outputfile, G) if G.rxs:
write_hdf5_sub_grid_outputfile(outputfile, G) write_hdf5_main_grid_outputfile(outputfile, G)
sg_rxs = [True for sg in G.subgrids if sg.rxs]
if sg_rxs:
write_hdf5_sub_grid_outputfile(outputfile, G)
def write_hdf5_main_grid_outputfile(outputfile, G): def write_hdf5_main_grid_outputfile(outputfile, G):

查看文件

@@ -93,7 +93,7 @@ class FractalSurface:
A = fftpack.fftshift(A) A = fftpack.fftshift(A)
# Generate fractal # Generate fractal
generate_fractal2D(surfacedims[0], surfacedims[1], config.model_configs[G.model_num].ompthreads, generate_fractal2D(surfacedims[0], surfacedims[1], config.get_model_config().ompthreads,
self.b, self.weighting, v1, A, self.fractalsurface) self.b, self.weighting, v1, A, self.fractalsurface)
# Shift the zero frequency component to start of the array # Shift the zero frequency component to start of the array
self.fractalsurface = fftpack.ifftshift(self.fractalsurface) self.fractalsurface = fftpack.ifftshift(self.fractalsurface)
@@ -180,7 +180,7 @@ class FractalVolume:
A = fftpack.fftshift(A) A = fftpack.fftshift(A)
# Generate fractal # Generate fractal
generate_fractal3D(self.nx, self.ny, self.nz, config.model_configs[G.model_num].ompthreads, generate_fractal3D(self.nx, self.ny, self.nz, config.get_model_config().ompthreads,
self.b, self.weighting, v1, A, self.fractalvolume) self.b, self.weighting, v1, A, self.fractalvolume)
# Shift the zero frequency component to the start of the array # Shift the zero frequency component to the start of the array

查看文件

@@ -113,8 +113,8 @@ class GeometryView:
def set_filename(self): def set_filename(self):
"""Construct filename from user-supplied name and model run number.""" """Construct filename from user-supplied name and model run number."""
parts = config.model_configs[self.G.model_num].output_file_path.parts parts = config.get_model_config().output_file_path.parts
self.filename = Path(*parts[:-1], self.filename + config.model_configs[self.G.model_num].appendmodelnumber) self.filename = Path(*parts[:-1], self.filename + config.get_model_config().appendmodelnumber)
self.filename = self.filename.with_suffix(self.fileext) self.filename = self.filename.with_suffix(self.fileext)
def write_vtk(self, G, pbar): def write_vtk(self, G, pbar):
@@ -452,8 +452,8 @@ class GeometryViewFineMultiGrid:
def set_filename(self): def set_filename(self):
"""Construct filename from user-supplied name and model run number.""" """Construct filename from user-supplied name and model run number."""
parts = config.model_configs[self.G.model_num].output_file_path.parts parts = config.get_model_config().output_file_path.parts
self.filename = Path(*parts[:-1], self.filename + config.model_configs[self.G.model_num].appendmodelnumber) self.filename = Path(*parts[:-1], self.filename + config.get_model_config().appendmodelnumber)
self.filename = self.filename.with_suffix(self.fileext) self.filename = self.filename.with_suffix(self.fileext)
def write_vtk(self, *args): def write_vtk(self, *args):

查看文件

@@ -41,15 +41,9 @@ class FDTDGrid:
accessing regularly used parameters. accessing regularly used parameters.
""" """
def __init__(self, model_num): def __init__(self):
"""
Args:
model_num (int): Model number.
"""
self.title = '' self.title = ''
self.name = 'main_grid' self.name = 'main_grid'
self.model_num = model_num
self.nx = 0 self.nx = 0
self.ny = 0 self.ny = 0
@@ -170,26 +164,26 @@ class FDTDGrid:
def initialise_dispersive_arrays(self): def initialise_dispersive_arrays(self):
"""Initialise field arrays when there are dispersive materials present.""" """Initialise field arrays when there are dispersive materials present."""
self.Tx = np.zeros((config.model_configs[self.model_num].materials['maxpoles'], self.Tx = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.model_configs[self.model_num].materials['dispersivedtype']) self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.get_model_config().materials['dispersivedtype'])
self.Ty = np.zeros((config.model_configs[self.model_num].materials['maxpoles'], self.Ty = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.model_configs[self.model_num].materials['dispersivedtype']) self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.get_model_config().materials['dispersivedtype'])
self.Tz = np.zeros((config.model_configs[self.model_num].materials['maxpoles'], self.Tz = np.zeros((config.get_model_config().materials['maxpoles'],
self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.model_configs[self.model_num].materials['dispersivedtype']) self.nx + 1, self.ny + 1, self.nz + 1), dtype=config.get_model_config().materials['dispersivedtype'])
def initialise_dispersive_update_coeff_array(self): def initialise_dispersive_update_coeff_array(self):
"""Initialise array for storing update coefficients when there are dispersive """Initialise array for storing update coefficients when there are dispersive
materials present. materials present.
""" """
self.updatecoeffsdispersive = np.zeros((len(self.materials), 3 * self.updatecoeffsdispersive = np.zeros((len(self.materials), 3 *
config.model_configs[self.model_num].materials['maxpoles']), config.get_model_config().materials['maxpoles']),
dtype=config.model_configs[self.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
def reset_fields(self): def reset_fields(self):
"""Clear arrays for field components and PMLs.""" """Clear arrays for field components and PMLs."""
# Clear arrays for field components # Clear arrays for field components
self.initialise_field_arrays() self.initialise_field_arrays()
if config.model_configs[self.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
self.initialise_dispersive_arrays() self.initialise_dispersive_arrays()
# Clear arrays for fields in PML # Clear arrays for fields in PML
@@ -242,9 +236,9 @@ class FDTDGrid:
mem_use (int): Memory (bytes). mem_use (int): Memory (bytes).
""" """
mem_use = int(3 * config.model_configs[self.model_num].materials['maxpoles'] * mem_use = int(3 * config.get_model_config().materials['maxpoles'] *
(self.nx + 1) * (self.ny + 1) * (self.nz + 1) * (self.nx + 1) * (self.ny + 1) * (self.nz + 1) *
np.dtype(config.model_configs[self.model_num].materials['dispersivedtype']).itemsize) np.dtype(config.get_model_config().materials['dispersivedtype']).itemsize)
return mem_use return mem_use
def tmx(self): def tmx(self):
@@ -293,8 +287,7 @@ class FDTDGrid:
class CUDAGrid(FDTDGrid): class CUDAGrid(FDTDGrid):
"""Additional grid methods for solving on GPU using CUDA.""" """Additional grid methods for solving on GPU using CUDA."""
def __init__(self, model_num): def __init__(self):
super().__init__(model_num)
# Threads per block - used for main electric/magnetic field updates # Threads per block - used for main electric/magnetic field updates
self.tpb = (128, 1, 1) self.tpb = (128, 1, 1)
@@ -345,7 +338,7 @@ class CUDAGrid(FDTDGrid):
# Copy arrays geometry and field component arrays # Copy arrays geometry and field component arrays
self.htod_geometry_arrays() self.htod_geometry_arrays()
self.htod_field_arrays() self.htod_field_arrays()
if config.model_configs[self.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
self.htod_dispersive_arrays() self.htod_dispersive_arrays()
# Copy arrays for fields in PML # Copy arrays for fields in PML
@@ -404,7 +397,7 @@ def dispersion_analysis(G):
# Set maximum frequency to a threshold drop from maximum power, ignoring DC value # Set maximum frequency to a threshold drop from maximum power, ignoring DC value
try: try:
freqthres = np.where(power[freqmaxpower:] < -config.model_configs[G.model_num].numdispersion['highestfreqthres'])[0][0] + freqmaxpower freqthres = np.where(power[freqmaxpower:] < -config.get_model_config().numdispersion['highestfreqthres'])[0][0] + freqmaxpower
results['maxfreq'].append(freqs[freqthres]) results['maxfreq'].append(freqs[freqthres])
except ValueError: except ValueError:
results['error'] = 'unable to calculate maximum power from waveform, most likely due to undersampling.' results['error'] = 'unable to calculate maximum power from waveform, most likely due to undersampling.'
@@ -445,9 +438,9 @@ def dispersion_analysis(G):
minwavelength = minvelocity / results['maxfreq'] minwavelength = minvelocity / results['maxfreq']
# Maximum spatial step # Maximum spatial step
if '3D' in config.model_configs[G.model_num].mode: if '3D' in config.get_model_config().mode:
delta = max(G.dx, G.dy, G.dz) delta = max(G.dx, G.dy, G.dz)
elif '2D' in config.model_configs[G.model_num].mode: elif '2D' in config.get_model_config().mode:
if G.nx == 1: if G.nx == 1:
delta = max(G.dy, G.dz) delta = max(G.dy, G.dz)
elif G.ny == 1: elif G.ny == 1:
@@ -462,7 +455,7 @@ def dispersion_analysis(G):
results['N'] = minwavelength / delta results['N'] = minwavelength / delta
# Check grid sampling will result in physical wave propagation # Check grid sampling will result in physical wave propagation
if int(np.floor(results['N'])) >= config.model_configs[G.model_num].numdispersion['mingridsampling']: if int(np.floor(results['N'])) >= config.get_model_config().numdispersion['mingridsampling']:
# Numerical phase velocity # Numerical phase velocity
vp = np.pi / (results['N'] * np.arcsin((1 / S) * np.sin((np.pi * S) / results['N']))) vp = np.pi / (results['N'] * np.arcsin((1 / S) * np.sin((np.pi * S) / results['N'])))

查看文件

@@ -62,7 +62,7 @@ def process_python_include_code(inputfile, usernamespace):
# Process any Python code # Process any Python code
if(inputlines[x].startswith('#python:')): if(inputlines[x].startswith('#python:')):
log.warning('#python blocks are deprecated and will be removed in the next release of gprMax. Please convert your model to use our Python API instead.') log.warning('#python blocks are deprecated and will be removed in the next release of gprMax. Please convert your model to use our Python API instead.\n')
# String to hold Python code to be executed # String to hold Python code to be executed
pythoncode = '' pythoncode = ''
x += 1 x += 1
@@ -168,7 +168,7 @@ def write_processed_file(processedlines, G):
G (FDTDGrid): Parameters describing a grid in a model. G (FDTDGrid): Parameters describing a grid in a model.
""" """
parts = config.model_configs[G.model_num].output_file_path.parts parts = config.get_model_config().output_file_path.parts
processedfile = (Path(*parts[:-1], parts[-1] + '_processed.in')) processedfile = (Path(*parts[:-1], parts[-1] + '_processed.in'))
with open(processedfile, 'w') as f: with open(processedfile, 'w') as f:
@@ -295,7 +295,7 @@ def parse_hash_commands(scene, G):
with open(config.sim_config.input_file_path) as inputfile: with open(config.sim_config.input_file_path) as inputfile:
usernamespace = config.model_configs[G.model_num].get_usernamespace() usernamespace = config.get_model_config().get_usernamespace()
# Read input file and process any Python and include file commands # Read input file and process any Python and include file commands
processedlines = process_python_include_code(inputfile, usernamespace) processedlines = process_python_include_code(inputfile, usernamespace)

查看文件

@@ -131,18 +131,18 @@ class DispersiveMaterial(Material):
# The implementation of the dispersive material modelling comes from the # The implementation of the dispersive material modelling comes from the
# derivation in: http://dx.doi.org/10.1109/TAP.2014.2308549 # derivation in: http://dx.doi.org/10.1109/TAP.2014.2308549
self.w = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.w = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
self.q = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.q = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
self.zt = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.zt = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
self.zt2 = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.zt2 = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
self.eqt = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.eqt = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
self.eqt2 = np.zeros(config.model_configs[G.model_num].materials['maxpoles'], self.eqt2 = np.zeros(config.get_model_config().materials['maxpoles'],
dtype=config.model_configs[G.model_num].materials['dispersivedtype']) dtype=config.get_model_config().materials['dispersivedtype'])
for x in range(self.poles): for x in range(self.poles):
if 'debye' in self.type: if 'debye' in self.type:
@@ -223,7 +223,7 @@ def process_materials(G):
print a table. print a table.
""" """
if config.model_configs[G.model_num].materials['maxpoles'] == 0: if config.get_model_config().materials['maxpoles'] == 0:
materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]', materialsdata = [['\nID', '\nName', '\nType', '\neps_r', 'sigma\n[S/m]',
'\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']] '\nmu_r', 'sigma*\n[Ohm/m]', 'Dielectric\nsmoothable']]
else: else:
@@ -243,7 +243,7 @@ def process_materials(G):
# Add update coefficients to overall storage for dispersive materials # Add update coefficients to overall storage for dispersive materials
if hasattr(material, 'poles'): if hasattr(material, 'poles'):
z = 0 z = 0
for pole in range(config.model_configs[G.model_num].materials['maxpoles']): for pole in range(config.get_model_config().materials['maxpoles']):
G.updatecoeffsdispersive[material.numID, z:z + 3] = (config.sim_config.em_consts['e0'] * G.updatecoeffsdispersive[material.numID, z:z + 3] = (config.sim_config.em_consts['e0'] *
material.eqt2[pole], material.eqt[pole], material.zt[pole]) material.eqt2[pole], material.eqt[pole], material.zt[pole])
z += 3 z += 3
@@ -255,7 +255,7 @@ def process_materials(G):
materialtext.append(material.type) materialtext.append(material.type)
materialtext.append(f'{material.er:g}') materialtext.append(f'{material.er:g}')
materialtext.append(f'{material.se:g}') materialtext.append(f'{material.se:g}')
if config.model_configs[G.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
if 'debye' in material.type: if 'debye' in material.type:
materialtext.append('\n'.join('{:g}'.format(deltaer) for deltaer in material.deltaer)) materialtext.append('\n'.join('{:g}'.format(deltaer) for deltaer in material.deltaer))
materialtext.append('\n'.join('{:g}'.format(tau) for tau in material.tau)) materialtext.append('\n'.join('{:g}'.format(tau) for tau in material.tau))
@@ -367,8 +367,8 @@ class PeplinskiSoil:
m.type = 'debye' m.type = 'debye'
m.averagable = False m.averagable = False
m.poles = 1 m.poles = 1
if m.poles > config.model_configs[G.model_num].materials['maxpoles']: if m.poles > config.get_model_config().materials['maxpoles']:
config.model_configs[G.model_num].materials['maxpoles'] = m.poles config.get_model_config().materials['maxpoles'] = m.poles
m.er = eri m.er = eri
m.se = sig m.se = sig
m.deltaer.append(er - eri) m.deltaer.append(er - eri)

查看文件

@@ -35,7 +35,7 @@ import gprMax.config as config
from .cython.yee_cell_build import build_electric_components from .cython.yee_cell_build import build_electric_components
from .cython.yee_cell_build import build_magnetic_components from .cython.yee_cell_build import build_magnetic_components
from .exceptions import GeneralError from .exceptions import GeneralError
from .fields_outputs import write_hdf5_outputfile from .fields_outputs import write_hdf5_outputfiles
from .grid import dispersion_analysis from .grid import dispersion_analysis
from .hash_cmds_file import parse_hash_commands from .hash_cmds_file import parse_hash_commands
from .materials import Material from .materials import Material
@@ -65,7 +65,7 @@ class ModelBuildRun:
# used with threaded model building methods, e.g. fractals. Can be # used with threaded model building methods, e.g. fractals. Can be
# changed by #num_threads command in input file or via API later for # changed by #num_threads command in input file or via API later for
# use with CPU solver. # use with CPU solver.
config.model_configs[self.G.model_num].ompthreads = set_omp_threads(config.model_configs[self.G.model_num].ompthreads) config.get_model_config().ompthreads = set_omp_threads(config.get_model_config().ompthreads)
def build(self): def build(self):
"""Builds the Yee cells for a model.""" """Builds the Yee cells for a model."""
@@ -76,14 +76,14 @@ 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.model_configs[G.model_num].reuse_geometry else self.build_geometry() self.reuse_geometry() if config.get_model_config().reuse_geometry else self.build_geometry()
log.info(f'\nOutput directory: {config.model_configs[G.model_num].output_file_path.parent.resolve()}') log.info(f'\nOutput directory: {config.get_model_config().output_file_path.parent.resolve()}')
# Adjust position of simple sources and receivers if required # Adjust position of simple sources and receivers if required
if G.srcsteps[0] != 0 or G.srcsteps[1] != 0 or G.srcsteps[2] != 0: if G.srcsteps[0] != 0 or G.srcsteps[1] != 0 or G.srcsteps[2] != 0:
for source in itertools.chain(G.hertziandipoles, G.magneticdipoles): for source in itertools.chain(G.hertziandipoles, G.magneticdipoles):
if G.model_num == 0: if config.model_num == 0:
if (source.xcoord + G.srcsteps[0] * config.sim_config.model_end < 0 or if (source.xcoord + G.srcsteps[0] * config.sim_config.model_end < 0 or
source.xcoord + G.srcsteps[0] * config.sim_config.model_end > G.nx or source.xcoord + G.srcsteps[0] * config.sim_config.model_end > G.nx or
source.ycoord + G.srcsteps[1] * config.sim_config.model_end < 0 or source.ycoord + G.srcsteps[1] * config.sim_config.model_end < 0 or
@@ -91,12 +91,12 @@ class ModelBuildRun:
source.zcoord + G.srcsteps[2] * config.sim_config.model_end < 0 or source.zcoord + G.srcsteps[2] * config.sim_config.model_end < 0 or
source.zcoord + G.srcsteps[2] * config.sim_config.model_end > G.nz): source.zcoord + G.srcsteps[2] * config.sim_config.model_end > G.nz):
raise GeneralError('Source(s) will be stepped to a position outside the domain.') raise GeneralError('Source(s) will be stepped to a position outside the domain.')
source.xcoord = source.xcoordorigin + G.model_num * G.srcsteps[0] source.xcoord = source.xcoordorigin + config.model_num * G.srcsteps[0]
source.ycoord = source.ycoordorigin + G.model_num * G.srcsteps[1] source.ycoord = source.ycoordorigin + config.model_num * G.srcsteps[1]
source.zcoord = source.zcoordorigin + G.model_num * G.srcsteps[2] source.zcoord = source.zcoordorigin + config.model_num * G.srcsteps[2]
if G.rxsteps[0] != 0 or G.rxsteps[1] != 0 or G.rxsteps[2] != 0: if G.rxsteps[0] != 0 or G.rxsteps[1] != 0 or G.rxsteps[2] != 0:
for receiver in G.rxs: for receiver in G.rxs:
if G.model_num == 0: if config.model_num == 0:
if (receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end < 0 or if (receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end < 0 or
receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end > G.nx or receiver.xcoord + G.rxsteps[0] * config.sim_config.model_end > G.nx or
receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end < 0 or receiver.ycoord + G.rxsteps[1] * config.sim_config.model_end < 0 or
@@ -104,9 +104,9 @@ class ModelBuildRun:
receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end < 0 or receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end < 0 or
receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end > G.nz): receiver.zcoord + G.rxsteps[2] * config.sim_config.model_end > G.nz):
raise GeneralError('Receiver(s) will be stepped to a position outside the domain.') raise GeneralError('Receiver(s) will be stepped to a position outside the domain.')
receiver.xcoord = receiver.xcoordorigin + G.model_num * G.rxsteps[0] receiver.xcoord = receiver.xcoordorigin + config.model_num * G.rxsteps[0]
receiver.ycoord = receiver.ycoordorigin + G.model_num * G.rxsteps[1] receiver.ycoord = receiver.ycoordorigin + config.model_num * G.rxsteps[1]
receiver.zcoord = receiver.zcoordorigin + G.model_num * G.rxsteps[2] receiver.zcoord = receiver.zcoordorigin + config.model_num * G.rxsteps[2]
# Write files for any geometry views and geometry object outputs # Write files for any geometry views and geometry object outputs
if not (G.geometryviews or G.geometryobjectswrite) and config.sim_config.args.geometry_only: if not (G.geometryviews or G.geometryobjectswrite) and config.sim_config.args.geometry_only:
@@ -132,7 +132,7 @@ class ModelBuildRun:
def build_geometry(self): def build_geometry(self):
G = self.G G = self.G
log.info(config.model_configs[G.model_num].inputfilestr) log.info(config.get_model_config().inputfilestr)
scene = self.build_scene() scene = self.build_scene()
@@ -152,7 +152,7 @@ class ModelBuildRun:
gb.update_voltage_source_materials() gb.update_voltage_source_materials()
gb.grid.initialise_field_arrays() gb.grid.initialise_field_arrays()
gb.grid.initialise_std_update_coeff_arrays() gb.grid.initialise_std_update_coeff_arrays()
if config.model_configs[gb.grid.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
gb.grid.initialise_dispersive_arrays() gb.grid.initialise_dispersive_arrays()
gb.grid.initialise_dispersive_update_coeff_array() gb.grid.initialise_dispersive_update_coeff_array()
gb.build_materials() gb.build_materials()
@@ -161,10 +161,10 @@ class ModelBuildRun:
results = dispersion_analysis(gb.grid) results = dispersion_analysis(gb.grid)
if results['error']: if results['error']:
log.warning(Fore.RED + f"\nNumerical dispersion analysis ({gb.grid.name}) not carried out as {results['error']}" + Style.RESET_ALL) log.warning(Fore.RED + f"\nNumerical dispersion analysis ({gb.grid.name}) not carried out as {results['error']}" + Style.RESET_ALL)
elif results['N'] < config.model_configs[gb.grid.model_num].numdispersion['mingridsampling']: elif results['N'] < config.get_model_config().numdispersion['mingridsampling']:
raise GeneralError(f"\nNon-physical wave propagation in {gb.grid.name} detected. Material '{results['material'].ID}' has wavelength sampled by {results['N']} cells, less than required minimum for physical wave propagation. Maximum significant frequency estimated as {results['maxfreq']:g}Hz") raise GeneralError(f"\nNon-physical wave propagation in {gb.grid.name} detected. Material '{results['material'].ID}' has wavelength sampled by {results['N']} cells, less than required minimum for physical wave propagation. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
elif (results['deltavp'] and np.abs(results['deltavp']) > elif (results['deltavp'] and np.abs(results['deltavp']) >
config.model_configs[gb.grid.model_num].numdispersion['maxnumericaldisp']): config.get_model_config().numdispersion['maxnumericaldisp']):
log.warning(Fore.RED + f"\n{gb.grid.name} has potentially significant numerical dispersion. Estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz" + Style.RESET_ALL) log.warning(Fore.RED + f"\n{gb.grid.name} has potentially significant numerical dispersion. Estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz" + Style.RESET_ALL)
elif results['deltavp']: elif results['deltavp']:
log.info(f"\nNumerical dispersion analysis ({gb.grid.name}): estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz") log.info(f"\nNumerical dispersion analysis ({gb.grid.name}): estimated largest physical phase-velocity error is {results['deltavp']:.2f}% in material '{results['material'].ID}' whose wavelength sampled by {results['N']} cells. Maximum significant frequency estimated as {results['maxfreq']:g}Hz")
@@ -172,14 +172,14 @@ 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.model_configs[self.G.model_num].set_inputfilestr(f'\n--- Model {config.model_configs[self.G.model_num].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().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}')
log.info(config.model_configs[self.G.model_num].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()
def build_scene(self): def build_scene(self):
# API for multiple scenes / model runs # API for multiple scenes / model runs
scene = config.model_configs[self.G.model_num].get_scene() scene = config.get_model_config().get_scene()
# If there is no scene, process the hash commands # If there is no scene, process the hash commands
if not scene: if not scene:
@@ -197,14 +197,14 @@ class ModelBuildRun:
to file(s). to file(s).
""" """
# Write an output file in HDF5 format # Write an output file(s) in HDF5 format
write_hdf5_outputfile(config.model_configs[self.G.model_num].output_file_path_ext, self.G) write_hdf5_outputfiles(config.get_model_config().output_file_path_ext, self.G)
# Write any snapshots to file # Write any snapshots to file
if self.G.snapshots: if self.G.snapshots:
# Create directory for snapshots # Create directory for snapshots
config.model_configs[self.G.model_num].set_snapshots_file_path() config.get_model_config().set_snapshots_file_path()
snapshotdir = config.model_configs[self.G.model_num].snapshot_file_path snapshotdir = config.get_model_config().snapshot_file_path
snapshotdir.mkdir(exist_ok=True) snapshotdir.mkdir(exist_ok=True)
log.info('') log.info('')
@@ -244,16 +244,16 @@ class ModelBuildRun:
# Check number of OpenMP threads # Check number of OpenMP threads
if config.sim_config.general['cpu']: if config.sim_config.general['cpu']:
log.info(f'CPU (OpenMP) threads for solving: {config.model_configs[self.G.model_num].ompthreads}\n') log.info(f'CPU (OpenMP) threads for solving: {config.get_model_config().ompthreads}\n')
if config.model_configs[self.G.model_num].ompthreads > config.sim_config.hostinfo['physicalcores']: if config.get_model_config().ompthreads > config.sim_config.hostinfo['physicalcores']:
log.warning(Fore.RED + f"You have specified more threads ({config.model_configs[self.G.model_num].ompthreads}) than available physical CPU cores ({config.sim_config.hostinfo['physicalcores']}). This may lead to degraded performance." + Style.RESET_ALL) log.warning(Fore.RED + f"You have specified more threads ({config.get_model_config().ompthreads}) than available physical CPU cores ({config.sim_config.hostinfo['physicalcores']}). This may lead to degraded performance." + Style.RESET_ALL)
# Print information about any GPU in use # Print information about any GPU in use
elif config.sim_config.general['cuda']: elif config.sim_config.general['cuda']:
log.info(f"GPU for solving: {config.model_configs[self.G.model_num].cuda['gpu'].deviceID} - {config.model_configs[self.G.model_num].cuda['gpu'].name}\n") log.info(f"GPU for solving: {config.get_model_config().cuda['gpu'].deviceID} - {config.get_model_config().cuda['gpu'].name}\n")
# Prepare iterator # Prepare iterator
if config.sim_config.is_messages(): if config.sim_config.is_messages():
iterator = tqdm(range(self.G.iterations), desc=f'Running model {self.G.model_num + 1}/{config.sim_config.model_end}', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.sim_config.general['progressbars']) iterator = tqdm(range(self.G.iterations), desc=f'Running model {config.model_num + 1}/{config.sim_config.model_end}', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.sim_config.general['progressbars'])
else: else:
iterator = range(self.G.iterations) iterator = range(self.G.iterations)
@@ -298,11 +298,11 @@ class GridBuilder:
pbar.close() pbar.close()
def tm_grid_update(self): def tm_grid_update(self):
if '2D TMx' == config.model_configs[self.grid.model_num].mode: if '2D TMx' == config.get_model_config().mode:
self.grid.tmx() self.grid.tmx()
elif '2D TMy' == config.model_configs[self.grid.model_num].mode: elif '2D TMy' == config.get_model_config().mode:
self.grid.tmy() self.grid.tmy()
elif '2D TMz' == config.model_configs[self.grid.model_num].mode: elif '2D TMz' == config.get_model_config().mode:
self.grid.tmz() self.grid.tmz()
def update_voltage_source_materials(self): def update_voltage_source_materials(self):

查看文件

@@ -24,22 +24,17 @@ from .updates import CPUUpdates
from .updates import CUDAUpdates from .updates import CUDAUpdates
def create_G(model_num): def create_G():
"""Create grid object according to solver. """Create grid object according to solver.
Args:
model_num (int): Model number.
Returns: Returns:
G (FDTDGrid): Holds essential parameters describing the model. G (FDTDGrid): Holds essential parameters describing the model.
""" """
if config.sim_config.general['cpu']: if config.sim_config.general['cpu']:
G = FDTDGrid(model_num) G = FDTDGrid()
elif config.sim_config.general['cuda']: elif config.sim_config.general['cuda']:
G = CUDAGrid(model_num) G = CUDAGrid()
elif config.sim_config.subgrid:
G = FDTDGrid(model_num)
return G return G
@@ -54,15 +49,7 @@ def create_solver(G):
solver (Solver): solver object. solver (Solver): solver object.
""" """
if config.sim_config.general['cpu']: if config.sim_config.general['subgrid']:
updates = CPUUpdates(G)
solver = Solver(updates)
props = updates.adapt_dispersive_config()
updates.set_dispersive_updates(props)
elif config.sim_config.general['cuda']:
updates = CUDAUpdates(G)
solver = Solver(updates)
elif config.sim_config.subgrid:
updates = create_subgrid_updates(G) updates = create_subgrid_updates(G)
solver = Solver(updates, hsg=True) solver = Solver(updates, hsg=True)
# A large range of different functions exist to advance the time step for # A large range of different functions exist to advance the time step for
@@ -70,6 +57,15 @@ def create_solver(G):
# the required numerical precision and dispersive material type. # the required numerical precision and dispersive material type.
props = updates.adapt_dispersive_config() props = updates.adapt_dispersive_config()
updates.set_dispersive_updates(props) updates.set_dispersive_updates(props)
elif config.sim_config.general['cpu']:
updates = CPUUpdates(G)
solver = Solver(updates)
props = updates.adapt_dispersive_config()
updates.set_dispersive_updates(props)
elif config.sim_config.general['cuda']:
updates = CUDAUpdates(G)
solver = Solver(updates)
return solver return solver

查看文件

@@ -19,6 +19,7 @@
from colorama import init, Fore, Style from colorama import init, Fore, Style
init() init()
import gprMax.config as config
from .base import SubGridBase 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
@@ -45,16 +46,16 @@ class SubGridHSG(SubGridBase):
# 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, self.nthreads) 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 + 1, self.nwy, self.nwz, 1, self.Hx, precursors.ey_bottom, precursors.ey_top, self.IDlookup['Hx'], -1, 1, 3, self.nthreads) 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)
# 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, self.nthreads) 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 + 1, self.nwz, self.nwx, 2, self.Hy, precursors.ez_left, precursors.ez_right, self.IDlookup['Hy'], -1, 1, 1, self.nthreads) 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)
# 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, self.nthreads) 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 + 1, self.nwz, self.nwy, 3, self.Hx, precursors.ez_front, precursors.ez_back, self.IDlookup['Hx'], 1, -1, 2, self.nthreads) 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)
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
@@ -64,16 +65,16 @@ 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, self.nthreads) 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 + 1, self.nwy, self.nwz, 1, self.Ey, precursors.hx_bottom, precursors.hx_top, self.IDlookup['Ey'], -1, 1, 3, self.nthreads) 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)
# 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, self.nthreads) 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 + 1, self.nwz, self.nwx, 2, self.Ez, precursors.hy_left, precursors.hy_right, self.IDlookup['Ez'], -1, 1, 1, self.nthreads) 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)
# 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, self.nthreads) 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 + 1, self.nwz, self.nwy, 3, self.Ez, precursors.hx_front, precursors.hx_back, self.IDlookup['Ez'], 1, -1, 2, self.nthreads) 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)
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
@@ -90,16 +91,16 @@ 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
# 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
# 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
def update_magnetic_os(self, main_grid): def update_magnetic_os(self, main_grid):
@@ -118,16 +119,16 @@ 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
# 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
# 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, main_grid.nthreads) 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 + 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, main_grid.nthreads) 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)
def __str__(self): def __str__(self):
@@ -141,7 +142,7 @@ class SubGridHSG(SubGridBase):
s += f'dt: {self.dt}s\n' s += f'dt: {self.dt}s\n'
s += f'Memory Estimate: {human_size(mem_use)}\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.io}, {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'
s += f'Working Region Cells: {self.nwx} {self.nwy} {self.nwz}\n' s += f'Working Region Cells: {self.nwx} {self.nwy} {self.nwz}\n'

查看文件

@@ -127,7 +127,7 @@ class SubgridUpdater(CPUUpdates):
"""This is the first half of the subgrid update. Takes the time step """This is the first half of the subgrid update. Takes the time step
up to the main grid electric update. up to the main grid electric update.
""" """
G = self.G G = self.G
sub_grid = self.grid sub_grid = self.grid
precursors = self.precursors precursors = self.precursors

查看文件

@@ -101,7 +101,7 @@ class CPUUpdates:
def update_electric_a(self): def update_electric_a(self):
"""Update electric field components.""" """Update electric field components."""
# All materials are non-dispersive so do standard update. # All materials are non-dispersive so do standard update.
if config.model_configs[self.grid.model_num].materials['maxpoles'] == 0: if config.get_model_config().materials['maxpoles'] == 0:
update_electric_cpu(self.grid.nx, update_electric_cpu(self.grid.nx,
self.grid.ny, self.grid.ny,
self.grid.nz, self.grid.nz,
@@ -122,7 +122,7 @@ class CPUUpdates:
self.grid.ny, self.grid.ny,
self.grid.nz, self.grid.nz,
config.sim_config.hostinfo['ompthreads'], config.sim_config.hostinfo['ompthreads'],
config.model_configs[self.grid.model_num].materials['maxpoles'], config.get_model_config().materials['maxpoles'],
self.grid.updatecoeffsE, self.grid.updatecoeffsE,
self.grid.updatecoeffsdispersive, self.grid.updatecoeffsdispersive,
self.grid.ID, self.grid.ID,
@@ -162,12 +162,12 @@ class CPUUpdates:
updated after the electric field has been updated by the PML and updated after the electric field has been updated by the PML and
source updates. source updates.
""" """
if config.model_configs[self.grid.model_num].materials['maxpoles'] != 0: if config.get_model_config().materials['maxpoles'] != 0:
self.dispersive_update_b(self.grid.nx, self.dispersive_update_b(self.grid.nx,
self.grid.ny, self.grid.ny,
self.grid.nz, self.grid.nz,
config.sim_config.hostinfo['ompthreads'], config.sim_config.hostinfo['ompthreads'],
config.model_configs[self.grid.model_num].materials['maxpoles'], config.get_model_config().materials['maxpoles'],
self.grid.updatecoeffsdispersive, self.grid.updatecoeffsdispersive,
self.grid.ID, self.grid.ID,
self.grid.Tx, self.grid.Tx,
@@ -183,7 +183,7 @@ class CPUUpdates:
Returns: Returns:
props (Props): Dispersive material properties. props (Props): Dispersive material properties.
""" """
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 1: if config.get_model_config().materials['maxpoles'] > 1:
poles = 'multi' poles = 'multi'
else: else:
poles = '1' poles = '1'
@@ -193,7 +193,7 @@ class CPUUpdates:
else: else:
type = 'double' type = 'double'
if config.model_configs[self.grid.model_num].materials['dispersivedtype'] == config.sim_config.dtypes['complex']: if config.get_model_config().materials['dispersivedtype'] == config.sim_config.dtypes['complex']:
dispersion = 'complex' dispersion = 'complex'
else: else:
dispersion = 'real' dispersion = 'real'
@@ -258,7 +258,7 @@ class CUDAUpdates:
self.drv.init() self.drv.init()
# Create device handle and context on specifc GPU device (and make it current context) # Create device handle and context on specifc GPU device (and make it current context)
self.dev = self.drv.Device(config.model_configs[self.grid.model_num].cuda['gpu'].deviceID) self.dev = self.drv.Device(config.get_model_config().cuda['gpu'].deviceID)
self.ctx = self.dev.make_context() self.ctx = self.dev.make_context()
# Initialise arrays on GPU, prepare kernels, and get kernel functions # Initialise arrays on GPU, prepare kernels, and get kernel functions
@@ -276,7 +276,7 @@ class CUDAUpdates:
"""Electric and magnetic field updates - prepare kernels, and """Electric and magnetic field updates - prepare kernels, and
get kernel functions. get kernel functions.
""" """
if config.model_configs[self.grid.model_num].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'], COMPLEX=config.sim_config.dtypes['C_complex'],
@@ -320,7 +320,7 @@ class CUDAUpdates:
# - get kernel functions and initialise array on GPU # - get kernel functions and initialise array on GPU
# If there are any dispersive materials (updates are split into two # If there are any dispersive materials (updates are split into two
# parts as they require present and updated electric field values). # parts as they require present and updated electric field values).
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
self.dispersive_update_a = kernels_fields.get_function("update_electric_dispersive_A") self.dispersive_update_a = kernels_fields.get_function("update_electric_dispersive_A")
self.dispersive_update_b = kernels_fields.get_function("update_electric_dispersive_B") self.dispersive_update_b = kernels_fields.get_function("update_electric_dispersive_B")
@@ -329,7 +329,7 @@ class CUDAUpdates:
self.grid.set_blocks_per_grid() self.grid.set_blocks_per_grid()
self.grid.htod_geometry_arrays() self.grid.htod_geometry_arrays()
self.grid.htod_field_arrays() self.grid.htod_field_arrays()
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
self.grid.htod_dispersive_arrays() self.grid.htod_dispersive_arrays()
def _set_pml_kernels(self): def _set_pml_kernels(self):
@@ -445,8 +445,8 @@ class CUDAUpdates:
# Check if coefficient arrays will fit on constant memory of GPU # Check if coefficient arrays will fit on constant memory of GPU
if (self.grid.updatecoeffsE.nbytes + self.grid.updatecoeffsH.nbytes if (self.grid.updatecoeffsE.nbytes + self.grid.updatecoeffsH.nbytes
> config.model_configs[self.grid.model_num].cuda['gpu'].constmem): > config.get_model_config().cuda['gpu'].constmem):
raise GeneralError(f"Too many materials in the model to fit onto constant memory of size {human_size(config.model_configs[self.grid.model_num].cuda['gpu'].constmem)} on {config.model_configs[self.grid.model_num].cuda['gpu'].deviceID} - {config.model_configs[self.grid.model_num].cuda['gpu'].name} GPU") raise GeneralError(f"Too many materials in the model to fit onto constant memory of size {human_size(config.get_model_config().cuda['gpu'].constmem)} on {config.get_model_config().cuda['gpu'].deviceID} - {config.get_model_config().cuda['gpu'].name} GPU")
updatecoeffsE = kernelE.get_global('updatecoeffsE')[0] updatecoeffsE = kernelE.get_global('updatecoeffsE')[0]
updatecoeffsH = kernelH.get_global('updatecoeffsH')[0] updatecoeffsH = kernelH.get_global('updatecoeffsH')[0]
@@ -478,7 +478,7 @@ class CUDAUpdates:
for i, snap in enumerate(self.grid.snapshots): for i, snap in enumerate(self.grid.snapshots):
if snap.time == iteration + 1: if snap.time == iteration + 1:
snapno = 0 if config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu'] else i snapno = 0 if config.get_model_config().cuda['snapsgpu2cpu'] else i
self.store_snapshot_gpu(np.int32(snapno), self.store_snapshot_gpu(np.int32(snapno),
np.int32(snap.xs), np.int32(snap.xs),
np.int32(snap.xf), np.int32(snap.xf),
@@ -503,7 +503,7 @@ class CUDAUpdates:
self.snapHz_gpu.gpudata, self.snapHz_gpu.gpudata,
block=Snapshot.tpb, block=Snapshot.tpb,
grid=Snapshot.bpg) grid=Snapshot.bpg)
if config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu']: if config.get_model_config().cuda['snapsgpu2cpu']:
dtoh_snapshot_array(self.grid.snapEx_gpu.get(), dtoh_snapshot_array(self.grid.snapEx_gpu.get(),
self.grid.snapEy_gpu.get(), self.grid.snapEy_gpu.get(),
self.grid.snapEz_gpu.get(), self.grid.snapEz_gpu.get(),
@@ -553,7 +553,7 @@ class CUDAUpdates:
def update_electric_a(self): def update_electric_a(self):
"""Update electric field components.""" """Update electric field components."""
# All materials are non-dispersive so do standard update. # All materials are non-dispersive so do standard update.
if config.model_configs[self.grid.model_num].materials['maxpoles'] == 0: if config.get_model_config().materials['maxpoles'] == 0:
self.update_electric_gpu(np.int32(self.grid.nx), self.update_electric_gpu(np.int32(self.grid.nx),
np.int32(self.grid.ny), np.int32(self.grid.ny),
np.int32(self.grid.nz), np.int32(self.grid.nz),
@@ -573,7 +573,7 @@ class CUDAUpdates:
self.dispersive_update_a(np.int32(self.grid.nx), self.dispersive_update_a(np.int32(self.grid.nx),
np.int32(self.grid.ny), np.int32(self.grid.ny),
np.int32(self.grid.nz), np.int32(self.grid.nz),
np.int32(config.model_configs[self.grid.model_num].materials['maxpoles']), np.int32(config.get_model_config().materials['maxpoles']),
self.grid.updatecoeffsdispersive_gpu.gpudata, self.grid.updatecoeffsdispersive_gpu.gpudata,
self.grid.Tx_gpu.gpudata, self.grid.Tx_gpu.gpudata,
self.grid.Ty_gpu.gpudata, self.grid.Ty_gpu.gpudata,
@@ -638,11 +638,11 @@ class CUDAUpdates:
updated after the electric field has been updated by the PML and updated after the electric field has been updated by the PML and
source updates. source updates.
""" """
if config.model_configs[self.grid.model_num].materials['maxpoles'] > 0: if config.get_model_config().materials['maxpoles'] > 0:
self.dispersive_update_b(np.int32(self.grid.nx), self.dispersive_update_b(np.int32(self.grid.nx),
np.int32(self.grid.ny), np.int32(self.grid.ny),
np.int32(self.grid.nz), np.int32(self.grid.nz),
np.int32(config.model_configs[self.grid.model_num].materials['maxpoles']), np.int32(config.get_model_config().materials['maxpoles']),
self.grid.updatecoeffsdispersive_gpu.gpudata, self.grid.updatecoeffsdispersive_gpu.gpudata,
self.grid.Tx_gpu.gpudata, self.grid.Tx_gpu.gpudata,
self.grid.Ty_gpu.gpudata, self.grid.Ty_gpu.gpudata,
@@ -690,7 +690,7 @@ class CUDAUpdates:
self.grid) self.grid)
# Copy data from any snapshots back to correct snapshot objects # Copy data from any snapshots back to correct snapshot objects
if self.grid.snapshots and not config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu']: if self.grid.snapshots and not config.get_model_config().cuda['snapsgpu2cpu']:
for i, snap in enumerate(self.grid.snapshots): for i, snap in enumerate(self.grid.snapshots):
dtoh_snapshot_arra(self.snapEx_gpu.get(), dtoh_snapshot_arra(self.snapEx_gpu.get(),
self.snapEy_gpu.get(), self.snapEy_gpu.get(),

查看文件

@@ -296,12 +296,12 @@ def get_host_info():
# CPU information # CPU information
try: try:
cpuIDinfo = subprocess.check_output("cat /proc/cpuinfo", shell=True, stderr=subprocess.STDOUT).decode('utf-8').strip() # Locale to ensure English
myenv = {**os.environ, 'LANG': 'en_US.utf8'}
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()
# Run lscpu with English locale
myenv = {**os.environ, 'LANG': 'en_US.utf8'}
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:
@@ -393,22 +393,21 @@ def mem_check_host(mem):
raise GeneralError(f"Memory (RAM) required ~{human_size(mem)} exceeds {human_size(config.sim_config.hostinfo['ram'], a_kilobyte_is_1024_bytes=True)} detected!\n") raise GeneralError(f"Memory (RAM) required ~{human_size(mem)} exceeds {human_size(config.sim_config.hostinfo['ram'], a_kilobyte_is_1024_bytes=True)} detected!\n")
def mem_check_gpu_snaps(model_num, total_mem, snaps_mem): def mem_check_gpu_snaps(total_mem, snaps_mem):
"""Check if the required amount of memory (RAM) for all snapshots can fit """Check if the required amount of memory (RAM) for all snapshots can fit
on specified GPU. on specified GPU.
Args: Args:
model_num (int): Model number.
total_mem (int): Total memory required for model (bytes). total_mem (int): Total memory required for model (bytes).
snaps_mem (int): Memory required for all snapshots (bytes). snaps_mem (int): Memory required for all snapshots (bytes).
""" """
if total_mem - snaps_mem > config.model_configs[model_num].cuda['gpu'].totalmem: if total_mem - snaps_mem > config.get_model_config().cuda['gpu'].totalmem:
raise GeneralError(f"Memory (RAM) required ~{human_size(total_mem)} exceeds {human_size(config.model_configs[model_num].cuda['gpu'].totalmem, a_kilobyte_is_1024_bytes=True)} detected on specified {config.model_configs[model_num].cuda['gpu'].deviceID} - {config.model_configs[model_num].cuda['gpu'].name} GPU!\n") raise GeneralError(f"Memory (RAM) required ~{human_size(total_mem)} exceeds {human_size(config.get_model_config().cuda['gpu'].totalmem, a_kilobyte_is_1024_bytes=True)} detected on specified {config.get_model_config().cuda['gpu'].deviceID} - {config.get_model_config().cuda['gpu'].name} GPU!\n")
# If the required memory without the snapshots will fit on the GPU then # If the required memory without the snapshots will fit on the GPU then
# transfer and store snaphots on host # transfer and store snaphots on host
if snaps_mem != 0 and total_mem - snaps_mem < config.model_configs[model_num].cuda['gpu'].totalmem: if snaps_mem != 0 and total_mem - snaps_mem < config.get_model_config().cuda['gpu'].totalmem:
config.model_configs[model_num].cuda['snapsgpu2cpu'] = True config.get_model_config().cuda['snapsgpu2cpu'] = True
def mem_check_all(grids): def mem_check_all(grids):
@@ -427,36 +426,36 @@ def mem_check_all(grids):
total_snaps_mem = 0 total_snaps_mem = 0
for grid in grids: for grid in grids:
config.model_configs[grid.model_num].mem_use += grid.mem_est_basic() config.get_model_config().mem_use += grid.mem_est_basic()
# Set datatype for dispersive arrays if there are any dispersive materials. # Set datatype for dispersive arrays if there are any dispersive materials.
if config.model_configs[grid.model_num].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]) drudelorentz = any([m for m in grid.materials if 'drude' in m.type or 'lorentz' in m.type])
if drudelorentz: if drudelorentz:
config.model_configs[grid.model_num].materials['dispersivedtype'] = config.sim_config.dtypes['complex'] config.get_model_config().materials['dispersivedtype'] = config.sim_config.dtypes['complex']
config.model_configs[grid.model_num].materials['dispersiveCdtype'] = config.sim_config.dtypes['C_complex'] config.get_model_config().materials['dispersiveCdtype'] = config.sim_config.dtypes['C_complex']
else: else:
config.model_configs[grid.model_num].materials['dispersivedtype'] = config.sim_config.dtypes['float_or_double'] config.get_model_config().materials['dispersivedtype'] = config.sim_config.dtypes['float_or_double']
config.model_configs[grid.model_num].materials['dispersiveCdtype'] = config.sim_config.dtypes['C_float_or_double'] config.get_model_config().materials['dispersiveCdtype'] = config.sim_config.dtypes['C_float_or_double']
# Update estimated memory (RAM) usage # Update estimated memory (RAM) usage
config.model_configs[grid.model_num].mem_use += grid.mem_est_dispersive() config.get_model_config().mem_use += grid.mem_est_dispersive()
# Calculate snapshot memory # Calculate snapshot memory
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.model_configs[grid.model_num].mem_use += int(2 * snap.datasizefield) config.get_model_config().mem_use += int(2 * snap.datasizefield)
total_snaps_mem += int(2 * snap.datasizefield) total_snaps_mem += int(2 * snap.datasizefield)
total_mem += config.model_configs[grid.model_num].mem_use 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 config.sim_config.general['cuda']:
mem_check_gpu_snaps(grid.model_num, total_mem, total_snaps_mem) mem_check_gpu_snaps(total_mem, total_snaps_mem)
return total_mem return total_mem

查看文件

@@ -123,8 +123,8 @@ with open('README.rst','r') as fd:
long_description = fd.read() long_description = fd.read()
# Python version # Python version
if sys.version_info[:2] < (3, 6): if sys.version_info[:2] < (3, 7):
sys.exit('\nExited: Requires Python 3.6 or newer!\n') sys.exit('\nExited: Requires Python 3.7 or newer!\n')
# Process 'build' command line argument # Process 'build' command line argument
if 'build' in sys.argv: if 'build' in sys.argv: