Skip to content

Commit f4e04b5

Browse files
authored
Merge pull request #530 from NREL/lcos_cost_inputs
Lcos cost inputs
2 parents 4f2ecdd + cc0a172 commit f4e04b5

21 files changed

+1078
-118
lines changed

ssc/cmod_battery.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -399,18 +399,18 @@ battstor::battstor(var_table& vt, bool setup_model, size_t nrec, double dt_hr, c
399399

400400

401401
// Battery bank replacement
402-
if (vt.is_assigned("om_replacement_cost1"))
402+
if (vt.is_assigned("om_batt_replacement_cost"))
403403
{
404404
std::vector<ssc_number_t> replacement_cost(nyears);
405-
ssc_number_t* parr = vt.as_array("om_replacement_cost1", &cnt);
405+
ssc_number_t* parr = vt.as_array("om_batt_replacement_cost", &cnt);
406406
if (cnt == 1)
407407
{
408408
for (i = 0; i < nyears; i++)
409409
replacement_cost[i] = parr[0] * (ssc_number_t)pow((double)(inflation_rate + 1), (double)i);
410410
}
411411
else if (cnt < nyears)
412412
{
413-
throw exec_error("battery", "Invalid number for om_replacement_cost1, must be 1 or equal to analysis_period.");
413+
throw exec_error("battery", "Invalid number for om_batt_replacement_cost, must be 1 or equal to analysis_period.");
414414
}
415415
else {
416416
for (i = 0; i < nyears; i++)

ssc/cmod_cashloan.cpp

Lines changed: 62 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2626
#include "lib_financial.h"
2727
#include "lib_util.h"
2828
#include "common_financial.h"
29-
#include <sstream>
3029
using namespace libfin;
30+
#include <sstream>
3131

3232
static var_info vtab_cashloan[] = {
3333
/* VARTYPE DATATYPE NAME LABEL UNITS META GROUP REQUIRED_IF CONSTRAINTS UI_HINTS*/
@@ -37,11 +37,13 @@ static var_info vtab_cashloan[] = {
3737

3838
{ SSC_INPUT, SSC_NUMBER, "total_installed_cost", "Total installed cost", "$", "", "System Costs", "*", "MIN=0", "" },
3939
{ SSC_INPUT, SSC_NUMBER, "salvage_percentage", "Salvage value percentage", "%", "", "Financial Parameters", "?=0.0", "MIN=0,MAX=100", "" },
40-
40+
//{ SSC_INPUT, SSC_NUMBER, "batt_salvage_percentage", "Net pre-tax cash battery salvage value", "%", "", "Financial Parameters", "?=0", "MIN=0,MAX=100", "" },
41+
4142
{ SSC_INPUT, SSC_ARRAY, "annual_energy_value", "Energy value", "$", "", "System Output", "*", "", "" },
4243
{ SSC_INPUT, SSC_ARRAY, "annual_themal_value", "Energy value", "$", "", "System Output", "", "", "" },
4344
{ SSC_INPUT, SSC_ARRAY, "gen", "Power generated by renewable resource", "kW", "", "System Output", "*", "", "" },
44-
{ SSC_INPUT, SSC_ARRAY, "degradation", "Annual degradation", "%", "", "System Output", "*", "", "" },
45+
46+
{ SSC_INPUT, SSC_ARRAY, "degradation", "Annual degradation", "%", "", "System Output", "*", "", "" },
4547
{ SSC_INPUT, SSC_NUMBER, "system_use_lifetime_output","Lifetime hourly system outputs", "0/1", "0=hourly first year,1=hourly lifetime", "Lifetime", "*", "INTEGER,MIN=0", "" },
4648

4749
/* financial outputs */
@@ -52,12 +54,15 @@ static var_info vtab_cashloan[] = {
5254
{ SSC_OUTPUT, SSC_NUMBER, "payback", "Payback period", "years", "", "Cash Flow", "*", "", "" },
5355
// added 9/26/16 for Owen Zinaman Mexico
5456
{ SSC_OUTPUT, SSC_NUMBER, "discounted_payback", "Discounted payback period", "years", "", "Cash Flow", "*", "", "" },
55-
{ SSC_OUTPUT, SSC_NUMBER, "npv", "Net present value", "$", "", "Cash Flow", "*", "", "" },
57+
58+
{ SSC_OUTPUT, SSC_NUMBER, "npv", "Net present value", "$", "", "Cash Flow", "*", "", "" },
5659

5760
{ SSC_OUTPUT, SSC_NUMBER, "present_value_oandm", "Present value of O&M expenses", "$", "", "Financial Metrics", "*", "", "" },
5861
{ SSC_OUTPUT, SSC_NUMBER, "present_value_oandm_nonfuel", "Present value of non-fuel O&M expenses", "$", "", "Financial Metrics", "*", "", "" },
5962
{ SSC_OUTPUT, SSC_NUMBER, "present_value_fuel", "Present value of fuel expenses", "$", "", "Financial Metrics", "*", "", "" },
6063
{ SSC_OUTPUT, SSC_NUMBER, "present_value_insandproptax", "Present value of insurance and property tax", "$", "", "Financial Metrics", "*", "", "" },
64+
65+
{ SSC_OUTPUT, SSC_NUMBER, "npv_energy_lcos_nom", "Present value of annual stored energy (nominal)", "kWh", "", "LCOE calculations", "", "", "" },
6166

6267
{ SSC_OUTPUT, SSC_NUMBER, "adjusted_installed_cost", "Net capital cost", "$", "", "Financial Metrics", "*", "", "" },
6368
{ SSC_OUTPUT, SSC_NUMBER, "loan_amount", "Debt", "$", "", "Financial Metrics", "*", "", "" },
@@ -162,7 +167,9 @@ extern var_info
162167
vtab_battery_replacement_cost[],
163168
vtab_fuelcell_replacement_cost[],
164169
vtab_tax_credits[],
165-
vtab_payment_incentives[];
170+
vtab_payment_incentives[],
171+
vtab_lcos_inputs[];
172+
166173

167174
enum {
168175
CF_degradation,
@@ -171,16 +178,6 @@ enum {
171178
CF_thermal_value,
172179
CF_value_added,
173180

174-
CF_om_fixed_expense,
175-
CF_om_production_expense,
176-
CF_om_capacity_expense,
177-
CF_om_fixed1_expense,
178-
CF_om_production1_expense,
179-
CF_om_capacity1_expense,
180-
CF_om_fixed2_expense,
181-
CF_om_production2_expense,
182-
CF_om_capacity2_expense,
183-
CF_om_fuel_expense,
184181

185182
CF_om_opt_fuel_2_expense,
186183
CF_om_opt_fuel_1_expense,
@@ -253,7 +250,29 @@ enum {
253250

254251
CF_nte,
255252

256-
CF_max };
253+
CF_om_fixed_expense,
254+
CF_om_production_expense,
255+
CF_om_capacity_expense,
256+
CF_om_fixed1_expense,
257+
CF_om_production1_expense,
258+
CF_om_capacity1_expense,
259+
CF_om_fixed2_expense,
260+
CF_om_production2_expense,
261+
CF_om_capacity2_expense,
262+
CF_om_fuel_expense,
263+
CF_energy_charged_grid,
264+
CF_energy_charged_pv,
265+
CF_energy_discharged,
266+
CF_charging_cost_pv,
267+
CF_charging_cost_grid,
268+
CF_om_cost_lcos,
269+
CF_salvage_cost_lcos,
270+
CF_investment_cost_lcos,
271+
CF_annual_cost_lcos,
272+
CF_util_escal_rate,
273+
274+
CF_max,
275+
};
257276

258277

259278

@@ -262,6 +281,7 @@ class cm_cashloan : public compute_module
262281
{
263282
private:
264283
util::matrix_t<double> cf;
284+
util::matrix_t<double> cf_lcos;
265285
double ibi_fed_amount;
266286
double ibi_sta_amount;
267287
double ibi_uti_amount;
@@ -290,6 +310,7 @@ class cm_cashloan : public compute_module
290310
add_var_info(vtab_battery_replacement_cost);
291311
add_var_info(vtab_fuelcell_replacement_cost);
292312
add_var_info(vtab_cashloan);
313+
add_var_info(vtab_lcos_inputs);
293314
}
294315

295316
void exec( )
@@ -299,7 +320,6 @@ class cm_cashloan : public compute_module
299320
bool is_commercial = (as_integer("market")==1);
300321
bool is_mortgage = (as_integer("mortgage")==1);
301322

302-
303323
// throw exec_error("cmod_cashloan", "mortgage = " + util::to_string(as_integer("mortgage")));
304324
// if (is_commercial) log("commercial market"); else log("residential market");
305325
// if (is_mortgage) log("mortgage loan"); else log("standard loan");
@@ -309,6 +329,7 @@ class cm_cashloan : public compute_module
309329

310330
// initialize cashflow matrix
311331
cf.resize_fill( CF_max, nyears+1, 0.0 );
332+
cf_lcos.resize_fill(CF_max, nyears + 1, 0.0);
312333

313334
// initialize energy and revenue
314335
size_t count = 0;
@@ -476,17 +497,17 @@ class cm_cashloan : public compute_module
476497

477498
if (add_om_num_types > 0)
478499
{
479-
escal_or_annual(CF_om_fixed1_expense, nyears, "om_fixed1", inflation_rate, 1.0, false, as_double("om_fixed_escal")*0.01);
480-
escal_or_annual(CF_om_production1_expense, nyears, "om_production1", inflation_rate, 0.001, false, as_double("om_production_escal")*0.01);
481-
escal_or_annual(CF_om_capacity1_expense, nyears, "om_capacity1", inflation_rate, 1.0, false, as_double("om_capacity_escal")*0.01);
482-
nameplate1 = as_number("om_capacity1_nameplate");
500+
escal_or_annual(CF_om_fixed1_expense, nyears, "om_batt_fixed_cost", inflation_rate, 1.0, false, as_double("om_fixed_escal") * 0.01);
501+
escal_or_annual(CF_om_production1_expense, nyears, "om_batt_variable_cost", inflation_rate, 0.001, false, as_double("om_production_escal") * 0.01);
502+
escal_or_annual(CF_om_capacity1_expense, nyears, "om_batt_capacity_cost", inflation_rate, 1.0, false, as_double("om_capacity_escal") * 0.01);
503+
nameplate1 = as_number("ui_batt_capacity");
483504
}
484505
if (add_om_num_types > 1)
485506
{
486-
escal_or_annual(CF_om_fixed2_expense, nyears, "om_fixed2", inflation_rate, 1.0, false, as_double("om_fixed_escal")*0.01);
487-
escal_or_annual(CF_om_production2_expense, nyears, "om_production2", inflation_rate, 0.001, false, as_double("om_production_escal")*0.01);
488-
escal_or_annual(CF_om_capacity2_expense, nyears, "om_capacity2", inflation_rate, 1.0, false, as_double("om_capacity_escal")*0.01);
489-
nameplate2 = as_number("om_capacity2_nameplate");
507+
escal_or_annual(CF_om_fixed2_expense, nyears, "om_fuelcell_fixed_cost", inflation_rate, 1.0, false, as_double("om_fixed_escal")*0.01);
508+
escal_or_annual(CF_om_production2_expense, nyears, "om_fuelcell_variable_cost", inflation_rate, 0.001, false, as_double("om_production_escal")*0.01);
509+
escal_or_annual(CF_om_capacity2_expense, nyears, "om_fuelcell_capacity_cost", inflation_rate, 1.0, false, as_double("om_capacity_escal")*0.01);
510+
nameplate2 = as_number("ui_fuelcell_capacity");
490511
}
491512

492513
// battery cost - replacement from lifetime analysis
@@ -509,7 +530,7 @@ class cm_cashloan : public compute_module
509530
}
510531
double batt_cap = as_double("batt_computed_bank_capacity");
511532
// updated 10/17/15 per 10/14/15 meeting
512-
escal_or_annual(CF_battery_replacement_cost_schedule, nyears, "om_replacement_cost1", inflation_rate, batt_cap, false, as_double("om_replacement_cost_escal") * 0.01);
533+
escal_or_annual(CF_battery_replacement_cost_schedule, nyears, "om_batt_replacement_cost", inflation_rate, batt_cap, false, as_double("om_replacement_cost_escal") * 0.01);
513534

514535
for (i = 0; i < nyears && i < (int)count; i++) {
515536
// batt_rep and the cash flow sheets are 1 indexed, replacement_percent is zero indexed
@@ -526,7 +547,7 @@ class cm_cashloan : public compute_module
526547
fuelcell_rep = as_array("fuelcell_replacement", &count); // replacements per year calculated
527548
else // user specified
528549
fuelcell_rep = as_array("fuelcell_replacement_schedule", &count); // replacements per year user-defined
529-
escal_or_annual(CF_fuelcell_replacement_cost_schedule, nyears, "om_replacement_cost2", inflation_rate, nameplate2, false, as_double("om_replacement_cost_escal")*0.01);
550+
escal_or_annual(CF_fuelcell_replacement_cost_schedule, nyears, "om_fuelcell_replacement_cost", inflation_rate, nameplate2, false, as_double("om_replacement_cost_escal")*0.01);
530551

531552
for ( i = 0; i < nyears && i < (int)count; i++) {
532553
cf.at(CF_fuelcell_replacement_cost, i + 1) = fuelcell_rep[i] *
@@ -1002,7 +1023,20 @@ class cm_cashloan : public compute_module
10021023
assign("lcoptc_sta_nom", var_data((ssc_number_t) lcoptc_sta_nom));
10031024
assign("lcoptc_sta_real", var_data((ssc_number_t) lcoptc_sta_real));
10041025

1005-
1026+
///////////////////////////////////////////////////////////////////////
1027+
//LCOS Calculations
1028+
if (is_assigned("battery_total_cost_lcos") && as_double("battery_total_cost_lcos") != 0) {
1029+
for (int y = 0; y <= nyears; y++) {
1030+
cf_lcos.at(0, y) = cf.at(CF_battery_replacement_cost, y);
1031+
cf_lcos.at(1, y) = cf.at(CF_battery_replacement_cost_schedule, y);
1032+
cf_lcos.at(6, y) = cf.at(CF_om_fixed1_expense, y); //Fixed OM Battery cost
1033+
cf_lcos.at(7, y) = cf.at(CF_om_production1_expense, y); //Produciton OM Battery cost
1034+
cf_lcos.at(8, y) = cf.at(CF_om_capacity1_expense, y); //Capacity OM Battery Cost
1035+
}
1036+
int grid_charging_cost_version = 0;
1037+
lcos_calc(this, cf_lcos, nyears, nom_discount_rate, inflation_rate, lcoe_real, total_cost, real_discount_rate, grid_charging_cost_version, 0);
1038+
}
1039+
/////////////////////////////////////////////////////////////////////////////////////////
10061040

10071041
double wacc = 0.0;
10081042
wacc = (1.0 - debt_frac)*nom_discount_rate + debt_frac*loan_rate*(1.0 - cf.at(CF_effective_tax_frac, 1));

0 commit comments

Comments
 (0)