def __init__(self, numDrifters, observation_variance=0.1, \ boundaryConditions=Common.BoundaryConditions(), \ domain_size_x=1.0, domain_size_y=1.0): """ Creates a GlobalParticles object for drift trajectory ensemble. numDrifters: number of drifers in the collection, not included the observation observation_variance: uncertainty of observation position boundaryConditions: BoundaryConditions object, relevant during re-initialization of particles. """ self.numDrifters = numDrifters # Observation index is the last particle self.obs_index = self.numDrifters self.observation_variance = observation_variance self.positions = None # Needs to be allocated in the child class # Should represent all particles plus observation self.domain_size_x = domain_size_x self.domain_size_y = domain_size_y # Boundary conditions are read from a BoundaryConditions object self.boundaryConditions = boundaryConditions
def fromfilename(cls, cl_ctx, filename, cont_write_netcdf=True): """ Initialize and hotstart simulation from nc-file. cont_write_netcdf: Continue to write the results after each superstep to a new netCDF file filename: Continue simulation based on parameters and last timestep in this file """ # open nc-file sim_reader = SimReader.SimNetCDFReader(filename, ignore_ghostcells=False) sim_name = str(sim_reader.get('simulator_short')) assert sim_name == cls.__name__, \ "Trying to initialize a " + \ cls.__name__ + " simulator with netCDF file based on " \ + sim_name + " results." # read parameters nx = sim_reader.get("nx") ny = sim_reader.get("ny") dx = sim_reader.get("dx") dy = sim_reader.get("dy") width = nx * dx height = ny * dy dt = sim_reader.get("dt") g = sim_reader.get("g") r = sim_reader.get("bottom_friction_r") A = sim_reader.get("eddy_viscosity_coefficient") f = sim_reader.get("coriolis_force") beta = sim_reader.get("coriolis_beta") minmodTheta = sim_reader.get("minmod_theta") timeIntegrator = sim_reader.get("time_integrator") y_zero_reference_cell = sim_reader.get("y_zero_reference_cell") wind_stress_type = sim_reader.get("wind_stress_type") wind = Common.WindStressParams(type=wind_stress_type) boundaryConditions = Common.BoundaryConditions( \ sim_reader.getBC()[0], sim_reader.getBC()[1], \ sim_reader.getBC()[2], sim_reader.getBC()[3], \ sim_reader.getBCSpongeCells()) h0 = sim_reader.getH() # get last timestep (including simulation time of last timestep) eta0, hu0, hv0, time0 = sim_reader.getLastTimeStep() return cls(cl_ctx, \ h0, eta0, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f, r, \ t=time0, \ wind_stress=wind, \ boundary_conditions=boundaryConditions, \ write_netcdf=cont_write_netcdf)
def setGridInfo(self, nx, ny, dx, dy, dt, boundaryConditions=Common.BoundaryConditions(), eta=None, hu=None, hv=None, H=None): self.nx = nx self.ny = ny self.dx = dx self.dy = dy self.dt = dt # Default values for now: self.initialization_variance = 10 * dx self.midPoint = 0.5 * np.array([self.nx * self.dx, self.ny * self.dy]) self.initialization_cov = np.eye(2) * self.initialization_variance self.boundaryConditions = boundaryConditions assert (self.simType == 'CDKLM16' ), 'CDKLM16 is currently the only supported scheme' #if self.simType == 'CDKLM16': self.ghostCells = np.array([2, 2, 2, 2]) if self.boundaryConditions.isSponge(): sponge = self.boundaryConditions.getSponge() for i in range(4): if sponge[i] > 0: self.ghostCells[i] = sponge[i] dataShape = (ny + self.ghostCells[0] + self.ghostCells[2], nx + self.ghostCells[1] + self.ghostCells[3]) self.base_eta = eta self.base_hu = hu self.base_hv = hv self.base_H = H # Create base initial data: if self.base_eta is None: self.base_eta = np.zeros(dataShape, dtype=np.float32, order='C') if self.base_hu is None: self.base_hu = np.zeros(dataShape, dtype=np.float32, order='C') if self.base_hv is None: self.base_hv = np.zeros(dataShape, dtype=np.float32, order='C') # Bathymetry: if self.base_H is None: waterDepth = 10 self.base_H = np.ones((dataShape[0] + 1, dataShape[1] + 1), dtype=np.float32, order='C') * waterDepth self.setParameters()
def __init__(self, cl_ctx, numDrifters, \ observation_variance=0.1, \ boundaryConditions=Common.BoundaryConditions(), \ domain_size_x=1.0, domain_size_y=1.0, \ cl_queue=None, \ block_width = 64): super(GPUDrifterCollection, self).__init__(numDrifters, observation_variance=observation_variance, boundaryConditions=boundaryConditions, domain_size_x=domain_size_x, domain_size_y=domain_size_y) # Define OpenCL environment: self.cl_ctx = cl_ctx self.block_width = block_width self.block_height = 1 # TODO: Where should the cl_queue come from? # For sure, the drifter and the ocean simulator should use # the same queue... self.cl_queue = cl_queue if self.cl_queue is None: self.cl_queue = pyopencl.CommandQueue(self.cl_ctx) self.sensitivity = 1.0 self.driftersHost = np.zeros((self.getNumDrifters() + 1, 2)).astype(np.float32, order='C') self.driftersDevice = Common.OpenCLArray2D(self.cl_ctx, \ 2, self.getNumDrifters()+1, 0, 0, \ self.driftersHost) self.driftKernels = Common.get_kernel(self.cl_ctx,\ "driftKernels.opencl", self.block_width, self.block_height) self.local_size = (self.block_width, self.block_height) self.global_size = (int(np.ceil((self.getNumDrifters() + 2)/float(self.block_width))*self.block_width), self.block_height )
def __init__(self, numDrifters, observation_variance=0.1, boundaryConditions=Common.BoundaryConditions(), domain_size_x=1.0, domain_size_y=1.0): """ Creates a GlobalParticles object for drift trajectory ensemble. numDrifters: number of drifters in the collection, not included the observation observation_variance: uncertainty of observation position boundaryConditions: BoundaryConditions object, relevant during re-initialization of particles. """ # Call parent constructor super(CPUDrifterCollection, self).__init__(numDrifters, observation_variance=observation_variance, boundaryConditions=boundaryConditions, domain_size_x=domain_size_x, domain_size_y=domain_size_y) # One position for every particle plus observation self.positions = np.zeros((self.numDrifters + 1, 2))
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, \ H, eta0, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f, r, A=0.0, \ t=0.0, \ 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 H: Water depth incl ghost cells, (nx+2)*(ny+2) cells 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 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) A: Eddy viscosity coefficient (O(dx)) t: Start simulation at time t 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 """ # Sort out internally represented ghost_cells in the presence of given # boundary conditions halo_x = 1 halo_y = 1 ghost_cells_x = 1 ghost_cells_y = 1 y_zero_reference_cell = y_zero_reference_cell + 1 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 = y_zero_reference_cell + boundary_conditions.spongeCells[ 2] # self.<parameters> are sat in parent constructor: rk_order = None theta = None super(CTCS, 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.u_kernel = Common.get_kernel(self.cl_ctx, "CTCS_U_kernel.opencl", block_width, block_height) self.v_kernel = Common.get_kernel(self.cl_ctx, "CTCS_V_kernel.opencl", block_width, block_height) self.eta_kernel = Common.get_kernel(self.cl_ctx, "CTCS_eta_kernel.opencl", block_width, block_height) # In PyOpenCL version 2, it would be more efficient to store the # exectutional kernel functions rather than the kernel object # currently used. # So, instead of self.u_kernel, we would like to use: # self.u_kernel_exec = self.u_kernel.computeUKernel #Create data by uploading to device self.H = Common.OpenCLArray2D(self.cl_ctx, nx, ny, halo_x, halo_y, H) self.cl_data = Common.SWEDataArakawaC(self.cl_ctx, nx, ny, halo_x, halo_y, eta0, hu0, hv0) # Global size needs to be larger than the default from parent.__init__ self.global_size = ( \ int(np.ceil((self.nx+2*halo_x) / float(self.local_size[0])) * self.local_size[0]), \ int(np.ceil((self.ny+2*halo_y) / float(self.local_size[1])) * self.local_size[1]) \ ) self.bc_kernel = CTCS_boundary_condition(self.cl_ctx, \ self.nx, \ self.ny, \ self.boundary_conditions, \ halo_x, halo_y \ ) if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, ignore_ghostcells=self.ignore_ghostcells, \ staggered_grid=True, offset_x=self.offset_x, offset_y=self.offset_y)
def __init__(self, \ cl_ctx, \ H, eta0, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f, r, \ wind_stress=Common.WindStressParams(), \ boundary_conditions=Common.BoundaryConditions(), \ write_netcdf=False, \ block_width=16, block_height=16): reload(Common) self.cl_ctx = cl_ctx self.boundary_conditions = boundary_conditions self.rk_order = 'NA' self.theta = 'NA' self.A = 'NA' #Create an OpenCL command queue self.cl_queue = cl.CommandQueue(self.cl_ctx) #Get kernels self.u_kernel = Common.get_kernel(self.cl_ctx, "FBL_U_kernel.opencl", block_width, block_height) self.v_kernel = Common.get_kernel(self.cl_ctx, "FBL_V_kernel.opencl", block_width, block_height) self.eta_kernel = Common.get_kernel(self.cl_ctx, "FBL_eta_kernel.opencl", block_width, block_height) #Create data by uploading to device ghost_cells_x = 0 ghost_cells_y = 0 self.ghost_cells_x = ghost_cells_x self.ghost_cells_y = ghost_cells_y self.asym_ghost_cells = [0, 0, 0, 0] # [N, E, S, W] # Add asym ghost cell if periodic boundary condition: if (self.boundary_conditions.north == 2) or \ (self.boundary_conditions.south == 2): self.asym_ghost_cells[0] = 1 if (self.boundary_conditions.east == 2) or \ (self.boundary_conditions.west == 2): self.asym_ghost_cells[1] = 1 if boundary_conditions.isSponge(): nx = nx + boundary_conditions.spongeCells[ 1] + boundary_conditions.spongeCells[ 3] # - self.asym_ghost_cells[1] - self.asym_ghost_cells[3] ny = ny + boundary_conditions.spongeCells[ 0] + boundary_conditions.spongeCells[ 2] # - self.asym_ghost_cells[0] - self.asym_ghost_cells[2] self.H = Common.OpenCLArray2D(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, H, self.asym_ghost_cells) self.cl_data = Common.SWEDataArakawaC(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, eta0, hu0, hv0, self.asym_ghost_cells) #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.nx_halo = np.int32(nx + self.asym_ghost_cells[1] + self.asym_ghost_cells[3]) self.ny_halo = np.int32(ny + self.asym_ghost_cells[0] + self.asym_ghost_cells[2]) 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.wind_stress = wind_stress #Initialize time self.t = np.float32(0.0) #Compute kernel launch parameters self.local_size = ( block_width, block_height ) # WARNING::: MUST MATCH defines of block_width/height in kernels! self.global_size = ( \ int(np.ceil(self.nx_halo / float(self.local_size[0])) * self.local_size[0]), \ int(np.ceil(self.ny_halo / float(self.local_size[1])) * self.local_size[1]) \ ) #print("FBL.local_size: " + str(self.local_size)) #print("FBL.global_size: " + str(self.global_size)) self.bc_kernel = FBL_periodic_boundary(self.cl_ctx, \ self.nx, \ self.ny, \ self.boundary_conditions, \ self.asym_ghost_cells ) self.totalNumIterations = 0 self.write_netcdf = write_netcdf self.sim_writer = None if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, staggered_grid=True)
def __init__(self, \ cl_ctx, \ H, eta0, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f, r, A, \ wind_stress=Common.WindStressParams(), \ boundary_conditions=Common.BoundaryConditions(), \ write_netcdf=False, \ block_width=16, block_height=16): reload(Common) self.cl_ctx = cl_ctx self.rk_order = 'NA' self.theta = 'NA' #Create an OpenCL command queue self.cl_queue = cl.CommandQueue(self.cl_ctx) reload(Common) #Get kernels self.u_kernel = Common.get_kernel(self.cl_ctx, "CTCS_U_kernel.opencl", block_width, block_height) self.v_kernel = Common.get_kernel(self.cl_ctx, "CTCS_V_kernel.opencl", block_width, block_height) self.eta_kernel = Common.get_kernel(self.cl_ctx, "CTCS_eta_kernel.opencl", block_width, block_height) #Create data by uploading to device halo_x = 1 halo_y = 1 self.ghost_cells_x = 1 self.ghost_cells_y = 1 self.boundary_conditions = boundary_conditions 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 self.H = Common.OpenCLArray2D(self.cl_ctx, nx, ny, halo_x, halo_y, H) self.cl_data = Common.SWEDataArakawaC(self.cl_ctx, nx, ny, halo_x, halo_y, eta0, hu0, hv0) #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.halo_x = np.int32(halo_x) self.halo_y = np.int32(halo_y) 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.A = np.float32(A) self.wind_stress = wind_stress #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+2*halo_x) / float(self.local_size[0])) * self.local_size[0]), \ int(np.ceil((self.ny+2*halo_y) / float(self.local_size[1])) * self.local_size[1]) \ ) self.bc_kernel = CTCS_boundary_condition(self.cl_ctx, \ self.nx, \ self.ny, \ self.boundary_conditions, \ halo_x, halo_y \ ) self.write_netcdf = write_netcdf self.sim_writer = None if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, staggered_grid=True)
def __init__(self, \ cl_ctx, \ H, eta0, hu0, hv0, \ nx, ny, \ dx, dy, dt, \ g, f, r, \ t=0.0, \ 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 H: Water depth incl ghost cells, (nx+2)*(ny+2) cells 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 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) coriolis_beta: Coriolis linear factor -> f = f + beta*y 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 """ #Create data by uploading to device ghost_cells_x = 0 ghost_cells_y = 0 y_zero_reference_cell = y_zero_reference_cell self.asym_ghost_cells = [0, 0, 0, 0] # [N, E, S, W] self.boundary_conditions = boundary_conditions # Add asym ghost cell if periodic boundary condition: if (self.boundary_conditions.north == 2) or \ (self.boundary_conditions.south == 2): self.asym_ghost_cells[0] = 1 if (self.boundary_conditions.east == 2) or \ (self.boundary_conditions.west == 2): self.asym_ghost_cells[1] = 1 if boundary_conditions.isSponge(): nx = nx + boundary_conditions.spongeCells[ 1] + boundary_conditions.spongeCells[ 3] # - self.asym_ghost_cells[1] - self.asym_ghost_cells[3] ny = ny + boundary_conditions.spongeCells[ 0] + boundary_conditions.spongeCells[ 2] # - self.asym_ghost_cells[0] - self.asym_ghost_cells[2] y_zero_reference_cell = y_zero_reference_cell + boundary_conditions.spongeCells[ 2] rk_order = None theta = None A = None super(FBL, 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.u_kernel = Common.get_kernel(self.cl_ctx, "FBL_U_kernel.opencl", block_width, block_height) self.v_kernel = Common.get_kernel(self.cl_ctx, "FBL_V_kernel.opencl", block_width, block_height) self.eta_kernel = Common.get_kernel(self.cl_ctx, "FBL_eta_kernel.opencl", block_width, block_height) self.H = Common.OpenCLArray2D(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, H, self.asym_ghost_cells) self.cl_data = Common.SWEDataArakawaC(self.cl_ctx, nx, ny, ghost_cells_x, ghost_cells_y, eta0, hu0, hv0, self.asym_ghost_cells) # Overwrite halo with asymetric ghost cells self.nx_halo = np.int32(nx + self.asym_ghost_cells[1] + self.asym_ghost_cells[3]) self.ny_halo = np.int32(ny + self.asym_ghost_cells[0] + self.asym_ghost_cells[2]) self.bc_kernel = FBL_periodic_boundary(self.cl_ctx, \ self.nx, \ self.ny, \ self.boundary_conditions, \ self.asym_ghost_cells ) self.totalNumIterations = 0 if self.write_netcdf: self.sim_writer = SimWriter.SimNetCDFWriter(self, ignore_ghostcells=self.ignore_ghostcells, \ staggered_grid=True, offset_x=self.offset_x, offset_y=self.offset_y)
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, \ 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)