dpinney / omf

The Open Modeling Framework for smart grid cost-benefit analysis.
https://omf.coop
GNU General Public License v2.0
112 stars 60 forks source link

solarFinancial model #262

Closed dpinney closed 9 years ago

dpinney commented 10 years ago

TODO (IN PRIORITY ORDER)

HARD TODO LIST

NICE TO HAVE FEATURES FOR LATER

dpinney commented 10 years ago

Task list massively updated.

dpinney commented 10 years ago

Example cashflow curves for the 5 financing options: image

dpinney commented 10 years ago

AC clipping by the inverter example: image

cshjin commented 9 years ago

Remove all the fields in the image below.

How to set the value of those fields? Set as default values?

dpinney commented 9 years ago

Yes, set as the PVwatts default. It should be the same as what's currently shown in the GUI.

cshjin commented 9 years ago

Add a derating section to the input with all variables described in the wireframes document section "GOSED Wirefram for Performance Analysis".

Where is the GOSED wireframe fro performance analysis?

https://www.dropbox.com/s/49061mowkvzevul/3.%20GOSED%20Wireframes.docx?dl=0

Relevant part is the box labeled "Losses" with the variables "PV Module derate", etc.

Add an SREC cashflow. Input variable is a vector e.g. [10,10,10,10,5]. This becomes another cashflow on the cash flow chart.

What is SREC?

Solar Renewable Energy Credit. We just need to pass the input vector into the cash flow chart as a new series.

change heatmap z-axis unit to watts, and make it average over the given monthXhour bin.

What do you mean by changing it to watts? Just add watts there? And what the average processing? Is that the shading_mxh field?

We need to average instead of sum for each box on the heatmap. Adding a "Average kW" label to the legend would be good (nice-to-have).

Nameplate line disappears when system size is fractional. Change scaling to always include nameplate line.

Which nameplate you referrers to?

Not an issue. I can't reproduce the bug.

Can we send lat/lon as input to PVWatts? Right now we think the TMY2 file might be the only way to specify lat/lon.

Currently the answer is NO, there is no API for providing an alternative location besides weather file. But just as you mensioned , we can use zipcode, lat/lon location and TMY to find out the nearest location, or just as the latest version of pvwatts, we can provide a address interface. Efforts needed on that.

Let's create a new issue for this. David will log this.

Implement NPV and IRR.

Can you specify more about this?

NPV and IRR are functions that take cash flow vectors to scalars.

I've got an xls that calculates them: https://www.dropbox.com/s/lu3pkapm45o8tud/NPV%20of%20Solar%20Farm.xlsx?dl=0

Is the TMY3 data good? We need a python function that graphs the climate variables in a TMY3 or TMY2 file. And then we need to look at a bunch of them.

I know there is a software to convert TMY3 to TMY2.

I just mark them down, and we can discuss them through meeting.

David will log another issue for this.

dpinney commented 9 years ago

My comments added to the above questions.

cshjin commented 9 years ago

Solving the IRR costs too much, since the the equation has high power. Is there any simple approach to get it?

dpinney commented 9 years ago

What's the python code you're currently using to calculate the IRR?

Oh my god real math IVE BEEN WAITING FOR THIS DAY. :neckbeard:

cshjin commented 9 years ago

Solving a function like this:

    from sympy import Eq, Symbol, solve
    r = Symbol("r")
    eqn = Eq(sum([outData["netCashFlow"][i]/(1+r)**i for i in range(30)]), 0)
    res = solve(eqn)
dpinney commented 9 years ago

I bet we can find a power series solution that we can do without sympy.

dpinney commented 9 years ago

Give me a sec to do the algebra...

dpinney commented 9 years ago

I feel obliged to find the result using Newton-Raphson. (Lol.) Sorry about just doing it in Python, I don't remember enough Latex to make this pretty.

''' snippet to calclate IRR. '''
# An example set of cashflows:
flows = [-20,10,10,10,10]
# The equation we want to find the roots of.
f = lambda r:sum([C/(1+r)**(1+i) for i, C in enumerate(flows)])
# The NR equivalence says we can calculate: r_n+1 = r_n - f(r_n)/f'(r_n)
# And we can do some calculus to get f'(r):
dfdr = lambda r:sum([(-i-1)*C/(1+r)**(i+2) for i, C in enumerate(flows)])
# Our r_0 guess:
rn = 0.01
# Now converge!
for step in range(100):
    rn = rn - f(rn)/dfdr(rn)
print "IRR is", rn
# Test against what Excel comes up with:
excelIrr = 0.349034
print "We're off by ", 1-excelIrr/rn
cshjin commented 9 years ago

I knew Newton's method, what a genius you are. :+1:

dpinney commented 9 years ago

genius idiot.

numpy.irr

cshjin commented 9 years ago
  1. I updated the NPV and IRR using numpy.
  2. I still a bit confused about the SREC cashflow, how to integrate into the highcharts? I may misunderstand some terminologies.
  3. I already have the excel data export demo ready, check here: https://www.dropbox.com/s/05fbs2dil7a6w0n/Sample%20Output.xls?dl=0, there are four separate sheets there. One issue remains: currently there is no formula inside the excel file. I am using xlwt package to dump data. I will follow the example here: https://github.com/python-excel/xlwt/blob/master/xlwt/examples/formulas.py
    Also, the excel data export is optional to user, right? Does it go with the model running, or after running the model, then user choose to export data? What is the secure way to download a file from the server(amazon s3)?
dpinney commented 9 years ago

Thanks, this is great progress.

SRECs: We should do SRECs as simply as possible. The HTML interface should have an input box labeled "SREC Cashflow" that the user types in a string like "5,5,5,3,2".

Then when the model is run, we interpret this as:

#EXAMPLE FOR SOLARFINANCIAL.PY
outData["srecCashFlow"] = map(float,inputDict.get("srecCashflow","").split(","))
# This should now be true (but only for this example):
assert outData["srecCashFlow"] == [5.0,5.0,5.0,3.0,2.0]
# And then we need to make sure this new cashflow is in the net:
outData["netCashFlow"] = [roundSig(x+y+z+a,2) for (x,y,z,a) in zip(outData["lifeGenerationDollars"], outData["lifeOmCosts"], outData["lifePurchaseCosts", outData["srecCashFlow"]])]

So what we're doing is adding another cashflow that represents money the PV owner gets from SRECs. Cashflow means how many dollars the owner gains or loses each year. But we're not calculating it--we're letting the user specify it. This is because SREC income is too complicated for us to calculate right now.

Excel: We should create the xls in the model directory when the model is run. Then the user can download it via a button in the model interface.

To get the file to the user, don't use S3. There's a way to do this with flask. I think what's needed is the send_from_directory function. But it might be easier to do what the CVR model used to do, which is base64 encode the file and insert it directly into the HTML. That way solarFinancial.py doesn't need to have flask code in it, and we don't have to put special logic in web.py.

Don't worry about getting the equations into the Excel. We can work on that much later.

dpinney commented 9 years ago

Approach to serving static files from web.py:

@app.route("/downloadModelData/<owner>/<modelName>/<fileName>")
@flask_login.login_required
def downloadModelData(owner, modelName, fileName):
    send_from_directory("data/"+owner+"/"+modelName, fileName) 
    pass # return a correct redirect here.

The actual download link would look like:

<a href="/downloadModelData/{{owner}}...
dpinney commented 9 years ago

A few todos added. We're close to closing this.

dpinney commented 9 years ago

Last todos finished. Tooltips waiting on #277.