你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 15:10:13 +08:00
Formatting and comments update.
这个提交包含在:
@@ -33,7 +33,7 @@ from ._version import __version__
|
|||||||
from .constants import c, e0, m0, z0
|
from .constants import c, e0, m0, z0
|
||||||
from .exceptions import GeneralError
|
from .exceptions import GeneralError
|
||||||
from .fields_update import update_electric, update_magnetic, update_electric_dispersive_multipole_A, update_electric_dispersive_multipole_B, update_electric_dispersive_1pole_A, update_electric_dispersive_1pole_B
|
from .fields_update import update_electric, update_magnetic, update_electric_dispersive_multipole_A, update_electric_dispersive_multipole_B, update_electric_dispersive_1pole_A, update_electric_dispersive_1pole_B
|
||||||
from .grid import FDTDGrid, dispersion_check, Ix, Iy, Iz
|
from .grid import FDTDGrid, dispersion_check
|
||||||
from .input_cmds_geometry import process_geometrycmds
|
from .input_cmds_geometry import process_geometrycmds
|
||||||
from .input_cmds_file import process_python_include_code, write_processed_file, check_cmd_names
|
from .input_cmds_file import process_python_include_code, write_processed_file, check_cmd_names
|
||||||
from .input_cmds_multiuse import process_multicmds
|
from .input_cmds_multiuse import process_multicmds
|
||||||
@@ -69,7 +69,7 @@ def main():
|
|||||||
|
|
||||||
def api(inputfile, n=1, mpi=False, benchmark=False, geometry_only=False, geometry_fixed=False, write_processed=False, opt_taguchi=False):
|
def api(inputfile, n=1, mpi=False, benchmark=False, geometry_only=False, geometry_fixed=False, write_processed=False, opt_taguchi=False):
|
||||||
"""If installed as a module this is the entry point."""
|
"""If installed as a module this is the entry point."""
|
||||||
|
|
||||||
class ImportArguments:
|
class ImportArguments:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -89,11 +89,11 @@ def api(inputfile, n=1, mpi=False, benchmark=False, geometry_only=False, geometr
|
|||||||
|
|
||||||
def run_main(args):
|
def run_main(args):
|
||||||
"""Top-level function that controls what mode of simulation (standard/optimsation/benchmark etc...) is run.
|
"""Top-level function that controls what mode of simulation (standard/optimsation/benchmark etc...) is run.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
args (dict): Namespace with input arguments from command line or api.
|
args (dict): Namespace with input arguments from command line or api.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
numbermodelruns = args.n
|
numbermodelruns = args.n
|
||||||
inputdirectory = os.path.dirname(os.path.abspath(args.inputfile))
|
inputdirectory = os.path.dirname(os.path.abspath(args.inputfile))
|
||||||
inputfile = os.path.abspath(os.path.join(inputdirectory, os.path.basename(args.inputfile)))
|
inputfile = os.path.abspath(os.path.join(inputdirectory, os.path.basename(args.inputfile)))
|
||||||
@@ -125,7 +125,7 @@ def run_main(args):
|
|||||||
else:
|
else:
|
||||||
run_std_sim(args, numbermodelruns, inputfile, usernamespace)
|
run_std_sim(args, numbermodelruns, inputfile, usernamespace)
|
||||||
|
|
||||||
print('\nSimulation completed.\n{}\n'.format(68*'*'))
|
print('\nSimulation completed.\n{}\n'.format(68 * '*'))
|
||||||
|
|
||||||
|
|
||||||
def run_std_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None):
|
def run_std_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None):
|
||||||
@@ -141,7 +141,7 @@ def run_std_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None)
|
|||||||
|
|
||||||
tsimstart = perf_counter()
|
tsimstart = perf_counter()
|
||||||
for modelrun in range(1, numbermodelruns + 1):
|
for modelrun in range(1, numbermodelruns + 1):
|
||||||
if optparams: # If Taguchi optimistaion, add specific value for each parameter to optimise for each experiment to user accessible namespace
|
if optparams: # If Taguchi optimistaion, add specific value for each parameter to optimise for each experiment to user accessible namespace
|
||||||
tmp = {}
|
tmp = {}
|
||||||
tmp.update((key, value[modelrun - 1]) for key, value in optparams.items())
|
tmp.update((key, value[modelrun - 1]) for key, value in optparams.items())
|
||||||
modelusernamespace = usernamespace.copy()
|
modelusernamespace = usernamespace.copy()
|
||||||
@@ -165,13 +165,14 @@ def run_benchmark_sim(args, inputfile, usernamespace):
|
|||||||
# Number of threads to test - start from max physical CPU cores and divide in half until 1
|
# Number of threads to test - start from max physical CPU cores and divide in half until 1
|
||||||
thread = psutil.cpu_count(logical=False)
|
thread = psutil.cpu_count(logical=False)
|
||||||
threads = [thread]
|
threads = [thread]
|
||||||
while not thread%2:
|
while not thread % 2:
|
||||||
thread /= 2
|
thread /= 2
|
||||||
threads.append(int(thread))
|
threads.append(int(thread))
|
||||||
|
|
||||||
benchtimes = np.zeros(len(threads))
|
benchtimes = np.zeros(len(threads))
|
||||||
|
|
||||||
numbermodelruns = len(threads)
|
numbermodelruns = len(threads)
|
||||||
|
usernamespace['number_model_runs'] = numbermodelruns
|
||||||
tsimstart = perf_counter()
|
tsimstart = perf_counter()
|
||||||
for modelrun in range(1, numbermodelruns + 1):
|
for modelrun in range(1, numbermodelruns + 1):
|
||||||
os.environ['OMP_NUM_THREADS'] = str(threads[modelrun - 1])
|
os.environ['OMP_NUM_THREADS'] = str(threads[modelrun - 1])
|
||||||
@@ -181,7 +182,7 @@ def run_benchmark_sim(args, inputfile, usernamespace):
|
|||||||
|
|
||||||
# Save number of threads and benchmarking times to NumPy archive
|
# Save number of threads and benchmarking times to NumPy archive
|
||||||
threads = np.array(threads)
|
threads = np.array(threads)
|
||||||
np.savez(os.path.splitext(inputfile)[0], threads=threads, benchtimes=benchtimes)
|
np.savez(os.path.splitext(inputfile)[0], threads=threads, benchtimes=benchtimes, version=__version__)
|
||||||
|
|
||||||
print('\nTotal simulation time [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart))))
|
print('\nTotal simulation time [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart))))
|
||||||
|
|
||||||
@@ -209,17 +210,17 @@ def run_mpi_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None)
|
|||||||
status = MPI.Status() # get MPI status object
|
status = MPI.Status() # get MPI status object
|
||||||
name = MPI.Get_processor_name() # get name of processor/host
|
name = MPI.Get_processor_name() # get name of processor/host
|
||||||
|
|
||||||
if rank == 0: # Master process
|
if rank == 0: # Master process
|
||||||
modelrun = 1
|
modelrun = 1
|
||||||
numworkers = size - 1
|
numworkers = size - 1
|
||||||
closedworkers = 0
|
closedworkers = 0
|
||||||
print('Master: PID {} on {} using {} workers.'.format(os.getpid(), name, numworkers))
|
print('Master: PID {} on {} using {} workers.'.format(os.getpid(), name, numworkers))
|
||||||
while closedworkers < numworkers:
|
while closedworkers < numworkers:
|
||||||
data = comm.recv(source=MPI.ANY_SOURCE, tag=MPI.ANY_TAG, status=status)
|
# data = comm.recv(source=MPI.ANY_SOURCE, tag=MPI.ANY_TAG, status=status) # Check if this line is really needed
|
||||||
source = status.Get_source()
|
source = status.Get_source()
|
||||||
tag = status.Get_tag()
|
tag = status.Get_tag()
|
||||||
|
|
||||||
if tag == tags.READY.value: # Worker is ready, so send it a task
|
if tag == tags.READY.value: # Worker is ready, so send it a task
|
||||||
if modelrun < numbermodelruns + 1:
|
if modelrun < numbermodelruns + 1:
|
||||||
comm.send(modelrun, dest=source, tag=tags.START.value)
|
comm.send(modelrun, dest=source, tag=tags.START.value)
|
||||||
print('Master: sending model {} to worker {}.'.format(modelrun, source))
|
print('Master: sending model {} to worker {}.'.format(modelrun, source))
|
||||||
@@ -234,16 +235,16 @@ def run_mpi_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None)
|
|||||||
print('Worker {}: exited.'.format(source))
|
print('Worker {}: exited.'.format(source))
|
||||||
closedworkers += 1
|
closedworkers += 1
|
||||||
|
|
||||||
else: # Worker process
|
else: # Worker process
|
||||||
print('Worker {}: PID {} on {} requesting {} OpenMP threads.'.format(rank, os.getpid(), name, os.environ.get('OMP_NUM_THREADS')))
|
print('Worker {}: PID {} on {} requesting {} OpenMP threads.'.format(rank, os.getpid(), name, os.environ.get('OMP_NUM_THREADS')))
|
||||||
while True:
|
while True:
|
||||||
comm.send(None, dest=0, tag=tags.READY.value)
|
comm.send(None, dest=0, tag=tags.READY.value)
|
||||||
modelrun = comm.recv(source=0, tag=MPI.ANY_TAG, status=status) # Receive a model number to run from the master
|
modelrun = comm.recv(source=0, tag=MPI.ANY_TAG, status=status) # Receive a model number to run from the master
|
||||||
tag = status.Get_tag()
|
tag = status.Get_tag()
|
||||||
|
|
||||||
# Run a model
|
# Run a model
|
||||||
if tag == tags.START.value:
|
if tag == tags.START.value:
|
||||||
if optparams: # If Taguchi optimistaion, add specific value for each parameter to optimise for each experiment to user accessible namespace
|
if optparams: # If Taguchi optimistaion, add specific value for each parameter to optimise for each experiment to user accessible namespace
|
||||||
tmp = {}
|
tmp = {}
|
||||||
tmp.update((key, value[modelrun - 1]) for key, value in optparams.items())
|
tmp.update((key, value[modelrun - 1]) for key, value in optparams.items())
|
||||||
modelusernamespace = usernamespace.copy()
|
modelusernamespace = usernamespace.copy()
|
||||||
@@ -281,8 +282,8 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
global G
|
global G
|
||||||
|
|
||||||
# Normal model reading/building process; bypassed if geometry information to be reused
|
# Normal model reading/building process; bypassed if geometry information to be reused
|
||||||
if not 'G' in globals():
|
if 'G' not in globals():
|
||||||
print('\n{}\n\nModel input file: {}\n'.format(68*'*', inputfile))
|
print('\n{}\n\nModel input file: {}\n'.format(68 * '*', inputfile))
|
||||||
|
|
||||||
# Add the current model run to namespace that can be accessed by user in any Python code blocks in input file
|
# Add the current model run to namespace that can be accessed by user in any Python code blocks in input file
|
||||||
usernamespace['current_model_run'] = modelrun
|
usernamespace['current_model_run'] = modelrun
|
||||||
@@ -355,7 +356,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
if G.messages:
|
if G.messages:
|
||||||
print('\nMaterials:\n')
|
print('\nMaterials:\n')
|
||||||
print('ID\tName\t\tProperties')
|
print('ID\tName\t\tProperties')
|
||||||
print('{}'.format('-'*50))
|
print('{}'.format('-' * 50))
|
||||||
for material in G.materials:
|
for material in G.materials:
|
||||||
|
|
||||||
# Calculate update coefficients for material
|
# Calculate update coefficients for material
|
||||||
@@ -370,7 +371,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
if Material.maxpoles != 0:
|
if Material.maxpoles != 0:
|
||||||
z = 0
|
z = 0
|
||||||
for pole in range(Material.maxpoles):
|
for pole in range(Material.maxpoles):
|
||||||
G.updatecoeffsdispersive[material.numID, z:z+3] = e0 * material.eqt2[pole], material.eqt[pole], material.zt[pole]
|
G.updatecoeffsdispersive[material.numID, z:z + 3] = e0 * material.eqt2[pole], material.eqt[pole], material.zt[pole]
|
||||||
z += 3
|
z += 3
|
||||||
|
|
||||||
if G.messages:
|
if G.messages:
|
||||||
@@ -423,7 +424,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
tgeostart = perf_counter()
|
tgeostart = perf_counter()
|
||||||
for geometryview in G.geometryviews:
|
for geometryview in G.geometryviews:
|
||||||
geometryview.write_vtk(modelrun, numbermodelruns, G)
|
geometryview.write_vtk(modelrun, numbermodelruns, G)
|
||||||
#geometryview.write_xdmf(modelrun, numbermodelruns, G)
|
# geometryview.write_xdmf(modelrun, numbermodelruns, G)
|
||||||
tgeoend = perf_counter()
|
tgeoend = perf_counter()
|
||||||
print('\nGeometry file(s) written in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tgeoend - tgeostart))))
|
print('\nGeometry file(s) written in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tgeoend - tgeostart))))
|
||||||
|
|
||||||
@@ -449,7 +450,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
tsolvestart = perf_counter()
|
tsolvestart = perf_counter()
|
||||||
# Absolute time
|
# Absolute time
|
||||||
abstime = 0
|
abstime = 0
|
||||||
|
|
||||||
for timestep in range(G.iterations):
|
for timestep in range(G.iterations):
|
||||||
if timestep == 0:
|
if timestep == 0:
|
||||||
tstepstart = perf_counter()
|
tstepstart = perf_counter()
|
||||||
@@ -463,9 +464,9 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
snapshot.write_vtk_imagedata(G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G)
|
snapshot.write_vtk_imagedata(G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G)
|
||||||
|
|
||||||
# Update electric field components
|
# Update electric field components
|
||||||
if Material.maxpoles == 0: # All materials are non-dispersive so do standard update
|
if Material.maxpoles == 0: # All materials are non-dispersive so do standard update
|
||||||
update_electric(G.nx, G.ny, G.nz, G.nthreads, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
update_electric(G.nx, G.ny, G.nz, G.nthreads, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
||||||
elif Material.maxpoles == 1: # If there are any dispersive materials do 1st part of dispersive update (it is split into two parts as it requires present and updated electric field values).
|
elif Material.maxpoles == 1: # If there are any dispersive materials do 1st part of dispersive update (it is split into two parts as it requires present and updated electric field values).
|
||||||
update_electric_dispersive_1pole_A(G.nx, G.ny, G.nz, G.nthreads, G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
update_electric_dispersive_1pole_A(G.nx, G.ny, G.nz, G.nthreads, G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
||||||
elif Material.maxpoles > 1:
|
elif Material.maxpoles > 1:
|
||||||
update_electric_dispersive_multipole_A(G.nx, G.ny, G.nz, G.nthreads, Material.maxpoles, G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
update_electric_dispersive_multipole_A(G.nx, G.ny, G.nz, G.nthreads, Material.maxpoles, G.updatecoeffsE, G.updatecoeffsdispersive, G.ID, G.Tx, G.Ty, G.Tz, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz)
|
||||||
@@ -478,7 +479,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
voltagesource.update_electric(abstime, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G)
|
voltagesource.update_electric(abstime, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G)
|
||||||
for transmissionline in G.transmissionlines:
|
for transmissionline in G.transmissionlines:
|
||||||
transmissionline.update_electric(abstime, G.Ex, G.Ey, G.Ez, G)
|
transmissionline.update_electric(abstime, G.Ex, G.Ey, G.Ez, G)
|
||||||
for hertziandipole in G.hertziandipoles: # Update any Hertzian dipole sources last
|
for hertziandipole in G.hertziandipoles: # Update any Hertzian dipole sources last
|
||||||
hertziandipole.update_electric(abstime, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G)
|
hertziandipole.update_electric(abstime, G.updatecoeffsE, G.ID, G.Ex, G.Ey, G.Ez, G)
|
||||||
|
|
||||||
# If there are any dispersive materials do 2nd part of dispersive update (it is split into two parts as it requires present and updated electric field values). Therefore it can only be completely updated after the electric field has been updated by the PML and source updates.
|
# If there are any dispersive materials do 2nd part of dispersive update (it is split into two parts as it requires present and updated electric field values). Therefore it can only be completely updated after the electric field has been updated by the PML and source updates.
|
||||||
@@ -519,8 +520,8 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
write_hdf5(outputfile, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G)
|
write_hdf5(outputfile, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G)
|
||||||
|
|
||||||
tsolveend = perf_counter()
|
tsolveend = perf_counter()
|
||||||
print('\n\nSolving took [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsolveend - tsolvestart))))
|
print('\n\nSolving took [HH:MM:SS]: {} @ {:g} cells/s'.format(datetime.timedelta(seconds=int(tsolveend - tsolvestart)), (G.nx * G.ny * G.nz) / (tsolveend - tsolvestart)))
|
||||||
print('Peak memory (approx) used: {}'.format(human_size(p.memory_info().rss)))
|
print('Memory (RAM) usage: ~{}'.format(human_size(p.memory_info().rss)))
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
# End - Main FDTD calculations #
|
# End - Main FDTD calculations #
|
||||||
@@ -531,7 +532,3 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace):
|
|||||||
del G
|
del G
|
||||||
|
|
||||||
return int(tsolveend - tsolvestart)
|
return int(tsolveend - tsolvestart)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
在新工单中引用
屏蔽一个用户