示例#1
0
    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
示例#2
0
    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
示例#3
0
    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])
示例#4
0
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)