diff --git a/gprMax/hash_cmds_file.py b/gprMax/hash_cmds_file.py index 27487a5b..3ed0d650 100644 --- a/gprMax/hash_cmds_file.py +++ b/gprMax/hash_cmds_file.py @@ -200,7 +200,7 @@ def check_cmd_names(processedlines, checkessential=True): singlecmds = dict.fromkeys(['#domain', '#dx_dy_dz', '#time_window', '#title', '#messages', '#num_threads', '#time_step_stability_factor', '#pml_formulation', '#pml_cells', '#excitation_file', '#src_steps', '#rx_steps', '#output_dir'], None) # Commands that there can be multiple instances of in a model - these will be lists within the dictionary - multiplecmds = {key: [] for key in ['#geometry_view', '#geometry_objects_write', '#material', '#soil_peplinski', '#add_dispersion_debye', '#add_dispersion_lorentz', '#add_dispersion_drude', '#waveform', '#voltage_source', '#hertzian_dipole', '#magnetic_dipole', '#transmission_line', '#rx', '#rx_array', '#snapshot', '#pml_cfs', '#include_file']} + multiplecmds = {key: [] for key in ['#geometry_view', '#geometry_objects_write', '#material', '#soil_peplinski', '#add_dispersion_debye', '#add_dispersion_lorentz', '#add_dispersion_drude', '#waveform', '#voltage_source', '#hertzian_dipole', '#magnetic_dipole', '#transmission_line', '#rx', '#rx_array', '#snapshot', '#include_file']} # Geometry object building commands that there can be multiple instances # of in a model - these will be lists within the dictionary diff --git a/gprMax/hash_cmds_multiuse.py b/gprMax/hash_cmds_multiuse.py index 527cc9e7..94679929 100644 --- a/gprMax/hash_cmds_multiuse.py +++ b/gprMax/hash_cmds_multiuse.py @@ -280,28 +280,4 @@ def process_multicmds(multicmds): gow = GeometryObjectsWrite(p1=p1, p2=p2, filename=tmp[6]) scene_objects.append(gow) - cmdname = '#pml_cfs' - if multicmds[cmdname] is not None: - if len(multicmds[cmdname]) > 2: - raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' can only be used up to two times, for up to a 2nd order PML') - for cmdinstance in multicmds[cmdname]: - tmp = cmdinstance.split() - if len(tmp) != 12: - raise CmdInputError("'" + cmdname + ': ' + ' '.join(tmp) + "'" + ' requires exactly twelve parameters') - - pml_cfs = PMLCFS(alphascalingprofile=tmp[0], - alphascalingdirection=tmp[1], - alphamin=tmp[2], - alphamax=tmp[3], - kappascalingprofile=tmp[4], - kappascalingdirection=tmp[5], - kappamin=tmp[6], - kappamax=tmp[7], - sigmascalingprofile=tmp[8], - sigmascalingdirection=tmp[9], - sigmamin=tmp[10], - sigmamax=tmp[11]) - - scene_objects.append(pml_cfs) - return scene_objects diff --git a/gprMax/model_build_run.py b/gprMax/model_build_run.py index 2bde60a4..b9a5a147 100644 --- a/gprMax/model_build_run.py +++ b/gprMax/model_build_run.py @@ -103,7 +103,7 @@ class ModelBuildRun: # 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() - log.info(f'\nOutput path: {config.model_configs[G.model_num].output_file_path.parent}') + log.info(f'\nOutput directory: {config.model_configs[G.model_num].output_file_path.parent.resolve()}') # Adjust position of simple sources and receivers if required if G.srcsteps[0] != 0 or G.srcsteps[1] != 0 or G.srcsteps[2] != 0: @@ -268,19 +268,19 @@ class ModelBuildRun: pbar.close() log.info('') - def print_resource_info(self, tsolve): + def print_resource_info(self, tsolve, memsolve): """Print resource information on runtime and memory usage. Args: - tsolve (float): time taken to execute solving (seconds). + tsolve (float): Time taken to execute solving (seconds). + memsolve (float): Memory (RAM) used on GPU. """ - mem_GPU = '' + memGPU_str = '' if config.sim_config.general['cuda']: - log.debug('Fix memory used calc for GPU') - # mem_GPU = f' host + ~{human_size(self.solver.get_memsolve())} GPU' + memGPU_str = f' host + ~{human_size(memsolve)} GPU' - log.info(f'\nMemory (RAM) used: ~{human_size(self.p.memory_full_info().uss)}{mem_GPU}') + log.info(f'\nMemory (RAM) used: ~{human_size(self.p.memory_full_info().uss)}{memGPU_str}') log.info(f'Solving time [HH:MM:SS]: {datetime.timedelta(seconds=tsolve)}') def solve(self, solver): @@ -293,7 +293,7 @@ class ModelBuildRun: tsolve (float): time taken to execute solving (seconds). """ - log.info(f'\nOutput file: {config.model_configs[self.G.model_num].output_file_path_ext}') + log.info(f'\nOutput file: {config.model_configs[self.G.model_num].output_file_path_ext.name}') # Check number of OpenMP threads if config.sim_config.general['cpu']: @@ -311,13 +311,13 @@ class ModelBuildRun: iterator = range(self.G.iterations) # Run solver - tsolve = solver.solve(iterator) + tsolve, memsolve = solver.solve(iterator) # Write output data, i.e. field data for receivers and snapshots to file(s) self.write_output_data() # Print resource information on runtime and memory usage - self.print_resource_info(tsolve) + self.print_resource_info(tsolve, memsolve) return tsolve diff --git a/gprMax/solvers.py b/gprMax/solvers.py index 78e1cbde..078d830f 100644 --- a/gprMax/solvers.py +++ b/gprMax/solvers.py @@ -15,7 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with gprMax. If not, see . -import sys + import gprMax.config as config from .grid import FDTDGrid from .grid import CUDAGrid @@ -92,6 +92,10 @@ class Solver: Args: iterator (iterator): can be range() or tqdm() + + Returns: + tsolve (float): Time taken to execute solving (seconds). + memsolve (float): Memory (RAM) used. """ self.updates.time_start() @@ -110,9 +114,10 @@ class Solver: if self.hsg: self.updates.hsg_1() self.updates.update_electric_b() + memsolve = self.updates.calculate_memsolve(iteration) if config.sim_config.general['cuda'] else None self.updates.finalise() tsolve = self.updates.calculate_tsolve() self.updates.cleanup() - return tsolve + return tsolve, memsolve diff --git a/gprMax/updates.py b/gprMax/updates.py index a3c2e529..93ea62f7 100644 --- a/gprMax/updates.py +++ b/gprMax/updates.py @@ -61,7 +61,7 @@ class CPUUpdates: """Store any snapshots. Args: - iteration (int): iteration number. + iteration (int): Iteration number. """ for snap in self.grid.snapshots: if snap.time == iteration + 1: @@ -225,9 +225,11 @@ class CPUUpdates: self.dispersive_update_b = disp_b_f def time_start(self): + """Start timer used to calculate solving time for model.""" self.timestart = timer() def calculate_tsolve(self): + """Calculate solving time for model.""" return timer() - self.timestart def finalise(self): @@ -243,7 +245,7 @@ class CUDAUpdates: def __init__(self, G): """ Args: - G (FDTDGrid): Holds essential parameters describing the model. + G (FDTDGrid): Parameters describing a grid in a model. """ self.grid = G @@ -465,7 +467,7 @@ class CUDAUpdates: for i, snap in enumerate(self.grid.snapshots): if snap.time == iteration + 1: - snapno = 0 if self.grid.snapsgpu2cpu else i + snapno = 0 if config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu'] else i self.store_snapshot_gpu(np.int32(snapno), np.int32(snap.xs), np.int32(snap.xf), @@ -490,7 +492,7 @@ class CUDAUpdates: self.snapHz_gpu.gpudata, block=Snapshot.tpb, grid=Snapshot.bpg) - if self.grid.snapsgpu2cpu: + if config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu']: gpu_get_snapshot_array(self.grid.snapEx_gpu.get(), self.grid.snapEy_gpu.get(), self.grid.snapEz_gpu.get(), @@ -649,6 +651,18 @@ class CUDAUpdates: self.iterstart.record() self.iterstart.synchronize() + def calculate_memsolve(iteration): + """Calculate memory used on last iteration. + + Args: + iteration (int): Iteration number. + + Returns: + Memory (RAM) used on GPU. + """ + if iteration == self.grid.iterations - 1: + return self.drv.mem_get_info()[1] - self.drv.mem_get_info()[0] + def calculate_tsolve(self): """Calculate solving time for model.""" self.iterend.record() @@ -666,7 +680,7 @@ class CUDAUpdates: self.grid) # Copy data from any snapshots back to correct snapshot objects - if self.grid.snapshots and not self.grid.snapsgpu2cpu: + if self.grid.snapshots and not config.model_configs[self.grid.model_num].cuda['snapsgpu2cpu']: for i, snap in enumerate(self.grid.snapshots): get_snapshot_array_gpu(self.snapEx_gpu.get(), self.snapEy_gpu.get(),