diff --git a/GPUSimulators/Autotuner.py b/GPUSimulators/Autotuner.py
index 47a3a41..55814e0 100644
--- a/GPUSimulators/Autotuner.py
+++ b/GPUSimulators/Autotuner.py
@@ -28,9 +28,9 @@ from socket import gethostname
import pycuda.driver as cuda
-
from GPUSimulators import Common, Simulator, CudaContext
+
class Autotuner:
def __init__(self,
nx=2048, ny=2048,
@@ -44,7 +44,6 @@ class Autotuner:
self.block_heights = block_heights
self.performance = {}
-
def benchmark(self, simulator, force=False):
logger = logging.getLogger(__name__)
@@ -95,13 +94,12 @@ class Autotuner:
# Save to file
np.savez_compressed(self.filename, **benchmark_data)
-
-
- """
- Function which reads a numpy file with autotuning data
- and reports the maximum performance and block size
- """
def get_peak_performance(self, simulator):
+ """
+ Function which reads a numpy file with autotuning data
+ and reports the maximum performance and block size
+ """
+
logger = logging.getLogger(__name__)
assert issubclass(simulator, Simulator.BaseSimulator)
@@ -140,13 +138,12 @@ class Autotuner:
#This should never happen
raise "Something wrong: Could not get autotuning data!"
return None
-
-
-
- """
- Runs a set of benchmarks for a single simulator
- """
+
def benchmark_single_simulator(simulator, arguments, block_widths, block_heights):
+ """
+ Runs a set of benchmarks for a single simulator
+ """
+
logger = logging.getLogger(__name__)
megacells = np.empty((len(block_heights), len(block_widths)))
@@ -168,11 +165,11 @@ class Autotuner:
return megacells
-
- """
- Runs a benchmark, and returns the number of megacells achieved
- """
def run_benchmark(simulator, arguments, timesteps=10, warmup_timesteps=2):
+ """
+ Runs a benchmark, and returns the number of megacells achieved
+ """
+
logger = logging.getLogger(__name__)
#Initialize simulator
@@ -218,12 +215,11 @@ class Autotuner:
logger.debug("%s [%d x %d] failed: gpu elapsed %f", simulator.__name__, arguments["block_width"], arguments["block_height"], gpu_elapsed)
return np.nan
-
-
- """
- Generates test dataset
- """
def gen_test_data(nx, ny, g):
+ """
+ Generates test dataset
+ """
+
width = 100.0
height = 100.0
dx = width / float(nx)
@@ -264,10 +260,11 @@ class Autotuner:
return h, hu, hv, dx, dy, dt
- """
- Checks that a variable is "sane"
- """
def sanity_check(variable, bound_min, bound_max):
+ """
+ Checks that a variable is "sane"
+ """
+
maxval = np.amax(variable)
minval = np.amin(variable)
if (np.isnan(maxval)
diff --git a/GPUSimulators/Common.py b/GPUSimulators/Common.py
index 76902c5..bf7b9f4 100644
--- a/GPUSimulators/Common.py
+++ b/GPUSimulators/Common.py
@@ -41,10 +41,6 @@ import pycuda.driver as cuda
from pycuda.tools import PageLockedMemoryPool
-
-
-
-
def safeCall(cmd):
logger = logging.getLogger(__name__)
try:
@@ -65,16 +61,20 @@ def safeCall(cmd):
return stdout
+
def getGitHash():
return safeCall(["git", "rev-parse", "HEAD"])
+
def getGitStatus():
return safeCall(["git", "status", "--porcelain", "-uno"])
+
def toJson(in_dict, compressed=True):
"""
Creates JSON string from a dictionary
"""
+
logger = logging.getLogger(__name__)
out_dict = in_dict.copy()
for key in out_dict:
@@ -89,12 +89,14 @@ def toJson(in_dict, compressed=True):
out_dict[key] = value
return json.dumps(out_dict)
+
def runSimulation(simulator, simulator_args, outfile, save_times, save_var_names=[], dt=None):
"""
Runs a simulation, and stores output in netcdf file. Stores the times given in
save_times, and saves all of the variables in list save_var_names. Elements in
save_var_names can be set to None if you do not want to save them
"""
+
profiling_data_sim_runner = { 'start': {}, 'end': {} }
profiling_data_sim_runner["start"]["t_sim_init"] = 0
profiling_data_sim_runner["end"]["t_sim_init"] = 0
@@ -208,14 +210,11 @@ def runSimulation(simulator, simulator_args, outfile, save_times, save_var_names
return outdata.filename, profiling_data_sim_runner, sim.profiling_data_mpi
-
-
-
-
class Timer(object):
"""
Class which keeps track of time spent for a section of code
"""
+
def __init__(self, tag, log_level=logging.DEBUG):
self.tag = tag
self.log_level = log_level
@@ -233,16 +232,14 @@ class Timer(object):
def elapsed(self):
return time.time() - self.start
-
-
-
-
+
class PopenFileBuffer(object):
"""
Simple class for holding a set of tempfiles
for communicating with a subprocess
"""
+
def __init__(self):
self.stdout = tempfile.TemporaryFile(mode='w+t')
self.stderr = tempfile.TemporaryFile(mode='w+t')
@@ -262,10 +259,12 @@ class PopenFileBuffer(object):
return cout, cerr
+
class IPEngine(object):
"""
Class for starting IPEngines for MPI processing in IPython
"""
+
def __init__(self, n_engines):
self.logger = logging.getLogger(__name__)
@@ -352,10 +351,6 @@ class IPEngine(object):
self.c_buff = None
gc.collect()
-
-
-
-
class DataDumper(object):
@@ -366,6 +361,7 @@ class DataDumper(object):
with DataDumper("filename") as data:
...
"""
+
def __init__(self, filename, *args, **kwargs):
self.logger = logging.getLogger(__name__)
@@ -400,7 +396,6 @@ class DataDumper(object):
#Log output
self.logger.info("Initialized " + self.filename)
-
def __enter__(self):
self.logger.info("Opening " + self.filename)
if (self.args):
@@ -414,7 +409,6 @@ class DataDumper(object):
self.logger.info("Closing " + self.filename)
self.ncfile.close()
-
def toJson(in_dict):
out_dict = in_dict.copy()
@@ -428,15 +422,13 @@ class DataDumper(object):
out_dict[key] = str(out_dict[key])
return json.dumps(out_dict)
-
-
-
class ProgressPrinter(object):
"""
Small helper class for
"""
+
def __init__(self, total_steps, print_every=5):
self.logger = logging.getLogger(__name__)
self.start = time.time()
@@ -487,19 +479,16 @@ class ProgressPrinter(object):
return progressbar
-
-
-
-
-
-"""
-Class that holds 2D data
-"""
class CudaArray2D:
"""
- Uploads initial data to the CUDA device
+ Class that holds 2D data
"""
+
def __init__(self, stream, nx, ny, x_halo, y_halo, cpu_data=None, dtype=np.float32):
+ """
+ Uploads initial data to the CUDA device
+ """
+
self.logger = logging.getLogger(__name__)
self.nx = nx
self.ny = ny
@@ -531,16 +520,16 @@ class CudaArray2D:
self.upload(stream, cpu_data, extent=[x, y, cpu_data.shape[1], cpu_data.shape[0]])
#self.logger.debug("Buffer <%s> [%dx%d]: Allocated ", int(self.data.gpudata), self.nx, self.ny)
-
def __del__(self, *args):
#self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny)
self.data.gpudata.free()
self.data = None
-
- """
- Enables downloading data from GPU to Python
- """
+
def download(self, stream, cpu_data=None, asynch=False, extent=None):
+ """
+ Enables downloading data from GPU to Python
+ """
+
if (extent is None):
x = self.x_halo
y = self.y_halo
@@ -583,7 +572,6 @@ class CudaArray2D:
return cpu_data
-
def upload(self, stream, cpu_data, extent=None):
if (extent is None):
x = self.x_halo
@@ -615,21 +603,17 @@ class CudaArray2D:
copy(stream)
-
-
-
-
-
-
-
-"""
-Class that holds 2D data
-"""
+
class CudaArray3D:
"""
- Uploads initial data to the CL device
+ Class that holds 3D data
"""
+
def __init__(self, stream, nx, ny, nz, x_halo, y_halo, z_halo, cpu_data=None, dtype=np.float32):
+ """
+ Uploads initial data to the CL device
+ """
+
self.logger = logging.getLogger(__name__)
self.nx = nx
self.ny = ny
@@ -688,16 +672,16 @@ class CudaArray3D:
#self.logger.debug("Buffer <%s> [%dx%d]: Allocated ", int(self.data.gpudata), self.nx, self.ny)
-
def __del__(self, *args):
#self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny)
self.data.gpudata.free()
self.data = None
- """
- Enables downloading data from GPU to Python
- """
def download(self, stream, asynch=False):
+ """
+ Enables downloading data from GPU to Python
+ """
+
#self.logger.debug("Downloading [%dx%d] buffer", self.nx, self.ny)
#Allocate host memory
#cpu_data = cuda.pagelocked_empty((self.ny, self.nx), np.float32)
@@ -727,18 +711,12 @@ class CudaArray3D:
return cpu_data
-
-
-
-
-
-
-
-
-"""
-A class representing an Arakawa A type (unstaggered, logically Cartesian) grid
-"""
+
class ArakawaA2D:
+ """
+ A class representing an Arakawa A type (unstaggered, logically Cartesian) grid
+ """
+
def __init__(self, stream, nx, ny, halo_x, halo_y, cpu_variables):
"""
Uploads initial data to the GPU device
diff --git a/GPUSimulators/CudaContext.py b/GPUSimulators/CudaContext.py
index 6c90636..cfbf6cb 100644
--- a/GPUSimulators/CudaContext.py
+++ b/GPUSimulators/CudaContext.py
@@ -19,8 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
-
import os
import numpy as np
@@ -38,11 +36,10 @@ import pycuda.driver as cuda
from GPUSimulators import Autotuner, Common
-
-"""
-Class which keeps track of the CUDA context and some helper functions
-"""
class CudaContext(object):
+ """
+ Class which keeps track of the CUDA context and some helper functions
+ """
def __init__(self, device=None, context_flags=None, use_cache=True, autotuning=True):
"""
@@ -50,6 +47,7 @@ class CudaContext(object):
Set device to an id or pci_bus_id to select a specific GPU
Set context_flags to cuda.ctx_flags.SCHED_BLOCKING_SYNC for a blocking context
"""
+
self.use_cache = use_cache
self.logger = logging.getLogger(__name__)
self.modules = {}
@@ -94,7 +92,6 @@ class CudaContext(object):
if (autotuning):
self.logger.info("Autotuning enabled. It may take several minutes to run the code the first time: have patience")
self.autotuner = Autotuner.Autotuner()
-
def __del__(self, *args):
self.logger.info("Cleaning up CUDA context handle <%s>", str(self.cuda_context.handle))
@@ -119,10 +116,8 @@ class CudaContext(object):
self.logger.debug("<%s> Detaching", str(self.cuda_context.handle))
self.cuda_context.detach()
-
def __str__(self):
return "CudaContext id " + str(self.cuda_context.handle)
-
def hash_kernel(kernel_filename, include_dirs):
# Generate a kernel ID for our caches
@@ -171,18 +166,19 @@ class CudaContext(object):
return kernel_hasher.hexdigest()
-
- """
- Reads a text file and creates an OpenCL kernel from that
- """
def get_module(self, kernel_filename,
include_dirs=[], \
defines={}, \
compile_args={'no_extern_c', True}, jit_compile_args={}):
"""
- Helper function to print compilation output
+ Reads a text file and creates an OpenCL kernel from that
"""
+
def cuda_compile_message_handler(compile_success_bool, info_str, error_str):
+ """
+ Helper function to print compilation output
+ """
+
self.logger.debug("Compilation returned %s", str(compile_success_bool))
if info_str:
self.logger.debug("Info: %s", info_str)
@@ -257,16 +253,18 @@ class CudaContext(object):
self.modules[kernel_hash] = module
return module
- """
- Clears the kernel cache (useful for debugging & development)
- """
def clear_kernel_cache(self):
+ """
+ Clears the kernel cache (useful for debugging & development)
+ """
+
self.logger.debug("Clearing cache")
self.modules = {}
gc.collect()
- """
- Synchronizes all streams etc
- """
def synchronize(self):
+ """
+ Synchronizes all streams etc
+ """
+
self.cuda_context.synchronize()
\ No newline at end of file
diff --git a/GPUSimulators/EE2D_KP07_dimsplit.py b/GPUSimulators/EE2D_KP07_dimsplit.py
index 2c3f810..b4e8d0f 100644
--- a/GPUSimulators/EE2D_KP07_dimsplit.py
+++ b/GPUSimulators/EE2D_KP07_dimsplit.py
@@ -27,33 +27,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-
-
-
-
-
-"""
-Class that solves the SW equations using the Forward-Backward linear scheme
-"""
class EE2D_KP07_dimsplit (BaseSimulator):
+ """
+ Class that solves the SW equations using the Forward-Backward linear scheme
+ """
- """
- Initialization routine
- rho: Density
- rho_u: Momentum along x-axis
- rho_v: Momentum along y-axis
- E: energy
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis
- dy: Grid cell spacing along y-axis
- dt: Size of each timestep
- g: Gravitational constant
- gamma: Gas constant
- p: pressure
- """
def __init__(self,
context,
rho, rho_u, rho_v, E,
@@ -65,7 +43,24 @@ class EE2D_KP07_dimsplit (BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=8):
-
+ """
+ Initialization routine
+
+ Args:
+ rho: Density
+ rho_u: Momentum along x-axis
+ rho_v: Momentum along y-axis
+ E: energy
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis
+ dy: Grid cell spacing along y-axis
+ dt: Size of each timestep
+ g: Gravitational constant
+ gamma: Gas constant
+ p: pressure
+ """
+
# Call super constructor
super().__init__(context,
nx, ny,
@@ -107,7 +102,6 @@ class EE2D_KP07_dimsplit (BaseSimulator):
dt_y = np.min(self.dy / (np.abs(rho_v/rho) + np.sqrt(gamma*rho)))
self.dt = min(dt_x, dt_y)
self.cfl_data.fill(self.dt, stream=self.stream)
-
def substep(self, dt, step_number, external=True, internal=True):
self.substepDimsplit(0.5*dt, step_number, external, internal)
diff --git a/GPUSimulators/FORCE.py b/GPUSimulators/FORCE.py
index 2e60be6..616d965 100644
--- a/GPUSimulators/FORCE.py
+++ b/GPUSimulators/FORCE.py
@@ -28,31 +28,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-
-
-
-
-
-
-"""
-Class that solves the SW equations
-"""
class FORCE (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -62,6 +42,20 @@ class FORCE (Simulator.BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/HLL.py b/GPUSimulators/HLL.py
index 9911f9b..52fc0ca 100644
--- a/GPUSimulators/HLL.py
+++ b/GPUSimulators/HLL.py
@@ -27,27 +27,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-
-
-"""
-Class that solves the SW equations using the Harten-Lax -van Leer approximate Riemann solver
-"""
class HLL (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the Harten-Lax -van Leer approximate Riemann solver
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -57,6 +41,20 @@ class HLL (Simulator.BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/HLL2.py b/GPUSimulators/HLL2.py
index 64fa765..9fdcdd8 100644
--- a/GPUSimulators/HLL2.py
+++ b/GPUSimulators/HLL2.py
@@ -26,30 +26,12 @@ import numpy as np
from pycuda import gpuarray
-
-
-
-
-
-
-"""
-Class that solves the SW equations using the Forward-Backward linear scheme
-"""
class HLL2 (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the Forward-Backward linear scheme
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -60,6 +42,20 @@ class HLL2 (Simulator.BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/KP07.py b/GPUSimulators/KP07.py
index 8e2af50..37ca7ec 100644
--- a/GPUSimulators/KP07.py
+++ b/GPUSimulators/KP07.py
@@ -32,25 +32,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-"""
-Class that solves the SW equations using the Forward-Backward linear scheme
-"""
class KP07 (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the Forward-Backward linear scheme
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -62,6 +48,20 @@ class KP07 (Simulator.BaseSimulator):
order=2,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/KP07_dimsplit.py b/GPUSimulators/KP07_dimsplit.py
index c90cf07..680adb7 100644
--- a/GPUSimulators/KP07_dimsplit.py
+++ b/GPUSimulators/KP07_dimsplit.py
@@ -32,26 +32,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-
-"""
-Class that solves the SW equations using the dimentionally split KP07 scheme
-"""
class KP07_dimsplit(Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the dimentionally split KP07 scheme
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -62,6 +47,20 @@ class KP07_dimsplit(Simulator.BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/LxF.py b/GPUSimulators/LxF.py
index 48d9127..e5833a9 100644
--- a/GPUSimulators/LxF.py
+++ b/GPUSimulators/LxF.py
@@ -21,43 +21,41 @@ along with this program. If not, see .
"""
#Import packages we need
-from GPUSimulators import Simulator, Common
+from GPUSimulators import CudaContext, Simulator, Common
from GPUSimulators.Simulator import BaseSimulator, BoundaryCondition
import numpy as np
from pycuda import gpuarray
-
-
-
-
-"""
-Class that solves the SW equations using the Lax Friedrichs scheme
-"""
class LxF (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the Lax Friedrichs scheme
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
- context,
- h0, hu0, hv0,
- nx, ny,
- dx, dy,
- g,
- cfl_scale=0.9,
+ context: CudaContext,
+ h0: float, hu0: float, hv0: float,
+ nx: int, ny: int,
+ dx: int, dy: int,
+ g: float,
+ cfl_scale: float=0.9,
boundary_conditions=BoundaryCondition(),
- block_width=16, block_height=16):
+ block_width: int=16, block_height: int=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
@@ -66,7 +64,7 @@ class LxF (Simulator.BaseSimulator):
boundary_conditions,
cfl_scale,
1,
- block_width, block_height);
+ block_width, block_height)
self.g = np.float32(g)
# Get kernels
@@ -99,6 +97,11 @@ class LxF (Simulator.BaseSimulator):
self.cfl_data.fill(dt, stream=self.stream)
def substep(self, dt, step_number):
+ """
+ Args:
+ dt: Size of each timestep (seconds)
+ """
+
self.kernel.prepared_async_call(self.grid_size, self.block_size, self.stream,
self.nx, self.ny,
self.dx, self.dy, dt,
diff --git a/GPUSimulators/MPISimulator.py b/GPUSimulators/MPISimulator.py
index 31f62e8..6dd4664 100644
--- a/GPUSimulators/MPISimulator.py
+++ b/GPUSimulators/MPISimulator.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
import logging
from GPUSimulators import Simulator
import numpy as np
@@ -30,12 +29,12 @@ import pycuda.driver as cuda
#import nvtx
-
class MPIGrid(object):
"""
Class which represents an MPI grid of nodes. Facilitates easy communication between
neighboring nodes
"""
+
def __init__(self, comm, ndims=2):
self.logger = logging.getLogger(__name__)
@@ -144,7 +143,6 @@ class MPIGrid(object):
return grid
-
def gather(self, data, root=0):
out_data = None
if (self.comm.rank == root):
@@ -206,6 +204,7 @@ class MPISimulator(Simulator.BaseSimulator):
"""
Class which handles communication between simulators on different MPI nodes
"""
+
def __init__(self, sim, grid):
self.profiling_data_mpi = { 'start': {}, 'end': {} }
self.profiling_data_mpi["start"]["t_mpi_halo_exchange"] = 0
@@ -353,12 +352,12 @@ class MPISimulator(Simulator.BaseSimulator):
self.logger.debug("Local dt: {:f}, global dt: {:f}".format(local_dt[0], global_dt[0]))
return global_dt[0]
-
def getExtent(self):
"""
Function which returns the extent of node with rank
rank in the grid
"""
+
width = self.sim.nx*self.sim.dx
height = self.sim.ny*self.sim.dy
i, j = self.grid.getCoordinate()
diff --git a/GPUSimulators/SHMEMSimulator.py b/GPUSimulators/SHMEMSimulator.py
index 4385919..55a85ee 100644
--- a/GPUSimulators/SHMEMSimulator.py
+++ b/GPUSimulators/SHMEMSimulator.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
import logging
from GPUSimulators import Simulator, CudaContext
import numpy as np
@@ -28,6 +27,7 @@ import pycuda.driver as cuda
import time
+
class SHMEMSimulator(Simulator.BaseSimulator):
"""
Class which handles communication and synchronization between simulators in different
diff --git a/GPUSimulators/SHMEMSimulatorGroup.py b/GPUSimulators/SHMEMSimulatorGroup.py
index fc11d50..cfa8351 100644
--- a/GPUSimulators/SHMEMSimulatorGroup.py
+++ b/GPUSimulators/SHMEMSimulatorGroup.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
import logging
from GPUSimulators import Simulator, CudaContext
import numpy as np
@@ -28,6 +27,7 @@ import pycuda.driver as cuda
import time
+
class SHMEMGrid(object):
"""
Class which represents an SHMEM grid of GPUs. Facilitates easy communication between
@@ -156,6 +156,7 @@ class SHMEMGrid(object):
return grid
+
class SHMEMSimulatorGroup(object):
"""
Class which handles communication and synchronization between simulators in different
@@ -277,7 +278,6 @@ class SHMEMSimulatorGroup(object):
self.s[i] = np.empty((self.nvars[i], self.read_s[i][3], self.read_s[i][2]), dtype=np.float32)
self.logger.debug("Initialized {:d} subdomains".format(len(self.sims)))
-
def substep(self, dt, step_number):
self.exchange()
diff --git a/GPUSimulators/Simulator.py b/GPUSimulators/Simulator.py
index 178183d..9188d99 100644
--- a/GPUSimulators/Simulator.py
+++ b/GPUSimulators/Simulator.py
@@ -29,23 +29,20 @@ import pycuda.compiler as cuda_compiler
import pycuda.gpuarray
import pycuda.driver as cuda
-from GPUSimulators import Common
-
-
-
+from GPUSimulators import Common, CudaContext
class BoundaryCondition(object):
"""
Class for holding boundary conditions for global boundaries
"""
-
-
+
class Type(IntEnum):
"""
Enum that describes the different types of boundary conditions
WARNING: MUST MATCH THAT OF common.h IN CUDA
"""
+
Dirichlet = 0,
Neumann = 1,
Periodic = 2,
@@ -60,6 +57,7 @@ class BoundaryCondition(object):
"""
Constructor
"""
+
self.north = types['north']
self.south = types['south']
self.east = types['east']
@@ -74,11 +72,11 @@ class BoundaryCondition(object):
def __str__(self):
return '[north={:s}, south={:s}, east={:s}, west={:s}]'.format(str(self.north), str(self.south), str(self.east), str(self.west))
-
def asCodedInt(self):
"""
Helper function which packs four boundary conditions into one integer
"""
+
bc = 0
bc = bc | (self.north & 0x0000000F) << 24
bc = bc | (self.south & 0x0000000F) << 16
@@ -98,39 +96,36 @@ class BoundaryCondition(object):
types['east'] = BoundaryCondition.Type((bc >> 8) & 0x0000000F)
types['west'] = BoundaryCondition.Type((bc >> 0) & 0x0000000F)
return types
-
-
-
-
-
-
-
-
+
+
class BaseSimulator(object):
def __init__(self,
- context,
- nx, ny,
- dx, dy,
- boundary_conditions,
- cfl_scale,
- num_substeps,
- block_width, block_height):
+ context: CudaContext,
+ nx: int, ny: int,
+ dx: int, dy: int,
+ boundary_conditions: BoundaryCondition,
+ cfl_scale: float,
+ num_substeps: int,
+ block_width: int, block_height: int):
"""
Initialization routine
- context: GPU context to use
- kernel_wrapper: wrapper function of GPU kernel
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- cfl_scale: Courant number
- num_substeps: Number of substeps to perform for a full step
+
+ Args:
+ context: GPU context to use
+ kernel_wrapper: wrapper function of GPU kernel
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ cfl_scale: Courant number
+ num_substeps: Number of substeps to perform for a full step
"""
+
#Get logger
self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
@@ -147,7 +142,7 @@ class BaseSimulator(object):
self.num_substeps = num_substeps
#Handle autotuning block size
- if (self.context.autotuner):
+ if self.context.autotuner:
peak_configuration = self.context.autotuner.get_peak_performance(self.__class__)
block_width = int(peak_configuration["block_width"])
block_height = int(peak_configuration["block_height"])
@@ -167,12 +162,10 @@ class BaseSimulator(object):
#Keep track of simulation time and number of timesteps
self.t = 0.0
self.nt = 0
-
def __str__(self):
return "{:s} [{:d}x{:d}]".format(self.__class__.__name__, self.nx, self.ny)
-
def simulate(self, t, dt=None):
"""
Function which simulates t_end seconds using the step function
@@ -216,11 +209,14 @@ class BaseSimulator(object):
e.args += ("Step={:d}, time={:f}".format(self.simSteps(), self.simTime()),)
raise
-
- def step(self, dt):
+ def step(self, dt: int):
"""
Function which performs one single timestep of size dt
+
+ Args:
+ dt: Size of each timestep (seconds)
"""
+
for i in range(self.num_substeps):
self.substep(dt, i)
@@ -253,6 +249,7 @@ class BaseSimulator(object):
"""
Function which performs one single substep with stepsize dt
"""
+
raise(NotImplementedError("Needs to be implemented in subclass"))
def getOutput(self):
@@ -264,23 +261,13 @@ class BaseSimulator(object):
def computeDt(self):
raise(NotImplementedError("Needs to be implemented in subclass"))
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
def stepOrderToCodedInt(step, order):
"""
Helper function which packs the step and order into a single integer
"""
+
step_order = (step << 16) | (order & 0x0000ffff)
#print("Step: {0:032b}".format(step))
#print("Order: {0:032b}".format(order))
diff --git a/GPUSimulators/WAF.py b/GPUSimulators/WAF.py
index 22860fc..21fd484 100644
--- a/GPUSimulators/WAF.py
+++ b/GPUSimulators/WAF.py
@@ -28,25 +28,11 @@ import numpy as np
from pycuda import gpuarray
-
-
-"""
-Class that solves the SW equations using the Forward-Backward linear scheme
-"""
class WAF (Simulator.BaseSimulator):
+ """
+ Class that solves the SW equations using the Forward-Backward linear scheme
+ """
- """
- Initialization routine
- h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
- hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
- hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
- nx: Number of cells along x-axis
- ny: Number of cells along y-axis
- dx: Grid cell spacing along x-axis (20 000 m)
- dy: Grid cell spacing along y-axis (20 000 m)
- dt: Size of each timestep (90 s)
- g: Gravitational accelleration (9.81 m/s^2)
- """
def __init__(self,
context,
h0, hu0, hv0,
@@ -56,6 +42,20 @@ class WAF (Simulator.BaseSimulator):
cfl_scale=0.9,
boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16):
+ """
+ Initialization routine
+
+ Args:
+ h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
+ hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
+ hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
+ nx: Number of cells along x-axis
+ ny: Number of cells along y-axis
+ dx: Grid cell spacing along x-axis (20 000 m)
+ dy: Grid cell spacing along y-axis (20 000 m)
+ dt: Size of each timestep (90 s)
+ g: Gravitational accelleration (9.81 m/s^2)
+ """
# Call super constructor
super().__init__(context,
diff --git a/GPUSimulators/helpers/InitialConditions.py b/GPUSimulators/helpers/InitialConditions.py
index ccfac48..bb0e200 100644
--- a/GPUSimulators/helpers/InitialConditions.py
+++ b/GPUSimulators/helpers/InitialConditions.py
@@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
from GPUSimulators.Simulator import BoundaryCondition
import numpy as np
import gc
@@ -73,10 +72,7 @@ def downsample(highres_solution, x_factor, y_factor=None):
return highres_solution.reshape([int(ny), int(y_factor), int(nx), int(x_factor)]).mean(3).mean(1)
-
-
-
-def bump(nx, ny, width, height,
+def bump(nx: int, ny: int, width: int, height: int,
bump_size=None,
ref_nx=None, ref_ny=None,
x_center=0.5, y_center=0.5,
@@ -189,12 +185,7 @@ def genShockBubble(nx, ny, gamma, grid=None):
}
return arguments
-
-
-
-
-
-
+
def genKelvinHelmholtz(nx, ny, gamma, roughness=0.125, grid=None, index=None):
"""
Roughness parameter in (0, 1.0] determines how "squiggly"
@@ -205,6 +196,7 @@ def genKelvinHelmholtz(nx, ny, gamma, roughness=0.125, grid=None, index=None):
"""
Generates the zones of the two fluids of K-H
"""
+
zone = np.zeros((ny, nx), dtype=np.int32)
@@ -298,13 +290,13 @@ def genKelvinHelmholtz(nx, ny, gamma, roughness=0.125, grid=None, index=None):
}
return arguments
-
-
-
+
+
def genRayleighTaylor(nx, ny, gamma, version=0, grid=None):
"""
Generates Rayleigh-Taylor instability case
"""
+
width = 0.5
height = 1.5
g = 0.1
diff --git a/GPUSimulators/helpers/Visualization.py b/GPUSimulators/helpers/Visualization.py
index a2ff8f1..59ec928 100644
--- a/GPUSimulators/helpers/Visualization.py
+++ b/GPUSimulators/helpers/Visualization.py
@@ -19,14 +19,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
"""
-
-
import numpy as np
from matplotlib.colors import Normalize
-
def genSchlieren(rho):
#Compute length of z-component of normalized gradient vector
normal = np.gradient(rho) #[x, y, 1]