Exemple #1
0
void daily_bgc (bgc_struct BGCM, bgc_grid * grid, const double t, const double naddfrac, int first_balance)
{
    siteconst_struct *sitec;
    metvar_struct  *metv;
    co2control_struct *co2;
    ndepcontrol_struct *ndepctrl;
    control_struct *ctrl;
    epconst_struct *epc;
    epvar_struct   *epv;
    psn_struct     *psn_sun, *psn_shade;
    wstate_struct  *ws;
    wflux_struct   *wf;
    cstate_struct  *cs;
    cflux_struct   *cf;
    nstate_struct  *ns;
    nflux_struct   *nf;
    ntemp_struct   *nt;
    phenology_struct *phen;
    summary_struct *summary;
    struct tm      *timestamp;
    time_t         *rawtime;

    /* miscelaneous variables for program control in main */
    int             simyr, yday, metyr, metday;
    int             annual_alloc;
    int             outv;
    int             i, nmetdays;
    double          tair_avg, tdiff;
    int             dayout;

    double          daily_ndep, daily_nfix, ndep_scalar, ndep_diff, ndep;
    int             ind_simyr;

    sitec = &grid->sitec;
    metv = &grid->metv;
    co2 = &BGCM->co2;
    ndepctrl = &BGCM->ndepctrl;
    ctrl = &BGCM->ctrl;
    epc = &grid->epc;
    epv = &grid->epv;
    ws = &grid->ws;
    wf = &grid->wf;
    cs = &grid->cs;
    cf = &grid->cf;
    ns = &grid->ns;
    nf = &grid->nf;
    nt = &grid->nt;
    phen = &grid->phen;
    psn_sun = &grid->psn_sun;
    psn_shade = &grid->psn_shade;
    summary = &grid->summary;

    rawtime = (time_t *) malloc (sizeof (time_t));
    *rawtime = (int)t;
    timestamp = gmtime (rawtime);


    /* Get co2 and ndep */
    if (ctrl->spinup == 1)      /* Spinup mode */
    {
        metv->co2 = co2->co2ppm;
        daily_ndep = ndepctrl->ndep / 365.0;
        daily_nfix = ndepctrl->nfix / 365.0;
    }
    else                        /* Model mode */
    {
        /* atmospheric CO2 and Ndep handling */
        if (!(co2->varco2))
        {
            /* constant CO2, constant Ndep */
            metv->co2 = co2->co2ppm;
            daily_ndep = ndepctrl->ndep / 365.0;
            daily_nfix = ndepctrl->nfix / 365.0;
        }
        else
        {
            /* When varco2 = 1, use file for co2 */
            if (co2->varco2 == 1)
                metv->co2 = get_co2 (BGCM->Forcing[CO2_TS][0], t);
            if (metv->co2 < -999)
            {
                printf ("Error finding CO2 value on %4.4d-%2.2d-%2.2d\n", timestamp->tm_year + 1900, timestamp->tm_mon + 1, timestamp->tm_mday);
                exit (1);
            }

            /* When varco2 = 2, use the constant CO2 value, but can vary
             * Ndep */
            if (co2->varco2 == 2)
                metv->co2 = co2->co2ppm;

            if (ndepctrl->varndep == 0)
            {
                /* Increasing CO2, constant Ndep */
                daily_ndep = ndepctrl->ndep / 365.0;
                daily_nfix = ndepctrl->nfix / 365.0;
            }
            else
            {
                daily_ndep = get_ndep (BGCM->Forcing[NDEP_TS][0], t);
                daily_nfix = ndepctrl->nfix / 365.0;
                if (daily_ndep < -999)
                {
                    printf ("Error finding NDEP %4.4d-%2.2d-%2.2d\n", timestamp->tm_year + 1900, timestamp->tm_mon + 1, timestamp->tm_mday);
                    exit (1);
                }
                else
                {
                    daily_ndep = daily_ndep / 365.0;
                }
            }
        }
    }

    precision_control (ws, cs, ns);

    /* zero all the daily flux variables */
    make_zero_flux_struct (wf, cf, nf);

    /* phenology fluxes */
    phenology (epc, metv, phen, epv, cs, cf, ns, nf);

    /* test for the annual allocation day */
    if (phen->remdays_litfall == 1)
        annual_alloc = 1;
    else
        annual_alloc = 0;

    /* Calculate leaf area index, sun and shade fractions, and specific
     * leaf area for sun and shade canopy fractions, then calculate
     * canopy radiation interception and transmission */
    radtrans (cs, epc, metv, epv, sitec->sw_alb);

    /* update the ann max LAI for annual diagnostic output */
    if (epv->proj_lai > epv->ytd_maxplai)
        epv->ytd_maxplai = epv->proj_lai;

    /* soil water potential */
    epv->vwc = metv->swc;
    soilpsi (sitec, epv->vwc, &epv->psi);

    /* daily maintenance respiration */
    maint_resp (cs, ns, epc, metv, cf, epv);

    /* begin canopy bio-physical process simulation */
    if (cs->leafc && metv->dayl)
    {
        /* conductance */
        canopy_et (metv, epc, epv, wf);
    }
    /* Do photosynthesis only when it is part of the current growth season, as
     * defined by the remdays_curgrowth flag.  This keeps the occurrence of
     * new growth consistent with the treatment of litterfall and
     * allocation */

    //printf ("leafc %lf dormant %lf, dayl %lf, soilc = %lf\n", cs->leafc, epv->dormant_flag, metv->dayl, summary->soilc);

    if (cs->leafc && !epv->dormant_flag && metv->dayl)
        total_photosynthesis (metv, epc, epv, cf, psn_sun, psn_shade);
    else
        epv->assim_sun = epv->assim_shade = 0.0;

    nf->ndep_to_sminn = daily_ndep;
    nf->nfix_to_sminn = daily_nfix;

    /* daily litter and soil decomp and nitrogen fluxes */
    decomp (metv->tsoil, epc, epv, cs, cf, ns, nf, nt);


    /* Daily allocation gets called whether or not this is a current growth
     * day, because the competition between decomp immobilization fluxes and
     * plant growth N demand is resolved here.  On days with no growth, no
     * allocation occurs, but immobilization fluxes are updated normally */
    daily_allocation (cf, cs, nf, ns, epc, epv, nt, naddfrac, ctrl->spinup);

    /* reassess the annual turnover rates for livewood --> deadwood, and for
     * evergreen leaf and fine root litterfall. This happens once each year,
     * on the annual_alloc day (the last litterfall day) */
    if (annual_alloc)
        annual_rates (epc, epv);

    /* daily growth respiration */
    growth_resp (epc, cf);

    /* daily update of carbon state variables */
    daily_carbon_state_update (cf, cs, annual_alloc, epc->woody, epc->evergreen);

    /* daily update of nitrogen state variables */
    daily_nitrogen_state_update (nf, ns, annual_alloc, epc->woody, epc->evergreen);

    /* Calculate N leaching loss.  This is a special state variable update
     * routine, done after the other fluxes and states are reconciled in order
     * to avoid negative sminn under heavy leaching potential */
    //nleaching(ns, nf, ws, wf);

    /* Calculate daily mortality fluxes and update state variables */
    /* This is done last, with a special state update procedure, to insure
     * that pools don't go negative due to mortality fluxes conflicting with
     * other proportional fluxes */
    mortality (epc, cs, cf, ns, nf);

    /* Test for carbon balance */
    check_carbon_balance (cs, &epv->old_c_balance, first_balance);

    /* Test for nitrogen balance */
    check_nitrogen_balance (ns, &epv->old_n_balance, first_balance);

    /* Calculate carbon summary variables */
    csummary (cf, cs, summary);
}
Exemple #2
0
void calc_day_growth(canopy_wk *cw, control *c, fluxes *f, met_arrays *ma,
                     met *m, params *p, state *s, double day_length, int doy,
                     double fdecay, double rdecay)
{
    double previous_topsoil_store, dummy,
           previous_rootzone_store, nitfac, ncbnew, nccnew, ncwimm, ncwnew;
    int    recalc_wb;

    /* Store the previous days soil water store */
    previous_topsoil_store = s->pawater_topsoil;
    previous_rootzone_store = s->pawater_root;

    if (c->sub_daily) {
        /* calculate 30 min two-leaf GPP/NPP, respiration and water fluxes */
        canopy(cw, c, f, ma, m, p, s);
    } else {
        /* calculate daily GPP/NPP, respiration and update water balance */
        carbon_daily_production(c, f, m, p, s, day_length);
        calculate_water_balance(c, f, m, p, s, day_length, dummy, dummy, dummy);
    }

    /* leaf N:C as a fraction of Ncmaxyoung, i.e. the max N:C ratio of
       foliage in young stand */
    nitfac = MIN(1.0, s->shootnc / p->ncmaxfyoung);

    /* figure out the C allocation fractions */
    if (c->deciduous_model){
        /* Allocation is annually for deciduous "tree" model, but we need to
           keep a check on stresses during the growing season and the LAI
           figure out limitations during leaf growth period. This also
           applies for deciduous grasses, need to do the growth stress
           calc for grasses here too. */
        if (s->leaf_out_days[doy] > 0.0) {

            calc_carbon_allocation_fracs(c, f, p, s, nitfac);

            /* store the days allocation fraction, we average these at the
               end of the year (for the growing season) */
            s->avg_alleaf += f->alleaf;
            s->avg_albranch += f->albranch;
            s->avg_alstem += f->alstem;
            s->avg_alroot += f->alroot;
            s->avg_alcroot += f->alcroot;

        }
    } else {
        /* daily allocation...*/
        calc_carbon_allocation_fracs(c, f, p, s, nitfac);
    }

    /* Distribute new C and N through the system */
    carbon_allocation(c, f, p, s, nitfac, doy);

    calculate_ncwood_ratios(c, p, s, nitfac, &ncbnew, &nccnew, &ncwimm,
                            &ncwnew);

    recalc_wb = nitrogen_allocation(c, f, p, s, ncbnew, nccnew, ncwimm, ncwnew,
                                    fdecay, rdecay, doy);

    if (c->exudation) {
        calc_root_exudation_release(f, s);
    }

    /* If we didn't have enough N available to satisfy wood demand, NPP
       is down-regulated and thus so is GPP. We also need to recalculate the
       water balance given the lower GPP. */
    if (recalc_wb) {
        s->pawater_topsoil = previous_topsoil_store;
        s->pawater_root = previous_rootzone_store;

        if (c->sub_daily) {
            /* reduce transpiration to match cut back GPP
                -there isn't an obvious way to make this work at the 30 min
                 timestep, so invert T from WUE assumption and use that
                 to recalculate the end day water balance
            */
            f->transpiration = f->gpp_gCm2 / f->wue;
            update_water_storage_recalwb(c, f, p, s, m);

        } else {
            calculate_water_balance(c, f, m, p, s, day_length, dummy, dummy,
                                    dummy);
        }

    }
    update_plant_state(c, f, p, s, fdecay, rdecay, doy);
    precision_control(f, s);

    return;
}