diff --git a/docs/Module/Powerflow/Global/Solver_profile_csv.md b/docs/Module/Powerflow/Global/Solver_profile_csv.md new file mode 100644 index 000000000..7808fe2a9 --- /dev/null +++ b/docs/Module/Powerflow/Global/Solver_profile_csv.md @@ -0,0 +1,23 @@ +[[/Module/Powerflow/Global/Solver_profile_csv]] -- Enable CSV formatting of solver profile data + +# Synopsis + +Shell: + +~~~ +bash$ gridlabd -D|--define solver_profile_csv={TRUE,FALSE} +~~~ + +GLM: + +~~~ + #set solver_profile_csv={TRUE,FALSE} +~~~ + +# Description + +This global enables formatting of solver output as CSV. + +# See also + +* [[/Module/Powerflow]] diff --git a/module/powerflow/init.cpp b/module/powerflow/init.cpp index a4206ac20..106305ac6 100644 --- a/module/powerflow/init.cpp +++ b/module/powerflow/init.cpp @@ -74,6 +74,8 @@ EXPORT CLASS *init(CALLBACKS *fntable, MODULE *module, int argc, char *argv[]) gl_global_create("powerflow::solver_profile_headers_included", PT_bool, &solver_profile_headers_included,PT_DESCRIPTION, "Flag to include headers in NR solver profile file",NULL); extern char1024 solver_headers; gl_global_create("powerflow::solver_headers", PT_char1024, &solver_headers,PT_DESCRIPTION, "Headers in NR solver profile file",NULL); + extern bool solver_profile_csv; + gl_global_create("powerflow::solver_profile_csv", PT_bool, &solver_profile_csv,PT_DESCRIPTION, "Flag output solver profile in CSV format",NULL); extern char1024 solver_py_config; gl_global_create("powerflow::solver_py_config", PT_char1024, &solver_py_config, PT_DESCRIPTION, "PY solver configuration file location",NULL); diff --git a/module/powerflow/solver_nr.cpp b/module/powerflow/solver_nr.cpp index 17b7cd36d..003e8f18d 100644 --- a/module/powerflow/solver_nr.cpp +++ b/module/powerflow/solver_nr.cpp @@ -52,12 +52,13 @@ using namespace std; #include #include -char1024 solver_profile_filename = "solver_nr_profile.csv"; -char1024 solver_headers = "timestamp,duration[microsec],iteration,bus_count,branch_count,error"; +char1024 solver_profile_filename = "solver_nr_profile.txt"; static FILE * nr_profile = NULL; +char1024 solver_headers = "timestamp,duration[microsec],iteration,bus_count,branch_count,error"; bool solver_profile_headers_included = true; bool solver_profile_enable = false; bool solver_dump_enable = false; +bool solver_profile_csv = false; //SuperLU variable structure //These are the working variables, but structured for island implementation @@ -71,8 +72,8 @@ typedef struct { //Initialize the sparse notation void sparse_init(SPARSE* sm, int nels, int ncols) { - if (solver_profile_enable) - { + if ( solver_profile_enable ) + { nr_profile = fopen(solver_profile_filename,"w"); if ( nr_profile == NULL ) { @@ -83,7 +84,16 @@ void sparse_init(SPARSE* sm, int nels, int ncols) } else if ( solver_profile_headers_included ) { - fprintf(nr_profile,"%s\n",(const char*)solver_headers); + if ( solver_profile_csv ) + { + + fprintf(nr_profile,"%s\n",(const char*)solver_headers); + } + else + { + fprintf(nr_profile,"timestamp duration[microsec] iteration bus_count branch_count error\n"); + fprintf(nr_profile,"----------------------- ------------------ --------- --------- ------------ -----\n"); + } } } int indexval; @@ -335,10 +345,11 @@ int64 solver_nr(unsigned int bus_count, if ( solver_python_init() == 0 ) { Iteration = solver_python_solve(bus_count,bus,branch_count,branch,powerflow_values,powerflow_type,mesh_imped_vals,bad_computations,Iteration); - if ( Iteration >= 0 ) + if ( Iteration == 0 ) { return Iteration; } + // else <0 proceed with NR solver } } catch (const char *msg) @@ -5027,7 +5038,7 @@ int64 solver_nr(unsigned int bus_count, } //Default else - it was a failure, just keep going } - Iteration = return_value_for_solver_NR; + Iteration = return_value_for_solver_NR+1; //Deflag the "island locker" NR_solver_working = false; @@ -5064,7 +5075,16 @@ int64 solver_nr(unsigned int bus_count, double t = clock() - t_start; char buffer[64]; if ( gl_printtime(gl_globalclock,buffer,sizeof(buffer)-1) > 0 ) - fprintf(nr_profile, "%s,%.1f,%.1lld,%d,%d,%s\n", buffer, t, return_value_for_solver_NR == 0 ? 1 : return_value_for_solver_NR,bus_count,branch_count,bad_computations ? "false" : "true"); + { + if ( solver_profile_csv ) + { + fprintf(nr_profile, "%s,%.1f,%.1lld,%d,%d,%d\n", buffer, t, Iteration,bus_count,branch_count,bad_computations ? 0 : 1); + } + else + { + fprintf(nr_profile, "%s %18.1f %9lld %9d %12d %s\n", buffer, t, Iteration,bus_count,branch_count,bad_computations ? "no" : "yes"); + } + } } //Return the maximum iteration count diff --git a/module/powerflow/solver_py.cpp b/module/powerflow/solver_py.cpp index 58d4f1c1d..a98325eeb 100644 --- a/module/powerflow/solver_py.cpp +++ b/module/powerflow/solver_py.cpp @@ -962,11 +962,11 @@ void sync_busdata_raw(PyObject *pModel,unsigned int &bus_count,BUSDATA *&bus,e_d SET_BUS(n,17,bus[n].I[2].i); SET_BUS(n,18,bus[n].V[0].Mag()); - SET_BUS(n,19,bus[n].V[0].Ang()); + SET_BUS(n,19,bus[n].V[0].Arg()); SET_BUS(n,20,bus[n].V[1].Mag()); - SET_BUS(n,21,bus[n].V[1].Ang()); + SET_BUS(n,21,bus[n].V[1].Arg()); SET_BUS(n,22,bus[n].V[2].Mag()); - SET_BUS(n,23,bus[n].V[2].Ang()); + SET_BUS(n,23,bus[n].V[2].Arg()); } } else if ( dir == ED_IN ) @@ -1165,6 +1165,13 @@ unsigned long long get_linkhash(unsigned int branch_count, BRANCHDATA *&branch, return hashcode; } +// Run python solver +// +// Returns: +// -1 call NR and initialize with guess +// 0 use guess and proceed without running NR +// <-1 error encountered, run NR and don't use the guess +// int solver_python_solve ( unsigned int &bus_count, BUSDATA *&bus, @@ -1192,7 +1199,7 @@ int solver_python_solve ( else if ( pResult && PyLong_Check(pResult) ) { result = PyLong_AsLong(pResult); - if ( result >= 0 ) + if ( result == -1 || result == 0 ) // -1 means no solution but guess is ok, 0 means solution is ok { sync_model(bus_count,bus,branch_count,branch,ED_IN); } diff --git a/source/cmdarg.cpp b/source/cmdarg.cpp index b83317744..07aa5d58f 100644 --- a/source/cmdarg.cpp +++ b/source/cmdarg.cpp @@ -378,15 +378,15 @@ int GldCmdarg::profile(int argc, const char *argv[]) const char *opt = strchr(argv[0],'='); if ( opt++ != NULL ) { - if ( strcmp(opt,"text") == 0 ) + if ( stricmp(opt,"text") == 0 || stricmp(opt,"txt") == 0 ) { global_profile_output_format = POF_TEXT; } - else if ( strcmp(opt,"csv") == 0 ) + else if ( stricmp(opt,"csv") == 0 ) { global_profile_output_format = POF_CSV; } - else if ( strcmp(opt,"json") == 0 ) + else if ( stricmp(opt,"json") == 0 ) { global_profile_output_format = POF_JSON; } @@ -395,8 +395,12 @@ int GldCmdarg::profile(int argc, const char *argv[]) output_error("profiler option '%s' is not valid",opt); return CMDERR; } + global_profiler = TRUE; + } + else + { + global_profiler = !global_profiler; } - global_profiler = !global_profiler; return 0; }