-
Notifications
You must be signed in to change notification settings - Fork 392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Round2 init state use #10662
base: develop
Are you sure you want to change the base?
Round2 init state use #10662
Conversation
@@ -653,6 +652,7 @@ namespace Curve { | |||
// initialize the array | |||
|
|||
int CurveNum = 0; // keep track of the current curve index in the main curve array | |||
state.dataCurveManager->UniqueCurveNames.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only change needed to allow curve manager getInput to be called more than once. It will likely not be called more than once but if it does it will give the same answer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably better to set a flag and make sure the body is not called twice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the outer getInput call does protect from the second call. If a unit test calls the root function multiple times it would need to give the same answer. I think I did this before removing init_state from the unit test fixture (last thing I did) so maybe I can fix this and not have to change any unit tests. I'll just move that flag down into GetCurveInputData.
if (state.dataCurveManager->GetCurvesInputFlag) {
GetCurveInput(state);
GetPressureSystemInput(state);
state.dataCurveManager->GetCurvesInputFlag = false;
}
void GetCurveInput(EnergyPlusData &state)
{
// wrapper for GetInput to allow unit testing when fatal inputs are detected - follow pattern from GetSetPointManagerInputs()
bool GetInputErrorsFound = false;
GetCurveInputData(state, GetInputErrorsFound);
state.dataCurveManager->GetCurvesInputFlag = false;
if (GetInputErrorsFound) {
ShowFatalError(state, "GetCurveInput: Errors found in getting Curve Objects. Preceding condition(s) cause termination.");
}
}
void GetCurveInputData(EnergyPlusData &state, bool &ErrorsFound)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a general practice in EnergyPlus of "protecting functions from bad inputs or bad calling contexts". This is actually counter-productive because it hides bad uses of the function. It's better programming to assert good inputs and good context (to the extent possible) within a function and then use those to progressively clean up the calling contexts.
this->dataFluidProps->init_state(state); // GetFluidPropertiesData | ||
this->dataPsychrometrics->init_state(state); // InitializePsychRoutines | ||
this->dataScheduleMgr->init_state(state); // ProcessScheduleInput - requires NumOfTimeStepInHour and AnyEnergyManagementSystemInModel | ||
this->dataCurveManager->init_state(state); // GetCurveInput, GetPressureSystemInput |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added schedules and curves to init_state
@@ -87,7 +87,7 @@ namespace EnergyPlus { | |||
TEST_F(EnergyPlusFixture, SetVSHPAirFlowTest_VSFurnaceFlowTest) | |||
{ | |||
|
|||
state->init_state(*state); | |||
state->init_state(*state); // get FluidProperties |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, why did I have to leave this here when FluidProperties is called in the fixture? Maybe this unit test needed something else now in init_state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's right. If the unit test does not have an idf snippet then process_idf will not be called and default fluids will not be set up yet. So this is correct.
@@ -6563,10 +6563,10 @@ TEST_F(EnergyPlusFixture, CO2ControlDesignOARateTest) | |||
" ** ~~~ ** This may be overriding desired ventilation controls. Check inputs for Minimum Outdoor Air Flow Rate, Minimum Outdoor Air " | |||
"Schedule Name and Controller:MechanicalVentilation", | |||
" ** ~~~ ** Minimum OA fraction = 2.9412E-003, Mech Vent OA fraction = 1.5603E-003", | |||
" ** ~~~ ** Environment=, at Simulation time= 00:00 - 00:00", | |||
" ** ~~~ ** Environment=, at Simulation time= 00:15 - 00:15", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that Timestep is processed in process_idf the time stamp is the first time step of the simulation. Before, NumTimeStepInHour = 0, now it is non-zero and Timestep defaults to 4.
@@ -2990,8 +2990,7 @@ namespace OutputProcessor { | |||
auto reportExtendedDataResults = queryResult("SELECT * FROM ReportExtendedData;", "ReportExtendedData"); | |||
|
|||
compare_eso_stream( | |||
delimited_string({"Program Version,", | |||
"1,11,Boiler1,Boiler NaturalGas Rate [W] !RunPeriod [Value,Min,Month,Day,Hour,Minute,Max,Month,Day,Hour,Minute]", | |||
delimited_string({"1,11,Boiler1,Boiler NaturalGas Rate [W] !RunPeriod [Value,Min,Month,Day,Hour,Minute,Max,Month,Day,Hour,Minute]", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all reversions of last effort changes.
@@ -112,6 +112,8 @@ TEST_F(EnergyPlusFixture, Test_PerformancePrecisionTradeoffs_DirectSolution_Mess | |||
|
|||
EXPECT_TRUE(process_idf(idf_objects, false)); | |||
|
|||
SimulationManager::GetProjectData(*state); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another revert, unit tests are now responsible for setting up the inputs. Either this way or calling init_state directly.
" ** Warning ** Output:Diagnostics: More than 1 occurrence of this object found, only first will be used.", | ||
}); | ||
EXPECT_TRUE(compare_err_stream(expectedError, true)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding back in what was here before last effort.
@@ -688,7 +688,6 @@ TEST_F(EnergyPlusFixture, ASHRAE_Tau2017ModelTest) | |||
|
|||
bool ErrorsFound(false); | |||
state->dataEnvrn->TotDesDays = 2; | |||
state->dataGlobal->NumOfTimeStepInHour = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NumOfTimeStepInHour is now 0 again because GetProjectData has not been called (i.e.,, I removed init_state from process_idf on this pass).
Unanticipated diff. The schedules are now read very early, so early that these 3 warnings are no longer included in the summary report.
|
Here's a thought at how to fix this.
|
I decided to just restore the error summary information since only a fraction of getInputs have been moved to init_state. |
@@ -610,6 +609,8 @@ namespace Curve { | |||
int IOStatus; // Used in GetObjectItem | |||
std::string CurrentModuleObject; // for ease in renaming. | |||
|
|||
if (!state.dataCurveManager->GetCurvesInputFlag) return; | |||
state.dataCurveManager->GetCurvesInputFlag = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😆 🤣 😄 This is excellent @rraustad !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow.
This diff in IndoorLivingWall is disturbing. There is in fact 1 curve in this input file that is unused. But "unused" here means it was never read in because there are no other objects in this example file that have a curve object name input and therefore the curves are never read in. In this branch, moving GetCurveInput to init_state means the curves are read in and there is no unused object message in the error file. More disturbing is that if any curve name was an object input then all curves would be read in, marked as used, and even if a dangling curve object was in the input file it would not show as an unused input object. This branch shows that a different method for determining an unused object is necessary. Debugging this I noticed that if an object is "read" using getObjectItem it is marked as used, when in fact my interpretation of "used" is if it is actually accessed by another object. If all object's getInput are moved to init_state then all objects will be marked as "used". Moving markObjectAsUsed from getObjectItem to getObjectIndex (e.g., GetFanIndex) might be one way to go (probably some effort needed to make sure all parent objects call for an index of child objects).
ScheduleManager uses the "actually accessed" method in GetScheduleIndex and accurately reports unused schedules:
and has it's own ReportOrphanedSchedule function:
|
MultiSpeedHeatPump_DirectSolution shows unused curve objects and that the PerformancePrecisionTradeoffs was processed during GetProjectData.
|
@@ -675,6 +675,7 @@ namespace Curve { | |||
CurrentModuleObject, | |||
state.dataIPShortCut->cAlphaFieldNames(1), | |||
ErrorsFound); | |||
state.dataInputProcessing->inputProcessor->unusedInputs.emplace(CurrentModuleObject, Alphas(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getObjectItem removes an object from the unusedInputs list just because it was read in. This change puts that curve back in the list and waits for a call to getCurveIndex before removing the curve from the unusedInputs list. This change was prompted by IndoorLivingWall not showing the unused curve warning in this branch. Now curves shown as unused are actually not used in the simulation (i.e., if I have 10 curves in the input and only use 1 then 9 curves are unused).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably change GetObjectItem
to not do this at some point.
state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsWarmup(NumWarningsDuringWarmup, NumSevereDuringWarmup); | ||
state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSizing(NumWarningsDuringSizing, NumSevereDuringSizing); | ||
state.dataResultsFramework->resultsFramework->SimulationInformation.setNumErrorsSummary(NumWarnings, NumSevere); | ||
|
||
ShowMessage( | ||
state, | ||
format("EnergyPlus Inputs Error Summary. During Inputs: {} Warning; {} Severe Errors.", NumWarningsDuringInputs, NumSevereDuringInputs)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not get the number of warning/severe errors to match what was reported previously so went ahead and added a summary for errors during getInput.
@@ -340,7 +340,8 @@ bool InputProcessor::checkVersionMatch(EnergyPlusData &state) | |||
Which = static_cast<int>(index(v, MatchVersion)); | |||
} | |||
if (Which != 0) { | |||
ShowWarningError(state, "Version: in IDF=\"" + v + "\" not the same as expected=\"" + MatchVersion + "\""); | |||
// this is reported in GetProjectData | |||
// ShowWarningError(state, "Version: in IDF=\"" + v + "\" not the same as expected=\"" + MatchVersion + "\""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am seeing duplicate messages so either the version issue is reported here or where the version object is read. I chose to comment this out here but maybe there is a reason to do the opposite (e.g., API calls).
** Warning ** Version: in IDF="24.1" not the same as expected="24.2"
** Warning ** Version: in IDF="24.1" not the same as expected="24.2"
@@ -610,6 +609,8 @@ namespace Curve { | |||
int IOStatus; // Used in GetObjectItem | |||
std::string CurrentModuleObject; // for ease in renaming. | |||
|
|||
if (!state.dataCurveManager->GetCurvesInputFlag) return; | |||
state.dataCurveManager->GetCurvesInputFlag = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow.
@@ -653,6 +652,7 @@ namespace Curve { | |||
// initialize the array | |||
|
|||
int CurveNum = 0; // keep track of the current curve index in the main curve array | |||
state.dataCurveManager->UniqueCurveNames.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a general practice in EnergyPlus of "protecting functions from bad inputs or bad calling contexts". This is actually counter-productive because it hides bad uses of the function. It's better programming to assert good inputs and good context (to the extent possible) within a function and then use those to progressively clean up the calling contexts.
@@ -675,6 +675,7 @@ namespace Curve { | |||
CurrentModuleObject, | |||
state.dataIPShortCut->cAlphaFieldNames(1), | |||
ErrorsFound); | |||
state.dataInputProcessing->inputProcessor->unusedInputs.emplace(CurrentModuleObject, Alphas(1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably change GetObjectItem
to not do this at some point.
@@ -824,6 +826,7 @@ namespace Curve { | |||
_, | |||
state.dataIPShortCut->cAlphaFieldNames, | |||
state.dataIPShortCut->cNumericFieldNames); | |||
state.dataInputProcessing->inputProcessor->unusedInputs.emplace(CurrentModuleObject, Alphas(1)); | |||
++CurveNum; | |||
GlobalNames::VerifyUniqueInterObjectName(state, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't have to be part of this PR, but look at how I am using std::map
to implement both VerifyUniqueObjectName
and GetObjectIndex
in one fast structure. There are examples in Fans
, OutputProcessor
and SetPointManager
.
@@ -207,6 +210,17 @@ namespace Curve { | |||
const Real64 Var4, // 4th independent variable | |||
const Real64 Var5, // 5th independent variable | |||
const Real64 Var6); | |||
|
|||
void markUsed(EnergyPlusData &state) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like this. Leave it for now but I'm going to look at how InputProcessor
is doing this.
@@ -548,6 +550,8 @@ int AbortEnergyPlus(EnergyPlusData &state) | |||
CloseMiscOpenFiles(state); | |||
NumWarnings = fmt::to_string(state.dataErrTracking->TotalWarningErrors); | |||
NumSevere = fmt::to_string(state.dataErrTracking->TotalSevereErrors); | |||
NumWarningsDuringInputs = fmt::to_string(state.dataErrTracking->TotalWarningErrorsDuringInputs); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracking numerical values using strings is just nutty. Why are we doing this? For results framework? There has to be a better way.
Given the timing, I am going to suggest we just push this until after release. No reason to rush this in. |
I agree. |
@rraustad @Myoldmopar it has been 28 days since this pull request was last updated. |
1 similar comment
@rraustad @Myoldmopar it has been 28 days since this pull request was last updated. |
Pull request overview
if (state.dataFluidProperties->GetInputFlag) call getFluidProperitesData
occurrences that I removed on the previous effort. I didn't do that here but it may be necessary for unit testing, not sure yet.NOTE: ENHANCEMENTS MUST FOLLOW A SUBMISSION PROCESS INCLUDING A FEATURE PROPOSAL AND DESIGN DOCUMENT PRIOR TO SUBMITTING CODE
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.