Sample5_CogenerationAdoptionSimulation.java
Created with JBuilder
import mads.core.*;
import mads.servicefunctions.*;

/**
 * <p><H1>Cogeneration Adoption Simulation</H1></p>
 *
 * <p><B>Sample project no. 5 </B><BR\> </p>
 * We combine the features presented in samples 1-4 to make a real world simulation. In this
 * simulation some firm, who needs both electricity and heat, must decide whether to buy
 * a standard boiler or one with a cogeneration system. In the case of the standard boiler,
 * the firm must buy electricity from the grid and natural gas (to heat the boiler) from some
 * supplier. In the case of the cogeneration system, the firm will start by buying only natural gas.
 * This will be used both for heating and for producing some amount of electricity, using the
 * cogeneration system. If this electricity is enough, none will be bought from the grid. If there
 * is a deficit, the required amount will be bought from the grid. If there is a surplus, the
 * unneeded amount will be sold back to the grid (at some buyback rate). The manager will consider
 * all costs (computed on the lifetime of the system, in this case of 20 years), including
 * investments (investments in cogeneration are substantially bigger than for a standard boiler).
 * If he discovers there is a financial advantage in switching to cogeneration, he will do so at
 * some time in the future when this advantage is maximized. <BR\>
 *
 */

public class Sample5_CogenerationAdoptionSimulation extends ASimulationAgent
{

  public void doWork(){

    /**
       First, all the data will be entered. This data will consist of economic and technological data,
       for the firm under study, and will be written in the form of service functions. These
       functions will be given as parameters when requesting service functions from service
       providing agents.
     */

    // Required heat load (MW)
    ServiceFunction heatLoad          = new ConstantServiceFunction(14);
    // Required electricity load (MW)
    ServiceFunction electricityLoad   = new ConstantServiceFunction(6);
    // Operation time (hours)
    ServiceFunction operationTime     = new ConstantServiceFunction(24*365);

    // Thermal efficiency of a steam boiler
    ServiceFunction thEffSteamBoiler  = new ConstantServiceFunction(0.9);
    // Thermal efficiency of a cogeneration system
    ServiceFunction thEffCogeneration = new ConstantServiceFunction(0.6);
    // Electrical efficiency for a cogeneration system
    ServiceFunction elEffCogeneration = new LogisticServiceFunction(0.151, 0.250, 2015, 1);

    // Investments required for a steam boiler
    ServiceFunction invSBoiler        = new ConstantServiceFunction(1.65*1000000);
    // Investments required for a cogeneration system
    ServiceFunction invCogeneration   = new ConstantServiceFunction(4.60*1000000);

    // Electricity buyback rate
    ServiceFunction buybackRate       = new ConstantServiceFunction(0.9);
    // Discount rate
    ServiceFunction discountRate      = new ConstantServiceFunction(0.05);


    /**
     * The prices for fuel and natural gas can be assumed constant, but that would be a very
     * rough approximation. Moreover, one of the most important drivers for the adoption of
     * one of these technologies are the changing prices for natural gas and electricity.
     * Because of these, the prices will not be assumed constant; they will be requested
     * from service providing agents. It should be noted how easy it is to use such data in
     * MADS (provided that it was previously entered in the system)
     */

    // Request the electricity price (low price scenario)
    ServiceFunction electricityPrice = new ConstantServiceFunction(60);//findRemoteServiceFunction("sags.Electricity.AElectricityInd_00_30_Lo");
    // Request natural gas price (high price scenario)
    ServiceFunction fossilFuelPrice = new ConstantServiceFunction(30);//findRemoteServiceFunction("sags.NaturalGas.ANaturalGasInd_00_30_Hi");

    /**
     * Using the above service functions as parameters, request service providing agents to
     * compute the lifetime costs for electricity and natural gas, for both systems
     */

    // Get CE_CHP (Electricity price for cogeneration)
    ServiceFunction sfCeChp = findRemoteServiceFunction("sags.Cogeneration.IndustrialCogeneration.AIndustrialCogeneration_ElectricityCost",
                              new ServiceFunction[] {electricityPrice, electricityLoad, heatLoad, thEffCogeneration, elEffCogeneration, discountRate, buybackRate, operationTime});
    // Get CE_SB (Electricity price for boiler)
    ServiceFunction sfCeSb = findRemoteServiceFunction("sags.Boilers.SteamBoiler.ASteamBoiler_ElectricityCost",
                             new ServiceFunction[] {electricityPrice, electricityLoad, discountRate, operationTime});
    // Computiong CF_CHP (Operating price for cogeneartion)
    ServiceFunction sfCfChp = findRemoteServiceFunction("sags.Cogeneration.IndustrialCogeneration.AIndustrialCogeneration_OpperatingCost",
                              new ServiceFunction[] {fossilFuelPrice, heatLoad, thEffCogeneration, discountRate, operationTime});
    // Computiong CF_SB (Operating price for bolier)
    ServiceFunction sfCfSb = findRemoteServiceFunction("sags.Boilers.SteamBoiler.ASteamBoiler_OpperatingCost",
                             new ServiceFunction[] {fossilFuelPrice, heatLoad, thEffSteamBoiler, discountRate, operationTime});

    /**
     * Now, having computed all the associated costs, we will compute the cost of switching to
     * a cogeneration system. Remember, this cost will be given as a service function. This function
     * will show at each time t (here, represeting the year) what would be the profit (or loss) if at that
     * moment the manager will switch to cogeneration.
     */

    // First, compute the profit as the difference in lifetime costs between the systems
    ServiceFunction deltaC = sfCeSb.minus(sfCeChp).minus(sfCfChp).plus(sfCfSb);
    // The compute the difference in investment costs
    ServiceFunction deltaI = invCogeneration.minus(invSBoiler);
    // Now the profit as the difference between these
    ServiceFunction profit = deltaC.minus(deltaI);
    // Now adjust the profit to show the risk aversion (inflation). This operation is known as
    // discounting and adjusts the actual amounts so that it will show the value at present. The
    // main idea is that money are more valuable now than in the future
    ServiceFunction disc = new DiscountServiceFunction(discountRate, 2000);
    ServiceFunction adjProfit = profit.multiply(new DiscountServiceFunction(discountRate, 2000));

    /**
     * The optimum adoption time is the time where the profit is maximum. One way to find it is
     * to look on the graphic. Another way is to use the routine for finding the maximum available
     * inside a service function
     */

    // Plot the function
    adjProfit.plot(2000, 2030, "Profit ($)", "Profit (or loss) for switching to cogeneration");
    // Find the maximum profit and the year this happens (thus the optimum time for adoption)
    System.out.print("The best year for adoption is " + Math.round(adjProfit.tmax()) + ", where the profit would be " + Math.round(adjProfit.max()) + "$");

  }

}



Sample5_CogenerationAdoptionSimulation.java
Created with JBuilder