def output_timestep(self): """Output the time step if on the right frequency. """ out_freq = (self.step_index * self.data_time_step / 3600.0) % self.options['output']['frequency'] == 0 last_time_step = self.step_index == len( self.options['time']['date_time']) - 1 if out_freq or last_time_step: self._logger.info('iPysnobal outputting {}'.format(self.time_step)) pysnobal_io.output_timestep(self.output_rec, self.time_step, self.options, self.awsm.pysnobal_output_vars) self.output_rec['time_since_out'] = self.init_zeros
def run_single(self, tstep, s, updater=None): """ Runs each timestep of Pysnobal when running with SMRF in non-threaded application. Args: tstep: datetime timestep s: smrf class instance updater: depth updater class """ # pbar = progressbar.ProgressBar(max_value=len(options['time']['date_time'])) self.input2 = {} for var, v in self.variable_list.items(): # get the data desired data = getattr(s.distribute[v['module']], v['variable']) if data is None: data = np.zeros((self.ny, self.nx)) self._logger.info( 'No data from smrf to iSnobal for {} in {}'.format( v, tstep)) self.input2[self.map_val[var]] = data else: self.input2[self.map_val[var]] = data # set ground temp self.input2['T_g'] = self.soil_temp * np.ones((self.ny, self.nx)) # convert variables to Kelvin self.input2['T_a'] += FREEZE self.input2['T_pp'] += FREEZE self.input2['T_g'] += FREEZE first_step = self.j # update depth if necessary if updater is not None: # if tstep.tz_localize(None) in updater.update_dates: if tstep in updater.update_dates: # print('doing that update thing') # self.output_rec = \ # updater.do_update_pysnobal(self.output_rec, tstep.tz_localize(None)) self.output_rec = \ updater.do_update_pysnobal(self.output_rec, tstep) first_step = 1 self._logger.info('running PySnobal for timestep: {}'.format(tstep)) rt = snobal.do_tstep_grid(self.input1, self.input2, self.output_rec, self.tstep_info, self.options['constants'], self.params, first_step=first_step, nthreads=self.nthreads) if rt != -1: self.logger.error( 'ipysnobal error on time step {}, pixel {}'.format(tstep, rt)) sys.exit() self._logger.info('Finished timestep: {}'.format(tstep)) self.input1 = self.input2.copy() # output at the frequency and the last time step if ((self.j)*(self.data_tstep/3600.0) % self.options['output']['frequency'] == 0)\ or (self.j == len(self.options['time']['date_time']) - 1): io_mod.output_timestep(self.output_rec, tstep, self.options, self.awsm_output_vars) self.output_rec['time_since_out'] = np.zeros( self.output_rec['elevation'].shape) self.j += 1
def run(self): """ mimic the main.c from the Snobal model. Runs Pysnobal while recieving forcing data from SMRF queue. """ force_variables = [ 'thermal', 'air_temp', 'vapor_pressure', 'wind_speed', 'net_solar', 'soil_temp', 'precip', 'percent_snow', 'snow_density', 'precip_temp' ] # loop through the input # do_data_tstep needs two input records so only go # to the last record-1 data_tstep = self.tstep_info[0]['time_step'] timeSinceOut = 0.0 tmp_date = self.date_time[0].replace(tzinfo=self.tzinfo) wyhr = utils.water_day(tmp_date)[0] * 24.0 start_step = wyhr # if restart then it would be higher if this were iSnobal # start_step = 0 # if restart then it would be higher if this were iSnobal step_time = start_step * data_tstep # step_time = start_step * 60.0 self.output_rec['current_time'] = step_time * np.ones( self.output_rec['elevation'].shape) self.output_rec['time_since_out'] = timeSinceOut * np.ones( self.output_rec['elevation'].shape) # map function from these values to the ones requried by snobal map_val = { 'air_temp': 'T_a', 'net_solar': 'S_n', 'thermal': 'I_lw', 'vapor_pressure': 'e_a', 'wind_speed': 'u', 'soil_temp': 'T_g', 'precip': 'm_pp', 'percent_snow': 'percent_snow', 'snow_density': 'rho_snow', 'precip_temp': 'T_pp' } # get first timestep input1 = {} for v in force_variables: if v in self.queue.keys(): data = self.queue[v].get(self.date_time[0], block=True, timeout=None) if data is None: data = np.zeros((self.ny, self.nx)) self._logger.info( 'No data from smrf to iSnobal for {} in {}'.format( v, self.date_time[0])) input1[map_val[v]] = data else: input1[map_val[v]] = data elif v != 'soil_temp': self._logger.error('Value not in keys: {}'.format(v)) # set ground temp input1['T_g'] = self.soil_temp * np.ones((self.ny, self.nx)) input1['T_a'] += FREEZE input1['T_pp'] += FREEZE input1['T_g'] += FREEZE # tell queue we assigned all the variables self.queue['isnobal'].put([self.date_time[0], True]) self._logger.info('Finished initializing first timestep for iPySnobal') j = 1 # for tstep in options['time']['date_time'][953:958]: for tstep in self.date_time[1:]: # get the output variables then pass to the function # this avoids zeroing of the energetics every timestep first_step = j input2 = {} for v in force_variables: if v in self.queue.keys(): # get variable from smrf queue data = self.queue[v].get(tstep, block=True, timeout=None) if data is None: data = np.zeros((self.ny, self.nx)) self._logger.info( 'No data from smrf to iSnobal for {} in {}'.format( v, tstep)) input2[map_val[v]] = data else: input2[map_val[v]] = data # set ground temp input2['T_g'] = self.soil_temp * np.ones((self.ny, self.nx)) # convert variables to Kelvin input2['T_a'] += FREEZE input2['T_pp'] += FREEZE input2['T_g'] += FREEZE first_step = j if self.updater is not None: #if tstep.tz_localize(None) in self.updater.update_dates: if tstep in self.updater.update_dates: # self.output_rec = \ # self.updater.do_update_pysnobal(self.output_rec, # tstep.tz_localize(None)) self.output_rec = \ self.updater.do_update_pysnobal(self.output_rec, tstep) first_step = 1 self._logger.info( 'running PySnobal for timestep: {}'.format(tstep)) rt = snobal.do_tstep_grid(input1, input2, self.output_rec, self.tstep_info, self.options['constants'], self.params, first_step=first_step, nthreads=self.nthreads) if rt != -1: self.logger.error( 'ipysnobal error on time step {}, pixel {}'.format( tstep, rt)) break self._logger.info('Finished timestep: {}'.format(tstep)) input1 = input2.copy() # output at the frequency and the last time step if ((j)*(data_tstep/3600.0) % self.options['output']['frequency'] == 0)\ or (j == len(self.options['time']['date_time']) - 1): io_mod.output_timestep(self.output_rec, tstep, self.options, self.awsm_output_vars) self.output_rec['time_since_out'] = \ np.zeros(self.output_rec['elevation'].shape) j += 1 # put the value into the output queue so clean knows it's done self.queue['isnobal'].put([tstep, True])
def run_ipysnobal(myawsm): """ Function to run PySnobal from netcdf of ipw forcing data, not from SMRF instance. Args: myawsm: awsm class """ # initialize ipysnobal state # get dem dem = myawsm.topo.dem myawsm._logger.info('Initializing from files') options, params, tstep_info, init, output_rec = \ ipysnobal.init_from_smrf(myawsm, dem=dem) data_tstep = tstep_info[0]['time_step'] timeSinceOut = 0.0 start_step = 0 # if restart then it would be higher if this were iSnobal step_time = start_step * data_tstep output_rec['current_time'] = step_time * np.ones(output_rec['elevation'].shape) output_rec['time_since_out'] = timeSinceOut * np.ones(output_rec['elevation'].shape) myawsm._logger.info('getting inputs for first timestep') if myawsm.forcing_data_type == 'netcdf': force = io_mod.open_files_nc(myawsm) input1 = initmodel.get_timestep_netcdf(force, options['time']['date_time'][0]) else: input_list, ppt_list = io_mod.open_files_ipw(myawsm) input1 = initmodel.get_timestep_ipw(options['time']['date_time'][0], input_list, ppt_list, myawsm) # initialize updater if required if myawsm.update_depth: updater = StateUpdater(myawsm) else: updater = None myawsm._logger.info('starting PySnobal time series loop') j = 1 # run PySnobal for tstep in options['time']['date_time'][1:]: # for tstep in options['time']['date_time'][953:958]: myawsm._logger.info('running PySnobal for timestep: {}'.format(tstep)) if myawsm.forcing_data_type == 'netcdf': input2 = initmodel.get_timestep_netcdf(force, tstep) else: input2 = initmodel.get_timestep_ipw(tstep, input_list, ppt_list, myawsm) first_step = j # update depth if necessary if updater is not None: if tstep in updater.update_dates: start_z = output_rec['z_s'].copy() output_rec = \ updater.do_update_pysnobal(output_rec, tstep) first_step = 1 rt = snobal.do_tstep_grid(input1, input2, output_rec, tstep_info, options['constants'], params, first_step=first_step, nthreads=myawsm.ipy_threads) if rt != -1: raise ValueError('ipysnobal error on time step %s, pixel %i' % (tstep, rt)) # break input1 = input2.copy() # output at the frequency and the last time step if ((j)*(data_tstep/3600.0) % options['output']['frequency'] == 0) \ or (j == len(options['time']['date_time']) - 1): myawsm._logger.info('Outputting {}'.format(tstep)) io_mod.output_timestep(output_rec, tstep, options, myawsm.pysnobal_output_vars) output_rec['time_since_out'] = np.zeros(output_rec['elevation'].shape) myawsm._logger.info('Finished timestep: {}'.format(tstep)) j += 1 # if input has run_for_nsteps, make sure not to go past it if myawsm.run_for_nsteps is not None: if j > myawsm.run_for_nsteps: break # close input files if myawsm.forcing_data_type == 'netcdf': io_mod.close_files(force)