Esempio n. 1
0
def penetrating_radiation(GRID, SWnet, dt, opt_dict=None):

    # Read and set options
    read_opt(opt_dict, globals())

    penetrating_allowed = ['Bintanja95']
    if penetrating_method == 'Bintanja95':
        subsurface_melt, Si = method_Bintanja(GRID, SWnet, dt)
    else:
        raise ValueError("Penetrating method = \"{:s}\" is not allowed, must be one of {:s}".format(penetrating_method, ", ".join(penetrating_allowed)))

    return subsurface_melt, Si
Esempio n. 2
0
def evaluate(stake_names, stake_data, df_, opt_dict=None):
    """ This methods evaluates the simulation with the stake measurements
        stake_name  ::  """
            
    # Read and set options
    read_opt(opt_dict, globals())
    if eval_method == 'rmse':
        stat = rmse(stake_names, stake_data, df_)
    else:
        stat = None
       
    return stat
Esempio n. 3
0
def updateRoughness(GRID, opt_dict=None):

    # Read and set options
    read_opt(opt_dict, globals())

    roughness_allowed = ['Moelg12']
    if roughness_method == 'Moelg12':
        sigma = method_Moelg(GRID)
    else:
        raise ValueError(
            "Roghness method = \"{:s}\" is not allowed, must be one of {:s}".
            format(roughness_method, ", ".join(roughness_allowed)))

    return sigma
Esempio n. 4
0
def solveHeatEquation(GRID, dt, opt_dict=None):

    # Read and set options
    read_opt(opt_dict, globals())

    heatEquation_method = 'default'
    heatEquation_allowed = ['default']

    if heatEquation_method == 'default':
        heatEquation_default(GRID, dt)
    else:
        raise ValueError(
            "Heat equation = \"{:s}\" is not allowed, must be one of {:s}".
            format(heatEquation_method, ", ".join(heatEquation_allowed)))
Esempio n. 5
0
def updateAlbedo(GRID, opt_dict):
    """ This methods updates the albedo """
    # Read and set options
    read_opt(opt_dict, globals())
    albedo_allowed = ['Oerlemans98']
    if albedo_method == 'Oerlemans98':
        alphaMod = method_Oerlemans(GRID)

    else:
        raise ValueError(
            "Albedo method = \"{:s}\" is not allowed, must be one of {:s}".
            format(albedo_method, ", ".join(albedo_allowed)))

    return alphaMod
Esempio n. 6
0
def refreezing(GRID, opt_dict=None):

    # Read and set options
    read_opt(opt_dict, globals())

    refreezing_method = 'default'
    refreezing_allowed = ['default']

    if refreezing_method == 'default':
        water_refreezed = refreezing_default(GRID)
    else:
        raise ValueError(
            "Refreezing method = \"{:s}\" is not allowed, must be one of {:s}".
            format(refreezing_method, ", ".join(refreezing_allowed)))

    return water_refreezed
Esempio n. 7
0
def percolation(GRID, water, dt, opt_dict=None):

    # Read and set options
    read_opt(opt_dict, globals())

    percolation_method = 'bucket'
    percolation_allowed = ['bucket']

    if percolation_method == 'bucket':
        Q = bucket(GRID, water, dt)
    else:
        raise ValueError(
            "Percolation method = \"{:s}\" is not allowed, must be one of {:s}"
            .format(percolation_method, ", ".join(percolation_allowed)))

    return Q
Esempio n. 8
0
    def __init__(self, DATA=None, opt_dict=None):
        """ Init IO Class"""

        # Read and set options
        read_opt(opt_dict, globals())
        # Read variable list from file
        config = configparser.ConfigParser()
        config.read('./cosipy/output')
        self.atm = config['vars']['atm']
        self.internal = config['vars']['internal']
        self.full = config['vars']['full']



        # Initialize data
        self.DATA = DATA
        self.RESTART = None
        self.RESULT = None
      
        # If local IO class is initialized we need to get the dimensions of the dataset
        if DATA is not None:
            self.time = self.DATA.dims['time']
def densification(GRID, SLOPE, dt, opt_dict=None):
    """ Densification of the snowpack
    Args:
        GRID    ::  GRID-Structure
	dt      ::  integration time
    """
    # Read and set options
    read_opt(opt_dict, globals())

    densification_allowed = ['Boone', 'Vionnet', 'empirical', 'constant']

    if densification_method == 'Boone':
        method_Boone(GRID, SLOPE, dt)
    elif densification_method == 'Vionnet':
        method_Vionnet(GRID, SLOPE, dt)
    elif densification_method == 'empirical':
        method_empirical(GRID, SLOPE, dt)
    elif densification_method == 'constant':
        pass
    else:
        raise ValueError(
            "Densification method = \"{:s}\" is not allowed, must be one of {:s}"
            .format(densification_method, ", ".join(densification_allowed)))
def update_surface_temperature(GRID,
                               dt,
                               z,
                               z0,
                               T2,
                               rH2,
                               p,
                               SWnet,
                               u2,
                               RAIN,
                               SLOPE,
                               LWin=None,
                               N=None,
                               opt_dict=None):
    """ This methods updates the surface temperature and returns the surface fluxes

    Given:

        GRID    ::  Grid structure
        T0      ::  Surface temperature [K]
	    dt      ::  Integration time [s] -- can vary in WRF_X_CSPY
        alpha   ::  Albedo [-]
	    z       ::  Measurement height [m] -- varies in WRF_X_CSPY
        z0      ::  Roughness length [m]
        T2      ::  Air temperature [K]
        rH2     ::  Relative humidity [%]
        p       ::  Air pressure [hPa]
        G       ::  Incoming shortwave radiation [W m^-2]
        u2      ::  Wind velocity [m S^-1]
        RAIN    ::  RAIN (mm)
        SLOPE   ::  Slope of the surface [degree]

        LWin    ::  Incoming longwave radiation [W m^-2]
        N       ::  Fractional cloud cover [-]

    Returns:

        Li      ::  Incoming longwave radiation [W m^-2]
        Lo      ::  Outgoing longwave radiation [W m^-2]
        H       ::  Sensible heat flux [W m^-2]
        L       ::  Latent heat flux [W m^-2]
        B       ::  Ground heat flux [W m^-2]
        Qrr     ::  Rain heat flux [W m^-2]
        SWnet   ::  Shortwave radiation budget [W m^-2]
        rho     ::  Air density [kg m^-3]
        Lv      ::  Latent heat of vaporization [J kg^-1]
	    MOL     ::  Monin-Obukhov length
        Cs_t    ::  Stanton number [-]
        Cs_q    ::  Dalton number [-]
        q0      ::  Mixing ratio at the surface [kg kg^-1]
        q2      ::  Mixing ratio at measurement height [kg kg^-1]
        phi     ::  Stability correction term [-]
    """

    # Read and set options
    read_opt(opt_dict, globals())

    #Interpolate subsurface temperatures to selected subsurface depths for GHF computation
    B_Ts = interp_subT(GRID)

    #Update surface temperature
    lower_bnd_ts = 220.

    if sfc_temperature_method == 'L-BFGS-B' or sfc_temperature_method == 'SLSQP':
        # Get surface temperature by minimizing the energy balance function (SWnet+Li+Lo+H+L=0)
        res = minimize(eb_optim,
                       GRID.get_node_temperature(0),
                       method=sfc_temperature_method,
                       bounds=((lower_bnd_ts, zero_temperature), ),
                       tol=1e-2,
                       args=(GRID, dt, z, z0, T2, rH2, p, SWnet, u2, RAIN,
                             SLOPE, B_Ts, LWin, N))

    elif sfc_temperature_method == 'Newton':
        try:
            res = newton(eb_optim,
                         np.array([GRID.get_node_temperature(0)]),
                         tol=1e-2,
                         maxiter=50,
                         args=(GRID, dt, z, z0, T2, rH2, p, SWnet, u2, RAIN,
                               SLOPE, B_Ts, LWin, N))
            if res < lower_bnd_ts:
                raise ValueError("TS Solution is out of bounds")
            res = SimpleNamespace(**{
                'x': min(np.array([zero_temperature]), res),
                'fun': None
            })

        except (RuntimeError, ValueError):
            #Workaround for non-convergence and unboundedness
            res = minimize(eb_optim,
                           GRID.get_node_temperature(0),
                           method='SLSQP',
                           bounds=((lower_bnd_ts, zero_temperature), ),
                           tol=1e-2,
                           args=(GRID, dt, z, z0, T2, rH2, p, SWnet, u2, RAIN,
                                 SLOPE, B_Ts, LWin, N))
    else:
        print('Invalid method for minimizing the residual')

    # Set surface temperature
    GRID.set_node_temperature(0, float(res.x))

    (Li, Lo, H, L, B, Qrr, rho, Lv, MOL, Cs_t, Cs_q, q0, q2) = eb_fluxes(
        GRID,
        res.x,
        dt,
        z,
        z0,
        T2,
        rH2,
        p,
        u2,
        RAIN,
        SLOPE,
        B_Ts,
        LWin,
        N,
    )

    # Consistency check
    if (float(res.x) > zero_temperature) or (float(res.x) < lower_bnd_ts):
        print('Surface temperature is outside bounds:',
              GRID.get_node_temperature(0))

    # Return fluxes
    return res.fun, res.x, Li, Lo, H, L, B, Qrr, rho, Lv, MOL, Cs_t, Cs_q, q0, q2
Esempio n. 11
0
def init_snowpack(DATA, opt_dict):
    ''' INITIALIZATION '''

    # Read and set options
    read_opt(opt_dict, globals())

    ##--------------------------------------
    ## Check for WRF data
    ##--------------------------------------
    if ('SNOWHEIGHT' in DATA):
        initial_snowheight = DATA.SNOWHEIGHT.values
        if np.isnan(initial_snowheight):
            initial_snowheight = 0.0
    else:
        initial_snowheight = initial_snowheight_constant
    temperature_top = np.minimum(DATA.T2.values[0], 273.16)

    #--------------------------------------
    # Do the vertical interpolation
    #--------------------------------------
    layer_heights = []
    layer_densities = []
    layer_T = []
    layer_liquid_water = []

    if (initial_snowheight > 0.0):
        optimal_height = 0.1  # 10 cm
        nlayers = int(min(initial_snowheight / optimal_height, 5))
        dT = (temperature_top - temperature_bottom) / (initial_snowheight +
                                                       initial_glacier_height)
        if nlayers == 0:
            layer_heights = np.array([initial_snowheight])
            layer_densities = np.array([initial_top_density_snowpack])
            layer_T = np.array([temperature_top])
            layer_liquid_water = np.array([0.0])
        elif nlayers > 0:
            drho = (initial_top_density_snowpack -
                    initial_bottom_density_snowpack) / initial_snowheight
            layer_heights = np.ones(nlayers) * (initial_snowheight / nlayers)
            layer_densities = np.array([
                initial_top_density_snowpack - drho *
                (initial_snowheight / nlayers) * i
                for i in range(1, nlayers + 1)
            ])
            layer_T = np.array([
                temperature_top - dT * (initial_snowheight / nlayers) * i
                for i in range(1, nlayers + 1)
            ])
            layer_liquid_water = np.zeros(nlayers)

        # add glacier
        nlayers = int(initial_glacier_height / initial_glacier_layer_heights)
        layer_heights = np.append(
            layer_heights,
            np.ones(nlayers) * initial_glacier_layer_heights)
        layer_densities = np.append(layer_densities,
                                    np.ones(nlayers) * ice_density)
        layer_T = np.append(layer_T, [
            layer_T[-1] - dT * initial_glacier_layer_heights * i
            for i in range(1, nlayers + 1)
        ])
        layer_liquid_water = np.append(layer_liquid_water, np.zeros(nlayers))

    else:

        # only glacier
        nlayers = int(initial_glacier_height / initial_glacier_layer_heights)
        dT = (temperature_top - temperature_bottom) / initial_glacier_height
        layer_heights = np.ones(nlayers) * initial_glacier_layer_heights
        layer_densities = np.ones(nlayers) * ice_density
        layer_T = np.array([
            temperature_top - dT * initial_glacier_layer_heights * i
            for i in range(1, nlayers + 1)
        ])
        layer_liquid_water = np.zeros(nlayers)

    # Initialize grid, the grid class contains all relevant grid information
    GRID = Grid(np.array(layer_heights, dtype=np.float64),
                np.array(layer_densities, dtype=np.float64),
                np.array(layer_T, dtype=np.float64),
                np.array(layer_liquid_water, dtype=np.float64), None, None,
                None, None)

    return GRID
Esempio n. 12
0
def cosipy_core(DATA, indY, indX, GRID_RESTART=None, stake_names=None, stake_data=None, opt_dict=None):
    """ Cosipy core function, which perform the calculations on one core.

    Params
    ======
    DATA: xarray.Dataset
      xarray dataset which contain one grid point
    indY: 
    indX:

    GRID_RESTART : boolean, optional
      If restart is given, no inital profile is created
    stake_name : boolean, optional
      stake names      
    stake_data : boolean, optional
      stake data
    Returns
    ======
    Returns all calculated variables of one grid point

    """
    



    # Replace values from constants.py if coupled
    from constants import max_layers, dt, z	#WTF python!
    if WRF_X_CSPY:
        dt = int(DATA.DT.values)
        max_layers = int(DATA.max_layers.values)
        z = float(DATA.ZLVL.values)

    # Replace imported variables with content of the opt_dict. If it's empty
    # nothing happens.
    read_opt(opt_dict, globals())
    # Local variables
    nt = len(DATA.time.values)         #accessing DATA is expensive 		
    _RRR = np.full(nt, np.nan)
    _RAIN = np.full(nt, np.nan)
    _SNOWFALL = np.full(nt, np.nan)
    _LWin = np.full(nt, np.nan)
    _LWout = np.full(nt, np.nan)
    _H = np.full(nt, np.nan)
    _LE = np.full(nt, np.nan)
    _B = np.full(nt, np.nan)
    _QRR = np.full(nt, np.nan)
    _MB = np.full(nt, np.nan)
    _surfMB = np.full(nt, np.nan)
    _MB = np.full(nt, np.nan)
    _Q = np.full(nt, np.nan)
    _SNOWHEIGHT = np.full(nt, np.nan)
    _TOTALHEIGHT = np.full(nt, np.nan)
    _TS = np.full(nt, np.nan)
    _ALBEDO = np.full(nt, np.nan)
    _ME = np.full(nt, np.nan)
    _intMB = np.full(nt, np.nan)
    _EVAPORATION = np.full(nt, np.nan)
    _SUBLIMATION = np.full(nt, np.nan)
    _CONDENSATION = np.full(nt, np.nan)
    _DEPOSITION = np.full(nt, np.nan)
    _REFREEZE = np.full(nt, np.nan)
    _NLAYERS = np.full(nt, np.nan)
    _subM = np.full(nt, np.nan)
    _Z0 = np.full(nt, np.nan)
    _surfM = np.full(nt, np.nan)
    _MOL = np.full(nt, np.nan)

    _LAYER_HEIGHT = np.full((nt,max_layers), np.nan)
    _LAYER_RHO = np.full((nt,max_layers), np.nan)
    _LAYER_T = np.full((nt,max_layers), np.nan)
    _LAYER_LWC = np.full((nt,max_layers), np.nan)
    _LAYER_CC = np.full((nt,max_layers), np.nan)
    _LAYER_POROSITY = np.full((nt,max_layers), np.nan)
    _LAYER_ICE_FRACTION = np.full((nt,max_layers), np.nan)
    _LAYER_IRREDUCIBLE_WATER = np.full((nt,max_layers), np.nan)
    _LAYER_REFREEZE = np.full((nt,max_layers), np.nan)


    #--------------------------------------------
    # Initialize snowpack or load restart grid
    #--------------------------------------------
    if GRID_RESTART is None:
        GRID = init_snowpack(DATA, opt_dict)
    else:
        GRID = load_snowpack(GRID_RESTART)

    # Create the local output datasets if not coupled
    RESTART = None
    if not WRF_X_CSPY:
        IO = IOClass(DATA, opt_dict)
        RESTART = IO.create_local_restart_dataset()

    # hours since the last snowfall (albedo module)
    hours_since_snowfall = 0

    #--------------------------------------------
    # Get data from file
    #--------------------------------------------
    T2 = DATA.T2.values
    RH2 = DATA.RH2.values
    PRES = DATA.PRES.values
    G = DATA.G.values
    U2 = DATA.U2.values

    #--------------------------------------------
    # Checks for optional input variables
    #--------------------------------------------
    if ('SNOWFALL' in DATA) and ('RRR' in DATA):
        SNOWF = DATA.SNOWFALL.values * mult_factor_RRR
        RRR = DATA.RRR.values * mult_factor_RRR

    elif ('SNOWFALL' in DATA):
        SNOWF = DATA.SNOWFALL.values * mult_factor_RRR
        RRR = None
        RAIN = None

    else:
        SNOWF = None
        RRR = DATA.RRR.values * mult_factor_RRR

    # Use RRR rather than snowfall?
    if force_use_TP:
        SNOWF = None

    if ('LWin' in DATA) and ('N' in DATA):
        LWin = DATA.LWin.values
        N = DATA.N.values

    elif ('LWin' in DATA):
        LWin = DATA.LWin.values

    else:
        LWin = None
        N = DATA.N.values

    # Use N rather than LWin
    if force_use_N:
        LWin = None

    if ('SLOPE' in DATA):
        SLOPE = DATA.SLOPE.values

    else:
        SLOPE = 0.0

    # Initial cumulative mass balance variable
    MB_cum = 0

    if stake_evaluation:
        # Create pandas dataframe for stake evaluation
        _df = pd.DataFrame(index=stake_data.index, columns=['mb','snowheight'], dtype='float')

    #--------------------------------------------
    # TIME LOOP
    #--------------------------------------------    
    for t in np.arange(nt):
        
        # Check grid
        GRID.grid_check()

        # get seconds since start
        timestamp = dt*t
        if WRF_X_CSPY:
            timestamp = np.float64(DATA.CURR_SECS.values)

        # Calc fresh snow density
        if (densification_method!='constant'):
            density_fresh_snow = np.maximum(109.0+6.0*(T2[t]-273.16)+26.0*np.sqrt(U2[t]), 50.0)
        else:
            density_fresh_snow = constant_density 

        # Derive snowfall [m] and rain rates [m w.e.]
        if (SNOWF is not None) and (RRR is not None):
            SNOWFALL = SNOWF[t]
            RAIN = RRR[t]-SNOWFALL*(density_fresh_snow/ice_density) * 1000.0
        elif (SNOWF is not None):
            SNOWFALL = SNOWF[t]
        else:
            # Else convert total precipitation [mm] to snowheight [m]; liquid/solid fraction
            SNOWFALL = (RRR[t]/1000.0)*(ice_density/density_fresh_snow)*(0.5*(-np.tanh(((T2[t]-zero_temperature) - center_snow_transfer_function) * spread_snow_transfer_function) + 1.0))
            RAIN = RRR[t]-SNOWFALL*(density_fresh_snow/ice_density) * 1000.0

        # if snowfall is smaller than the threshold
        if SNOWFALL<minimum_snowfall:
            SNOWFALL = 0.0

        # if rainfall is smaller than the threshold
        if RAIN<(minimum_snowfall*(density_fresh_snow/ice_density)*1000.0):
            RAIN = 0.0

        if SNOWFALL > 0.0:
            # Add a new snow node on top
           GRID.add_fresh_snow(SNOWFALL, density_fresh_snow, np.minimum(float(T2[t]),zero_temperature), 0.0)
        else:
           GRID.set_fresh_snow_props_update_time(dt)

        # Guarantee that solar radiation is greater equal zero
        if (G[t]<0.0):
            G[t] = 0.0

        #--------------------------------------------
        # Merge grid layers, if necessary
        #--------------------------------------------
        GRID.update_grid()

        #--------------------------------------------
        # Calculate albedo and roughness length changes if first layer is snow
        #--------------------------------------------
        alpha = updateAlbedo(GRID, opt_dict)

        #--------------------------------------------
        # Update roughness length
        #--------------------------------------------
        z0 = updateRoughness(GRID, opt_dict)

        #--------------------------------------------
        # Surface Energy Balance
        #--------------------------------------------
        # Calculate net shortwave radiation
        SWnet = G[t] * (1 - alpha)

        # Penetrating SW radiation and subsurface melt
        if SWnet > 0.0:
            subsurface_melt, G_penetrating = penetrating_radiation(GRID, SWnet, dt, opt_dict)
        else:
            subsurface_melt = 0.0
            G_penetrating = 0.0

        # Calculate residual net shortwave radiation (penetrating part removed)
        sw_radiation_net = SWnet - G_penetrating

        if LWin is not None:
            # Find new surface temperature (LW is used from the input file)
            fun, surface_temperature, lw_radiation_in, lw_radiation_out, sensible_heat_flux, latent_heat_flux, \
                ground_heat_flux, rain_heat_flux, rho, Lv, MOL, Cs_t, Cs_q, q0, q2 \
                = update_surface_temperature(GRID, dt, z, z0, T2[t], RH2[t], PRES[t],
                                             sw_radiation_net, U2[t], RAIN, SLOPE, LWin=LWin[t], opt_dict=opt_dict)
        else:
            # Find new surface temperature (LW is parametrized using cloud fraction)
            fun, surface_temperature, lw_radiation_in, lw_radiation_out, sensible_heat_flux, latent_heat_flux, \
                ground_heat_flux, rain_heat_flux, rho, Lv, MOL, Cs_t, Cs_q, q0, q2 \
                = update_surface_temperature(GRID, dt, z, z0, T2[t], RH2[t], PRES[t],
                                             sw_radiation_net, U2[t], RAIN, SLOPE, N=N[t], opt_dict=opt_dict)

        #--------------------------------------------
        # Surface mass fluxes [m w.e.q.]
        #--------------------------------------------
        if surface_temperature < zero_temperature:
            sublimation = min(latent_heat_flux / (water_density * lat_heat_sublimation), 0) * dt
            deposition = max(latent_heat_flux / (water_density * lat_heat_sublimation), 0) * dt
            evaporation = 0
            condensation = 0
        else:
            sublimation = 0
            deposition = 0
            evaporation = min(latent_heat_flux / (water_density * lat_heat_vaporize), 0) * dt
            condensation = max(latent_heat_flux / (water_density * lat_heat_vaporize), 0) * dt

        #--------------------------------------------
        # Melt process - mass changes of snowpack (melting, sublimation, deposition, evaporation, condensation)
        #--------------------------------------------
        # Melt energy in [W m^-2 or J s^-1 m^-2]
        melt_energy = max(0, sw_radiation_net + lw_radiation_in + lw_radiation_out + ground_heat_flux + rain_heat_flux +
                          sensible_heat_flux + latent_heat_flux)

        # Convert melt energy to m w.e.q.
        melt = melt_energy * dt / (1000 * lat_heat_melting)

        # Remove melt [m w.e.q.]
        lwc_from_melted_layers = GRID.remove_melt_weq(melt - sublimation - deposition)

        #--------------------------------------------
        # Percolation
        #--------------------------------------------
        Q  = percolation(GRID, melt + condensation + RAIN/1000.0 + lwc_from_melted_layers, dt, opt_dict)

        #--------------------------------------------
        # Refreezing
        #--------------------------------------------
        water_refreezed = refreezing(GRID, opt_dict)

        #--------------------------------------------
        # Solve the heat equation
        #--------------------------------------------
        solveHeatEquation(GRID, dt, opt_dict)

        #--------------------------------------------
        # Calculate new density to densification
        #--------------------------------------------
        densification(GRID, SLOPE, dt, opt_dict)

        #--------------------------------------------
        # Calculate mass balance
        #--------------------------------------------
        surface_mass_balance = SNOWFALL * (density_fresh_snow / ice_density) - melt + sublimation + deposition + evaporation
        internal_mass_balance = water_refreezed - subsurface_melt
        mass_balance = surface_mass_balance + internal_mass_balance

        internal_mass_balance2 = melt-Q  + subsurface_melt
        mass_balance_check = surface_mass_balance + internal_mass_balance2

        # Cumulative mass balance for stake evaluation 
        MB_cum = MB_cum + mass_balance
        
        # Store cumulative MB in pandas frame for validation
        if stake_names:
            if (DATA.isel(time=t).time.values in stake_data.index):
                _df['mb'].loc[DATA.isel(time=t).time.values] = MB_cum 
                _df['snowheight'].loc[DATA.isel(time=t).time.values] = GRID.get_total_snowheight() 
        
        # Save results
        _RAIN[t] = RAIN
        _SNOWFALL[t] = SNOWFALL * (density_fresh_snow/ice_density)
        _LWin[t] = lw_radiation_in
        _LWout[t] = lw_radiation_out
        _H[t] = sensible_heat_flux
        _LE[t] = latent_heat_flux
        _B[t] = ground_heat_flux
        _QRR[t] = rain_heat_flux
        _MB[t] = mass_balance
        _surfMB[t] = surface_mass_balance
        _Q[t] = Q
        _SNOWHEIGHT[t] = GRID.get_total_snowheight()
        _TOTALHEIGHT[t] = GRID.get_total_height()
        _TS[t] = surface_temperature
        _ALBEDO[t] = alpha
        _NLAYERS[t] = GRID.get_number_layers()
        _ME[t] = melt_energy
        _intMB[t] = internal_mass_balance
        _EVAPORATION[t] = evaporation
        _SUBLIMATION[t] = sublimation
        _CONDENSATION[t] = condensation
        _DEPOSITION[t] = deposition
        _REFREEZE[t] = water_refreezed
        _subM[t] = subsurface_melt
        _Z0[t] = z0
        _surfM[t] = melt
        _MOL[t] = MOL

        if full_field:
            if GRID.get_number_layers()>max_layers:
                print('Maximum number of layers reached')
            else:
                _LAYER_HEIGHT[t, 0:GRID.get_number_layers()] = GRID.get_height()
                _LAYER_RHO[t, 0:GRID.get_number_layers()] = GRID.get_density()
                _LAYER_T[t, 0:GRID.get_number_layers()] = GRID.get_temperature()
                _LAYER_LWC[t, 0:GRID.get_number_layers()] = GRID.get_liquid_water_content()
                _LAYER_CC[t, 0:GRID.get_number_layers()] = GRID.get_cold_content()
                _LAYER_POROSITY[t, 0:GRID.get_number_layers()] = GRID.get_porosity()
                _LAYER_ICE_FRACTION[t, 0:GRID.get_number_layers()] = GRID.get_ice_fraction()
                _LAYER_IRREDUCIBLE_WATER[t, 0:GRID.get_number_layers()] = GRID.get_irreducible_water_content()
                _LAYER_REFREEZE[t, 0:GRID.get_number_layers()] = GRID.get_refreeze()
        else:
            _LAYER_HEIGHT = None
            _LAYER_RHO = None
            _LAYER_T = None
            _LAYER_LWC = None
            _LAYER_CC = None
            _LAYER_POROSITY = None
            _LAYER_ICE_FRACTION = None
            _LAYER_IRREDUCIBLE_WATER = None
            _LAYER_REFREEZE = None

    if stake_evaluation:
        # Evaluate stakes
        _stat = evaluate(stake_names, stake_data, _df)
    else:
        _stat = None
        _df = None

    # Restart
    if not WRF_X_CSPY:
        new_snow_height, new_snow_timestamp, old_snow_timestamp = GRID.get_fresh_snow_props()
        RESTART.NLAYERS.values[:] = GRID.get_number_layers()
        RESTART.NEWSNOWHEIGHT.values[:] = new_snow_height
        RESTART.NEWSNOWTIMESTAMP.values[:] = new_snow_timestamp
        RESTART.OLDSNOWTIMESTAMP.values[:] = old_snow_timestamp
        RESTART.LAYER_HEIGHT[0:GRID.get_number_layers()] = GRID.get_height()
        RESTART.LAYER_RHO[0:GRID.get_number_layers()] = GRID.get_density()
        RESTART.LAYER_T[0:GRID.get_number_layers()] = GRID.get_temperature()
        RESTART.LAYER_LWC[0:GRID.get_number_layers()] = GRID.get_liquid_water_content()
        RESTART.LAYER_IF[0:GRID.get_number_layers()] = GRID.get_ice_fraction()

    return (indY,indX,RESTART,_RAIN,_SNOWFALL,_LWin,_LWout,_H,_LE,_B, _QRR, \
            _MB,_surfMB,_Q,_SNOWHEIGHT,_TOTALHEIGHT,_TS,_ALBEDO,_NLAYERS, \
            _ME,_intMB,_EVAPORATION,_SUBLIMATION,_CONDENSATION,_DEPOSITION,_REFREEZE, \
            _subM,_Z0,_surfM, _MOL, \
            _LAYER_HEIGHT,_LAYER_RHO,_LAYER_T,_LAYER_LWC,_LAYER_CC,_LAYER_POROSITY,_LAYER_ICE_FRACTION, \
            _LAYER_IRREDUCIBLE_WATER,_LAYER_REFREEZE,stake_names,_stat,_df)