<jupyter_start><jupyter_text>PySAM WorkshopOct 14, 2020dguittethttps://sam.nrel.gov/software-development-kit-sdk/pysam.html  How to Get Started64-bit Python 3.5-3.8 for Linux, Mac and WindowsPyPi: ```pip install nrel-pysam```Anaconda:```conda install -u nrel nrel-pysam```  Model InitializationEach technology and financial configuration is composed of unit modules. Module documentation is in [Modules](https://nrel-pysam.readthedocs.io/en/master/Models.html) or refer to [Module Index](https://nrel-pysam.readthedocs.io/en/master/py-modindex.html). Each module can be imported by:```import PySAM.```There are four ways to initialize a model:1. new2. default3. from_existing4. wrap<jupyter_code>import PySAM.Pvwattsv7 as pv
import PySAM.Utilityrate5 as ur<jupyter_output><empty_output><jupyter_text>NewCreates an instance with empty attributes.<jupyter_code>new_model = pv.new()
print(type(new_model))
new_model.export()<jupyter_output><class 'Pvwattsv7'><jupyter_text>DefaultThere is a lot of data needed to run a model. Entering that data with assignment statements in PySAM can be tedious. One way to get a full set of data is to load the default setup, which are the same as in SAM. A module's default values are unique for each SAM configuration type. Default config names are __case insensitive__. The list of options can be found on the module's PySAM doc page or as below:<jupyter_code># list configuration options
help(pv.default)
default_model = pv.default("FuelCellCommercial")
default_model.export()<jupyter_output><empty_output><jupyter_text>This is good if your situation is close to the default.Often, however, this is not the case. When your setup is significantly different than the default,you can enter the data using SAM, and save that data to a JSON file, which can then be loaded by PySAM.You can then modify and use the data in PySAM as needed. This is shown in [To import a case from the SAM GUI](https://nrel-pysam.readthedocs.io/en/master/Import.html) and was a subject of last year's webinar. from_existingWhen running more than one unit module in a sequence, data needs to get passed from one to the subsequent models. For example, a technology module's `analysis_period` and generation profile `gen`, are inputs to the utility rate calculator in order to calculate the `annual_energy_value`, the energy value in each year of the analysis period due to electricity bill savings.`from_existing` is used create a new model that shares the underlying data with an existing model. This new model can be created with default values if a default configuration name is provided, similar to ``default``.<jupyter_code>shared_model = ur.from_existing(default_model, "FuelCellCommercial")
print(default_model.Lifetime.analysis_period)
print(shared_model.Lifetime.analysis_period)
# change in analysis period reflected in both models
default_model.Lifetime.analysis_period = 20
print(default_model.Lifetime.analysis_period)
print(shared_model.Lifetime.analysis_period)<jupyter_output>20.0
20.0<jupyter_text>All variables and their values, including inputs and outputs (after model execution), are shared between models linked in this way. When the PV model below is executed, its outputs will automatically be available to the Utility rate model. __Order of execution matters.__Simulation data is passed between unit modules when the name of a unit module's output is the same as another unit module's input, such as `gen`. __The group names can be different.__<jupyter_code># gen doesn't exist yet because simulation hasn't been executed
default_model.Outputs.gen
# can't calculate utility rate value without a generation profile
shared_model.execute(0)
# execute PV then utility rate calculations
default_model.SolarResource.solar_resource_file = "/Users/dguittet/SAM Downloaded Weather Files/weather.csv"
default_model.execute(0)
print('gen\n', default_model.Outputs.gen[0:10])

shared_model.execute(0)
print('\nannual energy value\n', shared_model.Outputs.annual_energy_value)<jupyter_output>gen
 (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 6.7173768653239625, 38.093735096127304, 66.2151813729102, 92.32749042996079)

annual energy value
 (0.0, 19312.694638148252, 19705.1961197949, 20105.70948665682, 20514.39916479452, 20931.43297677669, 21356.982212359246, 21791.221700670074, 22234.329883910086, 22686.488892602734, 23147.88479144977, 23618.70751153189, 24098.476481945985, 24587.636684686244, 25086.767494430936, 25596.073343827808, 26115.41719989743, 26644.62172995456, 27184.591130222427, 27735.545629398508, 28297.70982604439)<jupyter_text>wrapCreates a model from a PySSC data structure. This allows compatibility with PySSC. This is used primarily during data import from SAM via JSON. This import feature was covered in the [2019 PySAM Webinar](https://sam.nrel.gov/software-development-kit-sdk/pysam.html) and is also shown in [To import a case from the SAM GUI](https://nrel-pysam.readthedocs.io/en/master/Import.html).<jupyter_code>import PySAM.PySSC as pyssc

ssc = pyssc.PySSC()
pv_dat = ssc.data_create()
ssc.data_set_number(pv_dat, b'analysis_period', 10)

wrap_model = pv.wrap(pv_dat)
wrap_model.export()<jupyter_output><empty_output><jupyter_text>Detailed PV-Battery - Commercial Owner Example<jupyter_code>import PySAM.Pvsamv1 as pvsam
import PySAM.Grid as grid
import PySAM.Utilityrate5 as ur
import PySAM.Cashloan as cl
import PySAM

print(PySAM.__version__)
# get all years of weather data
import glob
import random
import PySAM.ResourceTools as tools
from PySAM.BatteryTools import battery_model_sizing

weather_folder = "/Users/dguittet/SAM Downloaded Weather Files/lexington_or/"
weather_files = glob.glob(weather_folder + "/*.csv")

# load data from file into dictionaries
weather_data = [tools.TMY_CSV_to_solar_data(f) for f in weather_files]
steps_per_year = len(weather_data[0]['year'])
print(steps_per_year)

# initialize all models
pvbatt_model = pvsam.default("PVBatteryCommercial")
grid_model = grid.from_existing(pvbatt_model, "PVBatteryCommercial")
ur_model = ur.from_existing(pvbatt_model, "PVBatteryCommercial")
cl_model = cl.from_existing(pvbatt_model, "PVBatteryCommercial")

# change simulation settings
pvbatt_model.Lifetime.analysis_period = 1
pvbatt_model.value("batt_room_temperature_celsius", (25,) * steps_per_year)
pvbatt_model.BatteryDispatch.batt_dispatch_choice = 0  # peak shaving
def installed_cost(pv_kw, battery_kw, battery_kwh):
    return pv_kw * 700 + battery_kw * 600 + battery_kwh * 300

print("batt_kw\tbatt_kwh\tavg_npv")
for battery_kw in range(10, 100, 10):
    battery_kwh = 4 * battery_kw  # four hour battery
    battery_model_sizing(pvbatt_model, battery_kw, battery_kwh, 500)
    
    npvs = []
    for solar_resource_data in weather_data:
        
        pvbatt_model.SolarResource.solar_resource_data = solar_resource_data
        pvbatt_model.execute(0)
        
        grid_model.execute(0)
        
        ur_model.execute(0)
        
        cl_model.total_installed_cost = installed_cost(pvbatt_model.SystemDesign.system_capacity, battery_kw, battery_kwh)
        cl_model.execute(0)
        
        npvs.append(cl_model.Outputs.npv)
        
    avg_npv = sum(npvs) / len(npvs)
    print("{}\t{}\t{}".format(battery_kw, battery_kwh, avg_npv))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08343659644774887, 'fraction_numerical': 0.06595070907338565, 'mean_word_length': 5.555956678700361, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '288270', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2694, 'n_tokens_neox': 2317, 'n_words': 690, 'path': 'Examples/PySAMWorkshop.ipynb', 'repo_name': 'mike-welch/pysam', 'size': '7263'}