Пример #1
0
def cosipy_core(DATA, GRID_RESTART=None):
    ''' INITIALIZATION '''

    # Start logging
    logger = logging.getLogger(__name__)

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

    # Create the local output datasets
    logger.debug('Create local datasets')
    IO = IOClass(DATA)
    RESULT = IO.create_local_result_dataset()
    RESTART = IO.create_local_restart_dataset()

    # Merge grid layers, if necessary
    logger.debug('Create local datasets')
    GRID.update_grid(merging, density_threshold_merging,
                     temperature_threshold_merging, merge_snow_threshold,
                     merge_max, split_max)

    # 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
    # Check whether snowfall data is availible
    if ('SNOWFALL' in DATA) and ('RRR' in DATA):
        SNOWF = DATA.SNOWFALL.values
        RRR = DATA.RRR.values
        print(
            "You can select between total precipitation and snowfall (default)\n"
        )
    elif ('SNOWFALL' in DATA):
        SNOWF = DATA.SNOWFALL.values
    else:
        SNOWF = None
        RRR = DATA.RRR.values

    if force_use_TP is True:
        SNOWF = None

    # Check whether longwave data is availible -> used for surface temperature calculations
    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

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

    else:
        SLOPE = 0.0

    # Profiling with bokeh
    cp = cProfile.Profile()

    #--------------------------------------------
    # TIME LOOP
    #--------------------------------------------
    logger.debug('Start time loop')

    for t in np.arange(len(DATA.time)):

        if (SNOWF is not None):
            # Snowfall is given in m
            SNOWFALL = SNOWF[t]

        else:
            # Rainfall is given as mm, so we convert to m snowheight
            SNOWFALL = (RRR[t] / 1000.0) * (
                ice_density / density_fresh_snow) * (0.5 * (-np.tanh(
                    ((T2[t] - zero_temperature) - 2.5) * 2.5) + 1))
            if SNOWFALL < 0.0:
                SNOWFALL = 0.0

        if SNOWFALL > 0.0:
            # Add a new snow node on top
            GRID.add_node(SNOWFALL, density_fresh_snow, float(T2[t]), 0.0, 0.0,
                          0.0, 0.0, 0.0)
            GRID.merge_new_snow(merge_snow_threshold)

        # Calculate rain
        RAIN = RRR[t] - SNOWFALL * (density_fresh_snow / ice_density)

        # Get hours since last snowfall for the albedo calculations
        if SNOWFALL < minimum_snow_to_reset_albedo:
            hours_since_snowfall += dt / 3600.0
        else:
            hours_since_snowfall = 0

        # Calculate albedo and roughness length changes if first layer is snow
        # Update albedo values
        alpha = updateAlbedo(GRID, hours_since_snowfall)

        # Update roughness length
        z0 = updateRoughness(GRID, hours_since_snowfall)

        # Calculate new density to densification
        # densification(GRID,SLOPE)

        # Merge grid layers, if necessary
        GRID.update_grid(merging, temperature_threshold_merging,
                         density_threshold_merging, merge_snow_threshold,
                         merge_max, split_max)

        # Solve the heat equation
        cpi = solveHeatEquation(GRID, dt)

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

        # Account layer temperature due to penetrating SW radiation and subsurface melt
        subsurface_melt, G_penetrating = penetrating_radiation(GRID, SWnet, dt)

        # Calculate new incoming shortwave radiation
        G_temp = G[t] - G_penetrating

        if LWin is not None:
            # Find new surface temperature
            fun, surface_temperature, lw_radiation_in, lw_radiation_out, sensible_heat_flux, latent_heat_flux, \
                ground_heat_flux, sw_radiation_net, rho, Lv, Cs, q0, q2, qdiff, phi \
                = update_surface_temperature(GRID, alpha, z0, T2[t], RH2[t], PRES[t], G_temp, U2[t], SLOPE, LWin=LWin[t])
        else:
            # Find new surface temperature
            fun, surface_temperature, lw_radiation_in, lw_radiation_out, sensible_heat_flux, latent_heat_flux, \
                ground_heat_flux, sw_radiation_net, rho, Lv, Cs, q0, q2, qdiff, phi \
                = update_surface_temperature(GRID, alpha, z0, T2[t], RH2[t], PRES[t], G_temp, U2[t], SLOPE, N=N[t])

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

        # 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 - 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.
        GRID.remove_melt_energy(melt + sublimation + deposition + evaporation +
                                condensation)

        # Merge first layer, if too small (for model stability)
        GRID.merge_new_snow(merge_snow_threshold)

        # Percolation/Refreezing
        Q, water_refreezed, LWCchange = percolation(GRID, melt, dt,
                                                    debug_level)

        # Write results
        logger.debug('Write data into local result structure')

        # Calculate mass balance
        surface_mass_balance = SNOWFALL * (
            density_fresh_snow / ice_density
        ) - melt - sublimation - deposition - evaporation - condensation
        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

        # Save results
        RESULT.T2[t] = T2[t]
        RESULT.RH2[t] = RH2[t]
        RESULT.U2[t] = U2[t]
        RESULT.RRR[t] = RRR[t]
        RESULT.RAIN[t] = RAIN
        RESULT.SNOWFALL[t] = SNOWFALL
        RESULT.PRES[t] = PRES[t]
        RESULT.G[t] = G[t]
        RESULT.LWin[t] = lw_radiation_in
        RESULT.LWout[t] = lw_radiation_out
        RESULT.H[t] = -sensible_heat_flux
        RESULT.LE[t] = -latent_heat_flux
        RESULT.B[t] = ground_heat_flux
        RESULT.ME[t] = melt_energy
        RESULT.MB[t] = mass_balance
        RESULT.surfMB[t] = surface_mass_balance
        RESULT.intMB[t] = internal_mass_balance
        RESULT.EVAPORATION[t] = evaporation
        RESULT.SUBLIMATION[t] = sublimation
        RESULT.CONDENSATION[t] = condensation
        RESULT.DEPOSITION[t] = deposition
        RESULT.surfM[t] = melt
        RESULT.subM[t] = subsurface_melt
        RESULT.Q[t] = Q
        RESULT.REFREEZE[t] = water_refreezed
        RESULT.SNOWHEIGHT[t] = GRID.get_total_snowheight()
        RESULT.TOTALHEIGHT[t] = GRID.get_total_height()
        RESULT.TS[t] = surface_temperature
        RESULT.ALBEDO[t] = alpha
        RESULT.Z0[t] = z0
        RESULT.NLAYERS[t] = GRID.get_number_layers()

        if LWin is None:
            RESULT.N[t] = N[t]

        if full_field:
            RESULT.LAYER_HEIGHT[
                t, 0:GRID.get_number_layers()] = GRID.get_height()
            RESULT.LAYER_RHO[t,
                             0:GRID.get_number_layers()] = GRID.get_density()
            RESULT.LAYER_T[
                t, 0:GRID.get_number_layers()] = GRID.get_temperature()
            RESULT.LAYER_LWC[
                t,
                0:GRID.get_number_layers()] = GRID.get_liquid_water_content()
            RESULT.LAYER_CC[
                t, 0:GRID.get_number_layers()] = GRID.get_cold_content()
            RESULT.LAYER_POROSITY[
                t, 0:GRID.get_number_layers()] = GRID.get_porosity()
            RESULT.LAYER_VOL[
                t,
                0:GRID.get_number_layers()] = GRID.get_max_vol_ice_content()
            RESULT.LAYER_REFREEZE[
                t, 0:GRID.get_number_layers()] = GRID.get_refreeze()

    # TODO Restart
    logger.debug('Write restart data into local restart structure')
    RESTART['NLAYERS'] = GRID.get_number_layers()
    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_CC[0:GRID.get_number_layers()] = GRID.get_cold_content()
    RESTART.LAYER_POROSITY[0:GRID.get_number_layers()] = GRID.get_porosity()
    RESTART.LAYER_VOL[0:GRID.get_number_layers(
    )] = GRID.get_max_vol_ice_content()
    RESTART.LAYER_REFREEZE[0:GRID.get_number_layers()] = GRID.get_refreeze()

    # Return results
    return RESULT, RESTART
Пример #2
0
def cosipy_core(DATA, indY, indX, GRID_RESTART=None):

    _RRR = np.full(len(DATA.time), np.nan)
    _RAIN = np.full(len(DATA.time), np.nan)
    _SNOWFALL = np.full(len(DATA.time), np.nan)
    _LWin = np.full(len(DATA.time), np.nan)
    _LWout = np.full(len(DATA.time), np.nan)
    _H = np.full(len(DATA.time), np.nan)
    _LE = np.full(len(DATA.time), np.nan)
    _B = np.full(len(DATA.time), np.nan)
    _MB = np.full(len(DATA.time), np.nan)
    _surfMB = np.full(len(DATA.time), np.nan)
    _MB = np.full(len(DATA.time), np.nan)
    _Q = np.full(len(DATA.time), np.nan)
    _SNOWHEIGHT = np.full(len(DATA.time), np.nan)
    _TOTALHEIGHT = np.full(len(DATA.time), np.nan)
    _TS = np.full(len(DATA.time), np.nan)
    _ALBEDO = np.full(len(DATA.time), np.nan)
    _ME = np.full(len(DATA.time), np.nan)
    _intMB = np.full(len(DATA.time), np.nan)
    _EVAPORATION = np.full(len(DATA.time), np.nan)
    _SUBLIMATION = np.full(len(DATA.time), np.nan)
    _CONDENSATION = np.full(len(DATA.time), np.nan)
    _DEPOSITION = np.full(len(DATA.time), np.nan)
    _REFREEZE = np.full(len(DATA.time), np.nan)
    _NLAYERS = np.full(len(DATA.time), np.nan)
    _subM = np.full(len(DATA.time), np.nan)
    _Z0 = np.full(len(DATA.time), np.nan)
    _surfM = np.full(len(DATA.time), np.nan)

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

    # Start logging
    logger = logging.getLogger(__name__)

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

    # Create the local output datasets
    logger.debug('Create local datasets')
    IO = IOClass(DATA)
    RESTART = IO.create_local_restart_dataset()

    # Merge grid layers, if necessary
    logger.debug('Create local datasets')

    # 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
        RRR = DATA.RRR.values
    elif ('SNOWFALL' in DATA):
        SNOWF = DATA.SNOWFALL.values
        RRR = None
        RAIN = None
    else:
        SNOWF = None
        RRR = DATA.RRR.values

    if force_use_TP is True:
        SNOWF = None

    # Check whether longwave data is availible -> used for surface temperature calculations
    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

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

    else:
        SLOPE = 0.0

    # Profiling with bokeh
    cp = cProfile.Profile()

    #--------------------------------------------
    # TIME LOOP
    #--------------------------------------------
    logger.debug('Start time loop')
    for t in np.arange(len(DATA.time)):

        # Check grid
        GRID.grid_check()

        # get seconds since start
        timestamp = dt * t

        # Calc fresh snow density
        density_fresh_snow = np.maximum(
            109.0 + 6.0 * (T2[t] - 273.16) + 26.0 * np.sqrt(U2[t]), 50.0)

        if (SNOWF is not None):
            SNOWFALL = SNOWF[t]
        else:
            # , else convert rainfall [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

        # if snofall is smaller than the threshold
        if SNOWFALL < minimum_snow_layer_height:
            SNOWFALL = 0.0

        # if rainfall is smaller than the threshold
        if RAIN < (minimum_snow_layer_height *
                   (density_fresh_snow / ice_density) * 1000):
            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, timestamp)

        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, timestamp)

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

        #--------------------------------------------
        # 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)
        else:
            subsurface_melt = 0.0
            G_penetrating = 0.0

        # Calculate residual incoming shortwave radiation (penetrating part removed)
        G_resid = G[t] - 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, sw_radiation_net, rho, Lv, Cs_t, Cs_q, q0, q2, qdiff, phi \
                = update_surface_temperature(GRID, alpha, z0, T2[t], RH2[t], PRES[t], G_resid, U2[t], SLOPE, LWin=LWin[t])
        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, sw_radiation_net, rho, Lv, Cs_t, Cs_q, q0, q2, qdiff, phi \
                = update_surface_temperature(GRID, alpha, z0, T2[t], RH2[t], PRES[t], G_resid, U2[t], SLOPE, N=N[t])

        #--------------------------------------------
        # Surface mass fluxes [m w.e.q.]
        #--------------------------------------------
        if surface_temperature < zero_temperature:
            sublimation = min(
                latent_heat_flux / (1000.0 * lat_heat_sublimation), 0) * dt
            deposition = max(
                latent_heat_flux / (1000.0 * lat_heat_sublimation), 0) * dt
            evaporation = 0
            condensation = 0
        else:
            sublimation = 0
            deposition = 0
            evaporation = min(latent_heat_flux /
                              (1000.0 * lat_heat_vaporize), 0) * dt
            condensation = max(latent_heat_flux /
                               (1000.0 * 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 + 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.]
        GRID.remove_melt_weq(melt - sublimation - deposition - evaporation)

        #--------------------------------------------
        # Percolation
        #--------------------------------------------
        Q = percolation(GRID, melt - condensation, dt)

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

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

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

        #--------------------------------------------
        # 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

        #GRID.grid_check()

        # Write results
        logger.debug('Write data into local result structure')

        # Save results
        _RAIN[t] = RAIN
        _SNOWFALL[t] = SNOWFALL
        _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
        _MB[t] = mass_balance
        _surfMB[t] = surface_mass_balance
        _MB[t] = 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

        if full_field:
            if GRID.get_number_layers() > max_layers:
                logger.error('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
    # Restart
    logger.debug('Write restart data into local restart structure')
    RESTART['NLAYERS'] = GRID.get_number_layers()
    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()

    return (indY,indX,RESTART,_RAIN,_SNOWFALL,_LWin,_LWout,_H,_LE,_B, \
            _MB,_surfMB,_Q,_SNOWHEIGHT,_TOTALHEIGHT,_TS,_ALBEDO,_NLAYERS, \
            _ME,_intMB,_EVAPORATION,_SUBLIMATION,_CONDENSATION,_DEPOSITION,_REFREEZE, \
            _subM,_Z0,_surfM, \
            _LAYER_HEIGHT,_LAYER_RHO,_LAYER_T,_LAYER_LWC,_LAYER_CC,_LAYER_POROSITY,_LAYER_ICE_FRACTION, \
            _LAYER_IRREDUCIBLE_WATER,_LAYER_REFREEZE)
Пример #3
0
def cosima():
    """ COSIMA main routine """
    start_time = datetime.now()
    ''' INITIALIZATION '''
    hours_since_snowfall = 0
    # Init layers
    layer_heights = 0.1 * np.ones(number_layers)

    rho = ice_density * np.ones(number_layers)
    rho[0] = 250.
    rho[1] = 400.
    rho[2] = 550.

    # read input data
    wind_speed, solar_radiation, temperature_2m, relative_humidity, snowfall, air_pressure, cloud_cover, initial_snow_height = read_input(
    )

    # Init temperature
    temperature_surface = temperature_bottom * np.ones(number_layers)
    for i in range(len(temperature_surface)):
        gradient = ((temperature_2m[0] - temperature_bottom) / number_layers)
        temperature_surface[i] = temperature_2m[0] - gradient * i

    # Init liquid water content
    liquid_water_content = np.zeros(number_layers)

    if merging_level == 0:
        print('Merging level 0')
    else:
        print('Merge in action!')

    # Initialize grid, the grid class contains all relevant grid information
    GRID = grd.Grid(layer_heights, rho, temperature_surface,
                    liquid_water_content, debug_level)
    # todo params handling?

    # Get some information on the grid setup
    GRID.info()

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

    result_sensible_heat_flux = []
    result_latent_heat_flux = []
    result_lw_radiation_in = []
    result_lw_radiation_out = []
    result_ground_heat_flux = []
    result_sw_radiation_net = []
    result_surface_temperature = []
    result_albedo = []
    result_snow_height = []

    if initial_snow_height[0]:
        snow_height = initial_snow_height
    else:
        snow_height = 0

    ' TIME LOOP '

    for t in range(time_start, time_end, 1):
        print(t)
        # Add snowfall
        snow_height = snow_height + snowfall[t]

        if snowfall[t] > 0.0:
            # TODO: Better use weq than snowheight

            # Add a new snow node on top
            GRID.add_node(float(snowfall[t]), density_fresh_snow,
                          float(temperature_2m[t]), 0)
            GRID.merge_new_snow(merge_snow_threshold)

        if snowfall[t] < 0.005:
            hours_since_snowfall += dt / 3600.0
        else:
            hours_since_snowfall = 0

        # Calculate albedo and roughness length changes if first layer is snow
        # Update albedo values
        alpha = updateAlbedo(GRID, hours_since_snowfall)

        # Update roughness length
        z0 = updateRoughness(GRID, hours_since_snowfall)

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

        # Solve the heat equation
        solveHeatEquation(GRID, dt)

        # Find new surface temperature
        fun, surface_temperature, lw_radiation_in, lw_radiation_out, sensible_heat_flux, latent_heat_flux, \
            ground_heat_flux, sw_radiation_net \
            = update_surface_temperature(GRID, alpha, z0, t)

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

        # Melt energy in [m w.e.q.]
        melt_energy = max(0, sw_radiation_net + lw_radiation_in +
                          lw_radiation_out - ground_heat_flux -
                          sensible_heat_flux -
                          latent_heat_flux)  # W m^-2 / J s^-1 ^m-2

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

        # Remove melt height from surface and store as runoff (R)
        GRID.remove_melt_energy(melt + sublimation + deposition + evaporation +
                                condensation)

        # Merge first layer, if too small (for model stability)
        GRID.merge_new_snow(merge_snow_threshold)

        # Account layer temperature due to penetrating SW radiation
        penetrating_radiation(GRID, sw_radiation_net, dt)

        # todo Percolation, fluid retention (liquid_water_content) & refreezing of melt water
        # and rain
        percolation(GRID, melt, dt)

        # write single variables to output variables
        result_lw_radiation_in.append(lw_radiation_in)
        result_lw_radiation_out.append(lw_radiation_out)
        result_sensible_heat_flux.append(sensible_heat_flux)
        result_latent_heat_flux.append(latent_heat_flux)
        result_ground_heat_flux.append(ground_heat_flux)
        result_surface_temperature.append(surface_temperature)
        result_sw_radiation_net.append(sw_radiation_net)
        result_albedo.append(alpha)
        result_snow_height.append(np.sum((GRID.get_height())))

    write_output_1D(result_lw_radiation_in, result_lw_radiation_out,
                    result_sensible_heat_flux, result_latent_heat_flux,
                    result_ground_heat_flux, result_surface_temperature,
                    result_sw_radiation_net, result_albedo, result_snow_height)

    GRID.info()
    duration_run = datetime.now() - start_time
    print("run duration in seconds ", duration_run.total_seconds())