Beispiel #1
0
def generateInitialConditions(sim_args, water_depth):
    from SWESimulators import CDKLM16, Common
    assert (MPI.COMM_WORLD.rank == 0)

    dataShape = (sim_args['ny'] + 4, sim_args['nx'] + 4)
    dataShapeHi = (sim_args['ny'] + 5, sim_args['nx'] + 5)

    sim_ic = {
        'H': np.ones(dataShapeHi, dtype=np.float32) * water_depth,
        'eta0': np.zeros(dataShape, dtype=np.float32),
        'hu0': np.zeros(dataShape, dtype=np.float32),
        'hv0': np.zeros(dataShape, dtype=np.float32)
    }

    #Very inefficient way of creating perturbed initial state, but works
    cuda_ctx = Common.CUDAContext()
    sim = CDKLM16.CDKLM16(cuda_ctx, **sim_args, **sim_ic)
    sim.perturbState(q0_scale=100)  # Create a random initial state
    sim_ic['eta0'], sim_ic['hu0'], sim_ic['hv0'] = sim.download(
        interior_domain_only=False)
    sim_ic['H'] = sim.downloadBathymetry()[0]
    sim = None
    gc.collect()

    return sim_ic
Beispiel #2
0
    def _init(self, driftersPerOceanModel=1):

        for i in range(self.numParticles + 1):

            particle_args, particle_init = self.doubleJetCase.getInitConditions(
            )
            self.particles[i] = CDKLM16.CDKLM16(**particle_args,
                                                **particle_init)

            if self.doubleJetCase.perturbation_type == DoubleJetCase.DoubleJetPerturbationType.ModelErrorPerturbation:
                self.particles[i].perturbState(q0_scale=20)

            if self.doubleJetCase.perturbation_type == DoubleJetCase.DoubleJetPerturbationType.SpinUp or \
               self.doubleJetCase.perturbation_type == DoubleJetCase.DoubleJetPerturbationType.LowFrequencySpinUp or \
               self.doubleJetCase.perturbation_type == DoubleJetCase.DoubleJetPerturbationType.LowFrequencyStandardSpinUp:
                self.particles[i].step(self.doubleJetCase.individualSpinUpTime)
                print('Individual spin up for particle ' + str(i))
            elif self.doubleJetCase.perturbation_type == DoubleJetCase.DoubleJetPerturbationType.NormalPerturbedSpinUp:
                self.particles[i].step(self.doubleJetCase.commonSpinUpTime * 2,
                                       apply_stochastic_term=False)
                self.particles[i].step(
                    self.doubleJetCase.individualSpinUpTime * 3)
                print('Individual spin up for particle ' + str(i))

        # Initialize and attach drifters to all particles.
        self._TO_DELETE_initialize_drifters(driftersPerOceanModel)

        # Create gpu kernels and buffers:
        self._setupGPU()

        # Put the initial positions into the observation array
        self._addObservation(self.observeTrueDrifters())
Beispiel #3
0
def initCDKLM():
        tic = time.time()
        
        ghosts = np.array([2,2,2,2]) # north, east, south, west
        dataShape = (args.ny + ghosts[0]+ghosts[2], 
                                 args.nx + ghosts[1]+ghosts[3])

        eta0 = np.fromfunction(lambda i, j: my_exp(i,j), dataShape, dtype=np.float32)
        u0 = np.zeros(dataShape, dtype=np.float32, order='C');
        v0 = np.zeros(dataShape, dtype=np.float32, order='C');
        Hi = np.ones((dataShape[0]+1, dataShape[1]+1), dtype=np.float32, order='C') * waterHeight;

        toc = time.time()
        print("{:02.4f} s: ".format(toc-tic) + "Generated initial conditions")
                        
        # Initialize simulator
        tic = time.time()
        
        kwargs = {'boundary_conditions': boundaryConditions, 'rk_order': 2, 'write_netcdf': True, 'comm': MPI.COMM_WORLD}
        if (args.block_width != None):
                kwargs['block_width'] = args.block_width
        if (args.block_height != None):
                kwargs['block_height'] = args.block_height
                
        sim = CDKLM16.CDKLM16(gpu_ctx, \
                                        eta0, u0, v0, Hi, \
                                        args.nx, args.ny, \
                                        dx, dy, dt, \
                                        g, f, r, \
                                        **kwargs)
        toc = time.time()
        print("{:02.4f} s: ".format(toc-tic) + "Created CDKLM simulator")
        
        return sim
Beispiel #4
0
    def _init(self, driftersPerOceanModel=1):
        """
        Initiating the ensemble by perturbing the input simulator and attaching drifters
        """
        self.driftersPerOceanModel = np.int32(driftersPerOceanModel)

        for i in range(self.numParticles + 1):
            self.particles[i] = CDKLM16.CDKLM16(self.gpu_ctx, \
                                                self.base_eta, self.base_hu, self.base_hv, \
                                                self.base_H, \
                                                self.nx, self.ny, self.dx, self.dy, self.dt, \
                                                self.g, self.f, self.r, \
                                                boundary_conditions=self.boundaryConditions, \
                                                write_netcdf=False, \
                                                small_scale_perturbation=True, \
                                                small_scale_perturbation_amplitude=self.small_scale_perturbation_amplitude,
                                                small_scale_perturbation_interpolation_factor=self.small_scale_perturbation_interpolation_factor)

            if self.initialization_variance_factor_ocean_field != 0.0:
                self.particles[i].perturbState(
                    q0_scale=self.initialization_variance_factor_ocean_field)

            # Add drifters
            drifters = GPUDrifterCollection.GPUDrifterCollection(
                self.gpu_ctx,
                self.driftersPerOceanModel,
                observation_variance=self.observation_variance,
                boundaryConditions=self.boundaryConditions,
                initialization_cov_drifters=self.initialization_cov_drifters,
                domain_size_x=self.nx * self.dx,
                domain_size_y=self.ny * self.dy)
            self.particles[i].attachDrifters(drifters)
Beispiel #5
0
    def __init__(self,
                 gpu_ctx,
                 numParticles,
                 doubleJetCase,
                 num_drifters=1,
                 observation_type=dautils.ObservationType.DrifterPosition,
                 observation_variance=None,
                 observation_variance_factor=5.0,
                 initialization_variance_factor_drifter_position=0.0,
                 initialization_variance_factor_ocean_field=0.0):

        assert(doubleJetCase.__class__.__name__=="DoubleJetCase"), \
            'This class can only be used with a DoubleJetCase object, and not a Simulator'

        # Create a simulator from the DoubleJetCase object
        self.doubleJetCase = doubleJetCase
        base_init_args, base_init_cond = doubleJetCase.getBaseInitConditions()
        tmp_sim = CDKLM16.CDKLM16(**base_init_args, **base_init_cond)

        # Call super class:
        print('Calling parent constructor from DoubleJetEnsemble')
        super(DoubleJetEnsemble,
              self).__init__(gpu_ctx, numParticles, tmp_sim, num_drifters,
                             observation_type, observation_variance,
                             observation_variance_factor,
                             initialization_variance_factor_drifter_position,
                             initialization_variance_factor_ocean_field)
Beispiel #6
0
    def init(self, driftersPerOceanModel=1):
        self.driftersPerOceanModel = driftersPerOceanModel

        # Define mid-points for the different drifters
        # Decompose the domain, so that we spread the drifters as much as possible
        sub_domains_y = np.int(np.round(np.sqrt(self.driftersPerOceanModel)))
        sub_domains_x = np.int(
            np.ceil(1.0 * self.driftersPerOceanModel / sub_domains_y))
        self.midPoints = np.empty((driftersPerOceanModel, 2))
        for sub_y in range(sub_domains_y):
            for sub_x in range(sub_domains_x):
                drifter_id = sub_y * sub_domains_x + sub_x
                if drifter_id >= self.driftersPerOceanModel:
                    break
                self.midPoints[drifter_id,
                               0] = (sub_x +
                                     0.5) * self.nx * self.dx / sub_domains_x
                self.midPoints[drifter_id,
                               1] = (sub_y +
                                     0.5) * self.ny * self.dy / sub_domains_y

        for i in range(self.numParticles + 1):
            self.particles[i] = CDKLM16.CDKLM16(self.gpu_ctx, \
                                                self.base_eta, self.base_hu, self.base_hv, \
                                                self.base_H, \
                                                self.nx, self.ny, self.dx, self.dy, self.dt, \
                                                self.g, self.f, self.r, \
                                                boundary_conditions=self.boundaryConditions, \
                                                write_netcdf=False, \
                                                small_scale_perturbation=True, \
                                                small_scale_perturbation_amplitude=self.small_scale_perturbation_amplitude)

            if self.initialization_variance_factor_ocean_field != 0.0:
                self.particles[i].perturbState(
                    q0_scale=self.initialization_variance_factor_ocean_field)

            drifters = GPUDrifterCollection.GPUDrifterCollection(
                self.gpu_ctx,
                driftersPerOceanModel,
                observation_variance=self.observation_variance,
                boundaryConditions=self.boundaryConditions,
                domain_size_x=self.nx * self.dx,
                domain_size_y=self.ny * self.dy)

            initPos = np.empty((self.driftersPerOceanModel, 2))
            for d in range(self.driftersPerOceanModel):
                initPos[d, :] = np.random.multivariate_normal(
                    self.midPoints[d, :], self.initialization_cov_drifters)
            drifters.setDrifterPositions(initPos)
            #print "drifter particles: ", drifter.getParticlePositions()
            #print "drifter observations: ", drifter.getObservationPosition()
            self.particles[i].attachDrifters(drifters)

        # Put the initial positions into the observation array
        self._addObservation(self.observeTrueDrifters())
    def __init__(self,
                 gpu_ctx,
                 sim_args,
                 sim_ic,
                 num_particles,
                 drifter_positions=[],
                 observation_variance=0.01**2,
                 initialization_variance_factor_ocean_field=0.0):
        """
        Constructor which creates num_particles slighly different ocean models
        based on the same initial conditions
        """

        self.logger = logging.getLogger(__name__)
        self.gpu_ctx = gpu_ctx
        self.sim_args = sim_args
        self.observation_variance = observation_variance
        self.initialization_variance_factor_ocean_field = initialization_variance_factor_ocean_field

        # Build observation covariance matrix:
        if np.isscalar(self.observation_variance):
            self.observation_cov = np.eye(2) * self.observation_variance
            self.observation_cov_inverse = np.eye(2) * (
                1.0 / self.observation_variance)
        else:
            # Assume that we have a correctly shaped matrix here
            self.observation_cov = self.observation_variance
            self.observation_cov_inverse = np.linalg.inv(self.observation_cov)

        # Generate ensemble members
        self.logger.debug("Creating %d particles (ocean models)",
                          num_particles)
        self.particles = [None] * num_particles
        for i in range(num_particles):
            self.particles[i] = CDKLM16.CDKLM16(self.gpu_ctx, **sim_ic,
                                                **self.sim_args)

            if self.initialization_variance_factor_ocean_field != 0.0:
                self.particles[i].perturbState(
                    q0_scale=self.initialization_variance_factor_ocean_field)

            # Attach drifters if requested
            self.logger.debug("Attaching %d drifters", len(drifter_positions))
            if (len(drifter_positions) > 0):
                drifters = GPUDrifterCollection.GPUDrifterCollection(
                    self.gpu_ctx,
                    len(drifter_positions),
                    observation_variance=self.observation_variance,
                    boundaryConditions=sim_ic['boundary_conditions'],
                    domain_size_x=sim_args['nx'] * sim_args['dx'],
                    domain_size_y=sim_args['ny'] * sim_args['dy'])
                drifters.setDrifterPositions(drifter_positions)
                self.particles[i].attachDrifters(drifters)
Beispiel #8
0
    def __init__(self,
                 gpu_ctx,
                 sim_args,
                 data_args,
                 numParticles,
                 observation_variance=0.01**2,
                 initialization_variance_factor_ocean_field=0.0,
                 super_dir_name=None,
                 netcdf_filename=None,
                 rank=0):
        """
        Constructor which creates numParticles slighly different ocean models
        based on the same initial conditions
        """

        self.logger = logging.getLogger(__name__)
        self.gpu_ctx = gpu_ctx
        self.sim_args = sim_args
        self.data_args = data_args
        self.numParticles = numParticles
        self.observation_variance = observation_variance
        self.initialization_variance_factor_ocean_field = initialization_variance_factor_ocean_field

        # Build observation covariance matrix:
        if np.isscalar(self.observation_variance):
            self.observation_cov = np.eye(2) * self.observation_variance
            self.observation_cov_inverse = np.eye(2) * (
                1.0 / self.observation_variance)
        else:
            # Assume that we have a correctly shaped matrix here
            self.observation_cov = self.observation_variance
            self.observation_cov_inverse = np.linalg.inv(self.observation_cov)

        # Generate ensemble members
        self.logger.debug("Creating %d particles (ocean models)", numParticles)
        self.particles = [None] * numParticles
        self.particleInfos = [None] * numParticles
        self.drifterForecast = [None] * numParticles
        for i in range(numParticles):
            self.particles[i] = CDKLM16.CDKLM16(
                self.gpu_ctx,
                **self.sim_args,
                **data_args,
                local_particle_id=i,
                super_dir_name=super_dir_name,
                netcdf_filename=netcdf_filename)
            self.particleInfos[i] = ParticleInfo.ParticleInfo()

            if self.initialization_variance_factor_ocean_field != 0.0:
                self.particles[i].perturbState(
                    q0_scale=self.initialization_variance_factor_ocean_field)
Beispiel #9
0
    def init(self, driftersPerOceanModel=1):
        self.windSpeed = 2.0
        self.directions = np.random.rand(self.numParticles + 1) * 360
        self.windX, self.windY = self.XandYfromDirections(self.directions)
        #print "Directions: ", self.directions
        self.driftersPerOceanModel = driftersPerOceanModel

        self.windT = np.zeros((1), dtype=np.float32)

        for i in range(self.numParticles + 1):

            wX = [self.windX[i] * np.ones((2, 2), dtype=np.float32)]
            wY = [self.windY[i] * np.ones((2, 2), dtype=np.float32)]

            wind = WindStress.WindStress(self.windT, wX, wY)
            #print ("Init with wind :", (wX, wY))

            self.particles[i] = CDKLM16.CDKLM16(self.gpu_ctx, \
                                                self.base_eta, self.base_hu, self.base_hv, \
                                                self.base_H, \
                                                self.nx, self.ny, self.dx, self.dy, self.dt, \
                                                self.g, self.f, self.r, \
                                                wind_stress=wind, \
                                                boundary_conditions=self.boundaryConditions, \
                                                write_netcdf=False)
            if i == self.numParticles:
                # All particles done, only the observation is left,
                # and for the observation we only use one drifter, regardless of the
                # number in the other particles.
                driftersPerOceanModel = 1

            drifters = GPUDrifterCollection.GPUDrifterCollection(
                self.gpu_ctx,
                driftersPerOceanModel,
                observation_variance=self.observation_variance,
                boundaryConditions=self.boundaryConditions,
                domain_size_x=self.nx * self.dx,
                domain_size_y=self.ny * self.dy)
            initPos = np.random.multivariate_normal(
                self.midPoint, self.initialization_cov_drifters,
                driftersPerOceanModel)
            drifters.setDrifterPositions(initPos)
            #print "drifter particles: ", drifter.getParticlePositions()
            #print "drifter observations: ", drifter.getObservationPosition()
            self.particles[i].attachDrifters(drifters)

        # Put the initial positions into the observation array
        self._addObservation(self.observeTrueDrifters())
        print("Added init to observation array")
Beispiel #10
0
    def test_periodicNS_central(self):
        self.setBoundaryConditions(bcSettings=3)
        self.allocData()
        addCentralBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "wallBC", "central")
        
        self.checkResults(eta1, u1, v1, eta2, u2, v2)
Beispiel #11
0
    def test_periodicEW_upperCorner(self):
        self.setBoundaryConditions(bcSettings=4)
        self.allocData()
        addUpperCornerBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "periodicEW", "upperCorner")
        
        self.checkResults(eta1, u1, v1, eta2, u2, v2)       
Beispiel #12
0
    def test_wall_corner(self):
        self.setBoundaryConditions()
        self.allocData()
        addCornerBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r) #, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "wallBC", "corner")

        self.checkResults(eta1, u1, v1, eta2, u2, v2)
Beispiel #13
0
    def test_bathymetry_central(self):
        self.setBoundaryConditions()
        self.allocData() 
        addCentralBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        makeBottomTopography(self.Hi, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r) #, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "wallBC", "central", "bathymetry_")

        self.checkResults(eta1, u1, v1, eta2, u2, v2)
Beispiel #14
0
    def test_coriolis_central(self):
        self.setBoundaryConditions()
        self.allocData()
        self.f = 0.01
        addCentralBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r) #, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "coriolis", "central")

        self.checkResults(eta1, u1, v1, eta2, u2, v2)
Beispiel #15
0
def initCDKLM():
    tic = time.time()

    ghosts = np.array([2, 2, 2, 2])  # north, east, south, west
    dataShape = (args.ny + ghosts[0] + ghosts[2],
                 args.nx + ghosts[1] + ghosts[3])

    eta0 = np.fromfunction(lambda i, j: my_exp(i, j),
                           dataShape,
                           dtype=np.float32)
    u0 = np.zeros(dataShape, dtype=np.float32, order='C')
    v0 = np.zeros(dataShape, dtype=np.float32, order='C')
    Hi = np.ones(
        (dataShape[0] + 1, dataShape[1] + 1), dtype=np.float32,
        order='C') * waterHeight

    toc = time.time()
    print("{:02.4f} s: ".format(toc - tic) + "Generated initial conditions")

    # Initialize simulator
    tic = time.time()

    kwargs = {'boundary_conditions': boundaryConditions, 'rk_order': 2}
    if (args.block_width != None):
        kwargs['block_width'] = args.block_width
    if (args.block_height != None):
        kwargs['block_height'] = args.block_height
    if (args.block_width_model_error != None):
        kwargs['block_width_model_error'] = args.block_width_model_error
    if (args.block_height_model_error != None):
        kwargs['block_height_model_error'] = args.block_height_model_error


    sim = CDKLM16.CDKLM16(gpu_ctx, \
                          eta0, u0, v0, Hi, \
                          args.nx, args.ny, \
                          dx, dy, dt, \
                          g, f, r, \
                          small_scale_perturbation = small_scale_perturbation, \
                          small_scale_perturbation_amplitude = small_scale_perturbation_amplitude, \
                          small_scale_perturbation_interpolation_factor = small_scale_perturbation_interpolation_factor, \
                          **kwargs)
    toc = time.time()
    print("{:02.4f} s: ".format(toc - tic) + "Created CDKLM simulator")

    return sim
Beispiel #16
0
    def init(self):

        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.base_eta, self.base_hu, self.base_hv, \
                                   self.base_H, \
                                   self.nx, self.ny, self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r, \
                                   wind_stress=self.wind, \
                                   boundary_conditions=self.boundaryConditions, \
                                   write_netcdf=False)

        # TO CHECK! Is it okay to have drifters as self.drifters - in order to easier reach its member functions?
        self.drifters = GPUDrifterCollection.GPUDrifterCollection(self.gpu_ctx, self.numParticles,
                      observation_variance=self.observation_variance,
                      boundaryConditions=self.boundaryConditions,
                      domain_size_x=self.nx*self.dx, domain_size_y=self.ny*self.dy)
        
        self.drifters.initializeUniform()
        self.sim.attachDrifters(self.drifters)
Beispiel #17
0
def initCDKLM():
    tic = time.time()

    ghosts = np.array([2, 2, 2, 2])  # north, east, south, west
    dataShape = (args.ny + ghosts[0] + ghosts[2],
                 args.nx + ghosts[1] + ghosts[3])

    eta0 = np.zeros(dataShape, dtype=np.float32, order='C')
    initEtaFV(eta0, ghosts)

    u0 = np.zeros(dataShape, dtype=np.float32, order='C')
    v0 = np.zeros(dataShape, dtype=np.float32, order='C')
    Hi = np.ones(
        (dataShape[0] + 1, dataShape[1] + 1), dtype=np.float32,
        order='C') * waterHeight

    dt = courant_number * dx / (4 * gravity_wave_speed)
    toc = time.time()
    print("{:02.4f} s: ".format(toc - tic) + "Generated initial conditions")

    # Initialize simulator
    tic = time.time()

    kwargs = {'boundary_conditions': boundaryConditions, 'rk_order': 2}
    if (args.block_width != None):
        kwargs['block_width'] = args.block_width
    if (args.block_height != None):
        kwargs['block_height'] = args.block_height

    sim = CDKLM16.CDKLM16(gpu_ctx, \
                                    eta0, u0, v0, Hi, \
                                    args.nx, args.ny, \
                                    dx, dy, dt, \
                                    g, f, r, \
                                    **kwargs)
    toc = time.time()
    print("{:02.4f} s: ".format(toc - tic) + "Created CDKLM simulator")

    print_memory_req(sim, fvd=True)

    return sim
Beispiel #18
0
    def test_betamodel_central(self):
        self.setBoundaryConditions()
        self.allocData()
        
        # Defining coriolis parameters and accounting for ghost cells:
        beta = 1e-6
        self.f = 0.01 - 2*beta*self.dy
        
        addCentralBump(self.eta0, self.nx, self.ny, self.dx, self.dy, self.validDomain)
        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, \
                                   self.eta0, self.u0, self.v0, self.Hi, \
                                   self.nx, self.ny, \
                                   self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r, coriolis_beta=beta)
    #, boundary_conditions=self.boundaryConditions)

        t = self.sim.step(self.T)
        eta1, u1, v1 = self.sim.download()
        eta2, u2, v2 = loadResults("CDKLM16", "betamodel", "central")

        self.checkResults(eta1, u1, v1, eta2, u2, v2)
Beispiel #19
0
    def setUpAndStartEnsemble(self):
        self.nx = 40
        self.ny = 40

        self.dx = 4.0
        self.dy = 4.0

        self.dt = 0.05
        self.g = 9.81
        self.r = 0.0

        self.f = 0.05
        self.beta = 0.0

        self.waterDepth = 10.0

        self.ensembleSize = 3
        self.driftersPerOceanModel = 3

        ghosts = np.array([2, 2, 2, 2])  # north, east, south, west
        validDomain = np.array([2, 2, 2, 2])
        self.boundaryConditions = Common.BoundaryConditions(2, 2, 2, 2)

        # Define which cell index which has lower left corner as position (0,0)
        x_zero_ref = 2
        y_zero_ref = 2

        dataShape = (self.ny + ghosts[0] + ghosts[2],
                     self.nx + ghosts[1] + ghosts[3])
        dataShapeHi = (self.ny + ghosts[0] + ghosts[2] + 1,
                       self.nx + ghosts[1] + ghosts[3] + 1)

        eta0 = np.zeros(dataShape, dtype=np.float32, order='C')
        eta0_extra = np.zeros(dataShape, dtype=np.float32, order='C')
        hv0 = np.zeros(dataShape, dtype=np.float32, order='C')
        hu0 = np.zeros(dataShape, dtype=np.float32, order='C')
        Hi = np.ones(dataShapeHi, dtype=np.float32,
                     order='C') * self.waterDepth

        # Add disturbance:
        rel_grid_size = self.nx * 1.0 / self.dx
        BC.addBump(eta0, self.nx, self.ny, self.dx, self.dy, 0.3, 0.5,
                   0.05 * rel_grid_size, validDomain)
        eta0 = eta0 * 0.3
        BC.addBump(eta0, self.nx, self.ny, self.dx, self.dy, 0.7, 0.3,
                   0.10 * rel_grid_size, validDomain)
        eta0 = eta0 * (-1.3)
        BC.addBump(eta0, self.nx, self.ny, self.dx, self.dy, 0.15, 0.8,
                   0.03 * rel_grid_size, validDomain)
        eta0 = eta0 * 1.0
        BC.addBump(eta0, self.nx, self.ny, self.dx, self.dy, 0.6, 0.75,
                   0.06 * rel_grid_size, validDomain)
        BC.addBump(eta0, self.nx, self.ny, self.dx, self.dy, 0.2, 0.2,
                   0.01 * rel_grid_size, validDomain)
        eta0 = eta0 * (-0.03)
        BC.addBump(eta0_extra, self.nx, self.ny, self.dx, self.dy, 0.5, 0.5,
                   0.4 * rel_grid_size, validDomain)
        eta0 = eta0 + 0.02 * eta0_extra
        BC.initializeBalancedVelocityField(eta0, Hi, hu0, hv0, \
                                           self.f, self.beta, self.g, \
                                           self.nx, self.ny, self.dx ,self.dy, ghosts)
        eta0 = eta0 * 0.5

        self.q0 = 0.5 * self.dt * self.f / (self.g * self.waterDepth)

        self.sim = CDKLM16.CDKLM16(self.gpu_ctx, eta0, hu0, hv0, Hi, \
                                   self.nx, self.ny, self.dx, self.dy, self.dt, \
                                   self.g, self.f, self.r, \
                                   boundary_conditions=self.boundaryConditions, \
                                   write_netcdf=False, \
                                   small_scale_perturbation=True, \
                                   small_scale_perturbation_amplitude=self.q0)

        self.ensemble = OceanNoiseEnsemble.OceanNoiseEnsemble(
            self.gpu_ctx,
            self.ensembleSize,
            self.sim,
            num_drifters=self.driftersPerOceanModel,
            observation_type=dautils.ObservationType.DirectUnderlyingFlow,
            observation_variance=0.01**2)

        self.iewpf = IEWPFOcean.IEWPFOcean(self.ensemble)
Beispiel #20
0
    tic = time.time()

    # Generate parameters and initial conditions (which includes spin up time)
    doubleJetCase = DoubleJetCase.DoubleJetCase(
        gpu_ctx, DoubleJetCase.DoubleJetPerturbationType.IEWPFPaperCase)

    doubleJetCase_args, doubleJetCase_init = doubleJetCase.getInitConditions()

    if (np.any(np.isnan(doubleJetCase_init["eta0"]))):
        print(" `-> ERROR: Not a number in spinup, aborting!")
        sys.exit(-1)

    toc = time.time()
    print("\n{:02.4f} s: ".format(toc - tic) +
          "Generated initial conditions for member " + str(ensemble_member))

    netcdf_filename = folder_name + 'double_jet_case_' + str(
        ensemble_member).zfill(2)
    netcdf_args = {'write_netcdf': True, 'netcdf_filename': netcdf_filename}

    tic = time.time()
    sim = CDKLM16.CDKLM16(**doubleJetCase_args, **doubleJetCase_init,
                          **netcdf_args)
    sim.cleanUp()

    toc = time.time()
    print("\n{:02.4f} s: ".format(toc - tic) +
          "Generated NetCDF file for member " + str(ensemble_member))

print("Spin-up of " + str(args.ensemble_size) + " members completed!\n")
Beispiel #21
0
    def __init__(self,
                 gpu_ctx,
                 perturbation_type=DoubleJetPerturbationType.SteadyState,
                 model_error=True,
                 commonSpinUpTime=200000):
        """
        Class that generates initial conditions for a double jet case (both perturbed and unperturbed).
        The use of initial perturbations/spin up periods are given by the perturbation_type argument,
        which should be a DoubleJetPerturbationType instance.
        """
        # The following parameters are the standard choices we have made for our double jet case.
        # If any of them are to be altered, they should be made optional input parameters to the
        # constructor, with the values below given as default parameters.

        # Check that the provided perturbation type is valid
        DoubleJetPerturbationType._assert_valid(perturbation_type)
        self.perturbation_type = perturbation_type

        # Domain-related parameters
        self.phi_0 = 72 * np.pi / 180.0
        self.phi_05 = 75 * np.pi / 180.0
        self.phi_1 = 78 * np.pi / 180.0

        self.midpoint_phi_pos = 73.5 * np.pi / 180
        self.midpoint_phi_neg = 76.5 * np.pi / 180

        self.phi_delta = 5.5 * np.pi / 180
        self.phi_pos_min = self.midpoint_phi_pos - self.phi_delta
        self.phi_pos_max = self.midpoint_phi_pos + self.phi_delta
        self.phi_neg_min = self.midpoint_phi_neg - self.phi_delta
        self.phi_neg_max = self.midpoint_phi_neg + self.phi_delta
        self.e_n = np.exp(-4 / (self.phi_delta * 2)**2)

        distance_between_latitudes = 111e3  # m
        degrees_0 = self.phi_0 * 180 / np.pi
        degrees_1 = self.phi_1 * 180 / np.pi
        y_south = degrees_0 * distance_between_latitudes
        y_north = degrees_1 * distance_between_latitudes
        degrees_mid = self.phi_05 * 180 / np.pi

        self.ny = 300
        self.dy = (y_north - y_south) / self.ny
        self.dx = self.dy
        self.nx = 500

        self.ghosts = np.array([2, 2, 2, 2])  # north, east, south, west
        self.dataShape = (self.ny + self.ghosts[0] + self.ghosts[2],
                          self.nx + self.ghosts[1] + self.ghosts[3])

        # Physical parameters
        self.g = 9.80616  # m/s^2 - gravitational acceleration
        omega = 7.2722e-5  # 1/s  - Angular rotation speed of the earth
        self.earth_radius = 6.37122e6  # m - radius of the Earth

        self.u_max = 3  # m/s   - Gulf stream has "maximum speed typically about 2.5 m/s"
        self.h_0 = 230  # m     - It was found to be 230.03, but with a dobious calculation.
        #       - Better then just to set the depth to a constant :)
        self.commonSpinUpTime = commonSpinUpTime  # s - Because it just seems like a good measure.
        self.individualSpinUpTime = 100000  # s - Because it just seems like a good measure.

        self.f = 2 * omega * np.sin(self.phi_05)
        self.tan = np.tan(self.phi_05)

        # Initial data
        sim_h_init, redef_hu_init = self._initSteadyState()
        sim_h_init_mean = sim_h_init.mean()

        self.delta_eta = np.max(sim_h_init) - np.min(sim_h_init)

        max_dt = 0.25 * self.dx / (np.max(redef_hu_init / sim_h_init +
                                          np.sqrt(self.g * sim_h_init)))
        dt = 0.8 * max_dt

        self.base_cpu_Hi = np.ones(
            (self.dataShape[0] + 1, self.dataShape[1] + 1),
            dtype=np.float32) * sim_h_init_mean
        self.base_cpu_eta = -np.ones(self.dataShape,
                                     dtype=np.float32) * sim_h_init_mean
        self.base_cpu_hu = np.zeros(self.dataShape, dtype=np.float32)
        self.base_cpu_hv = np.zeros(self.dataShape, dtype=np.float32)

        for i in range(self.dataShape[1]):
            self.base_cpu_eta[:, i] += sim_h_init
            self.base_cpu_hu[:, i] = redef_hu_init

        self.sim_args = {
            "gpu_ctx": gpu_ctx,
            "nx": self.nx,
            "ny": self.ny,
            "dx": self.dy,
            "dy": self.dy,
            "dt": dt,
            "g": self.g,
            "f": self.f,
            "coriolis_beta": 0.0,
            "r": 0.0,
            "H": self.base_cpu_Hi,
            "t": 0.0,
            "rk_order": 2,
            "boundary_conditions": Common.BoundaryConditions(2, 2, 2, 2),
            "small_scale_perturbation": model_error,
            "small_scale_perturbation_amplitude": 0.0003,
            "small_scale_perturbation_interpolation_factor": 5,
        }

        self.base_init = {
            "eta0": self.base_cpu_eta,
            "hu0": self.base_cpu_hu,
            "hv0": self.base_cpu_hv
        }

        if self.perturbation_type == DoubleJetPerturbationType.SpinUp or \
           self.perturbation_type == DoubleJetPerturbationType.LowFrequencySpinUp or \
           self.perturbation_type == DoubleJetPerturbationType.LowFrequencyStandardSpinUp:
            if self.perturbation_type == DoubleJetPerturbationType.LowFrequencySpinUp:
                self.commonSpinUpTime = self.commonSpinUpTime
                self.individualSpinUpTime = self.individualSpinUpTime * 1.5

            elif self.perturbation_type == DoubleJetPerturbationType.LowFrequencyStandardSpinUp:
                self.sim_args, self.base_init = self.getStandardPerturbedInitConditions(
                )
                self.commonSpinUpTime = self.commonSpinUpTime * 2

            tmp_sim = CDKLM16.CDKLM16(**self.sim_args, **self.base_init)
            tmp_t = tmp_sim.step(self.commonSpinUpTime)

            tmp_eta, tmp_hu, tmp_hv = tmp_sim.download(
                interior_domain_only=False)
            self.base_init['eta0'] = tmp_eta
            self.base_init['hu0'] = tmp_hu
            self.base_init['hv0'] = tmp_hv
            self.sim_args['t'] = tmp_sim.t
            tmp_sim.cleanUp()

        # The IEWPFPaperCase - isolated to give a better overview
        if self.perturbation_type == DoubleJetPerturbationType.IEWPFPaperCase:
            self.sim_args["small_scale_perturbation_amplitude"] = 0.00025
            self.sim_args["model_time_step"] = 60  # sec

            tmp_sim = CDKLM16.CDKLM16(**self.sim_args, **self.base_init)
            tmp_sim.updateDt()

            three_days = 3 * 24 * 60 * 60
            tmp_t = tmp_sim.dataAssimilationStep(three_days)

            tmp_eta, tmp_hu, tmp_hv = tmp_sim.download(
                interior_domain_only=False)
            self.base_init['eta0'] = tmp_eta
            self.base_init['hu0'] = tmp_hu
            self.base_init['hv0'] = tmp_hv
            self.sim_args['t'] = tmp_sim.t
            tmp_sim.cleanUp()
def simulate_gpuocean_deterministic(source_url,
                                    domain,
                                    initx,
                                    inity,
                                    sim_args,
                                    erode_land=1,
                                    wind_drift_factor=0.0,
                                    rescale=0,
                                    outfolder=None,
                                    start_forecast_hours=0,
                                    forecast_duration=23):
    """
    source_url: url or local file or list of either with fielddata in NetCDF-format
    domain: array/list on form [x0,x1,y0,y1] defining the domain for the simulation
    initx, inity = initial coordinates of single drifter or lists with coordinates for multiple drifters. 
                   In local cartesian coordinates of simulation-domain. 
    sim_args, erode_land, observation_type: arguments needed for simulator and observation object. sim_args must be given.
    wind_drift_factor: fraction of wind-speed at which objects will be advected. Default is 0 (no direct wind-drift)
    rescale: factor setting resolution of simulation-grid. 0 indicates no rescaling(original resolution), 
             while any other number changes the resolution (ie 2 gives double resolution)
    outfolder: outfolder
    start_forecast_hours = number hours after which to start simulating drifttrajectories(ocean model starts at beginning of field-data)
                           Default is at beginning of field-data. 
    forecast_duration = duration of simulation(including possibly only ocean simulation). Default is 24 hours.
    """

    end_forecast_hours = start_forecast_hours + forecast_duration

    #Create simulator
    data_args = NetCDFInitialization.getInitialConditions(
        source_url,
        domain[0],
        domain[1],
        domain[2],
        domain[3],
        timestep_indices=None,
        erode_land=erode_land,
        download_data=False)

    if wind_drift_factor:
        wind_data = data_args.pop('wind', None)
    else:
        wind_data = None

    if rescale:
        data_args = NetCDFInitialization.rescaleInitialConditions(
            data_args, scale=rescale)

    sim = CDKLM16.CDKLM16(**sim_args,
                          **NetCDFInitialization.removeMetadata(data_args))

    #Forecast
    observation_type = dautils.ObservationType.UnderlyingFlow

    observation_args = {
        'observation_type': observation_type,
        'nx': sim.nx,
        'ny': sim.ny,
        'domain_size_x': sim.nx * sim.dx,
        'domain_size_y': sim.ny * sim.dy,
        'land_mask': sim.getLandMask()
    }

    trajectory_forecast = Observation.Observation(**observation_args)

    if outfolder is not None:
        trajectory_forecast_filename = 'trajectory_forecast_' + str(
            start_forecast_hours) + '_to_' + str(
                end_forecast_hours) + '.pickle'

    #Drifters
    #Assumes initx, inity same format/shape
    if type(initx) is not list:
        initx = [initx]
        inity = [inity]

    num_drifters = len(initx)

    drifters = GPUDrifterCollection.GPUDrifterCollection(
        sim_args['gpu_ctx'],
        num_drifters,
        wind=wind_data,
        wind_drift_factor=wind_drift_factor,
        boundaryConditions=sim.boundary_conditions,
        domain_size_x=trajectory_forecast.domain_size_x,
        domain_size_y=trajectory_forecast.domain_size_y,
        gpu_stream=sim.gpu_stream)

    drifter_pos_init = np.array([initx, inity]).T

    #Run simulation
    num_total_hours = end_forecast_hours

    five_mins_in_an_hour = 12
    sub_dt = 5 * 60  # five minutes

    progress = Common.ProgressPrinter(5)
    pp = display(progress.getPrintString(0), display_id=True)

    for hour in range(num_total_hours):

        if hour == start_forecast_hours:
            # Attach drifters
            drifters.setDrifterPositions(drifter_pos_init)
            sim.attachDrifters(drifters)
            trajectory_forecast.add_observation_from_sim(sim)

        for mins in range(five_mins_in_an_hour):
            t = sim.step(sub_dt)
            if hour >= start_forecast_hours:
                trajectory_forecast.add_observation_from_sim(sim)

        pp.update(progress.getPrintString(hour / (end_forecast_hours - 1)))

    if outfolder is not None:
        trajectory_forecast.to_pickle(trajectory_forecast_path)

    return trajectory_forecast
Beispiel #23
0
def generateTruth(gpu_ctx,
                  destination_dir,
                  duration_in_days=13,
                  duration_in_hours=0,
                  folder_name=None,
                  log_to_screen=False):
    """
    This funtion generates a truth simulation that will be the subject for 
    data assimilation experiments. It is based on the DoubleJetCase parameters 
    and initial conditions, and is (by default) spun up for 3 days before starting 
    to write its state to file. The generated data set should cover time range from
    day 3 to day 13.
    
    The end time of the truth is duration_in_days + duration_in_hours.
    """

    #--------------------------------------------------------------
    # PARAMETERS
    #--------------------------------------------------------------
    # This file takes no parameters, as it is should clearly define a specific truth.
    # If we come to a time where we need to specify a lot of different truths, we can introduce argparser again.

    # Time parameters
    start_time = 3 * 24 * 60 * 60  #  3 days
    end_time = (duration_in_days * 24 + duration_in_hours) * 60 * 60
    simulation_time = end_time - start_time
    observation_frequency = 5 * 60  # 5 minutes
    netcdf_frequency = 60 * 60  # every hour

    # Drifter parameters:
    num_drifters = 64

    assert (os.path.exists(destination_dir)
            ), 'destination_dir does not exist: ' + str(destination_dir)

    # File parameters:
    folder = os.path.join(
        destination_dir,
        "truth_" + datetime.datetime.now().strftime("%Y_%m_%d-%H_%M_%S"))
    if folder_name is not None:
        folder = os.path.join(destination_dir, folder_name)
    assert (not os.path.exists(folder)
            ), 'The directory ' + folder + ' already exists!'
    os.makedirs(folder)

    netcdf_filename = os.path.join(folder, "double_jet_case_truth.nc")
    drifter_filename = os.path.join(folder, "drifter_observations.pickle")

    if log_to_screen:
        print("------ Generating initial ensemble ---------------")
    if log_to_screen: print("Writing truth to file: " + netcdf_filename)

    # Create CUDA context
    device_name = gpu_ctx.cuda_device.name()

    #--------------------------------------------------------------
    # Creating the Case (including spin up)
    #--------------------------------------------------------------
    if log_to_screen: print("Initializing the truth")

    tic = time.time()
    sim = None
    doubleJetCase = None

    try:
        doubleJetCase = DoubleJetCase.DoubleJetCase(
            gpu_ctx, DoubleJetCase.DoubleJetPerturbationType.IEWPFPaperCase)

        doubleJetCase_args, doubleJetCase_init = doubleJetCase.getInitConditions(
        )

        if (np.any(np.isnan(doubleJetCase_init["eta0"]))):
            print(" `-> ERROR: Not a number in spinup, aborting!")
            raise RuntimeError('Not a number in spinup')

        toc = time.time()
        if log_to_screen:
            print("\n{:02.4f} s: ".format(toc - tic) +
                  "Generated initial conditions at day 3")

        #--------------------------------------------------------------
        # Initialize the truth from the Case (spin up is done in the Case)
        #--------------------------------------------------------------

        toc = time.time()
        if log_to_screen:
            print("\n{:02.4f} s: ".format(toc - tic) +
                  "Generated initial conditions for truth")

        #netcdf_args = {}
        netcdf_args = {
            'write_netcdf': True,
            'netcdf_filename': netcdf_filename
        }

        tic = time.time()
        sim = CDKLM16.CDKLM16(**doubleJetCase_args, **doubleJetCase_init,
                              **netcdf_args)

        toc = time.time()
        if log_to_screen:
            print("\n{:02.4f} s: ".format(toc - tic) +
                  "Truth simulator initiated")

        t = sim.t
        if log_to_screen:
            print("Three days = " + str(start_time) +
                  " seconds, but sim.t = " + str(sim.t) + ". Same? " +
                  str(start_time == sim.t))
        assert (round(start_time) == round(
            sim.t)), 'Spin up time seems to be wrong'

        #--------------------------------------------------------------
        # Create drifters at t = 3 days
        #--------------------------------------------------------------
        drifters = GPUDrifterCollection.GPUDrifterCollection(
            gpu_ctx,
            num_drifters,
            boundaryConditions=doubleJetCase_args['boundary_conditions'],
            domain_size_x=sim.nx * sim.dx,
            domain_size_y=sim.ny * sim.dy)
        sim.attachDrifters(drifters)

        #--------------------------------------------------------------
        # Create observation object and write the first drifter positions
        #--------------------------------------------------------------
        observations = Observation.Observation(domain_size_x=sim.nx * sim.dx,
                                               domain_size_y=sim.ny * sim.dy,
                                               nx=sim.nx,
                                               ny=sim.ny)

        # Configure observations to register static positions
        observations.setBuoyCellsByFrequency(25, 25)
        observations.add_observation_from_sim(sim)

        netcdf_iterations = int(simulation_time / netcdf_frequency)
        observation_sub_iterations = int(netcdf_frequency /
                                         observation_frequency)

        if log_to_screen:            print("We will now make " + str(netcdf_iterations) + " iterations with writing netcdf, and  " + \
str(observation_sub_iterations) + " subiterations with registering drifter positions.")

        theoretical_time = start_time

        ########################
        # Main simulation loop #
        ########################
        tic = time.time()

        time_error = 0

        for netcdf_it in range(netcdf_iterations):
            for observation_sub_it in range(observation_sub_iterations):

                next_obs_time = t + observation_frequency

                # Step until next observation
                sim.dataAssimilationStep(next_obs_time, write_now=False)

                # Store observation
                observations.add_observation_from_sim(sim)

                t = sim.t

                time_error += t - next_obs_time
                theoretical_time += observation_frequency

            sim.writeState()

            if netcdf_it % 10 == 0:

                # Check that everything looks okay
                eta, hu, hv = sim.download()
                if (np.any(np.isnan(eta))):
                    raise RuntimeError('Not a number at time ' + str(sim.t))

                sub_t = time.time() - tic
                if log_to_screen:
                    print("{:02.4f} s into loop: ".format(sub_t) +
                          "Done with netcdf iteration " + str(netcdf_it) +
                          " of " + str(netcdf_iterations))

        toc = time.time()
        if log_to_screen:
            print("{:02.4f} s: ".format(toc - tic) +
                  "Done with generating thruth")

        if log_to_screen: print("sim.t:            " + str(sim.t))

        ########################
        # Simulation loop DONE #
        ########################

        # Dump drifter observations to file:
        tic = time.time()
        observations.to_pickle(drifter_filename)
        toc = time.time()
        if log_to_screen:
            print("\n{:02.4f} s: ".format(toc - tic) +
                  "Drifter observations written to " + drifter_filename)

        return os.path.abspath(folder)

    except:

        raise

    finally:
        if sim is not None:
            sim.cleanUp()
        if doubleJetCase is not None:
            doubleJetCase.cleanUp()
        if log_to_screen:
            print("\n{:02.4f} s: ".format(toc - tic) +
                  "Clean up simulator done.")
Beispiel #24
0
    def test_netcdf_cdklm(self):
        
        # Create simulator and write to file:
        doubleJetCase = DoubleJetCase.DoubleJetCase(self.gpu_ctx,
                                                    DoubleJetCase.DoubleJetPerturbationType.IEWPFPaperCase)

        doubleJetCase_args, doubleJetCase_init = doubleJetCase.getInitConditions()
        netcdf_args = {
            'write_netcdf': True,
            'netcdf_filename': 'netcdf_test/netcdf_test.nc'
        }
        self.sim = CDKLM16.CDKLM16(**doubleJetCase_args, **doubleJetCase_init, **netcdf_args)
        self.sim.closeNetCDF()
        
        
        # Create new simulator from the newly created file
        self.file_sim = CDKLM16.CDKLM16.fromfilename(self.gpu_ctx, netcdf_args['netcdf_filename'], cont_write_netcdf=False)
        
        # Loop over object attributes and compare those that are scalars
        for attr in dir(self.sim):
            if not attr.startswith('__'):
                if np.isscalar(getattr(self.sim, attr)):
                    sim_attr      = getattr(self.sim,      attr)
                    file_sim_attr = getattr(self.file_sim, attr)

                    # Round the simulation time to make it comparable
                    if attr == 't':
                        file_sim_attr = round(file_sim_attr) 
                        sim_attr      = round(sim_attr)

                    # Create error message and compare values of attributes
                    assert_msg = "Discrepancy in attribute " + attr + ":\n" + \
                                 "         sim."+ attr + ": " + str(sim_attr) + \
                                 "    file_sim."+ attr + ": " + str(file_sim_attr)
                    self.assertEqual(sim_attr, file_sim_attr, msg=assert_msg)
                    
                    if self.printall:
                        print('file_sim.' + attr + ': ' + str(file_sim_attr))
                        print('     sim.' + attr + ': ' + str(sim_attr))
                        if np.isreal(file_sim_attr):
                            print('Diff: ' + str(file_sim_attr - sim_attr))
                        print('')

                    #if np.isreal(getattr(file_sim, attr)):
                    #    print('Diff: ' + str(getattr(file_sim, attr) - getattr(sim, attr)))

        # Loop over attributes in the model error
        for attr in dir(self.sim.small_scale_model_error):
            if not attr.startswith('__'):
                if np.isscalar(getattr(self.sim.small_scale_model_error, attr)):
                    
                    sim_attr      = getattr(self.sim.small_scale_model_error,      attr)
                    file_sim_attr = getattr(self.file_sim.small_scale_model_error, attr)
                    
                    # Create error message and compare values of attributes
                    assert_msg = "Discrepancy in attribute " + attr + ":\n" + \
                                 "         sim.small_scale_model_error"+ attr + ": " + str(sim_attr) + \
                                 "    file_sim.small_scale_model_error"+ attr + ": " + str(file_sim_attr)
                    self.assertEqual(sim_attr, file_sim_attr, msg=assert_msg)
                    
                    if self.printall:
                        print('file_sim.small_scale_model_error.' + attr + ': ' + str(file_sim_attr))
                        print('     sim.small_scale_model_error.' + attr + ': ' + str(sim_attr))
                        if np.isreal(file_sim_attr):
                            print('Diff: ' + str(file_sim_attr - sim_attr))
                        print('')

                        
        # Compare ocean state:
        s_eta0, s_hu0, s_hv0 = self.sim.download()
        f_eta0, f_hu0, f_hv0 = self.file_sim.download()
        self.checkResults(s_eta0, s_hu0, s_hv0, f_eta0, f_hu0, f_hv0)
        
        dt = self.sim.dt
        self.sim.step(100*dt, apply_stochastic_term=False)
        self.file_sim.step(100*dt, apply_stochastic_term=False)
        s_eta0, s_hu0, s_hv0 = self.sim.download()
        f_eta0, f_hu0, f_hv0 = self.file_sim.download()
        self.checkResults(s_eta0, s_hu0, s_hv0, f_eta0, f_hu0, f_hv0)
Beispiel #25
0
def simulate_gpuocean_deterministic(source_url, domain, initx, inity, 
                                    sim_args, norkyst_data = True, erode_land = 1, 
                                    wind_drift_factor = 0.0, rescale=0,
                                    forecast_file = None, start_forecast_hours = 0, duration = 23, 
                                    ocean_state_file = None, netcdf_frequency = 5 ):
    """
    source_url: url or local file or list of either with fielddata in NetCDF-format
    domain: array/list on form [x0,x1,y0,y1] defining the domain for the simulation
    initx, inity = initial coordinates of single drifter or lists with coordinates for multiple drifters. 
                   In local cartesian coordinates of simulation-domain. 
    norkyst_data: (default True) If True, assumes data from norkyst800. Else, works with norfjords160m(and probably other ROMS data).
    sim_args, erode_land, observation_type: arguments needed for simulator and observation object. sim_args must be given.
    wind_drift_factor: fraction of wind-speed at which objects will be advected. Default is 0 (no direct wind-drift)
    rescale: factor setting resolution of simulation-grid. 0 indicates no rescaling(original resolution), 
             while any other number changes the resolution (ie 2 gives double resolution)
    forecast_file: optional file for storing trajectory (pickle)
    ocean_state_file: optional file for storing ocean state (netcdf)
    netcdf_frequency: frequency(in hours) for storing of ocean states. 
    start_forecast_hours = number hours after which to start simulating drifttrajectories(ocean model starts at beginning of field-data)
                           Default is at beginning of field-data. 
    forecast_duration = duration of simulation(including possibly only ocean simulation). Default is 24 hours.
    """

    end_forecast_hours = start_forecast_hours + duration
    
    #Create simulator
    data_args = NetCDFInitialization.getInitialConditions(source_url, domain[0], domain[1], domain[2],domain[3] , 
                     timestep_indices = None,norkyst_data = norkyst_data, erode_land = erode_land, download_data = False)
    
    if wind_drift_factor:
        wind_data = data_args.pop('wind', None)
    else:
        wind_data = None
        
    if rescale:
        data_args = NetCDFInitialization.rescaleInitialConditions(data_args, scale=rescale)

    sim = CDKLM16.CDKLM16(**sim_args, **NetCDFInitialization.removeMetadata(data_args))
    
    #Forecast
    observation_type = dautils.ObservationType.UnderlyingFlow 
    
    observation_args = {'observation_type': observation_type,
                    'nx': sim.nx, 'ny': sim.ny,
                    'domain_size_x': sim.nx*sim.dx,
                    'domain_size_y': sim.ny*sim.dy,
                    'land_mask': sim.getLandMask()
                   }

    trajectory_forecast = Observation.Observation(**observation_args)
    
    #Drifters
    #Assumes initx, inity same format/shape
    if type(initx) is not list:
        initx = [initx]
        inity = [inity]
    
    num_drifters = len(initx)
    
    drifters = GPUDrifterCollection.GPUDrifterCollection(sim_args['gpu_ctx'], num_drifters, wind = wind_data, 
                                                         wind_drift_factor = wind_drift_factor,
                                                     boundaryConditions = sim.boundary_conditions,
                                                     domain_size_x = trajectory_forecast.domain_size_x,
                                                     domain_size_y = trajectory_forecast.domain_size_y,
                                                     gpu_stream = sim.gpu_stream)
    
    drifter_pos_init = np.array([initx, inity]).T
        
    try:
        if ocean_state_file is not None:
            print("Storing ocean state to netCDF-file: " + ocean_state_file)
            ncfile = Dataset(ocean_state_file, 'w')

            var = {}
            var['eta'], var['hu'], var['hv'] = sim.download(interior_domain_only=False)
            _, var['Hm'] = sim.downloadBathymetry(interior_domain_only=False)

            ny, nx = var['eta'].shape

            # Create dimensions
            ncfile.createDimension('time', None) # unlimited
            ncfile.createDimension('x', nx)
            ncfile.createDimension('y', ny)

            ncvar = {}

            # Create variables for dimensions
            ncvar['time'] = ncfile.createVariable('time', 'f8', ('time',))
            ncvar['x'] = ncfile.createVariable('x', 'f4', ('x',))
            ncvar['y'] = ncfile.createVariable('y', 'f4', ('y',))

            # Fill dimension variables
            ncvar['x'][:] = np.linspace(0, nx*sim.dx, nx)
            ncvar['y'][:] = np.linspace(0, ny*sim.dy, ny)

            # Create static variables
            ncvar['Hm'] = ncfile.createVariable('Hm', 'f8', ('y', 'x',), zlib=True)
            ncvar['Hm'][:,:] = var['Hm'][:,:]

            # Create time varying data variables
            for varname in ['eta', 'hu', 'hv']:
                ncvar[varname] = ncfile.createVariable(varname, 'f8', ('time', 'y', 'x',), zlib=True)
            ncvar['num_iterations'] = ncfile.createVariable('num_iterations', 'i4', ('time',))

        #Run simulation
        num_total_hours = end_forecast_hours

        five_mins_in_an_hour = 12
        sub_dt = 5*60 # five minutes

        progress = Common.ProgressPrinter(5)
        pp = display(progress.getPrintString(0), display_id=True)

        netcdf_counter = 0
        for hour in range(num_total_hours):

            if hour == start_forecast_hours:
                # Attach drifters
                drifters.setDrifterPositions(drifter_pos_init)
                sim.attachDrifters(drifters)
                trajectory_forecast.add_observation_from_sim(sim)

            for mins in range(five_mins_in_an_hour):
                t = sim.step(sub_dt)
                if hour >= start_forecast_hours:
                    trajectory_forecast.add_observation_from_sim(sim)

            if ocean_state_file is not None and hour%netcdf_frequency == 0:
                var['eta'], var['hu'], var['hv'] = sim.download(interior_domain_only=False)
                ncvar['time'][netcdf_counter] = sim.t
                ncvar['num_iterations'][netcdf_counter] = sim.num_iterations

                abort=False
                for varname in ['eta', 'hu', 'hv']:
                    ncvar[varname][netcdf_counter,:,:] = var[varname][:,:] #np.ma.masked_invalid(var[varname][:,:])
                    if (np.any(np.isnan(var[varname]))):
                        print("Variable " + varname + " contains NaN values!")
                        abort=True
                netcdf_counter += 1

                if (abort):
                    print("Aborting at t=" + str(sim.t))
                    ncfile.sync()
                    break

            pp.update(progress.getPrintString(hour/(end_forecast_hours-1)))
    
        if forecast_file is not None:
            trajectory_forecast.to_pickle(forecast_file)
            
    except Exception as e:
        print("Something went wrong:" + str(e))
        raise e
    finally:
        if ocean_state_file is not None:
            ncfile.close()
        
    return trajectory_forecast