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
Beispiel #2
0
    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 )
Beispiel #5
0
    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))
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
    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)
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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)
Beispiel #12
0
    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)