Skip to content

Commit

Permalink
Merge pull request #1584 from NREL/pysam_hybrids
Browse files Browse the repository at this point in the history
Pysam hybrids
  • Loading branch information
sjanzou committed Mar 6, 2024
2 parents 54b86fd + 4ea27ba commit 5f9f0e6
Show file tree
Hide file tree
Showing 752 changed files with 1,318,918 additions and 29,953 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,11 @@ jobs:
run: |
echo "GITHUB_REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER}" >> $GITHUB_ENV
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/lk.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "LK_BRANCH=patch" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "LK_BRANCH=develop" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/wex.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "WEX_BRANCH=patch" >> $GITHUB_ENV; else echo "WEX_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "WEX_BRANCH=develop" >> $GITHUB_ENV; else echo "WEX_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/ssc.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "SSC_BRANCH=patch" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "SSC_BRANCH=develop" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
- name: Install wxWidgets
run: |
Expand Down Expand Up @@ -211,11 +211,11 @@ jobs:
run: |
echo "GITHUB_REPOSITORY_OWNER=${GITHUB_REPOSITORY_OWNER}" >> $GITHUB_ENV
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/lk.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "LK_BRANCH=patch" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "LK_BRANCH=develop" >> $GITHUB_ENV; else echo "LK_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/wex.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "WEX_BRANCH=patch" >> $GITHUB_ENV; else echo "WEX_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "WEX_BRANCH=develop" >> $GITHUB_ENV; else echo "WEX_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
git ls-remote --heads --exit-code https://github.com/${GITHUB_REPOSITORY_OWNER}/ssc.git $GIT_BRANCH
if [[ $? != "0" ]]; then echo "SSC_BRANCH=patch" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
if [[ $? != "0" ]]; then echo "SSC_BRANCH=develop" >> $GITHUB_ENV; else echo "SSC_BRANCH=$GIT_BRANCH" >> $GITHUB_ENV; fi
- name: Install wxWidgets
run: |
Expand Down
36 changes: 30 additions & 6 deletions api/api_autogen/builder_C_API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


// C++17 only - not in patch branch
//#include <filesystem>
#include <wx/file.h>
#include <shared/lib_util.h>

#include "builder_C_API.h"
Expand All @@ -39,8 +40,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
void builder_C_API::create_SAM_headers(const std::string &cmod, const std::string &file_dir, bool stateful) {
std::string cmod_symbol = format_as_symbol(cmod);

if (cmod_symbol == "6parsolve")
cmod_symbol = "SixParsolve";
else if (cmod_symbol == "Tcsmslf")
cmod_symbol = "TcsMSLF";
else if (root->m_vardefs.find(cmod_symbol) != root->m_vardefs.end())
cmod_symbol += "Model";

std::string filename = file_dir + "/SAM_" + cmod_symbol + ".h";
// if (std::filesystem::exists(filename))
if (wxFileExists(filename))
return;

std::ofstream fx_file;
fx_file.open(file_dir + "/SAM_" + cmod_symbol + ".h");
fx_file.open(filename);
assert(fx_file.is_open());

fx_file << "#ifndef SAM_" << util::upper_case(cmod_symbol)<< "_H_\n"
Expand Down Expand Up @@ -193,8 +206,20 @@ void builder_C_API::create_SAM_headers(const std::string &cmod, const std::strin
void builder_C_API::create_SAM_definitions(const std::string &cmod, const std::string &file_dir, bool stateful) {
std::string cmod_symbol = format_as_symbol(cmod);

if (cmod_symbol == "6parsolve")
cmod_symbol = "SixParsolve";
else if (cmod_symbol == "Tcsmslf")
cmod_symbol = "TcsMSLF";
else if (root->m_vardefs.find(cmod_symbol) != root->m_vardefs.end())
cmod_symbol += "Model";

std::string filename = file_dir + "/SAM_" + cmod_symbol + ".cpp";
// if (std::filesystem::exists(filename))
if (wxFileExists(filename))
return;

std::ofstream fx_file;
fx_file.open(file_dir + "/SAM_" + cmod_symbol + ".cpp");
fx_file.open(filename);
assert(fx_file.is_open());

fx_file << "#include <string>\n"
Expand Down Expand Up @@ -228,6 +253,7 @@ void builder_C_API::create_SAM_definitions(const std::string &cmod, const std::s

if (mm->first == "AdjustmentFactors")
continue;


for (auto & vardef : vardefs) {
std::string var_symbol = vardef.first;
Expand Down Expand Up @@ -335,8 +361,6 @@ void builder_C_API::create_SAM_definitions(const std::string &cmod, const std::s
else{
throw std::runtime_error(vd.type + " for " + var_name);
}
fx_file << "\n\n";

}
}
fx_file.close();
Expand Down
75 changes: 66 additions & 9 deletions api/api_autogen/builder_PySAM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,19 +173,21 @@ void builder_PySAM::all_options_of_cmod(const std::string &cmod) {
void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::string &file_dir, bool stateful) {
std::string cmod_symbol = format_as_symbol(cmod);

std::string tech_symbol = cmod_symbol;
if (cmod_symbol == "6parsolve")
tech_symbol = "SixParsolve";
cmod_symbol = "SixParsolve";
else if (cmod_symbol == "Tcsmslf")
cmod_symbol = "TcsMSLF";
else if (root->m_vardefs.find(cmod_symbol) != root->m_vardefs.end())
tech_symbol += "Model";
cmod_symbol += "Model";
std::string tech_symbol = cmod_symbol;

std::ofstream fx_file;
fx_file.open(file_dir + "/modules/" + tech_symbol + ".c");
assert(fx_file.is_open());

fx_file << "#include <Python.h>\n"
"\n"
"#include <SAM_" << cmod_symbol << ".h>\n"
"#include <SAM_" << tech_symbol << ".h>\n"
"#include <SAM_api.h>\n"
"\n"
"#include \"PySAM_utils.h\"\n\n";
Expand Down Expand Up @@ -612,6 +614,30 @@ void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::strin

fx_file << "\tPyObject_Del(self);\n"
"}\n\n\n";
fx_file << "static PyObject *\n"
"" << tech_symbol << "_get_data_ptr(" << object_type << " *self, PyObject *args)\n"
"{\n\tPyObject* ptr = PyLong_FromVoidPtr((void*)self->data_ptr);\n"
"\treturn ptr;\n}\n\n\n";

fx_file << "static PyObject *\n"
"" << tech_symbol << "_set_data_ptr(" << object_type << " *self, PyObject *args)\n"
"{\n"
"\tlong long int ptr = 0; // 64 bit arch\n"
"\tif (!PyArg_ParseTuple(args, \"L:data_ptr\", &ptr)){\n"
"\t\tPyErr_BadArgument();\n"
"\t\treturn NULL;\n"
"\t}\n\tself->data_ptr = (void*)ptr;\n";

// modify the data ptr for all the groups
for (auto& i : root->vardefs_order) {
auto mm = root->m_vardefs.find(i);
if (mm->second.empty()) continue;
std::string module_symbol = format_as_symbol(mm->first);
fx_file << "\tVarGroupObject* " << module_symbol << "_obj = (VarGroupObject*)PyDict_GetItemString(self->x_attr, \"" << module_symbol << "\");\n"
"\t" << module_symbol << "_obj->data_ptr = (void*)ptr;\n";
}

fx_file << "\treturn Py_None;\n}\n\n\n";

if (stateful) {
fx_file << "static PyObject *\n"
Expand Down Expand Up @@ -693,6 +719,10 @@ void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::strin

fx_file << "\t\t{\"execute\", (PyCFunction)" << tech_symbol << "_execute, METH_VARARGS,\n"
"\t\t\t\tPyDoc_STR(\"execute(int verbosity) -> None\\n Execute simulation with verbosity level 0 (default) or 1\")},\n"
"\t\t{\"get_data_ptr\", (PyCFunction)" << tech_symbol << "_get_data_ptr, METH_VARARGS,\n"
"\t\t\t\tPyDoc_STR(\"get_data_ptr() -> Pointer\\n Get ssc_data_t pointer\")},\n"
"\t\t{\"set_data_ptr\", (PyCFunction)" << tech_symbol << "_set_data_ptr, METH_VARARGS,\n"
"\t\t\t\tPyDoc_STR(\"set_data_ptr(data_ptr)\\n Set ssc_data_t pointer\")},\n"
"\t\t{\"assign\", (PyCFunction)" << tech_symbol << "_assign, METH_VARARGS,\n"
"\t\t\t\tPyDoc_STR(\"assign(dict) -> None\\n Assign attributes from nested dictionary, except for Outputs\\n\\n"
"``nested_dict = { '" << root->vardefs_order[0] << "': { var: val, ...}, ...}``\")},\n"
Expand Down Expand Up @@ -1100,8 +1130,17 @@ void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::strin
fx_file << "-";
fx_file << "-\n\n";

fx_file << ".. autoclass:: PySAM." << tech_symbol << "." << tech_symbol << "." << module_symbol << "\n";
fx_file << "\t:members:\n\n";
if (module_symbol == "AdjustmentFactors") {
fx_file << ".. autoclass:: PySAM.AdjustmentFactors.AdjustmentFactors\n";
}
else {
fx_file << ".. autoclass:: PySAM." << tech_symbol << "." << tech_symbol << "." << module_symbol << "\n";
}
fx_file << "\t:members:\n";
if (module_symbol == "AdjustmentFactors") {
fx_file << "\t:noindex:\n";
}
fx_file << "\n";
}

fx_file.close();
Expand All @@ -1127,6 +1166,12 @@ void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::strin
"\tdef export(self):\n"
"\t\tpass\n"
"\n"
"\tdef get_data_ptr(self):\n"
"\t\tpass\n"
"\n"
"\tdef set_data_ptr(self, data_ptr):\n"
"\t\tpass\n"
"\n"
"\tdef __getattribute__(self, *args, **kwargs):\n"
"\t\tpass\n"
"\n"
Expand Down Expand Up @@ -1159,14 +1204,26 @@ void builder_PySAM::create_PySAM_files(const std::string &cmod, const std::strin
"\t\t\tpass\n"
"\t\n"
"\t\tconstant = float\n"
"\t\ten_hourly = float\n"
"\t\ten_periods = float\n"
"\t\ten_timeindex = float\n"
"\t\thourly = tuple\n"
"\t\tperiods = tuple\n"
"\t\timeindex = tuple\n"
"\t\tdc_constant = float\n"
"\t\tdc_en_hourly = float\n"
"\t\tdc_en_periods = float\n"
"\t\tdc_en_timeindex = float\n"
"\t\tdc_hourly = tuple\n"
"\t\tdc_periods = tuple\n"
"\t\thourly = tuple\n"
"\t\tperiods = tuple\n"
"\t\tdc_imeindex = tuple\n"
"\t\tsf_constant = float\n"
"\t\tsf_en_hourly = float\n"
"\t\tsf_en_periods = float\n"
"\t\tsf_en_timeindex = float\n"
"\t\tsf_hourly = tuple\n"
"\t\tsf_periods = tuple\n\n";
"\t\tsf_periods = tuple\n"
"\t\tsf_timeindex = tuple\n\n";
continue;
}

Expand Down
62 changes: 30 additions & 32 deletions api/api_autogen/builder_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <shared/lib_util.h>
#include <ssc/sscapi.h>
#include <ssc/ssc_equations.h>
#include <ssc/core.h>

#include "lk_env.h"
#include "lk_eval.h"
Expand All @@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "builder_C_API.h"
#include "builder_PySAM.h"


std::unordered_map<std::string, bool> SAM_completed_cmods;


Expand All @@ -80,8 +82,11 @@ builder_generator::builder_generator(config_extractor *ce){
for (size_t i = 0; i < cmods.size(); i++){
std::string cmod_name = cmods[i];
ssc_module_t p_mod = ssc_module_create(const_cast<char*>(cmod_name.c_str()));
ssc_module_objects.insert({cmod_name, p_mod});

if (config_name.find("Hybrid") != std::string::npos) {
ssc_module_hybridize(p_mod);
}
ssc_module_objects.insert({cmod_name, p_mod});
}
}

Expand Down Expand Up @@ -123,12 +128,18 @@ void builder_generator::select_ui_variables(std::string ui_name, std::map<std::s
void builder_generator::gather_variables_ssc(const std::string &cmod_name) {
ssc_module_t p_mod = ssc_module_create(const_cast<char*>(cmod_name.c_str()));

// hybrid technology compute modules have extra financial variables that need to be exported to defaults
if (active_config.find("Hybrid") != std::string::npos) {
ssc_module_hybridize(p_mod);
}

digraph* graph = nullptr;
if (SAM_config_to_variable_graph.find(active_config) != SAM_config_to_variable_graph.end())
graph = SAM_config_to_variable_graph[active_config];

int var_index = 0;
ssc_info_t mod_info = ssc_module_var_info(p_mod, var_index);
var_info* mod_info_cast = static_cast<var_info*>(mod_info);
std::map<std::string, var_def> adj_map;
std::map<std::string, var_def> outputs_map;
while (mod_info){
Expand Down Expand Up @@ -173,17 +184,6 @@ void builder_generator::gather_variables_ssc(const std::string &cmod_name) {
std::vector<std::string> ssctype_str = {"invalid", "string", "number", "array", "matrix", "table"};
vd.type_n = ssc_info_data_type(mod_info);
vd.type = ssctype_str[vd.type_n];
/*
if (vd.group == "Adjustment Factors") {
size_t pos = vd.name.find(':');
size_t pos2 = vd.name.find("adjust");
vd.name = vd.name.substr(0, pos2) + vd.name.substr(pos+1);
adj_map.insert({vd.name, vd});
++var_index;
mod_info = ssc_module_var_info(p_mod, var_index);
continue;
}
*/
int var_type = ssc_info_var_type(mod_info);

size_t pos = vd.name.find(':');
Expand Down Expand Up @@ -419,32 +419,31 @@ void builder_generator::export_variables_json(const std::string &cmod, const std

VarValue* vv = nullptr;

/* // if adjustment factors, the default values are stored in a table
if (module_name == "AdjustmentFactors"){
// if adjustment factors, the variables need to have the 'adjust_' prefix removed
if (module_symbol == "AdjustmentFactors"){
size_t pos = v.name.find('_');
std::string adj_type = "adjust";
if (pos != std::string::npos){
adj_type = v.name.substr(0, pos + 1) + adj_type;
}
vv = SAM_config_to_defaults[config_name][adj_type];
vv = SAM_config_to_defaults[config_name][v.name];
if (vv){
std::string name = v.name.substr(pos+1);
if (name == "hourly" && !(vv->Table().Get("en_hourly")->Boolean()))
continue;
if (name == "periods" && !(vv->Table().Get("en_periods")->Boolean()))
continue;
vv = vv->Table().Get(name);
var_symbol = v.name.substr(pos+1);
}
else
continue;
}
else
*/ vv = SAM_config_to_defaults[config_name][v.name];
else{
if (config_name.find("Hybrid") != std::string::npos){
VarValue* vt = SAM_config_to_defaults[config_name].Get(format_as_symbol(cmod));
if (!vt)
vt = SAM_config_to_defaults[config_name].Get("Hybrid");
vv = vt->Table()[v.name];
}
else{
vv = SAM_config_to_defaults[config_name][v.name];

// if it's a battery configuration, turn on battery by default
if ((cmod == "battery" && v.name == "en_batt") || (cmod == "battwatts" && v.name == "batt_simple_enable"))
vv->Set(1);
// if it's a battery configuration, turn on battery by default. Hybrid techs don't need this because cmod_hybrid does it
if ((cmod == "battery" && v.name == "en_batt") || (cmod == "battwatts" && v.name == "batt_simple_enable"))
vv->Set(1);
}
}

// vv can be null in the case of variables not available in UI
if (!vv && v.reqif != "*")
Expand All @@ -458,7 +457,6 @@ void builder_generator::export_variables_json(const std::string &cmod, const std
json << "\n\t\t\t\"" + format_as_variable(var_symbol) + "\": ";
json << ssc_value_to_json(v.type_n, vv);


first = false;
}
json << "\n\t\t}";
Expand Down
2 changes: 1 addition & 1 deletion api/api_autogen/builder_generator_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ std::string ssc_value_to_json(int ssc_type, VarValue* vv){
break;
case SSC_ARRAY:
json += "[";
if (vv){
if (vv && vv->Array().size()){
std::vector<double> vec = vv->Array();
for (size_t j = 0; j < vec.size(); j++){
if (vec[j] > std::numeric_limits<double>::max()){
Expand Down

0 comments on commit 5f9f0e6

Please sign in to comment.