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
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())
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
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)
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)
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)
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)
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")
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)
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)
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)
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)
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)
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
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)
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
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)
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)
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")
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
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.")
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)
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