public void Run(Clock clock, IImpactSeaLevelRiseState state, IDimensions dimensions)
        {
            var s = state;
            var t = clock.Current;

            if (clock.IsFirstTimestep)
            {
                foreach (var r1 in dimensions.GetValues<Region>())
                {
                    foreach (var r2 in dimensions.GetValues<Region>())
                    {
                        double immsumm = 0;
                        foreach (var i in dimensions.GetValues<Region>())
                        {
                            immsumm += s.migrate[i, r1];
                        }
                        s.imigrate[r1, r2] = s.migrate[r2, r1] / immsumm;
                    }

                    var t0 = clock.StartTime;
                    s.landloss[t0, r1] = 0.0;
                    s.cumlandloss[t0, r1] = 0.0;
                    s.cumwetlandloss[t0, r1] = 0.0;
                    s.wetlandgrowth[t0, r1] = 0.0;
                }
            }
            else
            {
                // slr in m/year
                double ds = s.sea[t] - s.sea[t - 1];

                foreach (var r in dimensions.GetValues<Region>())
                {
                    double ypc = s.income[t, r] / s.population[t, r] * 1000.0;
                    double ypcprev = s.income[t - 1, r] / s.population[t - 1, r] * 1000.0;
                    double ypcgrowth = ypc / ypcprev - 1.0;

                    if (t == Timestep.FromYear(1951))
                        ypcgrowth = 0;

                    // Needs to be in $bn per km^2
                    // Income is in billion, area is in km^2
                    double incomedens = s.income[t, r] / s.area[t, r];

                    double incomedensprev = s.income[t - 1, r] / s.area[t - 1, r];

                    double incomedensgrowth = incomedens / incomedensprev - 1.0;

                    // In population/km^2
                    // population is in million, area is in km^2
                    double popdens = s.population[t, r] / s.area[t, r] * 1000000.0;
                    double popdensprev = s.population[t - 1, r] / s.area[t - 1, r] * 1000000.0;
                    double popdensgrowth = popdens / popdensprev - 1.0;

                    // Unit of dryval is $bn/km^2
                    s.dryval[t, r] = s.dvbm * Math.Pow(incomedens / s.incdens, s.dvydl);

                    // Unit of wetval is $bn/km^2
                    s.wetval[t, r] = s.wvbm *
                        Math.Pow(ypc / s.slrwvypc0, s.wvel) *
                        Math.Pow(popdens / s.slrwvpopdens0, s.wvpdl) *
                        Math.Pow((s.wetland90[r] - s.cumwetlandloss[t - 1, r]) / s.wetland90[r], s.wvsl);

                    double potCumLandloss = Math.Min(s.maxlandloss[r], s.cumlandloss[t - 1, r] + s.dlbm[r] * Math.Pow(s.sea[t], s.drylandlossparam[r]));

                    double potLandloss = potCumLandloss - s.cumlandloss[t - 1, r];

                    // If sea levels fall, no protection is build
                    if (ds < 0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 0;
                    }
                    // If the discount rate < -100% people will not build protection
                    else if ((1.0 + s.slrprtp[r] + ypcgrowth) < 0.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 0;
                    }
                    // Dryland value is worthless
                    else if (((1.0 + s.dvydl * incomedensgrowth) < 0.0))
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 0;
                    }
                    // Is protecting the coast infinitly expensive?
                    else if ((1.0 / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 0;
                    }
                    // Is dryland infinitly valuable?
                    else if (((1.0 + s.dvydl * incomedensgrowth) / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 1;
                    }
                    // Is wetland infinitly valuable?
                    else if (((1.0 + s.wvel * ypcgrowth + s.wvpdl * popdensgrowth + s.wvsl * s.wetlandgrowth[t - 1, r]) / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r] = 0;
                        s.npdrycost[t, r] = 0;
                        s.protlev[t, r] = 0;
                    }
                    else
                    {
                        // NPV of protecting the whole coast
                        // pc is in $bn/m
                        s.npprotcost[t, r] = s.pc[r] * ds * (1.0 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth);

                        // NPV of wetland
                        if ((1.0 + s.wvel * ypcgrowth + s.wvpdl * popdensgrowth + s.wvsl * s.wetlandgrowth[t - 1, r]) < 0.0)
                            s.npwetcost[t, r] = 0;
                        else
                            s.npwetcost[t, r] = s.wmbm[r] * ds * s.wetval[t, r] * (1.0 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth - s.wvel * ypcgrowth - s.wvpdl * popdensgrowth - s.wvsl * s.wetlandgrowth[t - 1, r]);

                        // NPV of dryland
                        if ((1.0 + s.dvydl * incomedensgrowth) < 0.0)
                            s.npdrycost[t, r] = 0;
                        else
                            s.npdrycost[t, r] = potLandloss * s.dryval[t, r] * (1 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth - s.dvydl * incomedensgrowth);

                        // Calculate protection level
                        s.protlev[t, r] = Math.Max(0.0, 1.0 - 0.5 * (s.npprotcost[t, r] + s.npwetcost[t, r]) / s.npdrycost[t, r]);

                        if (s.protlev[t, r] > 1)
                            throw new Exception("protlevel >1 should not happen");
                    }

                    // Calculate actual wetland loss and cost
                    s.wetlandloss[t, r] = Math.Min(
                        s.wlbm[r] * ds + s.protlev[t, r] * s.wmbm[r] * ds,
                        s.wetmax[r] - s.cumwetlandloss[t - 1, r]);

                    s.cumwetlandloss[t, r] = s.cumwetlandloss[t - 1, r] + s.wetlandloss[t, r];

                    // Calculate wetland growth
                    s.wetlandgrowth[t, r] = (s.wetland90[r] - s.cumwetlandloss[t, r]) / (s.wetland90[r] - s.cumwetlandloss[t - 1, r]) - 1.0;

                    s.wetcost[t, r] = s.wetval[t, r] * s.wetlandloss[t, r];

                    s.landloss[t, r] = (1.0 - s.protlev[t, r]) * potLandloss;

                    s.cumlandloss[t, r] = s.cumlandloss[t - 1, r] + s.landloss[t, r];
                    s.drycost[t, r] = s.dryval[t, r] * s.landloss[t, r];

                    s.protcost[t, r] = s.protlev[t, r] * s.pc[r] * ds;

                    if (s.landloss[t, r] < 0)
                        s.leave[t, r] = 0;
                    else
                        s.leave[t, r] = s.coastpd[r] * popdens * s.landloss[t, r];

                    s.leavecost[t, r] = s.emcst * ypc * s.leave[t, r] / 1000000000;
                }

                foreach (var destination in dimensions.GetValues<Region>())
                {
                    double enter = 0.0;
                    foreach (var source in dimensions.GetValues<Region>())
                    {
                        enter += s.leave[t, source] * s.imigrate[source, destination];
                    }
                    s.enter[t, destination] = enter;
                }

                foreach (var r in dimensions.GetValues<Region>())
                {
                    double ypc = s.income[t, r] / s.population[t, r] * 1000.0;
                    s.entercost[t, r] = s.immcst * ypc * s.enter[t, r] / 1000000000;
                }
            }
        }
Example #2
0
        public void Run(Clock clock, IImpactSeaLevelRiseState state, IDimensions dimensions)
        {
            var s = state;
            var t = clock.Current;

            if (clock.IsFirstTimestep)
            {
                foreach (var r1 in dimensions.GetValues <Region>())
                {
                    foreach (var r2 in dimensions.GetValues <Region>())
                    {
                        double immsumm = 0;
                        foreach (var i in dimensions.GetValues <Region>())
                        {
                            immsumm += s.migrate[i, r1];
                        }
                        s.imigrate[r1, r2] = s.migrate[r2, r1] / immsumm;
                    }

                    var t0 = clock.StartTime;
                    s.landloss[t0, r1]       = 0.0;
                    s.cumlandloss[t0, r1]    = 0.0;
                    s.cumwetlandloss[t0, r1] = 0.0;
                    s.wetlandgrowth[t0, r1]  = 0.0;
                }
            }
            else
            {
                // slr in m/year
                double ds = s.sea[t] - s.sea[t - 1];

                foreach (var r in dimensions.GetValues <Region>())
                {
                    double ypc       = s.income[t, r] / s.population[t, r] * 1000.0;
                    double ypcprev   = s.income[t - 1, r] / s.population[t - 1, r] * 1000.0;
                    double ypcgrowth = ypc / ypcprev - 1.0;

                    if (t == Timestep.FromYear(1951))
                    {
                        ypcgrowth = 0;
                    }

                    // Needs to be in $bn per km^2
                    // Income is in billion, area is in km^2
                    double incomedens = s.income[t, r] / s.area[t, r];

                    double incomedensprev = s.income[t - 1, r] / s.area[t - 1, r];

                    double incomedensgrowth = incomedens / incomedensprev - 1.0;

                    // In population/km^2
                    // population is in million, area is in km^2
                    double popdens       = s.population[t, r] / s.area[t, r] * 1000000.0;
                    double popdensprev   = s.population[t - 1, r] / s.area[t - 1, r] * 1000000.0;
                    double popdensgrowth = popdens / popdensprev - 1.0;

                    // Unit of dryval is $bn/km^2
                    s.dryval[t, r] = s.dvbm * Math.Pow(incomedens / s.incdens, s.dvydl);

                    // Unit of wetval is $bn/km^2
                    s.wetval[t, r] = s.wvbm *
                                     Math.Pow(ypc / s.slrwvypc0, s.wvel) *
                                     Math.Pow(popdens / s.slrwvpopdens0, s.wvpdl) *
                                     Math.Pow((s.wetland90[r] - s.cumwetlandloss[t - 1, r]) / s.wetland90[r], s.wvsl);

                    double potCumLandloss = Math.Min(s.maxlandloss[r], s.dlbm[r] * Math.Pow(s.sea[t], s.drylandlossparam[r]));

                    double potLandloss = potCumLandloss - s.cumlandloss[t - 1, r];

                    // If sea levels fall, no protection is build
                    if (ds < 0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 0;
                    }
                    // If the discount rate < -100% people will not build protection
                    else if ((1.0 + s.slrprtp[r] + ypcgrowth) < 0.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 0;
                    }
                    // Dryland value is worthless
                    else if (((1.0 + s.dvydl * incomedensgrowth) < 0.0))
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 0;
                    }
                    // Is protecting the coast infinitly expensive?
                    else if ((1.0 / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 0;
                    }
                    // Is dryland infinitly valuable?
                    else if (((1.0 + s.dvydl * incomedensgrowth) / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 1;
                    }
                    // Is wetland infinitly valuable?
                    else if (((1.0 + s.wvel * ypcgrowth + s.wvpdl * popdensgrowth + s.wvsl * s.wetlandgrowth[t - 1, r]) / (1.0 + s.slrprtp[r] + ypcgrowth)) >= 1.0)
                    {
                        s.npprotcost[t, r] = 0;
                        s.npwetcost[t, r]  = 0;
                        s.npdrycost[t, r]  = 0;
                        s.protlev[t, r]    = 0;
                    }
                    else
                    {
                        // NPV of protecting the whole coast
                        // pc is in $bn/m
                        s.npprotcost[t, r] = s.pc[r] * ds * (1.0 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth);

                        // NPV of wetland
                        if ((1.0 + s.wvel * ypcgrowth + s.wvpdl * popdensgrowth + s.wvsl * s.wetlandgrowth[t - 1, r]) < 0.0)
                        {
                            s.npwetcost[t, r] = 0;
                        }
                        else
                        {
                            s.npwetcost[t, r] = s.wmbm[r] * ds * s.wetval[t, r] * (1.0 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth - s.wvel * ypcgrowth - s.wvpdl * popdensgrowth - s.wvsl * s.wetlandgrowth[t - 1, r]);
                        }

                        // NPV of dryland
                        if ((1.0 + s.dvydl * incomedensgrowth) < 0.0)
                        {
                            s.npdrycost[t, r] = 0;
                        }
                        else
                        {
                            s.npdrycost[t, r] = potLandloss * s.dryval[t, r] * (1 + s.slrprtp[r] + ypcgrowth) / (s.slrprtp[r] + ypcgrowth - s.dvydl * incomedensgrowth);
                        }

                        // Calculate protection level
                        s.protlev[t, r] = Math.Max(0.0, 1.0 - 0.5 * (s.npprotcost[t, r] + s.npwetcost[t, r]) / s.npdrycost[t, r]);

                        if (s.protlev[t, r] > 1)
                        {
                            throw new Exception("protlevel >1 should not happen");
                        }
                    }

                    // Calculate actual wetland loss and cost
                    s.wetlandloss[t, r] = Math.Min(
                        s.wlbm[r] * ds + s.protlev[t, r] * s.wmbm[r] * ds,
                        s.wetmax[r] - s.cumwetlandloss[t - 1, r]);

                    s.cumwetlandloss[t, r] = s.cumwetlandloss[t - 1, r] + s.wetlandloss[t, r];

                    // Calculate wetland growth
                    s.wetlandgrowth[t, r] = (s.wetland90[r] - s.cumwetlandloss[t, r]) / (s.wetland90[r] - s.cumwetlandloss[t - 1, r]) - 1.0;

                    s.wetcost[t, r] = s.wetval[t, r] * s.wetlandloss[t, r];

                    s.landloss[t, r] = (1.0 - s.protlev[t, r]) * potLandloss;

                    s.cumlandloss[t, r] = s.cumlandloss[t - 1, r] + s.landloss[t, r];
                    s.drycost[t, r]     = s.dryval[t, r] * s.landloss[t, r];

                    s.protcost[t, r] = s.protlev[t, r] * s.pc[r] * ds;

                    if (s.landloss[t, r] < 0)
                    {
                        s.leave[t, r] = 0;
                    }
                    else
                    {
                        s.leave[t, r] = s.coastpd[r] * popdens * s.landloss[t, r];
                    }

                    s.leavecost[t, r] = s.emcst * ypc * s.leave[t, r] / 1000000000;
                }

                foreach (var destination in dimensions.GetValues <Region>())
                {
                    double enter = 0.0;
                    foreach (var source in dimensions.GetValues <Region>())
                    {
                        enter += s.leave[t, source] * s.imigrate[source, destination];
                    }
                    s.enter[t, destination] = enter;
                }

                foreach (var r in dimensions.GetValues <Region>())
                {
                    double ypc = s.income[t, r] / s.population[t, r] * 1000.0;
                    s.entercost[t, r] = s.immcst * ypc * s.enter[t, r] / 1000000000;
                }
            }
        }