diff --git a/gprMax/model_build_run.py b/gprMax/model_build_run.py index 6197785e..ef5b29ab 100644 --- a/gprMax/model_build_run.py +++ b/gprMax/model_build_run.py @@ -54,7 +54,8 @@ from .materials import Material from .materials import process_materials from .pml import CFS from .pml import PML -from .pml import build_pmls +from .pml import build_pml +from .pml import pml_information from .receivers import gpu_initialise_rx_arrays from .receivers import gpu_get_rx_array from .receivers import Rx @@ -96,45 +97,29 @@ def run_model(solver, sim_config, model_config): G = solver.G - # Estimate and check memory (RAM) usage - G.memory_estimate_basic() - G.memory_check() - if sim_config.general['messages']: - print(G.memory_message) + # api for multiple scenes / model runs + try: + scene = model_config.scene + # process using hashcommands + except AttributeError: + scene = Scene() + # parse the input file into user objects and add them to the scene + scene = parse_hash_commands(args, usernamespace, appendmodelnumber, G, scene) - # Initialise an array for volumetric material IDs (solid), boolean - # arrays for specifying materials not to be averaged (rigid), - # an array for cell edge IDs (ID) - G.initialise_geometry_arrays() + # Creates the internal simulation objects. + scene.create_internal_objects(G) - # Initialise arrays for the field components - G.initialise_field_arrays() - - # Build the PMLs and calculate initial coefficients - - # print stuff about PML + # print PML information if config.general['messages']: - # no pml - if all(value == 0 for value in G.pmlthickness.values()): - print('PML: switched off') + print(pml_information(G)) - if all(value == G.pmlthickness['x0'] for value in G.pmlthickness.values()): - pmlinfo = str(G.pmlthickness['x0']) - else: - pmlinfo = '' - for key, value in G.pmlthickness.items(): - pmlinfo += '{}: {}, '.format(key, value) - pmlinfo = pmlinfo[:-2] + ' cells' - print('PML: formulation: {}, order: {}, thickness: {}'.format(G.pmlformulation, len(G.cfs), pmlinfo)) + # build the PMLS + pbar = tqdm(total=sum(1 for value in G.pmlthickness.values() if value > 0), desc='Building PML boundaries', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars']) - # build the PMLS - pbar = tqdm(total=sum(1 for value in G.pmlthickness.values() if value > 0), desc='Building PML boundaries', ncols=get_terminal_width() - 1, file=sys.stdout, disable=not config.general['progressbars']) - - for pml_id, thickness in G.pmlthickness.items(): - build_pml(G, pml_id, thickness) - pbar.update() - - pbar.close() + for pml_id, thickness in G.pmlthickness.items(): + build_pml(G, pml_id, thickness) + pbar.update() + pbar.close() # Build the model, i.e. set the material properties (ID) for every edge # of every Yee cell @@ -225,6 +210,8 @@ def run_model(solver, sim_config, model_config): elif results['deltavp'] and config.general['messages']: print("\nNumerical dispersion analysis: estimated largest physical phase-velocity error is {:.2f}% in material '{}' whose wavelength sampled by {} cells. Maximum significant frequency estimated as {:g}Hz".format(results['deltavp'], results['material'].ID, results['N'], results['maxfreq'])) + disp_a = update_f.format(model_config.poles, 'A', model_config.precision, model_config.dispersion_type) + # set the dispersive update functions based on the model configuration solver.updates.set_dispersive_updates(model_config) diff --git a/gprMax/pml.py b/gprMax/pml.py index 59547254..486935ed 100644 --- a/gprMax/pml.py +++ b/gprMax/pml.py @@ -431,8 +431,21 @@ class PML(object): config.dtypes['float_or_double'](self.d), block=config.cuda['gpus'].tpb, grid=config.cuda['gpus'].bpg) +def pml_information(G): + # no pml + if all(value == 0 for value in G.pmlthickness.values()): + return 'PML: switched off' -def build_pmls(G, pbar): + if all(value == G.pmlthickness['x0'] for value in G.pmlthickness.values()): + pmlinfo = str(G.pmlthickness['x0']) + else: + pmlinfo = '' + for key, value in G.pmlthickness.items(): + pmlinfo += '{}: {}, '.format(key, value) + pmlinfo = pmlinfo[:-2] + ' cells' + return 'PML: formulation: {}, order: {}, thickness: {}'.format(G.pmlformulation, len(G.cfs), pmlinfo)) + +def build_pml(G, key, thickness): """This function builds instances of the PML and calculates the initial parameters and coefficients including setting profile (based on underlying material er and mr from solid array). @@ -440,58 +453,54 @@ def build_pmls(G, pbar): Args: G (class): Grid class instance - holds essential parameters describing the model. - pbar (class): Progress bar class instance. """ + if value > 0: + sumer = 0 # Sum of relative permittivities in PML slab + summr = 0 # Sum of relative permeabilities in PML slab - for key, value in G.pmlthickness.items(): - if value > 0: - sumer = 0 # Sum of relative permittivities in PML slab - summr = 0 # Sum of relative permeabilities in PML slab + if key[0] == 'x': + if key == 'x0': + pml = PML(G, ID=key, direction='xminus', xf=value, yf=G.ny, zf=G.nz) + elif key == 'xmax': + pml = PML(G, ID=key, direction='xplus', xs=G.nx - value, xf=G.nx, yf=G.ny, zf=G.nz) + G.pmls.append(pml) + for j in range(G.ny): + for k in range(G.nz): + numID = G.solid[pml.xs, j, k] + material = next(x for x in G.materials if x.numID == numID) + sumer += material.er + summr += material.mr + averageer = sumer / (G.ny * G.nz) + averagemr = summr / (G.ny * G.nz) - if key[0] == 'x': - if key == 'x0': - pml = PML(G, ID=key, direction='xminus', xf=value, yf=G.ny, zf=G.nz) - elif key == 'xmax': - pml = PML(G, ID=key, direction='xplus', xs=G.nx - value, xf=G.nx, yf=G.ny, zf=G.nz) - G.pmls.append(pml) + elif key[0] == 'y': + if key == 'y0': + pml = PML(G, ID=key, direction='yminus', yf=value, xf=G.nx, zf=G.nz) + elif key == 'ymax': + pml = PML(G, ID=key, direction='yplus', ys=G.ny - value, xf=G.nx, yf=G.ny, zf=G.nz) + G.pmls.append(pml) + for i in range(G.nx): + for k in range(G.nz): + numID = G.solid[i, pml.ys, k] + material = next(x for x in G.materials if x.numID == numID) + sumer += material.er + summr += material.mr + averageer = sumer / (G.nx * G.nz) + averagemr = summr / (G.nx * G.nz) + + elif key[0] == 'z': + if key == 'z0': + pml = PML(G, ID=key, direction='zminus', zf=value, xf=G.nx, yf=G.ny) + elif key == 'zmax': + pml = PML(G, ID=key, direction='zplus', zs=G.nz - value, xf=G.nx, yf=G.ny, zf=G.nz) + G.pmls.append(pml) + for i in range(G.nx): for j in range(G.ny): - for k in range(G.nz): - numID = G.solid[pml.xs, j, k] - material = next(x for x in G.materials if x.numID == numID) - sumer += material.er - summr += material.mr - averageer = sumer / (G.ny * G.nz) - averagemr = summr / (G.ny * G.nz) + numID = G.solid[i, j, pml.zs] + material = next(x for x in G.materials if x.numID == numID) + sumer += material.er + summr += material.mr + averageer = sumer / (G.nx * G.ny) + averagemr = summr / (G.nx * G.ny) - elif key[0] == 'y': - if key == 'y0': - pml = PML(G, ID=key, direction='yminus', yf=value, xf=G.nx, zf=G.nz) - elif key == 'ymax': - pml = PML(G, ID=key, direction='yplus', ys=G.ny - value, xf=G.nx, yf=G.ny, zf=G.nz) - G.pmls.append(pml) - for i in range(G.nx): - for k in range(G.nz): - numID = G.solid[i, pml.ys, k] - material = next(x for x in G.materials if x.numID == numID) - sumer += material.er - summr += material.mr - averageer = sumer / (G.nx * G.nz) - averagemr = summr / (G.nx * G.nz) - - elif key[0] == 'z': - if key == 'z0': - pml = PML(G, ID=key, direction='zminus', zf=value, xf=G.nx, yf=G.ny) - elif key == 'zmax': - pml = PML(G, ID=key, direction='zplus', zs=G.nz - value, xf=G.nx, yf=G.ny, zf=G.nz) - G.pmls.append(pml) - for i in range(G.nx): - for j in range(G.ny): - numID = G.solid[i, j, pml.zs] - material = next(x for x in G.materials if x.numID == numID) - sumer += material.er - summr += material.mr - averageer = sumer / (G.nx * G.ny) - averagemr = summr / (G.nx * G.ny) - - pml.calculate_update_coeffs(averageer, averagemr, G) - pbar.update() + pml.calculate_update_coeffs(averageer, averagemr, G)