diff --git a/api/include/SAM_FresnelPhysical.h b/api/include/SAM_FresnelPhysical.h index 138c210bb..4d605754f 100644 --- a/api/include/SAM_FresnelPhysical.h +++ b/api/include/SAM_FresnelPhysical.h @@ -2655,6 +2655,8 @@ extern "C" SAM_EXPORT double* SAM_FresnelPhysical_Outputs_rec_thermal_eff_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_FresnelPhysical_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_FresnelPhysical_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err); SAM_EXPORT double* SAM_FresnelPhysical_Outputs_rh_aget(SAM_table ptr, int* length, SAM_error *err); diff --git a/api/include/SAM_FresnelPhysicalIph.h b/api/include/SAM_FresnelPhysicalIph.h index 073c78369..8f9dfd16a 100644 --- a/api/include/SAM_FresnelPhysicalIph.h +++ b/api/include/SAM_FresnelPhysicalIph.h @@ -2713,6 +2713,8 @@ extern "C" SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_rec_thermal_eff_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err); SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_rh_aget(SAM_table ptr, int* length, SAM_error *err); diff --git a/api/include/SAM_TroughPhysical.h b/api/include/SAM_TroughPhysical.h index 2b838746c..2aa4a5af2 100644 --- a/api/include/SAM_TroughPhysical.h +++ b/api/include/SAM_TroughPhysical.h @@ -3655,6 +3655,8 @@ extern "C" SAM_EXPORT double* SAM_TroughPhysical_Outputs_rec_op_mode_final_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_TroughPhysical_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_TroughPhysical_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err); SAM_EXPORT double SAM_TroughPhysical_Outputs_required_number_of_loops_for_SM1_nget(SAM_table ptr, SAM_error *err); diff --git a/api/include/SAM_TroughPhysicalIph.h b/api/include/SAM_TroughPhysicalIph.h index 9cbcaf7db..784742c23 100644 --- a/api/include/SAM_TroughPhysicalIph.h +++ b/api/include/SAM_TroughPhysicalIph.h @@ -3519,6 +3519,8 @@ extern "C" SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_qinc_costh_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err); + SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err); SAM_EXPORT double SAM_TroughPhysicalIph_Outputs_required_number_of_loops_for_SM1_nget(SAM_table ptr, SAM_error *err); diff --git a/api/modules/SAM_FresnelPhysical.cpp b/api/modules/SAM_FresnelPhysical.cpp index c06e4e326..be1c996ee 100644 --- a/api/modules/SAM_FresnelPhysical.cpp +++ b/api/modules/SAM_FresnelPhysical.cpp @@ -4953,6 +4953,16 @@ SAM_EXPORT double* SAM_FresnelPhysical_Outputs_rec_thermal_eff_aget(SAM_table pt return result; } +SAM_EXPORT double* SAM_FresnelPhysical_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err){ + double* result = nullptr; + translateExceptions(err, [&]{ + result = ssc_data_get_array(ptr, "rec_time_in_startup", length); + if (!result) + make_access_error("SAM_FresnelPhysical", "rec_time_in_startup"); + }); + return result; +} + SAM_EXPORT double* SAM_FresnelPhysical_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err){ double* result = nullptr; translateExceptions(err, [&]{ diff --git a/api/modules/SAM_FresnelPhysicalIph.cpp b/api/modules/SAM_FresnelPhysicalIph.cpp index 14dcda4be..7dfcab117 100644 --- a/api/modules/SAM_FresnelPhysicalIph.cpp +++ b/api/modules/SAM_FresnelPhysicalIph.cpp @@ -5077,6 +5077,16 @@ SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_rec_thermal_eff_aget(SAM_table return result; } +SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err){ + double* result = nullptr; + translateExceptions(err, [&]{ + result = ssc_data_get_array(ptr, "rec_time_in_startup", length); + if (!result) + make_access_error("SAM_FresnelPhysicalIph", "rec_time_in_startup"); + }); + return result; +} + SAM_EXPORT double* SAM_FresnelPhysicalIph_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err){ double* result = nullptr; translateExceptions(err, [&]{ diff --git a/api/modules/SAM_TroughPhysical.cpp b/api/modules/SAM_TroughPhysical.cpp index 7e75226da..e2988d782 100644 --- a/api/modules/SAM_TroughPhysical.cpp +++ b/api/modules/SAM_TroughPhysical.cpp @@ -6898,6 +6898,16 @@ SAM_EXPORT double* SAM_TroughPhysical_Outputs_rec_op_mode_final_aget(SAM_table p return result; } +SAM_EXPORT double* SAM_TroughPhysical_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err){ + double* result = nullptr; + translateExceptions(err, [&]{ + result = ssc_data_get_array(ptr, "rec_time_in_startup", length); + if (!result) + make_access_error("SAM_TroughPhysical", "rec_time_in_startup"); + }); + return result; +} + SAM_EXPORT double* SAM_TroughPhysical_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err){ double* result = nullptr; translateExceptions(err, [&]{ diff --git a/api/modules/SAM_TroughPhysicalIph.cpp b/api/modules/SAM_TroughPhysicalIph.cpp index a7effbe7b..f9eadb19c 100644 --- a/api/modules/SAM_TroughPhysicalIph.cpp +++ b/api/modules/SAM_TroughPhysicalIph.cpp @@ -6630,6 +6630,16 @@ SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_qinc_costh_aget(SAM_table ptr, return result; } +SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_rec_time_in_startup_aget(SAM_table ptr, int* length, SAM_error *err){ + double* result = nullptr; + translateExceptions(err, [&]{ + result = ssc_data_get_array(ptr, "rec_time_in_startup", length); + if (!result) + make_access_error("SAM_TroughPhysicalIph", "rec_time_in_startup"); + }); + return result; +} + SAM_EXPORT double* SAM_TroughPhysicalIph_Outputs_recirculating_aget(SAM_table ptr, int* length, SAM_error *err){ double* result = nullptr; translateExceptions(err, [&]{ diff --git a/src/casewin.cpp b/src/casewin.cpp index bba6634ce..7ec9f91eb 100644 --- a/src/casewin.cpp +++ b/src/casewin.cpp @@ -37,6 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include @@ -65,6 +66,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "macro.h" #include "../resource/graph.cpng" +#include "../resource/notes.cpng" + class CollapsePaneCtrl : public wxPanel { @@ -147,16 +150,11 @@ BEGIN_EVENT_TABLE( CaseWindow, wxSplitterWindow ) EVT_LISTBOX( ID_INPUTPAGELIST, CaseWindow::OnCommand ) EVT_DATAVIEW_SELECTION_CHANGED(ID_TechTree, CaseWindow::OnTree) EVT_DATAVIEW_ITEM_COLLAPSING(ID_TechTree, CaseWindow::OnTreeCollapsing) - -// EVT_DATAVIEW_ITEM_START_EDITING(ID_TechTree, CaseWindow::OnTreeActivated) -// EVT_DATAVIEW_ITEM_ACTIVATED(ID_TechTree, CaseWindow::OnTreeActivated) - //EVT_LISTBOX( ID_TechTree, CaseWindow::OnCommand) EVT_BUTTON( ID_EXCL_BUTTON, CaseWindow::OnCommand ) EVT_LISTBOX( ID_EXCL_RADIO, CaseWindow::OnCommand) EVT_CHECKBOX( ID_COLLAPSE, CaseWindow::OnCommand ) EVT_MENU_RANGE( ID_EXCL_OPTION, ID_EXCL_OPTION_MAX, CaseWindow::OnCommand ) EVT_LISTBOX( ID_EXCL_TABLIST, CaseWindow::OnCommand ) - EVT_NOTEBOOK_PAGE_CHANGED( ID_PAGES, CaseWindow::OnSubNotebookPageChanged ) EVT_NOTEBOOK_PAGE_CHANGED( ID_BASECASE_PAGES, CaseWindow::OnSubNotebookPageChanged ) END_EVENT_TABLE() @@ -177,7 +175,7 @@ CaseWindow::CaseWindow( wxWindow *parent, Case *c ) wxFont lafont(*wxNORMAL_FONT); lafont.SetWeight(wxFONTWEIGHT_BOLD); - m_pageNote = 0; + m_pageNote = new PageNote(this); // create page note before m_pageFlipper adds pages m_currentGroup = 0; // navigation menu objects @@ -297,8 +295,6 @@ CaseWindow::CaseWindow( wxWindow *parent, Case *c ) SetMinimumPaneSize( 50 ); SplitVertically( m_left_panel, m_pageFlipper, (int)(210*xScale) ); - m_pageNote = new PageNote( this ); - // load page note window geometry int nw_xrel, nw_yrel, nw_w, nw_h; double sf = wxGetScreenHDScale(); @@ -637,6 +633,8 @@ bool CaseWindow::GenerateReport( wxString pdffile, wxString templfile, VarValue void CaseWindow::OnTree(wxDataViewEvent &evt) { + UpdateNotesIcon(); // when leaving a page and notes erased + m_pageFlipper->SetSelection(0); wxDataViewItem dvi = evt.GetItem(); if (!dvi.IsOk()) @@ -660,10 +658,30 @@ void CaseWindow::OnTree(wxDataViewEvent &evt) else { m_currentSelection = evt.GetItem(); } + + /* + if (HasPageNote(GetCurrentContext())) { + m_navigationMenu->SetItemIcon(m_currentSelection, wxBitmapBundle::FromBitmap(wxBITMAP_PNG_FROM_DATA(notes))); + //m_navigationMenu->im // TODO set images and override onImagesChanged method to show notes icon + m_navigationMenu->Refresh(); + } + // update all navigation items note icon + m_navigationMenu->get + auto bmb = wxBitmapBundle::FromBitmap(wxBITMAP_PNG_FROM_DATA(notes)); + for (size_t i = 0; i < m_pageGroups.size(); i++) + if (HasPageNote(m_pageGroups[i]->HelpContext) + m_currentGroup = m_pageGroups[i]; + + */ + + wxString title = m_navigationMenu->GetItemText(m_currentSelection); m_navigationMenu->SetFocus(); SwitchToInputPage(title); + m_left_panel->Layout(); // Issue 1552 +// wxVariant x = wxDataViewIconText("text", wxBitmapBundle::FromBitmap(wxBITMAP_PNG_FROM_DATA(notes))); +// m_navigationMenu->SetItemData(m_currentSelection,(wxClientData*) & x); } void CaseWindow::OnTreeCollapsing(wxDataViewEvent& evt) @@ -1076,7 +1094,7 @@ bool CaseWindow::SwitchToInputPage( const wxString &name ) wxBusyCursor wait; // m_inputPagePanel->Freeze(); - //DetachCurrentInputPage(); +// DetachCurrentInputPage(); m_currentGroup = 0; for( size_t i=0;iGetStringSelection() != name ) int p = m_inputPageList->Find(name); m_inputPageList->Select( p ); + m_inputPageList->Refresh(); + m_left_panel->Layout();// try to force onPaint call for the input page list return true; } @@ -1469,7 +1489,7 @@ void CaseWindow::UpdateConfiguration() if (cfg->TechnologyFullName.Contains("Generic")) return; //if generic get out of the loop wxDataViewItem dvi = m_navigationMenu->GetNthChild(wxDataViewItem(0), 0); - if (m_navigationMenu->IsContainer(dvi)) { + if (dvi.IsOk() && m_navigationMenu->IsContainer(dvi)) { dvi = m_navigationMenu->GetNthChild(dvi, 0); } @@ -1479,7 +1499,7 @@ void CaseWindow::UpdateConfiguration() } // check for orphaned notes and if any found add to first page per Github issue 796 - CheckAndUpdateNotes(inputPageHelpContext); +// CheckAndUpdateNotes(inputPageHelpContext); m_szsims->Clear(true); if (m_case->GetTechnology().Contains("wave") || m_case->GetTechnology().Contains("tidal")) { @@ -1577,12 +1597,56 @@ void CaseWindow::UpdatePageNote() // update ID m_lastPageNoteId = GetCurrentContext(); - // update text on page note + // update text on page note wxString text = m_case->RetrieveNote( m_lastPageNoteId ); m_pageNote->SetText(text); - m_pageNote->Show( SamApp::Window()->GetCurrentCaseWindow() == this && !text.IsEmpty() ); + + bool bShowNote = SamApp::Window()->GetCurrentCaseWindow() == this && !text.IsEmpty(); + + m_pageNote->Show( bShowNote ); + + UpdateNotesIcon(); } +void CaseWindow::UpdateNotesIcon() +{ + wxDataViewModel* model = m_navigationMenu->GetModel(); + if (!model) + return; + + // Get the invisible root item + wxDataViewItem root = model->GetParent(wxDataViewItem(nullptr)); + + // Start iteration (depth-first traversal shown) + UpdateNotesIconChildren(model, root); +} + +void CaseWindow::UpdateNotesIconChildren(wxDataViewModel* model, const wxDataViewItem& parent) +{ + wxDataViewItemArray children; + model->GetChildren(parent, children); + for (const wxDataViewItem& child : children) { + // Check if the child item has a note + bool bShowNote = false; + for (auto pg : m_pageGroups) { + if (pg->SideBarLabel == m_navigationMenu->GetItemText(child)) + bShowNote = HasPageNote(pg->HelpContext); + } + + if (bShowNote) { + m_navigationMenu->SetItemIcon(child, wxBitmapBundle::FromBitmap(wxBITMAP_PNG_FROM_DATA(notes))); + } + else { + m_navigationMenu->SetItemIcon(child, wxNullBitmap); + } + // Recursively check its children if it's a container + if (model->IsContainer(child)) { + UpdateNotesIconChildren(model, child); + } + } +} + + void CaseWindow::ShowPageNote() { m_pageNote->Show(); @@ -1600,7 +1664,7 @@ bool CaseWindow::HasPageNote(const wxString &id) return !id.IsEmpty() && !m_case->RetrieveNote(id).IsEmpty(); } -void CaseWindow::OnSubNotebookPageChanged( wxNotebookEvent & ) +void CaseWindow::OnSubNotebookPageChanged( wxNotebookEvent &evt ) { // common event handler for notebook page events to update the page note UpdatePageNote(); diff --git a/src/casewin.h b/src/casewin.h index cb9b90375..19559750b 100644 --- a/src/casewin.h +++ b/src/casewin.h @@ -87,6 +87,9 @@ class CaseWindow : public wxSplitterWindow, CaseEventListener wxString GetCurrentContext(); void UpdatePageNote(); + void UpdateNotesIcon(); + void UpdateNotesIconChildren(wxDataViewModel* model, const wxDataViewItem& parent); + //void IterateChildren(wxDataViewCtrl* myDVC, wxDataViewModel* model, const wxDataViewItem& parent) void CheckAndUpdateNotes(const wxArrayString& inputPageHelpContext); bool HasPageNote( const wxString &id ); void ShowPageNote( ); @@ -175,7 +178,6 @@ class CaseWindow : public wxSplitterWindow, CaseEventListener virtual void OnCaseEvent( Case *, CaseEvent & ); void OnSubNotebookPageChanged( wxNotebookEvent &evt ); - DECLARE_EVENT_TABLE(); }; diff --git a/src/ipagelist.cpp b/src/ipagelist.cpp index 6449aef7f..8920342b7 100644 --- a/src/ipagelist.cpp +++ b/src/ipagelist.cpp @@ -68,7 +68,7 @@ static wxColour SelectColour(204,204,204); static wxColour BackColour(243,243,243); InputPageList::InputPageList(wxWindow *parent, int id, const wxPoint &pos, const wxSize &size) - : wxScrolledWindow(parent,id, pos, size, wxBORDER_NONE) + : wxScrolledWindow(parent,id, pos, size, wxBORDER_NONE | wxFULL_REPAINT_ON_RESIZE) { SetBackgroundStyle(wxBG_STYLE_CUSTOM); SetBackgroundColour( BackColour ); @@ -273,8 +273,8 @@ void InputPageList::OnPaint(wxPaintEvent &) dc.SetBackground( wxBrush( GetBackgroundColour() ) ); - if (g_notesBitmap.IsOk() && m_caseWin - && m_caseWin->HasPageNote( m_items[i].resource ) ) +// if (g_notesBitmap.IsOk() && m_caseWin +// && m_caseWin->HasPageNote( m_items[i].resource ) ) { // int tx_w = dc.GetTextExtent( m_items[i].name ).GetWidth(); dc.DrawBitmap(g_notesBitmap, diff --git a/src/main.cpp b/src/main.cpp index 8ab8a0f8d..902364d9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -478,6 +478,8 @@ bool MainWindow::CreateNewCase( const wxString &_name, wxString tech, wxString f c->LoadDefaults(); m_project.AddCase(GetUniqueCaseName(_name), c); CreateCaseWindow( c ); + UpdateAllPageNotes(); + return true; } @@ -533,6 +535,11 @@ void MainWindow::DeleteCaseWindow( Case *c ) m_caseNotebook->DeletePage( m_caseNotebook->FindPage( cw ) ); m_caseTabList->Remove( m_project.GetCaseName( c ) ); m_caseTabList->Refresh(); + + if (m_caseTabList->Count() > 0) { + wxString case_name = m_caseTabList->GetLabel(0); + SwitchToCaseWindow(case_name); + } } extern void ShowIDEWindow(); @@ -1240,17 +1247,22 @@ bool MainWindow::SwitchToCaseWindow( const wxString &case_name ) } } - // update all the page notes so they get - // hidden/shown appropriately - for( size_t i=0;iGetPageCount();i++ ) - if ( CaseWindow *cw = dynamic_cast( m_caseNotebook->GetPage(i) ) ) - cw->UpdatePageNote(); + UpdateAllPageNotes(); return true; } else return false; } +void MainWindow::UpdateAllPageNotes() +{ + // update all the page notes so they get + // hidden/shown appropriately + for (size_t i = 0; iGetPageCount(); i++) + if (CaseWindow* cw = dynamic_cast(m_caseNotebook->GetPage(i))) + cw->UpdatePageNote(); +} + void MainWindow::OnCaseTabChange( wxCommandEvent &evt ) { int sel = evt.GetSelection(); diff --git a/src/main.h b/src/main.h index 7a21bb59c..df7e0967c 100644 --- a/src/main.h +++ b/src/main.h @@ -102,6 +102,8 @@ class MainWindow : public wxFrame void DeleteCaseWindow( Case *c ); bool SwitchToCaseWindow( const wxString &name ); + void UpdateAllPageNotes(); + bool LoadProject( const wxString &file ); bool SaveProject( const wxString &file ); diff --git a/test_results_win64.csv b/test_results_win64.csv index b28778021..6f7a71d5c 100644 --- a/test_results_win64.csv +++ b/test_results_win64.csv @@ -60,7 +60,7 @@ Standalone Battery,Merchant Plant,-6.8282e+06,28.139,NA,; Warning: IRR at end of Standalone Battery,Leveraged Partnership Flip,-6.8282e+06,75.8238,72.8932,; Warning: IRR at end of analysis period is not a number (NaN). This can indicate that revenues are too low to cover costs, or that they are excessively high compared to costs. Warning: IRR in target year is not a number (NaN). This can indicate that revenues are too low to cover costs, or that they are excessively high compared to costs. Warning: NPV is $-1.51094e+07. A negative NPV indicates project costs are higher than revenues. Standalone Battery,All Equity Partnership Flip,-6.8282e+06,80.0715,72.8932,; Warning: IRR at end of analysis period is not a number (NaN). This can indicate that revenues are too low to cover costs, or that they are excessively high compared to costs. Warning: IRR in target year is not a number (NaN). This can indicate that revenues are too low to cover costs, or that they are excessively high compared to costs. Warning: NPV is $-3.88136e+07. A negative NPV indicates project costs are higher than revenues. Standalone Battery,Sale Leaseback,-6.8282e+06,76.249,72.8932,; Warning: IRR at end of analysis period is not a number (NaN). This can indicate that revenues are too low to cover costs, or that they are excessively high compared to costs. Warning: NPV is $-1.98418e+07. A negative NPV indicates project costs are higher than revenues. Warning: NPV is $-8.19532e+07. A negative NPV indicates project costs are higher than revenues. -ETES,Single Owner,-466572896,15.0793,7.40746,; +ETES,Single Owner,-466572416,15.0793,7.40746,; PTES,Single Owner,-197595520,19.0302,10.3676,; Physical Trough,Single Owner,377430080,14.7263,14.5131,; Physical Trough,Merchant Plant,377430080,13.3388,NA,; @@ -105,9 +105,9 @@ Generic CSP System,All Equity Partnership Flip,592360448,12.8552,11.2639,; Warni Generic CSP System,Sale Leaseback,592360448,13.0371,11.2639,; Warning: NPV is $-1.04309e+08. A negative NPV indicates project costs are higher than revenues. Notice: time 0.00 { Generic solar model 2 }:\ The interpolation code must be 1 (interpolate) or 2 (nearest neighbor)The input value was 0, so it was reset to 1 Generic CSP System,LCOE Calculator,592360448,NA,NA,; Notice: time 0.00 { Generic solar model 2 }:\ The interpolation code must be 1 (interpolate) or 2 (nearest neighbor)The input value was 0, so it was reset to 1 Generic CSP System,None,592360448,NA,NA,; Notice: time 0.00 { Generic solar model 2 }:\ The interpolation code must be 1 (interpolate) or 2 (nearest neighbor)The input value was 0, so it was reset to 1 -MSPT IPH,None,1497517184,NA,NA,; -MSPT IPH,LCOH Calculator,1497517184,NA,NA,; -MSPT IPH,Single Owner,1550383232,6.2643,6.83681,; Notice: At time = 6087 CR_ON__PC_RM_HI__TES_FULL__AUX_OFF converged to a power cycle thermal input 278.765 [MWt] less than the target 279.126 [MWt]. +MSPT IPH,None,1497516928,NA,NA,; +MSPT IPH,LCOH Calculator,1497516928,NA,NA,; +MSPT IPH,Single Owner,1550383104,6.2643,6.83681,; Notice: At time = 6087 CR_ON__PC_RM_HI__TES_FULL__AUX_OFF converged to a power cycle thermal input 278.765 [MWt] less than the target 279.126 [MWt]. Physical Trough IPH,None,20907466,NA,NA,; Physical Trough IPH,LCOH Calculator,20907466,NA,NA,; Physical Trough IPH,Single Owner,20907466,7.5501,7.02159,;