Esempio n. 1
0
void mortality_rates_test::test_annual_to_monthly_conversion()
{
    for(unsigned int j = 0; j < annual_rates().size(); ++j)
        {
        BOOST_TEST
            (materially_equal
                (                          monthly_rates()[j]
                ,coi_rate_from_q<double>()(annual_rates ()[j], 1.0)
                )
            );
        }
}
Esempio n. 2
0
void mortality_rates_test::test_guaranteed_rates
    (double           mult
    ,double           max
    ,round_to<double> rounder
    )
{
    MortalityRates z;
    z.Length_            = annual_rates().size();

    z.GCoiMultiplier_    = std::vector<double>(z.Length_, mult);
    z.MaxMonthlyCoiRate_ = max;
    z.round_coi_rate_    = rounder;

    std::cout
        << "Testing with"
        << " mult = "      << mult
        << ", max = "      << max
        << ", decimals = " << rounder.decimals()
        << ", style = "    << rounder.style()
        << ".\n"
        << std::flush
        ;

    z.GCoiIsAnnual_   = true;
    z.MonthlyGuaranteedCoiRates_ = annual_rates();
    z.SetGuaranteedRates();
    std::vector<double> v0 = z.MonthlyGuaranteedCoiRates_;

    z.GCoiIsAnnual_   = false;
    z.MonthlyGuaranteedCoiRates_ = monthly_rates();
    z.SetGuaranteedRates();
    std::vector<double> v1 = z.MonthlyGuaranteedCoiRates_;

    for(int j = 0; j < z.Length_; ++j)
        {
        double x = z.GCoiMultiplier_[j] * monthly_rates()[j];
        x = std::min(x, z.MaxMonthlyCoiRate_);
        x = rounder(x);

        double y = z.GCoiMultiplier_[j] * annual_rates()[j];
        y = coi_rate_from_q<double>()(y, z.MaxMonthlyCoiRate_);
        y = rounder(y);

        BOOST_TEST(materially_equal(y, v0[j]));
        BOOST_TEST(materially_equal(x, v1[j]));
// This needn't necessarily hold:
//        BOOST_TEST(materially_equal(x, y));
// To compare values:
//        std::cout << j << '\t' << x << '\t' << y << std::endl;
        }
}
Esempio n. 3
0
 static void test()
     {
     LMI_ASSERT(annual_rates().size() == monthly_rates().size());
     test_4095_4096ths();
     test_annual_to_monthly_conversion();
     test_guaranteed_rates( 1.0, 1.0, round_to<double>(0, r_not_at_all));
     test_guaranteed_rates( 0.9, 1.0, round_to<double>(0, r_not_at_all));
     test_guaranteed_rates( 1.1, 1.0, round_to<double>(0, r_not_at_all));
     test_guaranteed_rates( 1.0, 0.9, round_to<double>(0, r_not_at_all));
     test_guaranteed_rates(10.0, 0.9, round_to<double>(0, r_not_at_all));
     }
Esempio n. 4
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);
}