# -*- coding: utf-8 -*- """ This python module implements the Kurganov-Petrova numerical scheme for the shallow water equations, described in A. Kurganov & Guergana Petrova A Second-Order Well-Balanced Positivity Preserving Central-Upwind Scheme for the Saint-Venant System Communications in Mathematical Sciences, 5 (2007), 133-160. Copyright (C) 2016 SINTEF ICT This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ #Import packages we need from GPUSimulators import Simulator, Common from GPUSimulators.Simulator import BaseSimulator, BoundaryCondition import numpy as np """ Class that solves the SW equations using the dimentionally split KP07 scheme """ class KP07_dimsplit (Simulator.BaseSimulator): """ 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, dt, \ g, \ theta=1.3, \ order=2, \ boundary_conditions=BoundaryCondition(), \ block_width=16, block_height=16): # Call super constructor super().__init__(context, \ nx, ny, \ dx, dy, dt, \ block_width, block_height) self.g = np.float32(g) self.theta = np.float32(theta) self.order = np.int32(order) self.boundary_conditions = boundary_conditions.asCodedInt() #Get kernels self.kernel = context.get_prepared_kernel("cuda/SWE2D_KP07_dimsplit.cu", "KP07DimsplitKernel", \ "iifffffiiPiPiPiPiPiPi", \ defines={ 'BLOCK_WIDTH': self.block_size[0], 'BLOCK_HEIGHT': self.block_size[1] }, \ compile_args={ 'no_extern_c': True, 'options': ["--use_fast_math"], }, \ jit_compile_args={}) #Create data by uploading to device self.u0 = Common.ArakawaA2D(self.stream, \ nx, ny, \ 2, 2, \ [h0, hu0, hv0]) self.u1 = Common.ArakawaA2D(self.stream, \ nx, ny, \ 2, 2, \ [None, None, None]) def step(self, dt): if (self.order == 1): self.substepDimsplit(dt, substep=(self.nt % 2)) elif (self.order == 2): self.substepDimsplit(dt, substep=0) self.substepDimsplit(dt, substep=1) else: raise(NotImplementedError("Order {:d} is not implemented".format(self.order))) self.t += dt self.nt += 1 def substepDimsplit(self, dt, substep): self.kernel.prepared_async_call(self.grid_size, self.block_size, self.stream, \ self.nx, self.ny, \ self.dx, self.dy, dt, \ self.g, \ self.theta, \ Simulator.stepOrderToCodedInt(step=substep, order=self.order), \ self.boundary_conditions, \ self.u0[0].data.gpudata, self.u0[0].data.strides[0], \ self.u0[1].data.gpudata, self.u0[1].data.strides[0], \ self.u0[2].data.gpudata, self.u0[2].data.strides[0], \ self.u1[0].data.gpudata, self.u1[0].data.strides[0], \ self.u1[1].data.gpudata, self.u1[1].data.strides[0], \ self.u1[2].data.gpudata, self.u1[2].data.strides[0]) self.u0, self.u1 = self.u1, self.u0 def download(self): return self.u0.download(self.stream)