Skip to content
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

Model DOAS Supplying Air to Inlets of Multiple AHUs #7230

Merged
merged 16 commits into from
Aug 19, 2019

Conversation

lgu1234
Copy link
Contributor

@lgu1234 lgu1234 commented Mar 18, 2019

Pull request overview

This new feature will allow EnergyPlus to model an outside air system supplying ventilation air to multiple air handlers.

Work Checklist

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • At least one of the following appropriate labels must be added to this PR to be consumed into the changelog:
    • Defect: This pull request repairs a github defect issue. The github issue should be referenced in the PR description
    • Refactoring: This pull request includes code changes that don't change the functionality of the program, just perform refactoring
    • NewFeature: This pull request includes code to add a new feature to EnergyPlus
    • Performance: This pull request includes code changes that are directed at improving the runtime performance of EnergyPlus
    • DoNoPublish: This pull request includes changes that shouldn't be included in the changelog

Review Checklist

This will not be exhaustively relevant to every PR.

  • Functional code review (it has to work!)
  • If defect, results of running current develop vs this branch should exhibit the fix
  • CI status: all green or justified
  • Performance: CI Linux results include performance check
  • Unit Test(s)
  • C++ checks:
    • Argument types
    • If any virtual classes, ensure virtual destructor included, other things
  • IDD changes:
    • Verify naming conventions and styles, memos and notes and defaults
    • Open windows IDF Editor with modified IDD to check for errors
    • If transition, add to input rules file for interfaces
    • If transition, add transition source
    • If transition, update idfs
  • If new idf included, locally check the err file and other outputs
  • Required documentation updates?
  • ExpandObjects changes?
  • If output changes, including tabular output structure, add to output rules file for interfaces


####New objects

The proposed new objects are AirLoopHVAC:DedicatedOutdoorAirSystem, AirLoopHVAC:DedicatedOutdoorAirSystem:Mixer, and AirLoopHVAC:DedicatedOutdoorAirSystem:Splitter.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zone equipment already allow DOAS connected to inlets. It would be better for GUIs if the same object was used to connect to air loop equipment. The object is AirTerminal:SingleDuct:Mixer/Splitter. There are existing functions that calculate the mixing and other functions used for component sizing. The functions are in SingleDuct.cc and at the bottom of ReportSizingManager. The existing functions in SingleDuct.cc could be used by all equipment models. Also, we already have AirloopHVAC that can act as DOAS and don't need another dedicated object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rraustad Thanks for your comment with quick feedback. The proposed new feature will have a central DOAS to serve multiple AirLoops. The name of AirTerminal:* may not be appropriated. I think any names with AirLoop are better. That is what is proposed. In addition, the proposed feature is a high level management to provide enough inputs to map required configurations. The detailed calculations will use existing functions. For example, any OA calculations will call existing OA controllers.

The proposed object is similar with the AirLoop object with two main differences. The first difference is that the proposed object requires two nodes: inlet and outlet only, while the AirLoopHVAC object requires two pairs of node based supply and demand sides. In addition, the proposed object requires more inputs, such as setpoint manager, AirLoopHVAC:DedicatedOutdoorAirSystem:Mixer, and AirLoopHVAC:DedicatedOutdoorAirSystem:Splitter.

The second difference is that AirLoopHVAC is used to serve multiple zones, while the proposed object is used to serve multiple AirLoops. Since difference purposes are specified, it should use different names to specify how to use these objects properly. In addition, we have issues with zone mass balance in an AirLoopHVAC. The proposed object deals with multiple AirLoops only and there is no potential mass balance issue. That is why I propose a new object name for a central DOAS system.

@mjwitte mjwitte added this to the EnergyPlus Future milestone Mar 18, 2019
@Myoldmopar
Copy link
Member

I was reviewing this offline while flying, so my apologies that these notes are not more integrated with the changes themselves. I can refine if needed:

  • I like the current state of objects and connections
  • My biggest concern when tying together systems that are not currently "coupled" is the flow imbalance, and it looks like that has been rigored over by Rich and Brent, and the design looks satisfactory
  • "Hope no iteration is needed" seems optimistic - it would be nice to have some commentary about possible solutions if it starts to be problematic
  • AirLoopHVAC:Mixer and Splitter objects - extensible comment with (Change numbering, please) is not quite right - remember users cannot modify the IDD and have it make an impact now

@lgu1234
Copy link
Contributor Author

lgu1234 commented Apr 3, 2019

@Myoldmopar Here are my answers to your concerns.

  1. "Hope no iteration is needed" seems optimistic
    As mentioned in the NFP, a possible call will be at the end of SolveAirLoopControllers in the SimAirServingZones module after AirLoopHVAC is looped to get OA flows from all OutdoorAir:Mixers. After OA is pre-treated from the proposed new feature, I expect to iterate 2 - 3 times among all served AirLoopHVAC and the proposed new feature until air properties of the inlet nodes from all OutdoorAir:Mixers are the same as ones after pre-treated air from the proposed new feature.

If successful, I will try to eliminate iteration to see what happens. If working, hope no iteration (this is what I mean). If not, use iteration approach already implemented in the beginning.

  1. Extensible fields

I am not aware of no change of IDD. Thanks for letting me know this restriction in the beginning. Do we allow extensible fields? If Yes, could you let me know how to do it. If not, I will use 500 node name, similar configuration of AirLoopHVAC:ZoneMixer. Please advise.

@nrel-bot
Copy link

@lgu1234 it has been 9 days since this pull request was last updated.

@nrel-bot
Copy link

nrel-bot commented May 3, 2019

@lgu1234 it has been 8 days since this pull request was last updated.

@nrel-bot-2
Copy link

@lgu1234 it has been 13 days since this pull request was last updated.

@nrel-bot-2c
Copy link

@lgu1234 it has been 7 days since this pull request was last updated.

@nrel-bot-2c
Copy link

@lgu1234 it has been 8 days since this pull request was last updated.

@mjwitte mjwitte added NewFeature Includes code to add a new feature to EnergyPlus IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) labels Jun 3, 2019
@nrel-bot-2c
Copy link

@lgu1234 it has been 7 days since this pull request was last updated.

@nrel-bot
Copy link

@lgu1234 it has been 12 days since this pull request was last updated.

@nrel-bot-2c
Copy link

@lgu1234 it has been 7 days since this pull request was last updated.

@nrel-bot-2b
Copy link

@lgu1234 it has been 7 days since this pull request was last updated.

Copy link
Contributor

@mjwitte mjwitte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgu1234 I've suggested some code to allow the branch objects to be eliminated.
But it turns out that SetUpCompSets needs some extra lines as well - it assumes that child objects all know what their inlet and outlet node names are, but AirloopHVAC:OutdoorAirSystems does not know it's node names. So, I understand now, by adding the branch object, you had to specify the inlet and outlet node names for the AirllopHVAC:OtudoorAirSystem.

Here are the code changes to SetUpCompSets:
image

Or if you want, I can push these changes up to your branch. Let me know.


thisDOAS.m_InletNodeNum = OutsideAirSys(thisDOAS.m_OASystemNum).InletNodeNum(1);
thisDOAS.m_OutletNodeNum = OutsideAirSys(thisDOAS.m_OASystemNum).OutletNodeNum(OutsideAirSys(thisDOAS.m_OASystemNum).NumComponents);
OutsideAirSys(thisDOAS.m_OASystemNum).AirLoopDOASNum = AirLoopDOASNum - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgu1234 If you add this code here, then you should be able to delete the DOAS BranchList and Branch objects:

                // Set up parent-child connection
                BranchNodeConnections::SetUpCompSets(cCurrentModuleObject,
                    thisDOAS.Name,
                    "AIRLOOPHVAC:OUTDOORAIRSYSTEM",
                    thisDOAS.OASystemName,
                    DataLoopNode::NodeID(thisDOAS.m_InletNodeNum),
                    DataLoopNode::NodeID(thisDOAS.m_OutletNodeNum));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjwitte I tested it. It worked. Thanks.

for (auto instance = instancesValue.begin(); instance != instancesValue.end(); ++instance) {

// *************** used only to eliminate unused object warning when using only Json type getInput **********
int TotalArgs = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getObjectItem isn't necessary here. You can use inputProcessor->markObjectAsUsed(cCurrentModuleObject, thisObjectName); to avoid unused warning. See WaterToWaterHeatPumpEIR.cc.

Of course, you'll have to change over the use of cAlphaFields and Alphas to use the json equivalents. Some for the other new objects in this feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjwitte I can follow your suggestion. However, my error messages need to know a field name, in addition to a field value. Which is the json equivalent for cAlphaFields? I talked to @rraustad and was told to hard-code it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know the method yet to get down to this level and grab the field name.

                "source_side_outlet_node_name": {
                    "field_type": "a", 
                    "field_name": "Source Side Outlet Node Name"
                }, 

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. Seems there must be a better way than hard coding. @mbadams5 Is there a method to access field names for use in error messages?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also needed for #7353.

if (errorsFound) {
ShowContinueError("Outlet node number is not found in " + CurrentModuleObject + " = " +
OutsideAirSys(thisDOAS.m_OASystemNum).ComponentName(CompNum));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These error messages are very repetitive. Could just store two error states and put a single instance of these after the if else if block.
If I am following this correctly, if one error occurs in any component (or if errorsFound has been set true before this loop) then every component will trigger Node number not found message, because errorsFound will stay true until the fatal error is called at line 1050.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjwitte Let me think how to make it.

! ***GENERAL SIMULATION PARAMETERS***
! Number of Zones: 6

Version,9.1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to move this to v9.2 and do any transitions required.
Also, this generates this error:
** Severe ** getFanObjectVectorIndex: did not find Fan:SystemModel name =PSZ-AC:1_FAN. Check inputs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mjwitte No transition is needed.

The version number has been changed in example file.

The new error is fixed.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Jul 31, 2019

@Myoldmopar I tried to add a default argument in

int getFanObjectVectorIndex(      // lookup vector index for fan object name in object array EnergyPlus::HVACFan::fanObjs
    std::string const &objectName, // IDF name in input
    bool const ErrorCheck = true)

Unfortunately, Visual Studio doe not accept, although default argument is accepted in C++.

The change I made is that I allow two arguments

int getFanObjectVectorIndex(      // lookup vector index for fan object name in object array EnergyPlus::HVACFan::fanObjs
    std::string const &objectName, // IDF name in input
    bool const ErrorCheck
)

Then I revised this function in 22 modules by adding one more argument.

@mjwitte
Copy link
Contributor

mjwitte commented Jul 31, 2019

@lgu1234 For future reference, there is (at least) one example of a default argument in the current code in Psychrometrics.hh

    inline Real64 PsyTdpFnTdbTwbPb(Real64 const TDB,                            // dry-bulb temperature {C}
                                   Real64 const TWB,                            // wet-bulb temperature {C}
                                   Real64 const PB,                             // barometric pressure (N/M**2) {Pascals}
                                   std::string const &CalledFrom = blank_string // routine this function was called from (error messages)
    )

Not sure why yours didn't work. Maybe it has to be &? But what you've done here is good.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Jul 31, 2019

@mjwitte Thanks for letting me know. I also searched the web at https://www.geeksforgeeks.org/default-arguments-c/ as Default Arguments in C++

The code is valid in C++ as below:

// A function with default arguments, it can be called with
// 2 arguments or 3 arguments or 4 arguments.
int sum(int x, int y, int z=0, int w=0)
{
return (x + y + z + w);
}

/* Driver program to test above function*/
int main()
{
cout << sum(10, 15) << endl;
cout << sum(10, 15, 25) << endl;
cout << sum(10, 15, 25, 30) << endl;
return 0;
}

When I added a default argument, HVACFan is OK for compiling. However, I got compile error to compile a whole project: Does not take 1 argument for this function. My guess is not a problem for C++ code. It may have some rules or restriction with HVACFan class (my guess).

@mbadams5
Copy link
Contributor

mbadams5 commented Aug 1, 2019

@lgu1234 When using the default argument, are you putting it in the header file (.hh)? The defaulted argument needs to be only in the header file and you need to use a non-defaulted argument in the implementation file (.cc).

// In header file
int getFanObjectVectorIndex(      // lookup vector index for fan object name in object array EnergyPlus::HVACFan::fanObjs
    std::string const &objectName, // IDF name in input
    bool const ErrorCheck = true);
// In implementation file
int getFanObjectVectorIndex(      // lookup vector index for fan object name in object array EnergyPlus::HVACFan::fanObjs
    std::string const &objectName, // IDF name in input
    bool const ErrorCheck)
{
// code
}

If you did this and it still does not work then that is surprising.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Aug 1, 2019

@mbadams5 Thanks. I am going to try and let you know what happens.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Aug 1, 2019

@mbadams5 It worked. I am going to commit it with a default argument. Thanks.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Aug 12, 2019

Solved conflicts a while ago.

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ERR cleanups are nice. Overall it's good, but there are a couple things that I think need to be tidied, and aren't big efforts. There is a for loop that uses a pointer reference, and that needs to be cleaned up - I've offered two possible solutions. There is also an if statement that has a trailing indented line without brackets, and that can be visually deceiving and difficult to debug if someone doesn't recognize that it isn't a block. The unit test is massive, which is disappointing for a new feature, but I won't let that hold up the merge. I'll need to do a little testing on this branch, but in the meantime, please address my minor changes and make sure it's up to date with develop to get "final" CI results.

@@ -65030,6 +65030,346 @@ AirLoopHVAC:ReturnPath,
\type object-list
\object-list ReturnPathComponentNames

AirLoopHVAC:DedicatedOutdoorAirSystem,
\extensible:1 Just duplicate last field and comments (changing numbering, please)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted to ask you to take out the (change numbering, please) comment, because changing the IDD is not an option for users, only developers. But it's OK, this can stay in.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar It is not clear how to change numbering. I just following other objects. Please give me an example.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it's OK. Just leave it.

}

std::string name;
static AirLoopMixer *factory(int object_type_of_num, std::string const objectName);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like where this is going already. 👍

AirLoopControlInfo(AirLoopNum).ReqstEconoLockoutWithCompressor = true;
} else {
AirLoopControlInfo(AirLoopNum).ReqstEconoLockoutWithCompressor = false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like AirLoopNum == -1 means one thing, AirLoopNum == 0 means another thing, and then AirLoopNum >= 1 means yet another thing. This is a bit complex.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar AirLoopNum == -1 means the function of SimDXCoolingSystem is called from SimOutdoorAirEquipComps at https://github.com/NREL/EnergyPlus/blob/Model-DOAS-to-Multiple-Air-Handling-Units/src/EnergyPlus/OutdoorAirUnit.cc#L2396. When AirLoopNum == 0, this module is called from AirLoopHVACDOAS. When AirLoopNum > 0, this module is called by both MixedAir and SimAirServingZones.

Therefore, I need to keep it. In order to make it clear, I am going to add comments for both options.

}

return NodeNum;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, you could simplify this up a bit. An acceptable function could be:

int GetAirOutletNodeNum(std::string const &HumidifierName,
	bool &ErrorsFound
)
{
	// PURPOSE OF THIS FUNCTION:
	// This function looks up the given humidifier and returns the air outlet node number.
	// If incorrect humidifier name is given, ErrorsFound is returned as true and node number as zero.

	if (GetInputFlag) {
		GetHumidifierInput();
		GetInputFlag = false;
	}

	int WhichHumidifier = UtilityRoutines::FindItemInList(HumidifierName, Humidifier);
	if (WhichHumidifier != 0) {
		return Humidifier(WhichHumidifier).AirOutNode;
	}
	else {
		ShowSevereError("GetAirInletNodeNum: Could not find Humidifier = \"" + HumidifierName +"\"");
		ErrorsFound = true;
		return 0;
	}
}

Note that it eliminates the local variables, and that you don't need as much comment markup.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar Done. Thanks.

@@ -1070,7 +1083,9 @@ namespace MixedAir {
cNumericFields);
UtilityRoutines::IsNameEmpty(AlphArray(1), CurrentModuleObject, ErrorsFound);
OutsideAirSys(OASysNum).Name = AlphArray(1);
GlobalNames::IntraObjUniquenessCheck(AlphArray(2), CurrentModuleObject, cAlphaFields(2), ControllerListUniqueNames, ErrorsFound);
if (!UtilityRoutines::SameString(AlphArray(2), "")) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use:

if (!AlphArray(2).empty()) {

to check if a string is blank.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar Done. Thanks.

@@ -2619,6 +2642,8 @@ namespace MixedAir {
// if ( BeginDayFlag ) {
// }

if (OutsideAirSys(OASysNum).AirLoopDOASNum > -1) return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot of these loop number flags floating around...I'm not able to track them fully at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar I know. The main purpose is for by-pass, when AirLoopDOAS is used. In order to reuse existing code, I need to use by-passes to meet AirLoopDOAS requirements.

}
thisAirLoopDOASObjec->SimAirLoopHVACDOAS(FirstHVACIteration, index);
OAMassFLowrate += thisAirLoopDOASObjec->SumMassFlowRate;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this whole loop could use range based looping:

for (auto & thisAirLoopDOASObjec : airloopDOAS) { // <- let compiler create the reference and do the looping
  if (thisAirLoopDOASObjec.m_AirLoopDOASNum > -1) {
    index = thisAirLoopDOASObjec.m_AirLoopDOASNum;
  } else {
    index = -1;
  }
  thisAirLoopDOASObjec.SimAirLoopHVACDOAS(FirstHVACIteration, index);
  OAMassFLowrate += thisAirLoopDOASObjec.SumMassFlowRate;
}

There's no need to introduce a pointer reference here. Even if you don't change the entire loop to a range based loop, it would be good to use a regular reference:

for (std::size_t loop = 0; loop < airloopDOAS.size(); ++loop) {
  auto &thisAirLoopDOASObjec = airloopDOAS[loop]; // <- regular reference variable, not a pointer
  if (thisAirLoopDOASObjec.m_AirLoopDOASNum > -1) {
    index = thisAirLoopDOASObjec.m_AirLoopDOASNum;
  } else {
    index = -1;
  }
  thisAirLoopDOASObjec.SimAirLoopHVACDOAS(FirstHVACIteration, index);
  OAMassFLowrate += thisAirLoopDOASObjec.SumMassFlowRate;
}

I don't want to introduce this pattern into the code, so this will be the first thing in my review that I would actually like to see get addressed. There may be other things as I go through, but this is the first thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar I am going to use a regular reference, so that the code change is less.


AllowWarmRestartFlag = true;
AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag = true;
if (AirLoopNum > 0) AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra logic checks are a waste of computation. Could this AirLoopNum be checked once and then a series of things be done only for that condition?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar Done. Thanks.

@@ -3097,7 +3188,8 @@ namespace SimAirServingZones {
AllowWarmRestartFlag);

// Detect whether the speculative warm restart feature is supported by each controller on this air loop.
AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag = AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag && AllowWarmRestartFlag;
if (AirLoopNum > 0)
AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag = AirLoopControlInfo(AirLoopNum).AllowWarmRestartFlag && AllowWarmRestartFlag;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code works fine, but it can cause visual indentation issues. It looks like you've started a new block since the statement portion of the IF statement is indented on the next line. But it's actually not. I would prefer to see brackets used here to avoid confusion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar Done. Thanks.


namespace EnergyPlus {

TEST_F(EnergyPlusFixture, AirLoopHVACDOASTest)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost 5000 lines for a single unit test. That's disappointing. I know writing unit tests for existing code can be difficult because of the interactions, but I always hope that for new features, it will be much more streamlined, since we know ahead of time we need to write unit tests for it, and things can be abstracted out to be nicely testable. Oh well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Myoldmopar I shrink the unit test with < 4000 line. However, I do need a lot of inputs to build the case for the unit test.

@lgu1234
Copy link
Contributor Author

lgu1234 commented Aug 16, 2019

@Myoldmopar Comments are addressed. The revisions are uploaded in GitHub. Please take a look and let me know if the revisions meet your requirements or not.

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing my comments @lgu1234

@Myoldmopar
Copy link
Member

Comments addressed, CI is happy. I just kicked Mac CI and it's coming online again, but I have no concerns. I'm going to merge this in.

@Myoldmopar Myoldmopar merged commit eb80a67 into develop Aug 19, 2019
@Myoldmopar Myoldmopar deleted the Model-DOAS-to-Multiple-Air-Handling-Units branch August 19, 2019 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
IDDChange Code changes impact the IDD file (cannot be merged after IO freeze) NewFeature Includes code to add a new feature to EnergyPlus
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants