def choose_tech(VE,D,j,N,energy,prices_lamp,tt,interes):
method=strategy(VE[j,2])
#returns the strategy to use over the different profiles
#(1)rational, (2) social, (3) conservative
#Rational method
if method==1: #180 hours of consume in average per month
cost=np.zeros((3,139)) #Payments over time of the different techs
cost_present=np.zeros(3) #Total present cost
#Analysis of energy consume
for i in range(139):
if VE[j,3]==1:
cost[0,i]=(-40*180/100)*energy[i+tt]*0.8
cost[1,i]=(-15*180/100)*energy[i+tt]*0.8
cost[2,i]=(-9*180/100)*energy[i+tt]*0.8
elif VE[j,3]==2:
cost[0,i]=(-40*180/100)*energy[i+tt]*1.2
cost[1,i]=(-15*180/100)*energy[i+tt]*1.2
cost[2,i]=(-9*180/100)*energy[i+tt]*1.2
#LED lamp cost
cost[2,0]=cost[2,0]-prices_lamp[2,tt]
#Fluorescent lamp cost (1:36:139)
for i in range(0,138,36):
cost[1,i]=cost[1,i]-prices_lamp[1,tt+i]
#Incandescent lamp cost (i=1:4:139)
for i in range(0,138,4):
cost[0,i]=cost[0,i]-prices_lamp[0,tt+i]
#Cost in present value
cost_present[0]=-np.npv(interes,cost[0,:])
cost_present[1]=-np.npv(interes,cost[1,:])
cost_present[2]=-np.npv(interes,cost[2,:])
#Selection of the best npv performance
tech=cost_present.argmin()
tech=tech+1
#Conservative method
if method==3:
tech=VE[j,0]
#Social method
if method==2:
S_t=np.zeros(3) #Counter of technologies in vicinity
D_N=D.neighbors(j) #Returns the list of neighbors
D_N_len=len(D_N) #Dimension of neighbors list
for k in range(D_N_len): #Iteration of evaluation
S_t[VE[D_N[k],0]-1]=S_t[VE[D_N[k],0]-1]+1
tech=S_t.argmax()+1
return(tech)
def net_present_value_for_loan(self, loan):
""" Calculates a loan's net present value from its cash flows.
Args:
loan: The loan which is being valued.
Returns: The net present value of the loan.
"""
cash_flows = self.cash_flows_df[self.cash_flows_df['loan_df_pk'] == loan.name]
npv = np.npv(self.discount_rate / 12, cash_flows['total_payments'])
return npv
def eq_subvention(montant, duree, taux):
""" Calcule l' "équivalent subvention" par rapport à un taux 0%
pour chacune des différentes combinaisons d'hypothèses possibles"""
# RAZ des résultats
equivalent_subvention = np.zeros((len(montant), len(duree), len(taux)))
part_subventionee = np.zeros((len(montant), len(duree), len(taux)))
# Calcule de l' "équivalent subvention"
for i in range(len(montant)):
for j in range(len(duree)):
# Périodicité des remboursements
per = np.arange(duree[j]) + 1
for k in range(len(taux)):
# Calcule l'échancier des intérêts perçus
echeancier_interets = -np.ipmt(taux[k], per, duree[j], montant[i])
# Calcule et enregistre l' "équivalent subvention" comparé
# à un taux 0 pour le jeu d'hypothèses considéré, les flux
# d'intérêt étant actualisés à 4%
equivalent_subvention[i, j, k] = np.npv(0.04, echeancier_interets)
# ou alternativemen, sans actualiser:
# equivalent_subvention[i,j,k]=np.sum(echeancier_interets)
part_subventionee[i, j, k] = (equivalent_subvention[i, j, k] / montant[i]) * 100
return equivalent_subvention, part_subventionee
开发者ID:milinc,项目名称:ptre,代码行数:22,代码来源:abaque.py
示例9: calc_npv
def calc_npv(r, ubi, inputs, n):
x = np.zeros((ubi['Years Post Transfer'], n))
y = np.zeros((ubi['Years Post Transfer'], n))
# iterate through years of benefits
for j in range(1, ubi['Years Post Transfer'] + 1):
# sum benefits during program
if(j < r):
x[j - 1] += ubi['Expected baseline per capita consumption (nominal USD)']* \
np.power((1.0 + inputs['UBI']['Expected annual consumption increase (without the UBI program)']), float(j))* \
inputs['UBI']['Work participation adjustment'] + \
ubi['Annual quantity of transfer money used for immediate consumtion (pre-discounting)']
# benefits after program
else:
x[j - 1] += ubi['Expected baseline per capita consumption (nominal USD)']* \
np.power((1.0 + inputs['UBI']['Expected annual consumption increase (without the UBI program)']), float(j))
# investments calculations
for k in range(n):
if(j < r + inputs['UBI']['Duration of investment benefits (in years) - UBI'][k]):
x[j - 1][k] += ubi['Annual return for each year of transfer investments (pre-discounting)'][k]* \
np.min([j, inputs['UBI']['Duration of investment benefits (in years) - UBI'][k], \
r, (inputs['UBI']['Duration of investment benefits (in years) - UBI'][k] + r - j)])
if(j > r):
x[j - 1][k] += ubi['Value eventually returned from one years investment (pre-discounting)'][k]
# log transform and subtact baseline
y[j - 1] = np.log(x[j - 1])
y[j - 1] -= np.log(ubi['Expected baseline per capita consumption (nominal USD)']* \
np.power((1.0 + inputs['UBI']['Expected annual consumption increase (without the UBI program)']), float(j)))
# npv on yearly data
z = np.zeros(n)
for i in range(n):
z[i] = np.npv(inputs['Shared']['Discount rate'][i], y[:, i])
return z
energySaleChange = sum(energySaleDRyear) - sum(energySaleArray)
peakDemandRed = PeakDemandCharge - PeakDemandChargeDR
# Calculating the Purchase Cost, Operation and Maint. Cost and Total Cost
outData["AnnualOpCost"] = [- AnnDROM for x in lifeYears[0:]]
LifetimeOperationCost = (sum(outData["AnnualOpCost"]))
outData["LifetimeOperationCost"] = abs(LifetimeOperationCost)
outData["lifePurchaseCosts"] = [-1.0 * DrTechCost] + [0 for x in lifeYears[1:]]
outData["TotalCost"] = abs(outData["LifetimeOperationCost"] + DrTechCost)
# Outputs of the Program Lifetime Cash Flow figure
outData["EnergySaleChangeBenefit"] = [energySaleChange * ScalingAnnual ** x for x in range(lifeSpan)]
outData["PeakDemandReduction"] = [peakDemandRed * ScalingAnnual ** x for x in range(lifeSpan)]
BenefitCurve = [x+y for x,y in zip(outData["EnergySaleChangeBenefit"], outData["PeakDemandReduction"])]
outData["TotalBenefit"] = sum(BenefitCurve)
outData["BenefittoCostRatio"] = float(outData["TotalBenefit"] / outData["TotalCost"])
netBenefit = [x+y+z for x,y,z in zip(outData["AnnualOpCost"],outData["lifePurchaseCosts"],BenefitCurve)]
outData["npv"] = npv(DiscountRate, netBenefit)
outData["cumulativeNetBenefit"] = [sum(netBenefit[0:i+1]) for i,d in enumerate(netBenefit)]
outData["SimplePaybackPeriod"] = DrTechCost / (outData["TotalBenefit"] / lifeSpan)
# Stdout/stderr.
outData["stdout"] = "Success"
outData["stderr"] = ""
# Write the output.
with open(pJoin(modelDir,"allOutputData.json"),"w") as outFile:
json.dump(outData, outFile, indent=4)
# Update the runTime in the input file.
endTime = datetime.datetime.now()
inputDict["runTime"] = str(datetime.timedelta(seconds=int((endTime - startTime).total_seconds())))
with open(pJoin(modelDir,"allInputData.json"),"w") as inFile:
json.dump(inputDict, inFile, indent=4)
except:
# If input range wasn't valid delete output, write error to disk.
def value_can_afford(monthly_payment):
# this is a 10 year average freddie mac interest rate
ten_year_average_interest = .055
return np.npv(ten_year_average_interest/12, [monthly_payment]*30*12)
def work(modelDir, inputDict):
''' Run the model in its directory.'''
if inputDict['dispatch_type'] == 'prediction':
return workForecast(modelDir, inputDict)
out = {}
try:
with open(pJoin(modelDir, 'demand.csv'), 'w') as f:
f.write(inputDict['demandCurve'].replace('\r', ''))
with open(pJoin(modelDir, 'demand.csv')) as f:
demand = [float(r[0]) for r in csv.reader(f)]
assert len(demand) == 8760
with open(pJoin(modelDir, 'temp.csv'), 'w') as f:
lines = inputDict['tempCurve'].split('\n')
out["tempData"] = [float(x) if x != '999.0' else float(inputDict['setpoint']) for x in lines[:-1]]
correctData = [x+'\n' if x != '999.0' else inputDict['setpoint']+'\n' for x in lines][:-1]
f.write(''.join(correctData))
assert len(correctData) == 8760
except:
raise Exception("CSV file is incorrect format. Please see valid format "
"definition at <a target='_blank' href = 'https://github.com/dpinney/"
"omf/wiki/Models-~-storagePeakShave#demand-file-csv-format'>\nOMF Wiki "
"storagePeakShave - Demand File CSV Format</a>")
# # created using calendar = {'1': 31, '2': 28, ..., '12': 31}
# m = [calendar[key]*24 for key in calendar]
# monthHours = [(sum(m[:i]), sum(m[:i+1])) for i, _ in enumerate(m)]
monthHours = [(0, 744), (744, 1416), (1416, 2160), (2160, 2880),
(2880, 3624), (3624, 4344), (4344, 5088), (5088, 5832),
(5832, 6552), (6552, 7296), (7296, 8016), (8016, 8760)]
P_lower, P_upper, E_UL = pyVbat(modelDir, inputDict)
P_lower, P_upper, E_UL = list(P_lower), list(P_upper), list(E_UL)
out["minPowerSeries"] = [-1*x for x in P_lower]
out["maxPowerSeries"] = P_upper
out["minEnergySeries"] = [-1*x for x in E_UL]
out["maxEnergySeries"] = E_UL
VBpower, out["VBenergy"] = pulpFunc(inputDict, demand, P_lower, P_upper, E_UL, monthHours)
out["VBpower"] = VBpower
out["dispatch_number"] = [len([p for p in VBpower[s:f] if p != 0]) for (s, f) in monthHours]
peakDemand = [max(demand[s:f]) for s, f in monthHours]
energyMonthly = [sum(demand[s:f]) for s, f in monthHours]
demandAdj = [d+p for d, p in zip(demand, out["VBpower"])]
peakAdjustedDemand = [max(demandAdj[s:f]) for s, f in monthHours]
energyAdjustedMonthly = [sum(demandAdj[s:f]) for s, f in monthHours]
rms = all([x == 0 for x in P_lower]) and all([x == 0 for x in P_upper])
out["dataCheck"] = 'VBAT returns no values for your inputs' if rms else ''
out["demand"] = demand
out["peakDemand"] = peakDemand
out["energyMonthly"] = energyMonthly
out["demandAdjusted"] = demandAdj
out["peakAdjustedDemand"] = peakAdjustedDemand
out["energyAdjustedMonthly"] = energyAdjustedMonthly
cellCost = float(inputDict["unitDeviceCost"])*float(inputDict["number_devices"])
eCost = float(inputDict["electricityCost"])
dCharge = float(inputDict["demandChargeCost"])
out["VBdispatch"] = [dal-d for dal, d in zip(demandAdj, demand)]
out["energyCost"] = [em*eCost for em in energyMonthly]
out["energyCostAdjusted"] = [eam*eCost for eam in energyAdjustedMonthly]
out["demandCharge"] = [peak*dCharge for peak in peakDemand]
out["demandChargeAdjusted"] = [pad*dCharge for pad in out["peakAdjustedDemand"]]
out["totalCost"] = [ec+dcm for ec, dcm in zip(out["energyCost"], out["demandCharge"])]
out["totalCostAdjusted"] = [eca+dca for eca, dca in zip(out["energyCostAdjusted"], out["demandChargeAdjusted"])]
out["savings"] = [tot-tota for tot, tota in zip(out["totalCost"], out["totalCostAdjusted"])]
annualEarnings = sum(out["savings"]) - float(inputDict["unitUpkeepCost"])*float(inputDict["number_devices"])
cashFlowList = [annualEarnings] * int(inputDict["projectionLength"])
cashFlowList.insert(0, -1*cellCost)
out["NPV"] = npv(float(inputDict["discountRate"])/100, cashFlowList)
out["SPP"] = cellCost / annualEarnings
out["netCashflow"] = cashFlowList
out["cumulativeCashflow"] = [sum(cashFlowList[:i+1]) for i, d in enumerate(cashFlowList)]
out["stdout"] = "Success"
return out
#.........这里部分代码省略.........
dailyPl = [P_lower[i:i+24] for i in range(0, len(P_lower), 24)]
dailyPu = [P_upper[i:i+24] for i in range(0, len(P_upper), 24)]
dailyEu = [E_UL[i:i+24] for i in range(0, len(E_UL), 24)]
vbp, vbe = [], []
dispatched_d = [False]*365
# Decide what days to dispatch
zipped = zip(dailyLoadPredictions, df['month'][-8760:], dailyPl, dailyPu, dailyEu)
for i, (load, m, pl, pu, eu) in enumerate(zipped):
peak = max(load)
if fc.shouldDispatchPS(peak, m, df, float(ind['confidence'])/100):
dispatched_d[i] = True
p, e = fc.pulp24hrVbat(ind, load, pl, pu, eu)
vbp.extend(p)
vbe.extend(e)
else:
vbp.extend([0]*24)
vbe.extend([0]*24)
### TESTING FOR ACCURACY ###
assert len(dailyPl) == 365
assert all([len(i) == 24 for i in dailyPl])
VB_power, VB_energy = vbp, vbe
# -------------------- MODEL ACCURACY ANALYSIS -------------------------- #
o['predictedLoad'] = list(clf.predict(X_test))
o['trainAccuracy'] = round(clf.score(X_train, y_train) * 100, 2)
o['testAccuracy'] = round(clf.score(X_test, y_test) * 100, 2)
# PRECISION AND RECALL
maxDays = []
for month in range(1, 13):
test = df[df['month'] == month]
maxDays.append(test.loc[test['load'].idxmax()]['dayOfYear'])
shouldHaveDispatched = [False]*365
for day in maxDays:
shouldHaveDispatched[day] = True
truePositive = len([b for b in [i and j for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b])
falsePositive = len([b for b in [i and (not j) for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b])
falseNegative = len([b for b in [(not i) and j for (i, j) in zip(dispatched_d, shouldHaveDispatched)] if b])
o['confidence'] = ind['confidence']
o['precision'] = round(truePositive / float(truePositive + falsePositive) * 100, 2)
o['recall'] = round(truePositive / float(truePositive + falseNegative) * 100, 2)
o['number_of_dispatches'] = len([i for i in dispatched_d if i])
o['MAE'] = round(sum([abs(l-m)/m*100 for l, m in zip(predictions, list(y_test))])/8760., 2)
# ---------------------- FINANCIAL ANALYSIS ----------------------------- #
o['VBpower'], o['VBenergy'] = list(VB_power), list(VB_energy)
# Calculate monthHours
year = df[-8760:].copy()
year.reset_index(inplace=True)
year['hour'] = list(year.index)
start = list(year.groupby('month').first()['hour'])
finish = list(year.groupby('month').last()['hour'])
monthHours = [(s, f+1) for (s, f) in zip(start, finish)]
demand = list(y_test)
peakDemand = [max(demand[s:f]) for s, f in monthHours]
energyMonthly = [sum(demand[s:f]) for s, f in monthHours]
demandAdj = [d+p for d, p in zip(demand, o['VBpower'])]
peakAdjustedDemand = [max(demandAdj[s:f]) for s, f in monthHours]
energyAdjustedMonthly = [sum(demandAdj[s:f]) for s, f in monthHours]
o['demand'] = demand
o['peakDemand'] = peakDemand
o['energyMonthly'] = energyMonthly
o['demandAdjusted'] = demandAdj
o['peakAdjustedDemand'] = peakAdjustedDemand
o['energyAdjustedMonthly'] = energyAdjustedMonthly
cellCost = float(ind['unitDeviceCost'])*float(ind['number_devices'])
eCost = float(ind['electricityCost'])
dCharge = float(ind['demandChargeCost'])
o['VBdispatch'] = [dal-d for dal, d in zip(demandAdj, demand)]
o['energyCost'] = [em*eCost for em in energyMonthly]
o['energyCostAdjusted'] = [eam*eCost for eam in energyAdjustedMonthly]
o['demandCharge'] = [peak*dCharge for peak in peakDemand]
o['demandChargeAdjusted'] = [pad*dCharge for pad in o['peakAdjustedDemand']]
o['totalCost'] = [ec+dcm for ec, dcm in zip(o['energyCost'], o['demandCharge'])]
o['totalCostAdjusted'] = [eca+dca for eca, dca in zip(o['energyCostAdjusted'], o['demandChargeAdjusted'])]
o['savings'] = [tot-tota for tot, tota in zip(o['totalCost'], o['totalCostAdjusted'])]
annualEarnings = sum(o['savings']) - float(ind['unitUpkeepCost'])*float(ind['number_devices'])
cashFlowList = [annualEarnings] * int(ind['projectionLength'])
cashFlowList.insert(0, -1*cellCost)
o['NPV'] = np.npv(float(ind['discountRate'])/100, cashFlowList)
o['SPP'] = cellCost / annualEarnings
o['netCashflow'] = cashFlowList
o['cumulativeCashflow'] = [sum(cashFlowList[:i+1]) for i, d in enumerate(cashFlowList)]
o['stdout'] = 'Success'
return o
def heavyProcessing(modelDir, inputDict):
''' Run the model in a separate process. web.py calls this to run the model.
This function will return fast, but results take a while to hit the file system.'''
# Delete output file every run if it exists
try:
# Ready to run.
startTime = datetime.datetime.now()
outData = {}
# Get variables.
cellCapacity = float(inputDict['cellCapacity'])
(cellCapacity, dischargeRate, chargeRate, cellQuantity, demandCharge, cellCost) = \
[float(inputDict[x]) for x in ('cellCapacity', 'dischargeRate', 'chargeRate', 'cellQuantity', 'demandCharge', 'cellCost')]
battEff = float(inputDict.get("batteryEfficiency", 92)) / 100.0 * float(inputDict.get("inverterEfficiency", 92)) / 100.0 * float(inputDict.get("inverterEfficiency", 92)) / 100.0
discountRate = float(inputDict.get('discountRate', 2.5)) / 100.0
retailCost = float(inputDict.get('retailCost', 0.07))
dodFactor = float(inputDict.get('dodFactor', 85)) / 100.0
projYears = int(inputDict.get('projYears',10))
# Put demand data in to a file for safe keeping.
with open(pJoin(modelDir,"demand.csv"),"w") as demandFile:
demandFile.write(inputDict['demandCurve'])
# Start running battery simulation.
battCapacity = cellQuantity * cellCapacity * dodFactor
battDischarge = cellQuantity * dischargeRate
battCharge = cellQuantity * chargeRate
# Most of our data goes inside the dc "table"
try:
dc = []
with open(pJoin(modelDir,"demand.csv")) as inFile:
reader = csv.DictReader(inFile)
for row in reader:
dc.append({'datetime': parse(row['timestamp']), 'power': float(row['power'])})
if len(dc)<8760: raise Exception
except:
errorMessage = "CSV file is incorrect format. Please see valid format definition at\n <a target='_blank' href = 'https://github.com/dpinney/omf/wiki/Models-~-energyStorage#demand-file-csv-format'>OMF Wiki energyStorage</a>"
raise Exception(errorMessage)
for row in dc:
row['month'] = row['datetime'].month-1
row['weekday'] = row['datetime'].weekday
outData['startDate'] = dc[0]['datetime'].isoformat()
ps = [battDischarge for x in range(12)]
dcGroupByMonth = [[t['power'] for t in dc if t['datetime'].month-1==x] for x in range(12)]
monthlyPeakDemand = [max(dcGroupByMonth[x]) for x in range(12)]
capacityLimited = True
while capacityLimited:
battSoC = battCapacity # Battery state of charge; begins full.
battDoD = [battCapacity for x in range(12)] # Depth-of-discharge every month, depends on dodFactor.
for row in dc:
month = int(row['datetime'].month)-1
powerUnderPeak = monthlyPeakDemand[month] - row['power'] - ps[month]
isCharging = powerUnderPeak > 0
isDischarging = powerUnderPeak <= 0
charge = isCharging * min(
powerUnderPeak * battEff, # Charge rate <= new monthly peak - row['power']
battCharge, # Charge rate <= battery maximum charging rate.
battCapacity - battSoC) # Charge rage <= capacity remaining in battery.
discharge = isDischarging * min(
abs(powerUnderPeak), # Discharge rate <= new monthly peak - row['power']
abs(battDischarge), # Discharge rate <= battery maximum charging rate.
abs(battSoC+.001)) # Discharge rate <= capacity remaining in battery.
# (Dis)charge battery
battSoC += charge
battSoC -= discharge
# Update minimum state-of-charge for this month.
battDoD[month] = min(battSoC,battDoD[month])
row['netpower'] = row['power'] + charge/battEff - discharge
row['battSoC'] = battSoC
capacityLimited = min(battDoD) < 0
ps = [ps[month]-(battDoD[month] < 0) for month in range(12)]
dcThroughTheMonth = [[t for t in iter(dc) if t['datetime'].month-1<=x] for x in range(12)]
hoursThroughTheMonth = [len(dcThroughTheMonth[month]) for month in range(12)]
peakShaveSum = sum(ps)
outData['SPP'] = (cellCost*cellQuantity)/(peakShaveSum*demandCharge)
cashFlowCurve = [peakShaveSum * demandCharge for year in range(projYears)]
cashFlowCurve[0]-= (cellCost * cellQuantity)
outData['netCashflow'] = cashFlowCurve
outData['cumulativeCashflow'] = [sum(cashFlowCurve[0:i+1]) for i,d in enumerate(cashFlowCurve)]
outData['NPV'] = npv(discountRate, cashFlowCurve)
outData['demand'] = [t['power']*1000.0 for t in dc]
outData['demandAfterBattery'] = [t['netpower']*1000.0 for t in dc]
outData['batterySoc'] = [t['battSoC']/battCapacity*100.0*dodFactor + (100-100*dodFactor) for t in dc]
# Estimate number of cyles the battery went through.
SoC = outData['batterySoc']
outData['cycleEquivalents'] = sum([SoC[i]-SoC[i+1] for i,x in enumerate(SoC[0:-1]) if SoC[i+1] < SoC[i]]) / 100.0
# # Output some matplotlib results as well.
# plt.plot([t['power'] for t in dc])
# plt.plot([t['netpower'] for t in dc])
# plt.plot([t['battSoC'] for t in dc])
# for month in range(12):
# plt.axvline(hoursThroughTheMonth[month])
# plt.savefig(pJoin(modelDir,"plot.png"))
# Summary of results
outData['months'] = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
totMonNum = []
monthlyDemand = []
for x in range (0, len(dcGroupByMonth)):
totMonNum.append(sum(dcGroupByMonth[x])/1000)
monthlyDemand.append([outData['months'][x], totMonNum[x]])
outData['monthlyDemand'] = totMonNum
outData['ps'] = ps
outData['monthlyDemandRed'] = [totMonNum - ps for totMonNum, ps in zip(totMonNum, ps)]
#.........这里部分代码省略.........
#.........这里部分代码省略.........
# keep shrinking peak shave (ps) until every month doesn't fully expend the battery
while True:
SoC = battCapacity
incorrect_shave = [False] * 12
for row in dc:
month = row['month']
if not incorrect_shave[month]:
powerUnderPeak = monthlyPeakDemand[month] - row['power'] - ps[month]
charge = (min(powerUnderPeak, battCharge, battCapacity - SoC) if powerUnderPeak > 0
else -1 * min(abs(powerUnderPeak), battDischarge, SoC))
if charge == -1 * SoC:
incorrect_shave[month] = True
SoC += charge
row['netpower'] = row['power'] + charge
row['battSoC'] = SoC
ps = [s-1 if incorrect else s for s, incorrect in zip(ps, incorrect_shave)]
if not any(incorrect_shave):
break
elif dispatchStrategy == 'daily':
start = int(inputDict.get('startPeakHour'))
end = int(inputDict.get('endPeakHour'))
for r in dc:
# Discharge if hour is within peak hours otherwise charge
charge = (-1*min(battDischarge, SoC) if start <= r['hour'] <= end
else min(battCharge, battCapacity - SoC))
r['netpower'] = r['power'] + charge
SoC += charge
r['battSoC'] = SoC
elif dispatchStrategy == 'customDispatch':
try:
with open(pJoin(modelDir,'dispatchStrategy.csv')) as f:
reader = csv.reader(f)
for d, r in zip(dc, reader):
d['dispatch'] = int(r[0])
assert all(['dispatch' in r for r in dc]) # ensure each row is filled
except:
if str(sys.exc_info()[0]) != "<type 'exceptions.SystemExit'>":
raise Exception("Dispatch Strategy file is in an incorrect "
"format. Please see valid format definition at <a target "
"= '_blank' href = 'https://github.com/dpinney/omf/wiki/"
"Models-~-storagePeakShave#custom-dispatch-strategy-file-"
"csv-format'>\nOMF Wiki storagePeakShave - Custom "
"Dispatch Strategy File Format</a>")
for r in dc:
# Discharge if there is a 1 in the dispatch strategy csv, otherwise charge the battery.
charge = (-1*min(battDischarge, SoC) if r['dispatch'] == 1
else min(battCharge, battCapacity-SoC))
r['netpower'] = r['power'] + charge
SoC += charge
r['battSoC'] = SoC
# ------------------------- CALCULATIONS ------------------------- #
netByMonth = [[t['netpower'] for t in dc if t['month']==x] for x in range(12)]
monthlyPeakNet = [max(net) for net in netByMonth]
ps = [h-s for h, s in zip(monthlyPeakDemand, monthlyPeakNet)]
dischargeByMonth = [[i-j for i, j in zip(k, l) if i-j < 0] for k, l in zip(netByMonth, demandByMonth)]
# Monthly Cost Comparison Table
out['monthlyDemand'] = [sum(lDemand)/1000 for lDemand in demandByMonth]
out['monthlyDemandRed'] = [t-p for t, p in zip(out['monthlyDemand'], ps)]
out['ps'] = ps
out['benefitMonthly'] = [x*demandCharge for x in ps]
# Demand Before and After Storage Graph
out['demand'] = [t['power']*1000.0 for t in dc] # kW -> W
out['demandAfterBattery'] = [t['netpower']*1000.0 for t in dc] # kW -> W
out['batteryDischargekW'] = [d-b for d, b in zip(out['demand'], out['demandAfterBattery'])]
out['batteryDischargekWMax'] = max(out['batteryDischargekW'])
# Battery State of Charge Graph
# Turn dc's SoC into a percentage, with dodFactor considered.
out['batterySoc'] = SoC = [t['battSoC']/battCapacity*100*dodFactor + (100-100*dodFactor) for t in dc]
# Estimate number of cyles the battery went through. Sums the percent of SoC.
cycleEquivalents = sum([SoC[i]-SoC[i+1] for i, x in enumerate(SoC[:-1]) if SoC[i+1] < SoC[i]]) / 100.0
out['cycleEquivalents'] = cycleEquivalents
out['batteryLife'] = batteryCycleLife / cycleEquivalents
# Cash Flow Graph
# inserting battery efficiency only into the cashflow calculation
# cashFlowCurve is $ in from peak shaving minus the cost to recharge the battery every day of the year
cashFlowCurve = [sum(ps)*demandCharge for year in range(projYears)]
cashFlowCurve.insert(0, -1 * cellCost * cellQuantity) # insert initial investment
# simplePayback is also affected by the cost to recharge the battery every day of the year
out['SPP'] = (cellCost*cellQuantity)/(sum(ps)*demandCharge)
out['netCashflow'] = cashFlowCurve
out['cumulativeCashflow'] = [sum(cashFlowCurve[:i+1]) for i, d in enumerate(cashFlowCurve)]
out['NPV'] = npv(discountRate, cashFlowCurve)
battCostPerCycle = cellQuantity * cellCost / batteryCycleLife
lcoeTotCost = cycleEquivalents*retailCost + battCostPerCycle*cycleEquivalents
out['LCOE'] = lcoeTotCost / (cycleEquivalents*battCapacity)
# Other
out['startDate'] = '2011-01-01' # dc[0]['datetime'].isoformat()
out['stderr'] = ''
# Seemingly unimportant. Ask permission to delete.
out['stdout'] = 'Success'
out['months'] = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]
return out
请发表评论