def __init__(self, \ cl_ctx, \ eta0, hu0, hv0, Hi, \ nx, ny, \ dx, dy, dt, \ g, f, r, \ t=0.0, \ theta=1.3, rk_order=2, \ coriolis_beta=0.0, \ y_zero_reference_cell = 0, \ max_wind_direction_perturbation = 0, \ wind_stress=WindStress.NoWindStress(), \ boundary_conditions=Common.BoundaryConditions(), \ h0AsWaterElevation=False, \ reportGeostrophicEquilibrium=False, \ write_netcdf=False, \ ignore_ghostcells=False, \ offset_x=0, offset_y=0, \ block_width=16, block_height=16): """ Initialization routine eta0: Initial deviation from mean sea level incl ghost cells, (nx+2)*(ny+2) cells hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+2) cells hv0: Initial momentum along y-axis incl ghost cells, (nx+2)*(ny+1) cells Hi: Depth from equilibrium defined on cell corners, (nx+5)*(ny+5) corners 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) f: Coriolis parameter (1.2e-4 s^1), effectively as f = f + beta*y r: Bottom friction coefficient (2.4e-3 m/s) t: Start simulation at time t theta: MINMOD theta used the reconstructions of the derivatives in the numerical scheme rk_order: Order of Runge Kutta method {1,2*,3} coriolis_beta: Coriolis linear factor -> f = f + beta*(y-y_0) y_zero_reference_cell: The cell representing y_0 in the above, defined as the lower face of the cell . max_wind_direction_perturbation: Large-scale model error emulation by per-time-step perturbation of wind direction by +/- max_wind_direction_perturbation (degrees) wind_stress: Wind stress parameters boundary_conditions: Boundary condition object h0AsWaterElevation: True if h0 is described by the surface elevation, and false if h0 is described by water depth reportGeostrophicEquilibrium: Calculate the Geostrophic Equilibrium variables for each superstep write_netcdf: Write the results after each superstep to a netCDF file """ ## After changing from (h, B) to (eta, H), several of the simulator settings used are wrong. This check will help detect that. if (np.sum(eta0 - Hi[:-1, :-1] > 0) > nx): assert ( False ), "It seems you are using water depth/elevation h and bottom topography B, while you should use water level eta and equillibrium depth H." assert (rk_order < 4 or rk_order > 0 ), "Only 1st, 2nd and 3rd order Runge Kutta supported" if (rk_order == 3): assert (r == 0.0 ), "3rd order Runge Kutta supported only without friction" # Sort out internally represented ghost_cells in the presence of given # boundary conditions ghost_cells_x = 2 ghost_cells_y = 2 y_zero_reference_cell = 2 + y_zero_reference_cell # Boundary conditions self.boundary_conditions = boundary_conditions if (boundary_conditions.isSponge()): nx = nx + boundary_conditions.spongeCells[ 1] + boundary_conditions.spongeCells[3] - 2 * ghost_cells_x ny = ny + boundary_conditions.spongeCells[ 0] + boundary_conditions.spongeCells[2] - 2 * ghost_cells_y y_zero_reference_cell = boundary_conditions.spongeCells[ 2] + y_zero_reference_cell A = None self.max_wind_direction_perturbation = max_wind_direction_perturbation super(CDKLM16, self).__init__(cl_ctx, \ nx, ny, \ ghost_cells_x, \ ghost_cells_y, \ dx, dy, dt, \ g, f, r, A, \ t, \ theta, rk_order, \ coriolis_beta, \ y_zero_reference_cell, \ wind_stress, \ write_netcdf, \ ignore_ghostcells, \ offset_x, offset_y, \ block_width, block_height) #Get kernels self.kernel = Common.get_kernel(self.cl_ctx, "CDKLM16_kernel.opencl", block_width, block_height) #Create data by uploading to device self.cl_data = Common.SWEDataArakawaA(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, eta0, hu0, hv0) ## Allocating memory for geostrophical equilibrium variables self.reportGeostrophicEquilibrium = np.int32( reportGeostrophicEquilibrium) dummy_zero_array = np.zeros( (ny + 2 * ghost_cells_y, nx + 2 * ghost_cells_x), dtype=np.float32, order='C') self.geoEq_uxpvy = Common.OpenCLArray2D(cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, dummy_zero_array) self.geoEq_Kx = Common.OpenCLArray2D(cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, dummy_zero_array) self.geoEq_Ly = Common.OpenCLArray2D(cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, dummy_zero_array) #Bathymetry self.bathymetry = Common.Bathymetry(self.cl_ctx, self.cl_queue, nx, ny, ghost_cells_x, ghost_cells_y, Hi, boundary_conditions) self.h0AsWaterElevation = h0AsWaterElevation if self.h0AsWaterElevation: self.bathymetry.waterElevationToDepth(self.cl_data.h0) self.bc_kernel = Common.BoundaryConditionsArakawaA(self.cl_ctx, \ self.nx, \ self.ny, \ ghost_cells_x, \ ghost_cells_y, \ self.boundary_conditions, \ ) if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, ignore_ghostcells=self.ignore_ghostcells, \ offset_x=self.offset_x, offset_y=self.offset_y)
def __init__(self, \ cl_ctx, \ h0, hu0, hv0, \ Bi, \ nx, ny, \ dx, dy, dt, \ g, f, r, \ theta=1.3, use_rk2=True, \ wind_stress=WindStress.NoWindStress(), \ boundary_conditions=Common.BoundaryConditions(), \ h0AsWaterElevation=True, \ block_width=16, block_height=16): print("Using RECURSIVE CDKLM scheme!") self.cl_ctx = cl_ctx #Create an OpenCL command queue self.cl_queue = cl.CommandQueue(self.cl_ctx) #Get kernels self.kernel = Common.get_kernel(self.cl_ctx, "recursiveCDKLM16_kernel.opencl", defines={'block_width': block_width, 'block_height': block_height}) # Boundary Conditions self.boundary_conditions = boundary_conditions self.boundaryType = np.int32(1) if (boundary_conditions.north == 2 and boundary_conditions.east == 2): self.boundaryType = np.int32(2) elif (boundary_conditions.north == 2): self.boundaryType = np.int32(3) elif (boundary_conditions.east == 2): self.boundaryType = np.int32(4) #Create data by uploading to device ghost_cells_x = 3 ghost_cells_y = 3 self.ghost_cells_x = 3 self.ghost_cells_y = 3 if (boundary_conditions.isSponge()): nx = nx + boundary_conditions.spongeCells[1] + boundary_conditions.spongeCells[3] - 2*self.ghost_cells_x ny = ny + boundary_conditions.spongeCells[0] + boundary_conditions.spongeCells[2] - 2*self.ghost_cells_y y_zero_reference = boundary_conditions.spongeCells[2] #Create data by uploading to device self.cl_data = Common.SWEDataArakawaA(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, h0, hu0, hv0) #Bathymetry self.bathymetry = Common.Bathymetry(self.cl_ctx, self.cl_queue, nx, ny, ghost_cells_x, ghost_cells_y, Bi, boundary_conditions) #Save input parameters #Notice that we need to specify them in the correct dataformat for the #OpenCL kernel self.nx = np.int32(nx) self.ny = np.int32(ny) self.dx = np.float32(dx) self.dy = np.float32(dy) self.dt = np.float32(dt) self.g = np.float32(g) self.f = np.float32(f) self.r = np.float32(r) self.theta = np.float32(theta) self.use_rk2 = use_rk2 self.wind_stress = wind_stress self.h0AsWaterElevation = h0AsWaterElevation #Initialize time self.t = np.float32(0.0) #Compute kernel launch parameters self.local_size = (block_width, block_height) self.global_size = ( \ int(np.ceil(self.nx / float(self.local_size[0])) * self.local_size[0]), \ int(np.ceil(self.ny / float(self.local_size[1])) * self.local_size[1]) \ ) self.bc_kernel = Common.BoundaryConditionsArakawaA(self.cl_ctx, \ self.nx, \ self.ny, \ ghost_cells_x, \ ghost_cells_y, \ self.boundary_conditions, \ ) if self.h0AsWaterElevation: self.bathymetry.waterElevationToDepth(self.cl_data.h0)
def __init__(self, \ cl_ctx, \ eta0, Hi, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f=0.0, r=0.0, \ t=0.0, \ theta=1.3, use_rk2=True, coriolis_beta=0.0, \ y_zero_reference_cell = 0, \ wind_stress=WindStress.NoWindStress(), \ boundary_conditions=Common.BoundaryConditions(), \ write_netcdf=False, \ ignore_ghostcells=False, \ offset_x=0, offset_y=0, \ block_width=16, block_height=16): """ Initialization routine eta0: Initial deviation from mean sea level incl ghost cells, (nx+2)*(ny+2) cells hu0: Initial momentum along x-axis incl ghost cells, (nx+1)*(ny+2) cells hv0: Initial momentum along y-axis incl ghost cells, (nx+2)*(ny+1) cells Hi: Depth from equilibrium defined on cell corners, (nx+5)*(ny+5) corners 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) f: Coriolis parameter (1.2e-4 s^1), effectively as f = f + beta*y r: Bottom friction coefficient (2.4e-3 m/s) t: Start simulation at time t theta: MINMOD theta used the reconstructions of the derivatives in the numerical scheme use_rk2: Boolean if to use 2nd order Runge-Kutta (false -> 1st order forward Euler) coriolis_beta: Coriolis linear factor -> f = f + beta*(y-y_0) y_zero_reference_cell: The cell representing y_0 in the above, defined as the lower face of the cell . wind_stress: Wind stress parameters boundary_conditions: Boundary condition object write_netcdf: Write the results after each superstep to a netCDF file """ ## After changing from (h, B) to (eta, H), several of the simulator settings used are wrong. This check will help detect that. if ( np.sum(eta0 - Hi[:-1, :-1] > 0) > nx): assert(False), "It seems you are using water depth/elevation h and bottom topography B, while you should use water level eta and equillibrium depth H." ghost_cells_x = 2 ghost_cells_y = 2 y_zero_reference_cell = 2.0 + y_zero_reference_cell # Boundary conditions self.boundary_conditions = boundary_conditions # Extend the computational domain if the boundary conditions # require it if (boundary_conditions.isSponge()): nx = nx + boundary_conditions.spongeCells[1] + boundary_conditions.spongeCells[3] - 2*ghost_cells_x ny = ny + boundary_conditions.spongeCells[0] + boundary_conditions.spongeCells[2] - 2*ghost_cells_y y_zero_reference_cell = boundary_conditions.spongeCells[2] + y_zero_reference_cell self.use_rk2 = use_rk2 rk_order = np.int32(use_rk2 + 1) A = None super(KP07, self).__init__(cl_ctx, \ nx, ny, \ ghost_cells_x, \ ghost_cells_y, \ dx, dy, dt, \ g, f, r, A, \ t, \ theta, rk_order, \ coriolis_beta, \ y_zero_reference_cell, \ wind_stress, \ write_netcdf, \ ignore_ghostcells, \ offset_x, offset_y, \ block_width, block_height) #Get kernels self.kp07_kernel = Common.get_kernel(self.cl_ctx, "KP07_kernel.opencl", block_width, block_height) #Create data by uploading to device self.cl_data = Common.SWEDataArakawaA(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, eta0, hu0, hv0) #Bathymetry self.bathymetry = Common.Bathymetry(self.cl_ctx, self.cl_queue, nx, ny, ghost_cells_x, ghost_cells_y, Hi, boundary_conditions) self.bc_kernel = Common.BoundaryConditionsArakawaA(self.cl_ctx, \ self.nx, \ self.ny, \ ghost_cells_x, \ ghost_cells_y, \ self.boundary_conditions) if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, ignore_ghostcells=self.ignore_ghostcells, \ offset_x=self.offset_x, offset_y=self.offset_y)