refactor(GPUSimulator): follow PEP 8 style guide

This commit is contained in:
Anthony Berg 2025-02-14 12:40:31 +01:00
parent ce8e834771
commit ef207432db
17 changed files with 286 additions and 354 deletions

View File

@ -28,9 +28,9 @@ from socket import gethostname
import pycuda.driver as cuda import pycuda.driver as cuda
from GPUSimulators import Common, Simulator, CudaContext from GPUSimulators import Common, Simulator, CudaContext
class Autotuner: class Autotuner:
def __init__(self, def __init__(self,
nx=2048, ny=2048, nx=2048, ny=2048,
@ -44,7 +44,6 @@ class Autotuner:
self.block_heights = block_heights self.block_heights = block_heights
self.performance = {} self.performance = {}
def benchmark(self, simulator, force=False): def benchmark(self, simulator, force=False):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -95,13 +94,12 @@ class Autotuner:
# Save to file # Save to file
np.savez_compressed(self.filename, **benchmark_data) 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): 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__) logger = logging.getLogger(__name__)
assert issubclass(simulator, Simulator.BaseSimulator) assert issubclass(simulator, Simulator.BaseSimulator)
@ -140,13 +138,12 @@ class Autotuner:
#This should never happen #This should never happen
raise "Something wrong: Could not get autotuning data!" raise "Something wrong: Could not get autotuning data!"
return None return None
"""
Runs a set of benchmarks for a single simulator
"""
def benchmark_single_simulator(simulator, arguments, block_widths, block_heights): def benchmark_single_simulator(simulator, arguments, block_widths, block_heights):
"""
Runs a set of benchmarks for a single simulator
"""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
megacells = np.empty((len(block_heights), len(block_widths))) megacells = np.empty((len(block_heights), len(block_widths)))
@ -168,11 +165,11 @@ class Autotuner:
return megacells return megacells
"""
Runs a benchmark, and returns the number of megacells achieved
"""
def run_benchmark(simulator, arguments, timesteps=10, warmup_timesteps=2): def run_benchmark(simulator, arguments, timesteps=10, warmup_timesteps=2):
"""
Runs a benchmark, and returns the number of megacells achieved
"""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
#Initialize simulator #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) logger.debug("%s [%d x %d] failed: gpu elapsed %f", simulator.__name__, arguments["block_width"], arguments["block_height"], gpu_elapsed)
return np.nan return np.nan
"""
Generates test dataset
"""
def gen_test_data(nx, ny, g): def gen_test_data(nx, ny, g):
"""
Generates test dataset
"""
width = 100.0 width = 100.0
height = 100.0 height = 100.0
dx = width / float(nx) dx = width / float(nx)
@ -264,10 +260,11 @@ class Autotuner:
return h, hu, hv, dx, dy, dt return h, hu, hv, dx, dy, dt
"""
Checks that a variable is "sane"
"""
def sanity_check(variable, bound_min, bound_max): def sanity_check(variable, bound_min, bound_max):
"""
Checks that a variable is "sane"
"""
maxval = np.amax(variable) maxval = np.amax(variable)
minval = np.amin(variable) minval = np.amin(variable)
if (np.isnan(maxval) if (np.isnan(maxval)

View File

@ -41,10 +41,6 @@ import pycuda.driver as cuda
from pycuda.tools import PageLockedMemoryPool from pycuda.tools import PageLockedMemoryPool
def safeCall(cmd): def safeCall(cmd):
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
try: try:
@ -65,16 +61,20 @@ def safeCall(cmd):
return stdout return stdout
def getGitHash(): def getGitHash():
return safeCall(["git", "rev-parse", "HEAD"]) return safeCall(["git", "rev-parse", "HEAD"])
def getGitStatus(): def getGitStatus():
return safeCall(["git", "status", "--porcelain", "-uno"]) return safeCall(["git", "status", "--porcelain", "-uno"])
def toJson(in_dict, compressed=True): def toJson(in_dict, compressed=True):
""" """
Creates JSON string from a dictionary Creates JSON string from a dictionary
""" """
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
out_dict = in_dict.copy() out_dict = in_dict.copy()
for key in out_dict: for key in out_dict:
@ -89,12 +89,14 @@ def toJson(in_dict, compressed=True):
out_dict[key] = value out_dict[key] = value
return json.dumps(out_dict) return json.dumps(out_dict)
def runSimulation(simulator, simulator_args, outfile, save_times, save_var_names=[], dt=None): 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 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_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 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': {}, 'end': {} }
profiling_data_sim_runner["start"]["t_sim_init"] = 0 profiling_data_sim_runner["start"]["t_sim_init"] = 0
profiling_data_sim_runner["end"]["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 return outdata.filename, profiling_data_sim_runner, sim.profiling_data_mpi
class Timer(object): class Timer(object):
""" """
Class which keeps track of time spent for a section of code Class which keeps track of time spent for a section of code
""" """
def __init__(self, tag, log_level=logging.DEBUG): def __init__(self, tag, log_level=logging.DEBUG):
self.tag = tag self.tag = tag
self.log_level = log_level self.log_level = log_level
@ -233,16 +232,14 @@ class Timer(object):
def elapsed(self): def elapsed(self):
return time.time() - self.start return time.time() - self.start
class PopenFileBuffer(object): class PopenFileBuffer(object):
""" """
Simple class for holding a set of tempfiles Simple class for holding a set of tempfiles
for communicating with a subprocess for communicating with a subprocess
""" """
def __init__(self): def __init__(self):
self.stdout = tempfile.TemporaryFile(mode='w+t') self.stdout = tempfile.TemporaryFile(mode='w+t')
self.stderr = tempfile.TemporaryFile(mode='w+t') self.stderr = tempfile.TemporaryFile(mode='w+t')
@ -262,10 +259,12 @@ class PopenFileBuffer(object):
return cout, cerr return cout, cerr
class IPEngine(object): class IPEngine(object):
""" """
Class for starting IPEngines for MPI processing in IPython Class for starting IPEngines for MPI processing in IPython
""" """
def __init__(self, n_engines): def __init__(self, n_engines):
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -352,10 +351,6 @@ class IPEngine(object):
self.c_buff = None self.c_buff = None
gc.collect() gc.collect()
class DataDumper(object): class DataDumper(object):
@ -366,6 +361,7 @@ class DataDumper(object):
with DataDumper("filename") as data: with DataDumper("filename") as data:
... ...
""" """
def __init__(self, filename, *args, **kwargs): def __init__(self, filename, *args, **kwargs):
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -400,7 +396,6 @@ class DataDumper(object):
#Log output #Log output
self.logger.info("Initialized " + self.filename) self.logger.info("Initialized " + self.filename)
def __enter__(self): def __enter__(self):
self.logger.info("Opening " + self.filename) self.logger.info("Opening " + self.filename)
if (self.args): if (self.args):
@ -414,7 +409,6 @@ class DataDumper(object):
self.logger.info("Closing " + self.filename) self.logger.info("Closing " + self.filename)
self.ncfile.close() self.ncfile.close()
def toJson(in_dict): def toJson(in_dict):
out_dict = in_dict.copy() out_dict = in_dict.copy()
@ -428,15 +422,13 @@ class DataDumper(object):
out_dict[key] = str(out_dict[key]) out_dict[key] = str(out_dict[key])
return json.dumps(out_dict) return json.dumps(out_dict)
class ProgressPrinter(object): class ProgressPrinter(object):
""" """
Small helper class for Small helper class for
""" """
def __init__(self, total_steps, print_every=5): def __init__(self, total_steps, print_every=5):
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
self.start = time.time() self.start = time.time()
@ -487,19 +479,16 @@ class ProgressPrinter(object):
return progressbar return progressbar
"""
Class that holds 2D data
"""
class CudaArray2D: 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): 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.logger = logging.getLogger(__name__)
self.nx = nx self.nx = nx
self.ny = ny 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.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) #self.logger.debug("Buffer <%s> [%dx%d]: Allocated ", int(self.data.gpudata), self.nx, self.ny)
def __del__(self, *args): def __del__(self, *args):
#self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny) #self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny)
self.data.gpudata.free() self.data.gpudata.free()
self.data = None self.data = None
"""
Enables downloading data from GPU to Python
"""
def download(self, stream, cpu_data=None, asynch=False, extent=None): def download(self, stream, cpu_data=None, asynch=False, extent=None):
"""
Enables downloading data from GPU to Python
"""
if (extent is None): if (extent is None):
x = self.x_halo x = self.x_halo
y = self.y_halo y = self.y_halo
@ -583,7 +572,6 @@ class CudaArray2D:
return cpu_data return cpu_data
def upload(self, stream, cpu_data, extent=None): def upload(self, stream, cpu_data, extent=None):
if (extent is None): if (extent is None):
x = self.x_halo x = self.x_halo
@ -615,21 +603,17 @@ class CudaArray2D:
copy(stream) copy(stream)
"""
Class that holds 2D data
"""
class CudaArray3D: 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): 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.logger = logging.getLogger(__name__)
self.nx = nx self.nx = nx
self.ny = ny 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) #self.logger.debug("Buffer <%s> [%dx%d]: Allocated ", int(self.data.gpudata), self.nx, self.ny)
def __del__(self, *args): def __del__(self, *args):
#self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny) #self.logger.debug("Buffer <%s> [%dx%d]: Releasing ", int(self.data.gpudata), self.nx, self.ny)
self.data.gpudata.free() self.data.gpudata.free()
self.data = None self.data = None
"""
Enables downloading data from GPU to Python
"""
def download(self, stream, asynch=False): def download(self, stream, asynch=False):
"""
Enables downloading data from GPU to Python
"""
#self.logger.debug("Downloading [%dx%d] buffer", self.nx, self.ny) #self.logger.debug("Downloading [%dx%d] buffer", self.nx, self.ny)
#Allocate host memory #Allocate host memory
#cpu_data = cuda.pagelocked_empty((self.ny, self.nx), np.float32) #cpu_data = cuda.pagelocked_empty((self.ny, self.nx), np.float32)
@ -727,18 +711,12 @@ class CudaArray3D:
return cpu_data return cpu_data
"""
A class representing an Arakawa A type (unstaggered, logically Cartesian) grid
"""
class ArakawaA2D: 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): def __init__(self, stream, nx, ny, halo_x, halo_y, cpu_variables):
""" """
Uploads initial data to the GPU device Uploads initial data to the GPU device

View File

@ -19,8 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import os import os
import numpy as np import numpy as np
@ -38,11 +36,10 @@ import pycuda.driver as cuda
from GPUSimulators import Autotuner, Common from GPUSimulators import Autotuner, Common
"""
Class which keeps track of the CUDA context and some helper functions
"""
class CudaContext(object): 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): 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 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 Set context_flags to cuda.ctx_flags.SCHED_BLOCKING_SYNC for a blocking context
""" """
self.use_cache = use_cache self.use_cache = use_cache
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
self.modules = {} self.modules = {}
@ -94,7 +92,6 @@ class CudaContext(object):
if (autotuning): if (autotuning):
self.logger.info("Autotuning enabled. It may take several minutes to run the code the first time: have patience") self.logger.info("Autotuning enabled. It may take several minutes to run the code the first time: have patience")
self.autotuner = Autotuner.Autotuner() self.autotuner = Autotuner.Autotuner()
def __del__(self, *args): def __del__(self, *args):
self.logger.info("Cleaning up CUDA context handle <%s>", str(self.cuda_context.handle)) 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.logger.debug("<%s> Detaching", str(self.cuda_context.handle))
self.cuda_context.detach() self.cuda_context.detach()
def __str__(self): def __str__(self):
return "CudaContext id " + str(self.cuda_context.handle) return "CudaContext id " + str(self.cuda_context.handle)
def hash_kernel(kernel_filename, include_dirs): def hash_kernel(kernel_filename, include_dirs):
# Generate a kernel ID for our caches # Generate a kernel ID for our caches
@ -171,18 +166,19 @@ class CudaContext(object):
return kernel_hasher.hexdigest() return kernel_hasher.hexdigest()
"""
Reads a text file and creates an OpenCL kernel from that
"""
def get_module(self, kernel_filename, def get_module(self, kernel_filename,
include_dirs=[], \ include_dirs=[], \
defines={}, \ defines={}, \
compile_args={'no_extern_c', True}, jit_compile_args={}): 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): 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)) self.logger.debug("Compilation returned %s", str(compile_success_bool))
if info_str: if info_str:
self.logger.debug("Info: %s", info_str) self.logger.debug("Info: %s", info_str)
@ -257,16 +253,18 @@ class CudaContext(object):
self.modules[kernel_hash] = module self.modules[kernel_hash] = module
return module return module
"""
Clears the kernel cache (useful for debugging & development)
"""
def clear_kernel_cache(self): def clear_kernel_cache(self):
"""
Clears the kernel cache (useful for debugging & development)
"""
self.logger.debug("Clearing cache") self.logger.debug("Clearing cache")
self.modules = {} self.modules = {}
gc.collect() gc.collect()
"""
Synchronizes all streams etc
"""
def synchronize(self): def synchronize(self):
"""
Synchronizes all streams etc
"""
self.cuda_context.synchronize() self.cuda_context.synchronize()

View File

@ -27,33 +27,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Forward-Backward linear scheme
"""
class EE2D_KP07_dimsplit (BaseSimulator): 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, def __init__(self,
context, context,
rho, rho_u, rho_v, E, rho, rho_u, rho_v, E,
@ -65,7 +43,24 @@ class EE2D_KP07_dimsplit (BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=8): 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 # Call super constructor
super().__init__(context, super().__init__(context,
nx, ny, 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))) dt_y = np.min(self.dy / (np.abs(rho_v/rho) + np.sqrt(gamma*rho)))
self.dt = min(dt_x, dt_y) self.dt = min(dt_x, dt_y)
self.cfl_data.fill(self.dt, stream=self.stream) self.cfl_data.fill(self.dt, stream=self.stream)
def substep(self, dt, step_number, external=True, internal=True): def substep(self, dt, step_number, external=True, internal=True):
self.substepDimsplit(0.5*dt, step_number, external, internal) self.substepDimsplit(0.5*dt, step_number, external, internal)

View File

@ -28,31 +28,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations
"""
class FORCE (Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -62,6 +42,20 @@ class FORCE (Simulator.BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -27,27 +27,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Harten-Lax -van Leer approximate Riemann solver
"""
class HLL (Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -57,6 +41,20 @@ class HLL (Simulator.BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -26,30 +26,12 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Forward-Backward linear scheme
"""
class HLL2 (Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -60,6 +42,20 @@ class HLL2 (Simulator.BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -32,25 +32,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Forward-Backward linear scheme
"""
class KP07 (Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -62,6 +48,20 @@ class KP07 (Simulator.BaseSimulator):
order=2, order=2,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -32,26 +32,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the dimentionally split KP07 scheme
"""
class KP07_dimsplit(Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -62,6 +47,20 @@ class KP07_dimsplit(Simulator.BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -21,43 +21,41 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
#Import packages we need #Import packages we need
from GPUSimulators import Simulator, Common from GPUSimulators import CudaContext, Simulator, Common
from GPUSimulators.Simulator import BaseSimulator, BoundaryCondition from GPUSimulators.Simulator import BaseSimulator, BoundaryCondition
import numpy as np import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Lax Friedrichs scheme
"""
class LxF (Simulator.BaseSimulator): 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, def __init__(self,
context, context: CudaContext,
h0, hu0, hv0, h0: float, hu0: float, hv0: float,
nx, ny, nx: int, ny: int,
dx, dy, dx: int, dy: int,
g, g: float,
cfl_scale=0.9, cfl_scale: float=0.9,
boundary_conditions=BoundaryCondition(), 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 # Call super constructor
super().__init__(context, super().__init__(context,
@ -66,7 +64,7 @@ class LxF (Simulator.BaseSimulator):
boundary_conditions, boundary_conditions,
cfl_scale, cfl_scale,
1, 1,
block_width, block_height); block_width, block_height)
self.g = np.float32(g) self.g = np.float32(g)
# Get kernels # Get kernels
@ -99,6 +97,11 @@ class LxF (Simulator.BaseSimulator):
self.cfl_data.fill(dt, stream=self.stream) self.cfl_data.fill(dt, stream=self.stream)
def substep(self, dt, step_number): 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.kernel.prepared_async_call(self.grid_size, self.block_size, self.stream,
self.nx, self.ny, self.nx, self.ny,
self.dx, self.dy, dt, self.dx, self.dy, dt,

View File

@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import logging import logging
from GPUSimulators import Simulator from GPUSimulators import Simulator
import numpy as np import numpy as np
@ -30,12 +29,12 @@ import pycuda.driver as cuda
#import nvtx #import nvtx
class MPIGrid(object): class MPIGrid(object):
""" """
Class which represents an MPI grid of nodes. Facilitates easy communication between Class which represents an MPI grid of nodes. Facilitates easy communication between
neighboring nodes neighboring nodes
""" """
def __init__(self, comm, ndims=2): def __init__(self, comm, ndims=2):
self.logger = logging.getLogger(__name__) self.logger = logging.getLogger(__name__)
@ -144,7 +143,6 @@ class MPIGrid(object):
return grid return grid
def gather(self, data, root=0): def gather(self, data, root=0):
out_data = None out_data = None
if (self.comm.rank == root): if (self.comm.rank == root):
@ -206,6 +204,7 @@ class MPISimulator(Simulator.BaseSimulator):
""" """
Class which handles communication between simulators on different MPI nodes Class which handles communication between simulators on different MPI nodes
""" """
def __init__(self, sim, grid): def __init__(self, sim, grid):
self.profiling_data_mpi = { 'start': {}, 'end': {} } self.profiling_data_mpi = { 'start': {}, 'end': {} }
self.profiling_data_mpi["start"]["t_mpi_halo_exchange"] = 0 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])) self.logger.debug("Local dt: {:f}, global dt: {:f}".format(local_dt[0], global_dt[0]))
return global_dt[0] return global_dt[0]
def getExtent(self): def getExtent(self):
""" """
Function which returns the extent of node with rank Function which returns the extent of node with rank
rank in the grid rank in the grid
""" """
width = self.sim.nx*self.sim.dx width = self.sim.nx*self.sim.dx
height = self.sim.ny*self.sim.dy height = self.sim.ny*self.sim.dy
i, j = self.grid.getCoordinate() i, j = self.grid.getCoordinate()

View File

@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import logging import logging
from GPUSimulators import Simulator, CudaContext from GPUSimulators import Simulator, CudaContext
import numpy as np import numpy as np
@ -28,6 +27,7 @@ import pycuda.driver as cuda
import time import time
class SHMEMSimulator(Simulator.BaseSimulator): class SHMEMSimulator(Simulator.BaseSimulator):
""" """
Class which handles communication and synchronization between simulators in different Class which handles communication and synchronization between simulators in different

View File

@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import logging import logging
from GPUSimulators import Simulator, CudaContext from GPUSimulators import Simulator, CudaContext
import numpy as np import numpy as np
@ -28,6 +27,7 @@ import pycuda.driver as cuda
import time import time
class SHMEMGrid(object): class SHMEMGrid(object):
""" """
Class which represents an SHMEM grid of GPUs. Facilitates easy communication between Class which represents an SHMEM grid of GPUs. Facilitates easy communication between
@ -156,6 +156,7 @@ class SHMEMGrid(object):
return grid return grid
class SHMEMSimulatorGroup(object): class SHMEMSimulatorGroup(object):
""" """
Class which handles communication and synchronization between simulators in different 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.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))) self.logger.debug("Initialized {:d} subdomains".format(len(self.sims)))
def substep(self, dt, step_number): def substep(self, dt, step_number):
self.exchange() self.exchange()

View File

@ -29,23 +29,20 @@ import pycuda.compiler as cuda_compiler
import pycuda.gpuarray import pycuda.gpuarray
import pycuda.driver as cuda import pycuda.driver as cuda
from GPUSimulators import Common from GPUSimulators import Common, CudaContext
class BoundaryCondition(object): class BoundaryCondition(object):
""" """
Class for holding boundary conditions for global boundaries Class for holding boundary conditions for global boundaries
""" """
class Type(IntEnum): class Type(IntEnum):
""" """
Enum that describes the different types of boundary conditions Enum that describes the different types of boundary conditions
WARNING: MUST MATCH THAT OF common.h IN CUDA WARNING: MUST MATCH THAT OF common.h IN CUDA
""" """
Dirichlet = 0, Dirichlet = 0,
Neumann = 1, Neumann = 1,
Periodic = 2, Periodic = 2,
@ -60,6 +57,7 @@ class BoundaryCondition(object):
""" """
Constructor Constructor
""" """
self.north = types['north'] self.north = types['north']
self.south = types['south'] self.south = types['south']
self.east = types['east'] self.east = types['east']
@ -74,11 +72,11 @@ class BoundaryCondition(object):
def __str__(self): 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)) 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): def asCodedInt(self):
""" """
Helper function which packs four boundary conditions into one integer Helper function which packs four boundary conditions into one integer
""" """
bc = 0 bc = 0
bc = bc | (self.north & 0x0000000F) << 24 bc = bc | (self.north & 0x0000000F) << 24
bc = bc | (self.south & 0x0000000F) << 16 bc = bc | (self.south & 0x0000000F) << 16
@ -98,39 +96,36 @@ class BoundaryCondition(object):
types['east'] = BoundaryCondition.Type((bc >> 8) & 0x0000000F) types['east'] = BoundaryCondition.Type((bc >> 8) & 0x0000000F)
types['west'] = BoundaryCondition.Type((bc >> 0) & 0x0000000F) types['west'] = BoundaryCondition.Type((bc >> 0) & 0x0000000F)
return types return types
class BaseSimulator(object): class BaseSimulator(object):
def __init__(self, def __init__(self,
context, context: CudaContext,
nx, ny, nx: int, ny: int,
dx, dy, dx: int, dy: int,
boundary_conditions, boundary_conditions: BoundaryCondition,
cfl_scale, cfl_scale: float,
num_substeps, num_substeps: int,
block_width, block_height): block_width: int, block_height: int):
""" """
Initialization routine Initialization routine
context: GPU context to use
kernel_wrapper: wrapper function of GPU kernel Args:
h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells context: GPU context to use
hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells kernel_wrapper: wrapper function of GPU kernel
hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells h0: Water depth incl ghost cells, (nx+1)*(ny+1) cells
nx: Number of cells along x-axis hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+1) cells
ny: Number of cells along y-axis hv0: Initial momentum along y-axis incl ghost cells, (nx+1)*(ny+1) cells
dx: Grid cell spacing along x-axis (20 000 m) nx: Number of cells along x-axis
dy: Grid cell spacing along y-axis (20 000 m) ny: Number of cells along y-axis
dt: Size of each timestep (90 s) dx: Grid cell spacing along x-axis (20 000 m)
cfl_scale: Courant number dy: Grid cell spacing along y-axis (20 000 m)
num_substeps: Number of substeps to perform for a full step dt: Size of each timestep (90 s)
cfl_scale: Courant number
num_substeps: Number of substeps to perform for a full step
""" """
#Get logger #Get logger
self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__) self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
@ -147,7 +142,7 @@ class BaseSimulator(object):
self.num_substeps = num_substeps self.num_substeps = num_substeps
#Handle autotuning block size #Handle autotuning block size
if (self.context.autotuner): if self.context.autotuner:
peak_configuration = self.context.autotuner.get_peak_performance(self.__class__) peak_configuration = self.context.autotuner.get_peak_performance(self.__class__)
block_width = int(peak_configuration["block_width"]) block_width = int(peak_configuration["block_width"])
block_height = int(peak_configuration["block_height"]) block_height = int(peak_configuration["block_height"])
@ -167,12 +162,10 @@ class BaseSimulator(object):
#Keep track of simulation time and number of timesteps #Keep track of simulation time and number of timesteps
self.t = 0.0 self.t = 0.0
self.nt = 0 self.nt = 0
def __str__(self): def __str__(self):
return "{:s} [{:d}x{:d}]".format(self.__class__.__name__, self.nx, self.ny) return "{:s} [{:d}x{:d}]".format(self.__class__.__name__, self.nx, self.ny)
def simulate(self, t, dt=None): def simulate(self, t, dt=None):
""" """
Function which simulates t_end seconds using the step function 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()),) e.args += ("Step={:d}, time={:f}".format(self.simSteps(), self.simTime()),)
raise raise
def step(self, dt: int):
def step(self, dt):
""" """
Function which performs one single timestep of size dt Function which performs one single timestep of size dt
Args:
dt: Size of each timestep (seconds)
""" """
for i in range(self.num_substeps): for i in range(self.num_substeps):
self.substep(dt, i) self.substep(dt, i)
@ -253,6 +249,7 @@ class BaseSimulator(object):
""" """
Function which performs one single substep with stepsize dt Function which performs one single substep with stepsize dt
""" """
raise(NotImplementedError("Needs to be implemented in subclass")) raise(NotImplementedError("Needs to be implemented in subclass"))
def getOutput(self): def getOutput(self):
@ -264,23 +261,13 @@ class BaseSimulator(object):
def computeDt(self): def computeDt(self):
raise(NotImplementedError("Needs to be implemented in subclass")) raise(NotImplementedError("Needs to be implemented in subclass"))
def stepOrderToCodedInt(step, order): def stepOrderToCodedInt(step, order):
""" """
Helper function which packs the step and order into a single integer Helper function which packs the step and order into a single integer
""" """
step_order = (step << 16) | (order & 0x0000ffff) step_order = (step << 16) | (order & 0x0000ffff)
#print("Step: {0:032b}".format(step)) #print("Step: {0:032b}".format(step))
#print("Order: {0:032b}".format(order)) #print("Order: {0:032b}".format(order))

View File

@ -28,25 +28,11 @@ import numpy as np
from pycuda import gpuarray from pycuda import gpuarray
"""
Class that solves the SW equations using the Forward-Backward linear scheme
"""
class WAF (Simulator.BaseSimulator): 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, def __init__(self,
context, context,
h0, hu0, hv0, h0, hu0, hv0,
@ -56,6 +42,20 @@ class WAF (Simulator.BaseSimulator):
cfl_scale=0.9, cfl_scale=0.9,
boundary_conditions=BoundaryCondition(), boundary_conditions=BoundaryCondition(),
block_width=16, block_height=16): 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 # Call super constructor
super().__init__(context, super().__init__(context,

View File

@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
from GPUSimulators.Simulator import BoundaryCondition from GPUSimulators.Simulator import BoundaryCondition
import numpy as np import numpy as np
import gc 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) return highres_solution.reshape([int(ny), int(y_factor), int(nx), int(x_factor)]).mean(3).mean(1)
def bump(nx: int, ny: int, width: int, height: int,
def bump(nx, ny, width, height,
bump_size=None, bump_size=None,
ref_nx=None, ref_ny=None, ref_nx=None, ref_ny=None,
x_center=0.5, y_center=0.5, x_center=0.5, y_center=0.5,
@ -189,12 +185,7 @@ def genShockBubble(nx, ny, gamma, grid=None):
} }
return arguments return arguments
def genKelvinHelmholtz(nx, ny, gamma, roughness=0.125, grid=None, index=None): def genKelvinHelmholtz(nx, ny, gamma, roughness=0.125, grid=None, index=None):
""" """
Roughness parameter in (0, 1.0] determines how "squiggly" 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 Generates the zones of the two fluids of K-H
""" """
zone = np.zeros((ny, nx), dtype=np.int32) 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 return arguments
def genRayleighTaylor(nx, ny, gamma, version=0, grid=None): def genRayleighTaylor(nx, ny, gamma, version=0, grid=None):
""" """
Generates Rayleigh-Taylor instability case Generates Rayleigh-Taylor instability case
""" """
width = 0.5 width = 0.5
height = 1.5 height = 1.5
g = 0.1 g = 0.1

View File

@ -19,14 +19,11 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
""" """
import numpy as np import numpy as np
from matplotlib.colors import Normalize from matplotlib.colors import Normalize
def genSchlieren(rho): def genSchlieren(rho):
#Compute length of z-component of normalized gradient vector #Compute length of z-component of normalized gradient vector
normal = np.gradient(rho) #[x, y, 1] normal = np.gradient(rho) #[x, y, 1]