LCOV - code coverage report
Current view: top level - EnergyPlus - PlantPipingSystemsManager.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 2363 2824 83.7 %
Date: 2023-01-17 19:17:23 Functions: 82 87 94.3 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cassert>
      50             : #include <cmath>
      51             : #include <memory>
      52             : #include <set>
      53             : 
      54             : // ObjexxFCL Headers
      55             : #include <ObjexxFCL/Array.functions.hh>
      56             : #include <ObjexxFCL/Fmath.hh>
      57             : #include <ObjexxFCL/floops.hh>
      58             : #include <ObjexxFCL/string.functions.hh>
      59             : 
      60             : // EnergyPlus Headers
      61             : #include <EnergyPlus/BranchNodeConnections.hh>
      62             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      63             : #include <EnergyPlus/DataEnvironment.hh>
      64             : #include <EnergyPlus/DataHVACGlobals.hh>
      65             : #include <EnergyPlus/DataHeatBalSurface.hh>
      66             : #include <EnergyPlus/DataHeatBalance.hh>
      67             : #include <EnergyPlus/DataIPShortCuts.hh>
      68             : #include <EnergyPlus/DataLoopNode.hh>
      69             : #include <EnergyPlus/DataSurfaces.hh>
      70             : #include <EnergyPlus/FluidProperties.hh>
      71             : #include <EnergyPlus/General.hh>
      72             : #include <EnergyPlus/GlobalNames.hh>
      73             : #include <EnergyPlus/GroundTemperatureModeling/GroundTemperatureModelManager.hh>
      74             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75             : #include <EnergyPlus/Material.hh>
      76             : #include <EnergyPlus/NodeInputManager.hh>
      77             : #include <EnergyPlus/OutputProcessor.hh>
      78             : #include <EnergyPlus/Plant/DataPlant.hh>
      79             : #include <EnergyPlus/PlantPipingSystemsManager.hh>
      80             : #include <EnergyPlus/PlantUtilities.hh>
      81             : #include <EnergyPlus/UtilityRoutines.hh>
      82             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      83             : 
      84             : namespace EnergyPlus {
      85             : 
      86             : namespace PlantPipingSystemsManager {
      87             : 
      88             :     // Module containing the routines dealing with the PipingSystems
      89             : 
      90             :     // MODULE INFORMATION:
      91             :     //       AUTHOR         Edwin Lee
      92             :     //       DATE WRITTEN   Summer 2011
      93             :     //       MODIFIED       na
      94             :     //       RE-ENGINEERED  na
      95             : 
      96             :     // PURPOSE OF THIS MODULE:
      97             :     // Simulate all cases of plant "piping systems"
      98             :     //      PipingSystem:Underground
      99             :     //      PipingSystem:Generalized
     100             : 
     101             :     // METHODOLOGY EMPLOYED:
     102             :     // A 3D mesh is established, with full 3D conduction being employed
     103             :     // For ground simulation, moisture content and soil freezing is included
     104             :     // The mesh can include any number of pipe circuits placed within the domain
     105             :     // The mesh can interact with basement walls also
     106             : 
     107             : #pragma clang diagnostic push
     108             : #pragma ide diagnostic ignored "cert-err58-cpp"
     109             :     // MODULE PARAMETER DEFINITIONS:
     110         771 :     std::string const ObjName_ug_GeneralDomain("PipingSystem:Underground:Domain");
     111         771 :     std::string const ObjName_Circuit("PipingSystem:Underground:PipeCircuit");
     112         771 :     std::string const ObjName_Segment("PipingSystem:Underground:PipeSegment");
     113         771 :     std::string const ObjName_HorizTrench("GroundHeatExchanger:HorizontalTrench");
     114         771 :     std::string const ObjName_ZoneCoupled_Slab("Site:GroundDomain:Slab");
     115         771 :     std::string const ObjName_ZoneCoupled_Basement("Site:GroundDomain:Basement");
     116             :     constexpr std::array<std::string_view, static_cast<int>(SegmentFlow::Num)> flowDirectionNamesUC = {"INCREASINGZ", "DECREASINGZ"};
     117             : 
     118             : #pragma clang diagnostic pop
     119             : 
     120         771 :     void CheckIfAnySlabs(EnergyPlusData &state)
     121             :     {
     122             :         // SUBROUTINE INFORMATION:
     123             :         //       AUTHOR         Matt Mitchell
     124             :         //       DATE WRITTEN   May 2014
     125             :         //       MODIFIED       na
     126             :         //       RE-ENGINEERED  na
     127         771 :         int numSlabsCheck(state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_ZoneCoupled_Slab));
     128         771 :         state.dataGlobal->AnySlabsInModel = (numSlabsCheck > 0);
     129         771 :     }
     130             : 
     131         771 :     void CheckIfAnyBasements(EnergyPlusData &state)
     132             :     {
     133             :         // SUBROUTINE INFORMATION:
     134             :         //       AUTHOR         Matt Mitchell
     135             :         //       DATE WRITTEN   May 2014
     136             :         //       MODIFIED       na
     137             :         //       RE-ENGINEERED  na
     138         771 :         int const numBasementsCheck(state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_ZoneCoupled_Basement));
     139         771 :         state.dataGlobal->AnyBasementsInModel = (numBasementsCheck > 0);
     140         771 :     }
     141             : 
     142           5 :     PlantComponent *Circuit::factory(EnergyPlusData &state, [[maybe_unused]] DataPlant::PlantEquipmentType objectType, const std::string &objectName)
     143             :     {
     144             :         // Process the input data for circuits if it hasn't been done already
     145           5 :         if (state.dataPlantPipingSysMgr->GetInputFlag) {
     146           5 :             GetPipingSystemsAndGroundDomainsInput(state);
     147           5 :             state.dataPlantPipingSysMgr->GetInputFlag = false;
     148             :         }
     149             :         // Now look for this particular pipe in the list
     150           5 :         for (auto &circuit : state.dataPlantPipingSysMgr->circuits) {
     151           5 :             if (circuit.Name == objectName) {
     152           5 :                 return &circuit;
     153             :             }
     154             :         }
     155             :         // If we didn't find it, fatal
     156           0 :         ShowFatalError(state,
     157             :                        "PipeCircuitInfoFactory: Error getting inputs for circuit named: " + objectName); // LCOV_EXCL_LINE
     158             :         // Shut up the compiler
     159             :         return nullptr; // LCOV_EXCL_LINE
     160             :     }
     161             : 
     162       14498 :     void Circuit::simulate(EnergyPlusData &state,
     163             :                            [[maybe_unused]] const PlantLocation &calledFromLocation,
     164             :                            [[maybe_unused]] bool const FirstHVACIteration,
     165             :                            [[maybe_unused]] Real64 &CurLoad,
     166             :                            [[maybe_unused]] bool const RunFlag)
     167             :     {
     168             :         // Retrieve the parent domain index for this pipe circuit
     169       14498 :         auto &thisDomain(state.dataPlantPipingSysMgr->domains[this->ParentDomainIndex]);
     170             : 
     171             :         // Do any initialization here
     172       14498 :         thisDomain.InitPipingSystems(state, this);
     173             : 
     174             :         // Update the temperature field
     175       14498 :         thisDomain.PerformIterationLoop(state, this);
     176             : 
     177             :         // Update outlet nodes, etc.
     178       14498 :         thisDomain.UpdatePipingSystems(state, this);
     179       14498 :     }
     180             : 
     181       13350 :     void SimulateGroundDomains(EnergyPlusData &state, bool initOnly)
     182             :     {
     183             : 
     184             :         // SUBROUTINE INFORMATION:
     185             :         //       AUTHOR         Matt Mitchell
     186             :         //       DATE WRITTEN   Spring 2014
     187             :         //       MODIFIED       by Sushobhit Acharya, March 2015
     188             :         //       RE-ENGINEERED  na
     189             : 
     190             :         // Read input if necessary
     191       13350 :         if (state.dataPlantPipingSysMgr->GetInputFlag) {
     192           6 :             GetPipingSystemsAndGroundDomainsInput(state);
     193           6 :             state.dataPlantPipingSysMgr->GetInputFlag = false;
     194             :         }
     195             : 
     196       26700 :         for (auto &thisDomain : state.dataPlantPipingSysMgr->domains) {
     197             : 
     198             :             // if the domain contains a pipe circuit, it shouldn't be initialized here, it has its own entry point
     199       13350 :             if (thisDomain.HasAPipeCircuit) continue;
     200             : 
     201       13350 :             if (thisDomain.DomainNeedsToBeMeshed) {
     202           6 :                 thisDomain.developMesh(state);
     203             :             }
     204             : 
     205       13350 :             thisDomain.DomainNeedsToBeMeshed = false;
     206             : 
     207             :             // The time init should be done here before we DoOneTimeInits because the DoOneTimeInits
     208             :             // includes a ground temperature initialization, which is based on the Cur%CurSimTimeSeconds variable
     209             :             // which would be carried over from the previous environment
     210       13350 :             thisDomain.Cur.CurSimTimeStepSize = state.dataGlobal->TimeStepZone * DataGlobalConstants::SecInHour;
     211       13350 :             thisDomain.Cur.CurSimTimeSeconds =
     212       26700 :                 ((state.dataGlobal->DayOfSim - 1) * 24 + (state.dataGlobal->HourOfDay - 1) +
     213       26700 :                  (state.dataGlobal->TimeStep - 1) * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed) *
     214             :                 DataGlobalConstants::SecInHour;
     215             : 
     216             :             // There are also some inits that are "close to one time" inits...( one-time in standalone, each envrn in E+ )
     217       13350 :             if ((state.dataGlobal->BeginSimFlag && thisDomain.BeginSimInit) || (state.dataGlobal->BeginEnvrnFlag && thisDomain.BeginSimEnvironment)) {
     218             : 
     219          12 :                 thisDomain.DoOneTimeInitializations(state, nullptr);
     220             : 
     221          12 :                 if (thisDomain.HasZoneCoupledSlab) {
     222          10 :                     int Xmax = ubound(thisDomain.Cells, 1);
     223             :                     // int yMax = ubound( thisDomain.Cells, 2 );
     224          10 :                     int Zmax = ubound(thisDomain.Cells, 3);
     225             : 
     226          10 :                     thisDomain.WeightingFactor.allocate({0, Xmax}, {0, Zmax});
     227          10 :                     thisDomain.WeightedHeatFlux.allocate({0, Xmax}, {0, Zmax});
     228             :                 }
     229             : 
     230          12 :                 thisDomain.BeginSimInit = false;
     231          12 :                 thisDomain.BeginSimEnvironment = false;
     232             :             }
     233       13350 :             if (!state.dataGlobal->BeginSimFlag) thisDomain.BeginSimInit = true;
     234       13350 :             if (!state.dataGlobal->BeginEnvrnFlag) thisDomain.BeginSimEnvironment = true;
     235             : 
     236             :             // Reset the heat fluxes if domain update has been completed
     237       13350 :             if (thisDomain.ResetHeatFluxFlag) {
     238       10561 :                 thisDomain.AggregateHeatFlux = 0;
     239       10561 :                 thisDomain.AggregateWallHeatFlux = 0;
     240       10561 :                 thisDomain.AggregateFloorHeatFlux = 0;
     241       10561 :                 thisDomain.NumHeatFlux = 0;
     242       10561 :                 thisDomain.ResetHeatFluxFlag = false;
     243             :             }
     244             : 
     245       13350 :             if (!initOnly) {
     246             :                 // Aggregate the heat flux
     247             :                 // Zone-coupled slab
     248       13344 :                 if (thisDomain.HasZoneCoupledSlab) {
     249       10560 :                     thisDomain.AggregateHeatFlux += thisDomain.GetZoneInterfaceHeatFlux(state);
     250       10560 :                     thisDomain.NumHeatFlux += 1;
     251       10560 :                     thisDomain.HeatFlux = thisDomain.AggregateHeatFlux / thisDomain.NumHeatFlux;
     252             :                 } else { // Coupled basement
     253             : 
     254             :                     // basement walls
     255        2784 :                     thisDomain.AggregateWallHeatFlux += thisDomain.GetBasementWallHeatFlux(state);
     256             :                     // basement floor
     257        2784 :                     thisDomain.AggregateFloorHeatFlux += thisDomain.GetBasementFloorHeatFlux(state);
     258             : 
     259        2784 :                     thisDomain.NumHeatFlux += 1;
     260        2784 :                     thisDomain.WallHeatFlux = thisDomain.AggregateWallHeatFlux / thisDomain.NumHeatFlux;
     261        2784 :                     thisDomain.FloorHeatFlux = thisDomain.AggregateFloorHeatFlux / thisDomain.NumHeatFlux;
     262             :                 }
     263             : 
     264             :                 // Aggregate the heat flux
     265             :                 // Zone-coupled slab
     266       13344 :                 if (thisDomain.HasZoneCoupledSlab) {
     267       10560 :                     thisDomain.AggregateHeatFlux += thisDomain.GetZoneInterfaceHeatFlux(state);
     268       10560 :                     thisDomain.NumHeatFlux += 1;
     269       10560 :                     thisDomain.HeatFlux = thisDomain.AggregateHeatFlux / thisDomain.NumHeatFlux;
     270        2784 :                 } else if (thisDomain.HasZoneCoupledBasement) { // Coupled basement
     271             :                     // basement walls
     272        2784 :                     thisDomain.AggregateWallHeatFlux += thisDomain.GetBasementWallHeatFlux(state);
     273             :                     // basement floor
     274        2784 :                     thisDomain.AggregateFloorHeatFlux += thisDomain.GetBasementFloorHeatFlux(state);
     275             : 
     276        2784 :                     thisDomain.NumHeatFlux += 1;
     277        2784 :                     thisDomain.WallHeatFlux = thisDomain.AggregateWallHeatFlux / thisDomain.NumHeatFlux;
     278        2784 :                     thisDomain.FloorHeatFlux = thisDomain.AggregateFloorHeatFlux / thisDomain.NumHeatFlux;
     279             :                 }
     280             : 
     281             :                 // Zone-coupled slab
     282       13344 :                 if (thisDomain.HasZoneCoupledSlab) {
     283             : 
     284       10560 :                     thisDomain.HeatFlux = thisDomain.AggregateHeatFlux / thisDomain.NumHeatFlux;
     285             : 
     286       10560 :                     Real64 ZoneTemp = 0.0;
     287             : 
     288             :                     // Set ZoneTemp equal to the average air temperature of the zones the coupled surfaces are part of.
     289       39168 :                     for (auto &z : thisDomain.ZoneCoupledSurfaces) {
     290       28608 :                         int ZoneNum = z.Zone;
     291       28608 :                         ZoneTemp += state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZTAV;
     292             :                     }
     293             : 
     294       10560 :                     ZoneTemp = ZoneTemp / thisDomain.ZoneCoupledSurfaces.size();
     295       10560 :                     Real64 AvgSlabTemp = thisDomain.GetAverageTempByType(state, CellType::ZoneGroundInterface);
     296             : 
     297       10560 :                     int yMax = ubound(thisDomain.Cells, 2);
     298             : 
     299      147840 :                     for (int Z = lbound(thisDomain.Cells, 3); Z <= ubound(thisDomain.Cells, 3); ++Z) {
     300     1921920 :                         for (int X = lbound(thisDomain.Cells, 1); X <= ubound(thisDomain.Cells, 1); ++X) {
     301             :                             // Zone interface cells
     302     1784640 :                             if (thisDomain.Cells(X, yMax, Z).cellType == CellType::ZoneGroundInterface) {
     303      380160 :                                 thisDomain.WeightingFactor(X, Z) =
     304      380160 :                                     std::abs((ZoneTemp - thisDomain.Cells(X, yMax, Z).Temperature_PrevTimeStep) / (ZoneTemp - AvgSlabTemp));
     305             :                             }
     306             :                         }
     307             :                     }
     308             : 
     309             :                     // Set initial weighted heat flux
     310      147840 :                     for (int Z = lbound(thisDomain.Cells, 3); Z <= ubound(thisDomain.Cells, 3); ++Z) {
     311     1921920 :                         for (int X = lbound(thisDomain.Cells, 1); X <= ubound(thisDomain.Cells, 1); ++X) {
     312             :                             // Zone interface cells
     313     1784640 :                             if (thisDomain.Cells(X, yMax, Z).cellType == CellType::ZoneGroundInterface) {
     314      380160 :                                 thisDomain.WeightedHeatFlux(X, Z) = thisDomain.WeightingFactor(X, Z) * thisDomain.HeatFlux;
     315             :                             }
     316             :                         }
     317             :                     }
     318             : 
     319             :                     // Weighted heat flux and uniform heat flux balance energy may not balance exactly
     320             :                     // Calculate difference and adjust
     321       10560 :                     thisDomain.TotalEnergyUniformHeatFlux = thisDomain.HeatFlux * thisDomain.SlabArea * thisDomain.Cur.CurSimTimeStepSize;
     322       10560 :                     thisDomain.TotalEnergyWeightedHeatFlux = 0.0;
     323             : 
     324      147840 :                     for (int Z = lbound(thisDomain.Cells, 3); Z <= ubound(thisDomain.Cells, 3); ++Z) {
     325     1921920 :                         for (int X = lbound(thisDomain.Cells, 1); X <= ubound(thisDomain.Cells, 1); ++X) {
     326             :                             // Zone interface cells
     327     1784640 :                             if (thisDomain.Cells(X, yMax, Z).cellType == CellType::ZoneGroundInterface) {
     328      380160 :                                 auto &cell(thisDomain.Cells(X, yMax, Z));
     329      380160 :                                 thisDomain.TotalEnergyWeightedHeatFlux +=
     330      380160 :                                     thisDomain.WeightedHeatFlux(X, Z) * cell.width() * cell.depth() * thisDomain.Cur.CurSimTimeStepSize;
     331             :                             }
     332             :                         }
     333             :                     }
     334             : 
     335       10560 :                     thisDomain.HeatFluxWeightingFactor = thisDomain.TotalEnergyWeightedHeatFlux / thisDomain.TotalEnergyUniformHeatFlux;
     336       10560 :                     thisDomain.TotalEnergyWeightedHeatFlux = 0.0;
     337             : 
     338             :                     // Finally, adjust the weighted heat flux so that energy balances
     339      147840 :                     for (int Z = lbound(thisDomain.Cells, 3); Z <= ubound(thisDomain.Cells, 3); ++Z) {
     340     1921920 :                         for (int X = lbound(thisDomain.Cells, 1); X <= ubound(thisDomain.Cells, 1); ++X) {
     341             :                             // Zone interface cells
     342     1784640 :                             if (thisDomain.Cells(X, yMax, Z).cellType == CellType::ZoneGroundInterface) {
     343      380160 :                                 auto &cell(thisDomain.Cells(X, yMax, Z));
     344      380160 :                                 thisDomain.WeightedHeatFlux(X, Z) = thisDomain.WeightedHeatFlux(X, Z) / thisDomain.HeatFluxWeightingFactor;
     345      380160 :                                 thisDomain.TotalEnergyWeightedHeatFlux +=
     346      380160 :                                     thisDomain.WeightedHeatFlux(X, Z) * cell.width() * cell.depth() * thisDomain.Cur.CurSimTimeStepSize;
     347             :                             }
     348             :                         }
     349             :                     }
     350             : 
     351             :                 } else { // Coupled basement
     352        2784 :                     thisDomain.WallHeatFlux = thisDomain.AggregateWallHeatFlux / thisDomain.NumHeatFlux;
     353        2784 :                     thisDomain.FloorHeatFlux = thisDomain.AggregateFloorHeatFlux / thisDomain.NumHeatFlux;
     354             :                 }
     355             : 
     356             :                 // Shift history arrays only if necessary
     357       13344 :                 if (std::abs(thisDomain.Cur.CurSimTimeSeconds - thisDomain.Cur.PrevSimTimeSeconds) > 1.0e-6) {
     358       13344 :                     thisDomain.Cur.PrevSimTimeSeconds = thisDomain.Cur.CurSimTimeSeconds;
     359       13344 :                     thisDomain.ShiftTemperaturesForNewTimeStep();
     360       13344 :                     thisDomain.DomainNeedsSimulation = true;
     361             :                 }
     362       13344 :                 thisDomain.PerformIterationLoop(state);
     363             :             }
     364             :         }
     365             : 
     366       13350 :         if (state.dataPlantPipingSysMgr->WriteEIOFlag) {
     367             :             // Write eio header
     368             :             static constexpr std::string_view DomainCellsToEIOHeader(
     369             :                 "! <Domain Name>, Total Number of Domain Cells, Total Number of Ground Surface Cells, Total Number of Insulation Cells\n");
     370           6 :             print(state.files.eio, DomainCellsToEIOHeader);
     371             : 
     372             :             // Write eio data
     373          12 :             for (auto &thisDomain : state.dataPlantPipingSysMgr->domains) {
     374             :                 static constexpr std::string_view DomainCellsToEIO("{},{:5},{:5},{:5}\n");
     375           6 :                 print(state.files.eio,
     376             :                       DomainCellsToEIO,
     377             :                       thisDomain.Name,
     378             :                       thisDomain.NumDomainCells,
     379             :                       thisDomain.NumGroundSurfCells,
     380             :                       thisDomain.NumInsulationCells);
     381             :             }
     382           6 :             state.dataPlantPipingSysMgr->WriteEIOFlag = false;
     383             :         }
     384       13350 :     }
     385             : 
     386          11 :     void GetPipingSystemsAndGroundDomainsInput(EnergyPlusData &state)
     387             :     {
     388             : 
     389             :         // SUBROUTINE INFORMATION:
     390             :         //       AUTHOR         Edwin Lee
     391             :         //       DATE WRITTEN   Summer 2011
     392             :         //       MODIFIED       na
     393             :         //       RE-ENGINEERED  na
     394             : 
     395             :         static constexpr std::string_view RoutineName("GetPipingSystemsAndGroundDomainsInput");
     396             : 
     397             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     398          11 :         bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
     399             : 
     400             :         // Read number of objects and allocate main data structures - first domains
     401          11 :         int NumGeneralizedDomains = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_ug_GeneralDomain);
     402          11 :         int NumHorizontalTrenches = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_HorizTrench);
     403          11 :         int NumZoneCoupledDomains = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_ZoneCoupled_Slab);
     404          11 :         int NumBasements = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_ZoneCoupled_Basement);
     405          11 :         int TotalNumDomains = NumGeneralizedDomains + NumHorizontalTrenches + NumZoneCoupledDomains + NumBasements;
     406          11 :         state.dataPlantPipingSysMgr->domains.resize(TotalNumDomains);
     407             : 
     408             :         // then circuits
     409          11 :         int NumPipeCircuits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_Circuit);
     410             : 
     411             :         // Read in raw inputs, don't try to interpret dependencies yet
     412          11 :         ReadGeneralDomainInputs(state, 1, NumGeneralizedDomains, ErrorsFound);
     413             :         // ReadPipeCircuitInputs(ErrorsFound);
     414          11 :         ReadHorizontalTrenchInputs(state, NumGeneralizedDomains + 1, NumPipeCircuits + 1, ErrorsFound);
     415             : 
     416             :         // This is heavily dependent on the order of the domains in the main array.
     417          11 :         ReadZoneCoupledDomainInputs(state, NumGeneralizedDomains + NumHorizontalTrenches + 1, NumZoneCoupledDomains, ErrorsFound);
     418             : 
     419             :         // This is heavily dependent on the order of the domains in the main array.
     420          11 :         ReadBasementInputs(state, NumGeneralizedDomains + NumHorizontalTrenches + NumZoneCoupledDomains + 1, NumBasements, ErrorsFound);
     421             : 
     422             :         // Report errors that are purely input problems
     423          11 :         if (ErrorsFound) ShowFatalError(state, std::string{RoutineName} + ": Preceding input errors cause program termination.");
     424             : 
     425             :         // Setup output variables
     426          11 :         SetupPipingSystemOutputVariables(state);
     427             : 
     428             :         // Validate DOMAIN-CIRCUIT cross references
     429          22 :         for (int DomainNum = 0; DomainNum < TotalNumDomains; ++DomainNum) {
     430             : 
     431             :             // Convenience
     432          11 :             auto &thisDomain = state.dataPlantPipingSysMgr->domains[DomainNum];
     433             : 
     434             :             // validate pipe domain-circuit name-to-index references
     435          16 :             for (auto &thisCircuit : thisDomain.circuits) {
     436           5 :                 thisCircuit->ParentDomainIndex = DomainNum;
     437             :             }
     438             : 
     439             :             // correct segment locations for: INTERNAL DATA STRUCTURE Y VALUE MEASURED FROM BOTTOM OF DOMAIN,
     440             :             //                                INPUT WAS MEASURED FROM GROUND SURFACE
     441          16 :             for (auto &thisCircuit : thisDomain.circuits) {
     442          19 :                 for (auto &thisSegment : thisCircuit->pipeSegments) {
     443          14 :                     thisSegment->PipeLocation.Y = thisDomain.Extents.yMax - thisSegment->PipeLocation.Y;
     444             :                 }
     445             :             }
     446             : 
     447             :             // correct segment locations for: BASEMENT X SHIFT
     448          11 :             if (thisDomain.HasBasement && thisDomain.BasementZone.ShiftPipesByWidth) {
     449           2 :                 for (auto &thisCircuit : thisDomain.circuits) {
     450           7 :                     for (auto &thisSegment : thisCircuit->pipeSegments) {
     451           6 :                         thisSegment->PipeLocation.X += thisDomain.BasementZone.Width;
     452             :                     }
     453             :                 }
     454             :             }
     455             : 
     456             :             // now we will have good values of pipe segment locations, we can validate them
     457          16 :             for (auto &thisCircuit : thisDomain.circuits) {
     458             :                 // check to make sure it isn't outside the domain
     459          19 :                 for (auto &thisSegment : thisCircuit->pipeSegments) {
     460          28 :                     if ((thisSegment->PipeLocation.X > thisDomain.Extents.xMax) || (thisSegment->PipeLocation.X < 0.0) ||
     461          28 :                         (thisSegment->PipeLocation.Y > thisDomain.Extents.yMax) || (thisSegment->PipeLocation.Y < 0.0)) {
     462           0 :                         ShowSevereError(state,
     463           0 :                                         "PipingSystems::" + std::string{RoutineName} +
     464             :                                             ": A pipe was outside of the domain extents after performing corrections for basement or burial depth.");
     465           0 :                         ShowContinueError(state, "Pipe segment name:" + thisSegment->Name);
     466           0 :                         ShowContinueError(
     467             :                             state,
     468           0 :                             format("Corrected pipe location: ( x,y )=( {:.2T},{:.2T} )", thisSegment->PipeLocation.X, thisSegment->PipeLocation.Y));
     469             :                     }
     470             :                 } // segment loop
     471             :             }     // circuit loop
     472             : 
     473             :         } // domain loop
     474             : 
     475             :         // If we encountered any other errors that we couldn't handle separately than stop now
     476          11 :         if (ErrorsFound) {
     477           0 :             ShowFatalError(state, std::string{RoutineName} + ':' + ObjName_ug_GeneralDomain + ": Errors found in input.");
     478             :         }
     479          11 :     }
     480             : 
     481          11 :     void ReadGeneralDomainInputs(EnergyPlusData &state, int const IndexStart, int const NumGeneralizedDomains, bool &ErrorsFound)
     482             :     {
     483             : 
     484             :         // SUBROUTINE INFORMATION:
     485             :         //       AUTHOR         Edwin Lee
     486             :         //       DATE WRITTEN   Summer 2011
     487             :         //       MODIFIED       na
     488             :         //       RE-ENGINEERED  na
     489             : 
     490             :         // SUBROUTINE PARAMETER DEFINITIONS:
     491             :         static constexpr std::string_view RoutineName("ReadGeneralDomainInputs");
     492             : 
     493             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     494             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
     495             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
     496             :         int IOStatus;   // Used in GetObjectItem
     497             :         int CurIndex;
     498             : 
     499          15 :         for (int DomainNum = IndexStart; DomainNum <= NumGeneralizedDomains; ++DomainNum) {
     500             : 
     501             :             // Set up all the inputs for this domain object
     502          28 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     503             :                                                                      ObjName_ug_GeneralDomain,
     504             :                                                                      DomainNum,
     505           4 :                                                                      state.dataIPShortCut->cAlphaArgs,
     506             :                                                                      NumAlphas,
     507           4 :                                                                      state.dataIPShortCut->rNumericArgs,
     508             :                                                                      NumNumbers,
     509             :                                                                      IOStatus,
     510           4 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     511           4 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     512           4 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     513           4 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     514             : 
     515           4 :             auto &thisDomain = state.dataPlantPipingSysMgr->domains[DomainNum - 1];
     516             : 
     517             :             // Get the name, validate
     518           4 :             thisDomain.Name = state.dataIPShortCut->cAlphaArgs(1);
     519           4 :             UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
     520             :             // Mesh extents, validated by IP
     521           4 :             thisDomain.Extents.xMax = state.dataIPShortCut->rNumericArgs(1);
     522           4 :             thisDomain.Extents.yMax = state.dataIPShortCut->rNumericArgs(2);
     523           4 :             thisDomain.Extents.zMax = state.dataIPShortCut->rNumericArgs(3);
     524             : 
     525             :             // X direction mesh inputs, validated by IP
     526           4 :             thisDomain.Mesh.X.RegionMeshCount = static_cast<int>(state.dataIPShortCut->rNumericArgs(4));
     527             :             {
     528           8 :                 auto const meshDistribution(uppercased(state.dataIPShortCut->cAlphaArgs(2)));
     529           4 :                 if (meshDistribution == "UNIFORM") {
     530           4 :                     thisDomain.Mesh.X.thisMeshDistribution = MeshDistribution::Uniform;
     531           0 :                 } else if (meshDistribution == "SYMMETRICGEOMETRIC") {
     532           0 :                     thisDomain.Mesh.X.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
     533           0 :                     if (mod(thisDomain.Mesh.X.RegionMeshCount, 2) != 0) {
     534           0 :                         ShowWarningError(state, "PipingSystems:" + std::string{RoutineName} + ": Invalid mesh type-count combination.");
     535           0 :                         ShowContinueError(state, "Instance:" + ObjName_ug_GeneralDomain + '=' + thisDomain.Name);
     536           0 :                         ShowContinueError(state, "An ODD-valued X mesh count was found in the input for symmetric geometric configuration.");
     537           0 :                         ShowContinueError(state, "This is invalid, mesh count incremented UP by one to next EVEN value.");
     538           0 :                         ++thisDomain.Mesh.X.RegionMeshCount;
     539           0 :                         thisDomain.Mesh.X.GeometricSeriesCoefficient = state.dataIPShortCut->rNumericArgs(5);
     540             :                     } else {
     541           0 :                         thisDomain.Mesh.X.GeometricSeriesCoefficient = 1.0;
     542             :                     }
     543             :                 } else {
     544           0 :                     IssueSevereInputFieldError(state,
     545             :                                                RoutineName,
     546             :                                                ObjName_ug_GeneralDomain,
     547           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     548           0 :                                                state.dataIPShortCut->cAlphaFieldNames(2),
     549           0 :                                                state.dataIPShortCut->cAlphaArgs(2),
     550             :                                                "Use a choice from the available mesh type keys.",
     551             :                                                ErrorsFound);
     552             :                 }
     553             :             }
     554             : 
     555             :             // Y direction mesh inputs, validated by IP
     556           4 :             thisDomain.Mesh.Y.RegionMeshCount = static_cast<int>(state.dataIPShortCut->rNumericArgs(6));
     557             :             {
     558           8 :                 auto const meshDistribution(stripped(state.dataIPShortCut->cAlphaArgs(3)));
     559           4 :                 if (meshDistribution == "UNIFORM") {
     560           4 :                     thisDomain.Mesh.Y.thisMeshDistribution = MeshDistribution::Uniform;
     561           0 :                 } else if (meshDistribution == "SYMMETRICGEOMETRIC") {
     562           0 :                     thisDomain.Mesh.Y.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
     563           0 :                     if (mod(thisDomain.Mesh.Y.RegionMeshCount, 2) != 0) {
     564           0 :                         ShowWarningError(state, "PipingSystems:" + std::string{RoutineName} + ": Invalid mesh type-count combination.");
     565           0 :                         ShowContinueError(state, "Instance:" + ObjName_ug_GeneralDomain + '=' + thisDomain.Name);
     566           0 :                         ShowContinueError(state, "An ODD-valued Y mesh count was found in the input for symmetric geometric configuration.");
     567           0 :                         ShowContinueError(state, "This is invalid, mesh count incremented UP by one to next EVEN value.");
     568           0 :                         ++thisDomain.Mesh.Y.RegionMeshCount;
     569           0 :                         thisDomain.Mesh.Y.GeometricSeriesCoefficient = state.dataIPShortCut->rNumericArgs(7);
     570             :                     } else {
     571           0 :                         thisDomain.Mesh.Y.GeometricSeriesCoefficient = 1.0;
     572             :                     }
     573             :                 } else {
     574           0 :                     IssueSevereInputFieldError(state,
     575             :                                                RoutineName,
     576             :                                                ObjName_ug_GeneralDomain,
     577           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     578           0 :                                                state.dataIPShortCut->cAlphaFieldNames(3),
     579           0 :                                                state.dataIPShortCut->cAlphaArgs(3),
     580             :                                                "Use a choice from the available mesh type keys.",
     581             :                                                ErrorsFound);
     582             :                 }
     583             :             }
     584             : 
     585             :             // Z direction mesh inputs, validated by IP
     586           4 :             thisDomain.Mesh.Z.RegionMeshCount = static_cast<int>(state.dataIPShortCut->rNumericArgs(8));
     587             :             {
     588           8 :                 auto const meshDistribution(stripped(state.dataIPShortCut->cAlphaArgs(4)));
     589           4 :                 if (meshDistribution == "UNIFORM") {
     590           4 :                     thisDomain.Mesh.Z.thisMeshDistribution = MeshDistribution::Uniform;
     591           0 :                 } else if (meshDistribution == "SYMMETRICGEOMETRIC") {
     592           0 :                     thisDomain.Mesh.Z.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
     593           0 :                     if (mod(thisDomain.Mesh.Z.RegionMeshCount, 2) != 0) {
     594           0 :                         ShowWarningError(state, "PipingSystems:" + std::string{RoutineName} + ": Invalid mesh type-count combination.");
     595           0 :                         ShowContinueError(state, "Instance:" + ObjName_ug_GeneralDomain + '=' + thisDomain.Name);
     596           0 :                         ShowContinueError(state, "An ODD-valued Z mesh count was found in the input for symmetric geometric configuration.");
     597           0 :                         ShowContinueError(state, "This is invalid, mesh count incremented UP by one to next EVEN value.");
     598           0 :                         ++thisDomain.Mesh.Z.RegionMeshCount;
     599           0 :                         thisDomain.Mesh.Z.GeometricSeriesCoefficient = state.dataIPShortCut->rNumericArgs(9);
     600             :                     } else {
     601           0 :                         thisDomain.Mesh.Z.GeometricSeriesCoefficient = 1.0;
     602             :                     }
     603             :                 } else {
     604           0 :                     IssueSevereInputFieldError(state,
     605             :                                                RoutineName,
     606             :                                                ObjName_ug_GeneralDomain,
     607           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     608           0 :                                                state.dataIPShortCut->cAlphaFieldNames(4),
     609           0 :                                                state.dataIPShortCut->cAlphaArgs(4),
     610             :                                                "Use a choice from the available mesh type keys.",
     611             :                                                ErrorsFound);
     612             :                 }
     613             :             }
     614             : 
     615             :             // Soil properties, validated min/max by IP
     616           4 :             thisDomain.GroundProperties.Conductivity = state.dataIPShortCut->rNumericArgs(10);
     617           4 :             thisDomain.GroundProperties.Density = state.dataIPShortCut->rNumericArgs(11);
     618           4 :             thisDomain.GroundProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(12);
     619             : 
     620             :             // Moisture properties, validated min/max by IP, and converted to a fraction for computation here
     621           4 :             thisDomain.Moisture.Theta_liq = state.dataIPShortCut->rNumericArgs(13) / 100.0;
     622           4 :             thisDomain.Moisture.Theta_sat = state.dataIPShortCut->rNumericArgs(14) / 100.0;
     623             : 
     624             :             // check if there is a basement
     625           4 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "YES")) {
     626           1 :                 thisDomain.HasBasement = true;
     627           3 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "NO")) {
     628           3 :                 thisDomain.HasBasement = false;
     629             :             } else {
     630           0 :                 IssueSevereInputFieldError(state,
     631             :                                            RoutineName,
     632             :                                            ObjName_ug_GeneralDomain,
     633           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
     634           0 :                                            state.dataIPShortCut->cAlphaFieldNames(7),
     635           0 :                                            state.dataIPShortCut->cAlphaArgs(7),
     636             :                                            "Must enter either yes or no.",
     637             :                                            ErrorsFound);
     638             :             }
     639             : 
     640             :             // more work to do if there is a basement
     641           4 :             if (thisDomain.HasBasement) {
     642             : 
     643             :                 // check if there are blank inputs related to the basement,
     644             :                 // IP can't catch this because they are inherently optional if there ISN'T a basement
     645           4 :                 if (state.dataIPShortCut->lNumericFieldBlanks(15) || state.dataIPShortCut->lNumericFieldBlanks(16) ||
     646           4 :                     state.dataIPShortCut->lAlphaFieldBlanks(8) || state.dataIPShortCut->lAlphaFieldBlanks(9) ||
     647           1 :                     state.dataIPShortCut->lAlphaFieldBlanks(10)) {
     648           0 :                     ShowSevereError(state, "Erroneous basement inputs for " + ObjName_ug_GeneralDomain + '=' + state.dataIPShortCut->cAlphaArgs(1));
     649           0 :                     ShowContinueError(state, "Object specified to have a basement, while at least one basement input was left blank.");
     650           0 :                     ErrorsFound = true;
     651             :                 }
     652             : 
     653             :                 // get dimensions for meshing
     654           1 :                 CurIndex = 15;
     655           1 :                 thisDomain.BasementZone.Width = state.dataIPShortCut->rNumericArgs(CurIndex);
     656           1 :                 if (thisDomain.BasementZone.Width <= 0.0) {
     657           0 :                     IssueSevereInputFieldError(state,
     658             :                                                RoutineName,
     659             :                                                ObjName_ug_GeneralDomain,
     660           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     661           0 :                                                state.dataIPShortCut->cNumericFieldNames(CurIndex),
     662           0 :                                                state.dataIPShortCut->rNumericArgs(CurIndex),
     663             :                                                "Basement width must be a positive nonzero value.",
     664             :                                                ErrorsFound);
     665             :                 }
     666             : 
     667           1 :                 CurIndex = 16;
     668           1 :                 thisDomain.BasementZone.Depth = state.dataIPShortCut->rNumericArgs(CurIndex);
     669           1 :                 if (thisDomain.BasementZone.Depth <= 0.0) {
     670           0 :                     IssueSevereInputFieldError(state,
     671             :                                                RoutineName,
     672             :                                                ObjName_ug_GeneralDomain,
     673           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     674           0 :                                                state.dataIPShortCut->cNumericFieldNames(CurIndex),
     675           0 :                                                state.dataIPShortCut->rNumericArgs(CurIndex),
     676             :                                                "Basement depth must be a positive nonzero value.",
     677             :                                                ErrorsFound);
     678             :                 }
     679             : 
     680             :                 // check for dimension shift
     681           1 :                 CurIndex = 8;
     682           1 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(CurIndex), "YES")) {
     683           1 :                     thisDomain.BasementZone.ShiftPipesByWidth = true;
     684           0 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(CurIndex), "NO")) {
     685           0 :                     thisDomain.BasementZone.ShiftPipesByWidth = false;
     686             :                 } else {
     687           0 :                     IssueSevereInputFieldError(state,
     688             :                                                RoutineName,
     689             :                                                ObjName_ug_GeneralDomain,
     690           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     691           0 :                                                state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     692           0 :                                                state.dataIPShortCut->cAlphaArgs(CurIndex),
     693             :                                                "Must enter either yes or no.",
     694             :                                                ErrorsFound);
     695             :                 }
     696             : 
     697             :                 // get boundary condition model names and indices --error check
     698           1 :                 CurIndex = 9;
     699           1 :                 thisDomain.BasementZone.WallBoundaryOSCMName = state.dataIPShortCut->cAlphaArgs(CurIndex);
     700           1 :                 thisDomain.BasementZone.WallBoundaryOSCMIndex =
     701           1 :                     UtilityRoutines::FindItemInList(thisDomain.BasementZone.WallBoundaryOSCMName, state.dataSurface->OSCM);
     702           1 :                 if (thisDomain.BasementZone.WallBoundaryOSCMIndex <= 0) {
     703           0 :                     IssueSevereInputFieldError(state,
     704             :                                                RoutineName,
     705             :                                                ObjName_ug_GeneralDomain,
     706           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     707           0 :                                                state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     708           0 :                                                state.dataIPShortCut->cAlphaArgs(CurIndex),
     709             :                                                "Could not match with an Other Side Conditions Model input object.",
     710             :                                                ErrorsFound);
     711             :                 } else {
     712           2 :                     auto const &wallIndexes = GetSurfaceIndecesForOSCM(state, thisDomain.BasementZone.WallBoundaryOSCMIndex);
     713           1 :                     if (wallIndexes.empty()) {
     714           0 :                         IssueSevereInputFieldError(
     715             :                             state,
     716             :                             RoutineName,
     717             :                             ObjName_ug_GeneralDomain,
     718           0 :                             state.dataIPShortCut->cAlphaArgs(1),
     719           0 :                             state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     720           0 :                             state.dataIPShortCut->cAlphaArgs(CurIndex),
     721             :                             "Entry matched an Other Side Conditions Model, but no surfaces were found to be using this Other Side Conditions Model.",
     722             :                             ErrorsFound);
     723             :                     } else {
     724           1 :                         thisDomain.BasementZone.WallSurfacePointers = wallIndexes;
     725             :                     }
     726             :                 }
     727             : 
     728           1 :                 CurIndex = 10;
     729           1 :                 thisDomain.BasementZone.FloorBoundaryOSCMName = state.dataIPShortCut->cAlphaArgs(CurIndex);
     730           1 :                 thisDomain.BasementZone.FloorBoundaryOSCMIndex =
     731           1 :                     UtilityRoutines::FindItemInList(thisDomain.BasementZone.FloorBoundaryOSCMName, state.dataSurface->OSCM);
     732           1 :                 if (thisDomain.BasementZone.FloorBoundaryOSCMIndex <= 0) {
     733           0 :                     IssueSevereInputFieldError(state,
     734             :                                                RoutineName,
     735             :                                                ObjName_ug_GeneralDomain,
     736           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     737           0 :                                                state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     738           0 :                                                state.dataIPShortCut->cAlphaArgs(CurIndex),
     739             :                                                "Could not match with an Other Side Conditions Model input object.",
     740             :                                                ErrorsFound);
     741             :                 } else {
     742           2 :                     auto const &floorIndexes = GetSurfaceIndecesForOSCM(state, thisDomain.BasementZone.FloorBoundaryOSCMIndex);
     743           1 :                     if (floorIndexes.empty()) {
     744           0 :                         IssueSevereInputFieldError(
     745             :                             state,
     746             :                             RoutineName,
     747             :                             ObjName_ug_GeneralDomain,
     748           0 :                             state.dataIPShortCut->cAlphaArgs(1),
     749           0 :                             state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     750           0 :                             state.dataIPShortCut->cAlphaArgs(CurIndex),
     751             :                             "Entry matched an Other Side Conditions Model, but no surfaces were found to be using this Other Side Conditions Model.",
     752             :                             ErrorsFound);
     753             :                     } else {
     754           1 :                         thisDomain.BasementZone.FloorSurfacePointers = floorIndexes;
     755             :                     }
     756             :                 }
     757             :             }
     758             : 
     759             :             // get some convergence tolerances, minimum/maximum are enforced by the IP, along with default values if user left them blank
     760           4 :             thisDomain.SimControls.Convergence_CurrentToPrevIteration = state.dataIPShortCut->rNumericArgs(17);
     761           4 :             thisDomain.SimControls.MaxIterationsPerTS = static_cast<int>(state.dataIPShortCut->rNumericArgs(18));
     762             : 
     763             :             // additional evapotranspiration parameter, min/max validated by IP
     764           4 :             thisDomain.Moisture.GroundCoverCoefficient = state.dataIPShortCut->rNumericArgs(19);
     765             : 
     766             :             // Allocate the circuit placeholder arrays
     767           4 :             int const NumCircuitsInThisDomain = int(state.dataIPShortCut->rNumericArgs(20));
     768             : 
     769             :             // Need to store the ground temp stuff because it will get wiped out in the call to the circuit factory
     770           8 :             std::string const groundTempType = state.dataIPShortCut->cAlphaArgs(5);
     771           8 :             std::string const groundTempName = state.dataIPShortCut->cAlphaArgs(6);
     772             : 
     773             :             // Need to loop once to store the names ahead of time because calling the segment factory will override cAlphaArgs
     774           8 :             std::vector<std::string> circuitNamesToFind;
     775           4 :             int constexpr NumAlphasBeforePipeCircOne = 10;
     776           8 :             for (int CircuitCtr = 1; CircuitCtr <= NumCircuitsInThisDomain; ++CircuitCtr) {
     777           4 :                 CurIndex = CircuitCtr + NumAlphasBeforePipeCircOne;
     778           4 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(CurIndex)) {
     779           0 :                     IssueSevereInputFieldError(state,
     780             :                                                RoutineName,
     781             :                                                ObjName_Segment,
     782           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
     783           0 :                                                state.dataIPShortCut->cAlphaFieldNames(CurIndex),
     784           0 :                                                state.dataIPShortCut->cAlphaArgs(CurIndex),
     785             :                                                "Expected a pipe circuit name, check pipe circuit count input field.",
     786             :                                                ErrorsFound);
     787             :                 }
     788           4 :                 circuitNamesToFind.push_back(state.dataIPShortCut->cAlphaArgs(CurIndex));
     789             :             }
     790             :             // then we can loop through and allow the factory to be called and carry on
     791           8 :             for (auto &circuitNameToFind : circuitNamesToFind) {
     792           4 :                 thisDomain.circuits.push_back(Circuit::factory(state, circuitNameToFind, ErrorsFound));
     793             :             }
     794             : 
     795             :             // Initialize ground temperature model and get pointer reference
     796           4 :             thisDomain.groundTempModel = GetGroundTempModelAndInit(state, groundTempType, groundTempName);
     797             :         }
     798          11 :     }
     799             : 
     800          11 :     void ReadZoneCoupledDomainInputs(EnergyPlusData &state, int const StartingDomainNumForZone, int const NumZoneCoupledDomains, bool &ErrorsFound)
     801             :     {
     802             : 
     803             :         // SUBROUTINE INFORMATION:
     804             :         //       AUTHOR         Edwin Lee
     805             :         //       DATE WRITTEN   Summer 2011
     806             :         //       MODIFIED       Spring 2014 by Matt Mitchell and Sushobhit Acharya to accommodate ground coupled calculations
     807             :         //       RE-ENGINEERED  na
     808             : 
     809             :         // SUBROUTINE PARAMETER DEFINITIONS:
     810             :         static constexpr std::string_view RoutineName("ReadZoneCoupledDomainInputs");
     811             : 
     812             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     813             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
     814             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
     815             :         int IOStatus;   // Used in GetObjectItem
     816             : 
     817             :         // initialize these counters properly so they can be incremented within the DO loop
     818          11 :         int DomainCtr = StartingDomainNumForZone - 1;
     819             : 
     820             :         // For each domain, we need to process the inputs into a local array of derived type, then resolve each one, creating definitions for a zone
     821             :         // coupled domain. This way, the outer get input routines can handle it as though they were generalized routines
     822             : 
     823          16 :         for (int ZoneCoupledDomainCtr = 1; ZoneCoupledDomainCtr <= NumZoneCoupledDomains; ++ZoneCoupledDomainCtr) {
     824             : 
     825             :             // Increment the domain counters here
     826           5 :             ++DomainCtr;
     827             : 
     828             :             // Read all the inputs for this domain object
     829          35 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     830             :                                                                      ObjName_ZoneCoupled_Slab,
     831             :                                                                      ZoneCoupledDomainCtr,
     832           5 :                                                                      state.dataIPShortCut->cAlphaArgs,
     833             :                                                                      NumAlphas,
     834           5 :                                                                      state.dataIPShortCut->rNumericArgs,
     835             :                                                                      NumNumbers,
     836             :                                                                      IOStatus,
     837           5 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     838           5 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     839           5 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     840           5 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     841             : 
     842           5 :             auto &thisDomain = state.dataPlantPipingSysMgr->domains[DomainCtr - 1];
     843             : 
     844             :             // Get the name, validate
     845             :             // Domain name
     846           5 :             thisDomain.Name = state.dataIPShortCut->cAlphaArgs(1);
     847             : 
     848          10 :             GlobalNames::VerifyUniqueInterObjectName(state,
     849           5 :                                                      state.dataPlantPipingSysMgr->GroundDomainUniqueNames,
     850           5 :                                                      state.dataIPShortCut->cAlphaArgs(1),
     851             :                                                      ObjName_ZoneCoupled_Slab,
     852           5 :                                                      state.dataIPShortCut->cAlphaFieldNames(1),
     853             :                                                      ErrorsFound);
     854             : 
     855             :             // Read in the rest of the inputs into the local type for clarity during transition
     856           5 :             thisDomain.Extents.yMax = state.dataIPShortCut->rNumericArgs(1);
     857           5 :             thisDomain.PerimeterOffset = state.dataIPShortCut->rNumericArgs(3);
     858           5 :             thisDomain.GroundProperties.Conductivity = state.dataIPShortCut->rNumericArgs(4);
     859           5 :             thisDomain.GroundProperties.Density = state.dataIPShortCut->rNumericArgs(5);
     860           5 :             thisDomain.GroundProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(6);
     861           5 :             thisDomain.Moisture.Theta_liq = state.dataIPShortCut->rNumericArgs(7) / 100.0;
     862           5 :             thisDomain.Moisture.Theta_sat = state.dataIPShortCut->rNumericArgs(8) / 100.0;
     863           5 :             thisDomain.Moisture.GroundCoverCoefficient = state.dataIPShortCut->rNumericArgs(9);
     864           5 :             thisDomain.HorizInsWidth = state.dataIPShortCut->rNumericArgs(10);
     865           5 :             thisDomain.VertInsDepth = state.dataIPShortCut->rNumericArgs(11);
     866             : 
     867             :             // Set flag for slab in-grade or slab on-grade
     868           5 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "INGRADE")) {
     869           4 :                 thisDomain.SlabInGradeFlag = true;
     870           1 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "ONGRADE")) {
     871           1 :                 thisDomain.SlabInGradeFlag = false;
     872             :             } else {
     873           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + "=" + state.dataIPShortCut->cAlphaArgs(5));
     874           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
     875           0 :                 ErrorsFound = true;
     876             :             }
     877             : 
     878             :             // Get slab material properties
     879           5 :             if (thisDomain.SlabInGradeFlag) {
     880          12 :                 thisDomain.SlabMaterialNum = UtilityRoutines::FindItemInList(
     881          12 :                     state.dataIPShortCut->cAlphaArgs(6), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
     882           4 :                 if (thisDomain.SlabMaterialNum == 0) {
     883           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + "=" + state.dataIPShortCut->cAlphaArgs(6));
     884           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     885           0 :                     ErrorsFound = true;
     886             :                 } else {
     887           4 :                     thisDomain.SlabThickness = state.dataMaterial->Material(thisDomain.SlabMaterialNum).Thickness;
     888           4 :                     thisDomain.SlabProperties.Density = state.dataMaterial->Material(thisDomain.SlabMaterialNum).Density;
     889           4 :                     thisDomain.SlabProperties.SpecificHeat = state.dataMaterial->Material(thisDomain.SlabMaterialNum).SpecHeat;
     890           4 :                     thisDomain.SlabProperties.Conductivity = state.dataMaterial->Material(thisDomain.SlabMaterialNum).Conductivity;
     891             :                 }
     892             :             }
     893             : 
     894             :             // set flag for horizontal insulation
     895           5 :             if (thisDomain.SlabInGradeFlag) {
     896           4 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "NO")) {
     897           0 :                     thisDomain.HorizInsPresentFlag = false;
     898           4 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "YES")) {
     899           4 :                     thisDomain.HorizInsPresentFlag = true;
     900             :                 } else {
     901           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(7) + "=" + state.dataIPShortCut->cAlphaArgs(7));
     902           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     903           0 :                     ErrorsFound = true;
     904             :                 }
     905             :             }
     906             : 
     907             :             // Get horizontal insulation material properties
     908           5 :             if (thisDomain.HorizInsPresentFlag) {
     909          12 :                 thisDomain.HorizInsMaterialNum = UtilityRoutines::FindItemInList(
     910          12 :                     state.dataIPShortCut->cAlphaArgs(8), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
     911           4 :                 if (thisDomain.HorizInsMaterialNum == 0) {
     912           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(8) + "=" + state.dataIPShortCut->cAlphaArgs(8));
     913           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     914           0 :                     ErrorsFound = true;
     915             :                 } else {
     916           4 :                     thisDomain.HorizInsThickness = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Thickness;
     917           4 :                     thisDomain.HorizInsProperties.Density = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Density;
     918           4 :                     thisDomain.HorizInsProperties.SpecificHeat = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).SpecHeat;
     919           4 :                     thisDomain.HorizInsProperties.Conductivity = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Conductivity;
     920           4 :                     if (SiteGroundDomainUsingNoMassMat(state, thisDomain.HorizInsThickness, thisDomain.HorizInsMaterialNum)) {
     921           0 :                         ErrorsFound = true;
     922           0 :                         SiteGroundDomainNoMassMatError(
     923           0 :                             state, state.dataIPShortCut->cAlphaFieldNames(8), state.dataIPShortCut->cAlphaArgs(8), thisDomain.Name);
     924             :                     }
     925             :                 }
     926             : 
     927             :                 // Set flag for horizontal insulation extents
     928           4 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "PERIMETER")) {
     929           0 :                     thisDomain.FullHorizInsPresent = false;
     930             :                     // Horizontal insulation perimeter width
     931           0 :                     if (thisDomain.HorizInsWidth <= 0.0) {
     932           0 :                         ShowSevereError(state, "Invalid " + state.dataIPShortCut->cNumericFieldNames(10));
     933           0 :                         ShowContinueError(state, "Found in: " + thisDomain.Name);
     934           0 :                         ErrorsFound = true;
     935             :                     }
     936           4 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "FULL")) {
     937           4 :                     thisDomain.FullHorizInsPresent = true;
     938             :                 } else {
     939           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + "=" + state.dataIPShortCut->cAlphaArgs(9));
     940           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     941           0 :                     ErrorsFound = true;
     942             :                 }
     943             :             }
     944             : 
     945             :             // set flag for vertical insulation
     946           5 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "NO")) {
     947           0 :                 thisDomain.VertInsPresentFlag = false;
     948           5 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(10), "YES")) {
     949           5 :                 thisDomain.VertInsPresentFlag = true;
     950             :             } else {
     951           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(10) + "=" + state.dataIPShortCut->cAlphaArgs(10));
     952           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
     953           0 :                 ErrorsFound = true;
     954             :             }
     955             : 
     956             :             // Get vertical insulation material properties
     957           5 :             if (thisDomain.VertInsPresentFlag) {
     958          15 :                 thisDomain.VertInsMaterialNum = UtilityRoutines::FindItemInList(
     959          15 :                     state.dataIPShortCut->cAlphaArgs(11), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
     960           5 :                 if (thisDomain.VertInsMaterialNum == 0) {
     961           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(11) + "=" + state.dataIPShortCut->cAlphaArgs(11));
     962           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     963           0 :                     ErrorsFound = true;
     964             :                 } else {
     965           5 :                     thisDomain.VertInsThickness = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Thickness;
     966           5 :                     thisDomain.VertInsProperties.Density = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Density;
     967           5 :                     thisDomain.VertInsProperties.SpecificHeat = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).SpecHeat;
     968           5 :                     thisDomain.VertInsProperties.Conductivity = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Conductivity;
     969           5 :                     if (SiteGroundDomainUsingNoMassMat(state, thisDomain.VertInsThickness, thisDomain.VertInsMaterialNum)) {
     970           0 :                         ErrorsFound = true;
     971           0 :                         SiteGroundDomainNoMassMatError(
     972           0 :                             state, state.dataIPShortCut->cAlphaFieldNames(11), state.dataIPShortCut->cAlphaArgs(11), thisDomain.Name);
     973             :                     }
     974             :                 }
     975             : 
     976             :                 // vertical insulation depth
     977           5 :                 if (thisDomain.VertInsDepth > thisDomain.Extents.yMax || thisDomain.VertInsDepth <= 0.0) {
     978           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cNumericFieldNames(11));
     979           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
     980           0 :                     ErrorsFound = true;
     981             :                 }
     982             :             }
     983             : 
     984             :             // Set simulation interval flag
     985           5 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(12), "TIMESTEP")) {
     986           3 :                 thisDomain.SimTimeStepFlag = true;
     987           2 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(12), "HOURLY")) {
     988           2 :                 thisDomain.SimHourlyFlag = true;
     989             :             } else {
     990           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(12) + "=" + state.dataIPShortCut->cAlphaArgs(12));
     991           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
     992           0 :                 ErrorsFound = true;
     993             :             }
     994             : 
     995             :             //******* We'll first set up the domain ********
     996           5 :             thisDomain.IsActuallyPartOfAHorizontalTrench = false;
     997           5 :             thisDomain.HasAPipeCircuit = false;
     998           5 :             thisDomain.HasZoneCoupledSlab = true;
     999             : 
    1000             :             // get boundary condition model names and indices -- error check
    1001           5 :             thisDomain.ZoneCoupledOSCMIndex = UtilityRoutines::FindItemInList(state.dataIPShortCut->cAlphaArgs(4), state.dataSurface->OSCM);
    1002           5 :             if (thisDomain.ZoneCoupledOSCMIndex <= 0) {
    1003           0 :                 IssueSevereInputFieldError(state,
    1004             :                                            RoutineName,
    1005             :                                            ObjName_ZoneCoupled_Slab,
    1006           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1007           0 :                                            state.dataIPShortCut->cAlphaFieldNames(4),
    1008           0 :                                            state.dataIPShortCut->cAlphaArgs(4),
    1009             :                                            "Could not match with an Other Side Conditions Model input object.",
    1010             :                                            ErrorsFound);
    1011           0 :                 ErrorsFound = true;
    1012             :             } else {
    1013           5 :                 int const NumSurfacesWithThisOSCM = GetSurfaceCountForOSCM(state, thisDomain.ZoneCoupledOSCMIndex);
    1014           5 :                 if (NumSurfacesWithThisOSCM <= 0) {
    1015           0 :                     IssueSevereInputFieldError(
    1016             :                         state,
    1017             :                         RoutineName,
    1018             :                         ObjName_ZoneCoupled_Slab,
    1019           0 :                         state.dataIPShortCut->cAlphaArgs(1),
    1020           0 :                         state.dataIPShortCut->cAlphaFieldNames(4),
    1021           0 :                         state.dataIPShortCut->cAlphaArgs(4),
    1022             :                         "Entry matched an Other Side Conditions Model, but no surfaces were found to be using this Other Side Conditions Model.",
    1023             :                         ErrorsFound);
    1024           0 :                     ErrorsFound = true;
    1025             :                 } else {
    1026           5 :                     thisDomain.ZoneCoupledSurfaces = GetSurfaceDataForOSCM(state, thisDomain.ZoneCoupledOSCMIndex);
    1027             :                 }
    1028             :             }
    1029             : 
    1030             :             // Total surface area
    1031          15 :             auto lambda = [](Real64 total, ZoneCoupledSurfaceData const &z) { return total + z.SurfaceArea; };
    1032           5 :             Real64 const ThisArea = std::accumulate(thisDomain.ZoneCoupledSurfaces.begin(), thisDomain.ZoneCoupledSurfaces.end(), 0.0, lambda);
    1033             : 
    1034           5 :             thisDomain.SlabArea = ThisArea / 4; // We are only interested in 1/4 of total area due to symmetry
    1035             : 
    1036             :             // Surface dimensions
    1037           5 :             Real64 thisAspectRatio = state.dataIPShortCut->rNumericArgs(2);
    1038           5 :             thisDomain.SlabWidth = std::sqrt(ThisArea / thisAspectRatio);
    1039           5 :             thisDomain.SlabLength = thisDomain.SlabWidth * thisAspectRatio;
    1040             : 
    1041             :             // Check horizontal insulation width so as to prevent overlapping insulation. VertInsThickness is used here since it is used for vertical
    1042             :             // partition thickness.
    1043           5 :             if (!thisDomain.FullHorizInsPresent && ThisArea > 0.0) {
    1044           2 :                 if (2 * (thisDomain.HorizInsWidth + thisDomain.VertInsThickness) > thisDomain.SlabWidth ||
    1045           1 :                     2 * (thisDomain.HorizInsWidth + thisDomain.VertInsThickness) > thisDomain.SlabLength) {
    1046           0 :                     ShowContinueError(state, std::string{RoutineName} + ": Perimeter insulation width is too large.");
    1047           0 :                     ShowContinueError(state, "This would cause overlapping insulation. Check inputs.");
    1048           0 :                     ShowContinueError(state, "Defaulting to full horizontal insulation.");
    1049           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1050           0 :                     thisDomain.FullHorizInsPresent = true;
    1051             :                 }
    1052             :             }
    1053             : 
    1054             :             // Set ground domain dimensions
    1055           5 :             thisDomain.Extents.xMax = thisDomain.PerimeterOffset + thisDomain.SlabWidth / 2;
    1056             :             // thisDomain.Extents.yMax read above
    1057           5 :             thisDomain.Extents.zMax = thisDomain.PerimeterOffset + thisDomain.SlabLength / 2;
    1058             : 
    1059             :             // Get mesh parameters
    1060             : 
    1061             :             // Mesh inputs
    1062           5 :             thisDomain.Mesh.X.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
    1063           5 :             thisDomain.Mesh.Y.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
    1064           5 :             thisDomain.Mesh.Z.thisMeshDistribution = MeshDistribution::SymmetricGeometric;
    1065             : 
    1066           5 :             Real64 MeshCoefficient = state.dataIPShortCut->rNumericArgs(12);
    1067           5 :             if (MeshCoefficient == 0.0) MeshCoefficient = 1.6;
    1068           5 :             thisDomain.Mesh.X.GeometricSeriesCoefficient = MeshCoefficient;
    1069           5 :             thisDomain.Mesh.Y.GeometricSeriesCoefficient = MeshCoefficient;
    1070           5 :             thisDomain.Mesh.Z.GeometricSeriesCoefficient = MeshCoefficient;
    1071             : 
    1072           5 :             int MeshCount = static_cast<int>(state.dataIPShortCut->rNumericArgs(13));
    1073           5 :             if (MeshCount == 0.0) MeshCount = 6;
    1074           5 :             thisDomain.Mesh.X.RegionMeshCount = MeshCount;
    1075           5 :             thisDomain.Mesh.Y.RegionMeshCount = MeshCount;
    1076           5 :             thisDomain.Mesh.Z.RegionMeshCount = MeshCount;
    1077             : 
    1078           5 :             thisDomain.NumSlabCells = thisDomain.Mesh.Y.RegionMeshCount; // Need to clean this out at some point
    1079             : 
    1080             :             // Farfield model
    1081           5 :             thisDomain.groundTempModel = GetGroundTempModelAndInit(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(3));
    1082             : 
    1083             :             // Other parameters
    1084           5 :             thisDomain.SimControls.Convergence_CurrentToPrevIteration = 0.001;
    1085           5 :             thisDomain.SimControls.MaxIterationsPerTS = 250;
    1086             : 
    1087             :             // setup output variables
    1088           5 :             thisDomain.SetupZoneCoupledOutputVariables(state);
    1089             :         }
    1090          11 :     }
    1091             : 
    1092          11 :     void ReadBasementInputs(EnergyPlusData &state, int const StartingDomainNumForBasement, int const NumBasements, bool &ErrorsFound)
    1093             :     {
    1094             : 
    1095             :         // SUBROUTINE INFORMATION:
    1096             :         //       AUTHOR         Edwin Lee
    1097             :         //       DATE WRITTEN   Summer 2011
    1098             :         //       MODIFIED       Summer 2014  Sushobhit Acharya to accommodate basement calculations
    1099             :         //       RE-ENGINEERED  na
    1100             : 
    1101             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1102             :         static constexpr std::string_view RoutineName("ReadBasementInputs");
    1103             : 
    1104             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1105             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
    1106             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
    1107             :         int IOStatus;   // Used in GetObjectItem
    1108             :         int CurIndex;
    1109             : 
    1110             :         // initialize these counters properly so they can be incremented within the DO loop
    1111          11 :         int DomainNum = StartingDomainNumForBasement - 1;
    1112             : 
    1113             :         // For each domain, we need to process the inputs into a local array of derived type, then resolve each one, creating definitions for a zone
    1114             :         // coupled domain. This way, the outer get input routines can handle it as though they were generalized routines
    1115             : 
    1116          12 :         for (int BasementCtr = 1; BasementCtr <= NumBasements; ++BasementCtr) {
    1117             : 
    1118             :             // Increment the domain counters here
    1119           1 :             ++DomainNum;
    1120             : 
    1121             :             // Read all the inputs for this domain object
    1122           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1123             :                                                                      ObjName_ZoneCoupled_Basement,
    1124             :                                                                      BasementCtr,
    1125           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1126             :                                                                      NumAlphas,
    1127           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    1128             :                                                                      NumNumbers,
    1129             :                                                                      IOStatus,
    1130           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1131           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1132           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1133           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1134             : 
    1135           1 :             auto &thisDomain = state.dataPlantPipingSysMgr->domains[DomainNum - 1];
    1136             : 
    1137             :             // Get the name, validate
    1138           1 :             thisDomain.Name = state.dataIPShortCut->cAlphaArgs(1);
    1139           2 :             GlobalNames::VerifyUniqueInterObjectName(state,
    1140           1 :                                                      state.dataPlantPipingSysMgr->GroundDomainUniqueNames,
    1141           1 :                                                      state.dataIPShortCut->cAlphaArgs(1),
    1142             :                                                      ObjName_ZoneCoupled_Basement,
    1143           1 :                                                      state.dataIPShortCut->cAlphaFieldNames(1),
    1144             :                                                      ErrorsFound);
    1145             : 
    1146             :             // Read in the some of the inputs into the local type for clarity during transition
    1147           1 :             thisDomain.Extents.yMax = state.dataIPShortCut->rNumericArgs(1);
    1148           1 :             Real64 const thisAspectRatio = state.dataIPShortCut->rNumericArgs(2);
    1149           1 :             thisDomain.PerimeterOffset = state.dataIPShortCut->rNumericArgs(3);
    1150           1 :             thisDomain.HorizInsWidth = state.dataIPShortCut->rNumericArgs(10);
    1151           1 :             thisDomain.VertInsDepth = state.dataIPShortCut->rNumericArgs(12);
    1152             : 
    1153             :             // Other inputs
    1154           1 :             thisDomain.Name = state.dataIPShortCut->cAlphaArgs(1);
    1155             : 
    1156             :             // Soil properties, validated min/max by IP
    1157           1 :             thisDomain.GroundProperties.Conductivity = state.dataIPShortCut->rNumericArgs(4);
    1158           1 :             thisDomain.GroundProperties.Density = state.dataIPShortCut->rNumericArgs(5);
    1159           1 :             thisDomain.GroundProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(6);
    1160             : 
    1161             :             // Moisture properties, validated min/max by IP, and converted to a fraction for computation here
    1162           1 :             thisDomain.Moisture.Theta_liq = state.dataIPShortCut->rNumericArgs(7) / 100.0;
    1163           1 :             thisDomain.Moisture.Theta_sat = state.dataIPShortCut->rNumericArgs(8) / 100.0;
    1164             : 
    1165             :             // check if there are blank inputs related to the basement,
    1166           2 :             if (state.dataIPShortCut->lNumericFieldBlanks(11) || state.dataIPShortCut->lAlphaFieldBlanks(5) ||
    1167           1 :                 state.dataIPShortCut->lAlphaFieldBlanks(10)) {
    1168           0 :                 ShowSevereError(state, "Erroneous basement inputs for " + ObjName_ZoneCoupled_Basement + '=' + state.dataIPShortCut->cAlphaArgs(1));
    1169           0 :                 ShowContinueError(state, "At least one basement input was left blank.");
    1170           0 :                 ErrorsFound = true;
    1171             :             }
    1172             : 
    1173             :             // Basement zone depth
    1174           1 :             CurIndex = 11;
    1175           1 :             thisDomain.BasementZone.Depth = state.dataIPShortCut->rNumericArgs(CurIndex);
    1176           1 :             if (thisDomain.BasementZone.Depth >= thisDomain.Extents.yMax || thisDomain.BasementZone.Depth <= 0.0) {
    1177           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cNumericFieldNames(CurIndex));
    1178           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
    1179           0 :                 ErrorsFound = true;
    1180             :             }
    1181             : 
    1182             :             // get boundary condition model names and indices --error check
    1183           1 :             CurIndex = 4;
    1184           1 :             thisDomain.BasementZone.FloorBoundaryOSCMName = state.dataIPShortCut->cAlphaArgs(CurIndex);
    1185           1 :             thisDomain.BasementZone.FloorBoundaryOSCMIndex =
    1186           1 :                 UtilityRoutines::FindItemInList(thisDomain.BasementZone.FloorBoundaryOSCMName, state.dataSurface->OSCM);
    1187           1 :             if (thisDomain.BasementZone.FloorBoundaryOSCMIndex <= 0) {
    1188           0 :                 IssueSevereInputFieldError(state,
    1189             :                                            RoutineName,
    1190             :                                            ObjName_ZoneCoupled_Basement,
    1191           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1192           0 :                                            state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1193           0 :                                            state.dataIPShortCut->cAlphaArgs(CurIndex),
    1194             :                                            "Could not match with an Other Side Conditions Model input object.",
    1195             :                                            ErrorsFound);
    1196             :             } else {
    1197           2 :                 auto const &floorIndexes = GetSurfaceIndecesForOSCM(state, thisDomain.BasementZone.FloorBoundaryOSCMIndex);
    1198           1 :                 if (floorIndexes.empty()) {
    1199           0 :                     IssueSevereInputFieldError(
    1200             :                         state,
    1201             :                         RoutineName,
    1202             :                         ObjName_ZoneCoupled_Basement,
    1203           0 :                         state.dataIPShortCut->cAlphaArgs(1),
    1204           0 :                         state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1205           0 :                         state.dataIPShortCut->cAlphaArgs(CurIndex),
    1206             :                         "Entry matched an Other Side Conditions Model, but no surfaces were found to be using this Other Side Conditions Model.",
    1207             :                         ErrorsFound);
    1208             :                 } else {
    1209           1 :                     thisDomain.BasementZone.FloorSurfacePointers = floorIndexes;
    1210             :                     // Create GetSurfaceDataForOSCM function
    1211           1 :                     thisDomain.ZoneCoupledSurfaces = GetSurfaceDataForOSCM(state, thisDomain.BasementZone.FloorBoundaryOSCMIndex);
    1212             :                 }
    1213             :             }
    1214             : 
    1215           1 :             CurIndex = 8;
    1216           1 :             thisDomain.BasementZone.WallBoundaryOSCMName = state.dataIPShortCut->cAlphaArgs(CurIndex);
    1217           1 :             thisDomain.BasementZone.WallBoundaryOSCMIndex =
    1218           1 :                 UtilityRoutines::FindItemInList(thisDomain.BasementZone.WallBoundaryOSCMName, state.dataSurface->OSCM);
    1219           1 :             if (thisDomain.BasementZone.WallBoundaryOSCMIndex <= 0) {
    1220           0 :                 IssueSevereInputFieldError(state,
    1221             :                                            RoutineName,
    1222             :                                            ObjName_ZoneCoupled_Basement,
    1223           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1224           0 :                                            state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1225           0 :                                            state.dataIPShortCut->cAlphaArgs(CurIndex),
    1226             :                                            "Could not match with an Other Side Conditions Model input object.",
    1227             :                                            ErrorsFound);
    1228           0 :                 ErrorsFound = true;
    1229             :             } else {
    1230           2 :                 auto const &wallIndexes = GetSurfaceIndecesForOSCM(state, thisDomain.BasementZone.WallBoundaryOSCMIndex);
    1231           1 :                 if (wallIndexes.empty()) {
    1232           0 :                     IssueSevereInputFieldError(
    1233             :                         state,
    1234             :                         RoutineName,
    1235             :                         ObjName_ZoneCoupled_Basement,
    1236           0 :                         state.dataIPShortCut->cAlphaArgs(1),
    1237           0 :                         state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1238           0 :                         state.dataIPShortCut->cAlphaArgs(CurIndex),
    1239             :                         "Entry matched an Other Side Conditions Model, but no surfaces were found to be using this Other Side Conditions Model.",
    1240             :                         ErrorsFound);
    1241           0 :                     ErrorsFound = true;
    1242             :                 } else {
    1243           1 :                     thisDomain.BasementZone.WallSurfacePointers = wallIndexes;
    1244             :                 }
    1245             :             }
    1246             : 
    1247             :             // get some convergence tolerances, minimum/maximum are enforced by the IP, along with default values if user left them blank
    1248           1 :             thisDomain.SimControls.Convergence_CurrentToPrevIteration = 0.01;
    1249           1 :             thisDomain.SimControls.MaxIterationsPerTS = 250;
    1250             : 
    1251             :             // additional evapotranspiration parameter, min/max validated by IP
    1252           1 :             thisDomain.Moisture.GroundCoverCoefficient = state.dataIPShortCut->rNumericArgs(9);
    1253             : 
    1254             :             // assign the mesh count
    1255             :             int meshCount;
    1256           1 :             if (state.dataIPShortCut->lNumericFieldBlanks(13)) {
    1257           1 :                 meshCount = 4;
    1258             :             } else {
    1259           0 :                 meshCount = static_cast<int>(state.dataIPShortCut->rNumericArgs(13));
    1260             :             }
    1261           1 :             thisDomain.Mesh.X.RegionMeshCount = meshCount;
    1262           1 :             thisDomain.Mesh.Y.RegionMeshCount = meshCount;
    1263           1 :             thisDomain.Mesh.Z.RegionMeshCount = meshCount;
    1264             : 
    1265           1 :             thisDomain.Mesh.X.thisMeshDistribution = MeshDistribution::Uniform;
    1266           1 :             thisDomain.Mesh.Y.thisMeshDistribution = MeshDistribution::Uniform;
    1267           1 :             thisDomain.Mesh.Z.thisMeshDistribution = MeshDistribution::Uniform;
    1268             : 
    1269             :             // Initialize properties for basement interface cells
    1270           1 :             thisDomain.BasementInterfaceProperties.Conductivity = 500.0;
    1271           1 :             thisDomain.BasementInterfaceProperties.SpecificHeat = 1.0;
    1272           1 :             thisDomain.BasementInterfaceProperties.Density = 1.0;
    1273             : 
    1274             :             // set flag for horizontal insulation
    1275             :             // Check state.dataIPShortCut->cAlphaArgs value
    1276           1 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "NO")) {
    1277           0 :                 thisDomain.HorizInsPresentFlag = false;
    1278           1 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "YES")) {
    1279           1 :                 thisDomain.HorizInsPresentFlag = true;
    1280             :             } else {
    1281           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(5) + "=" + state.dataIPShortCut->cAlphaArgs(5));
    1282           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
    1283           0 :                 ErrorsFound = true;
    1284             :             }
    1285             : 
    1286             :             // Get horizontal insulation material properties
    1287           1 :             if (thisDomain.HorizInsPresentFlag) {
    1288           3 :                 thisDomain.HorizInsMaterialNum = UtilityRoutines::FindItemInList(
    1289           3 :                     state.dataIPShortCut->cAlphaArgs(6), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
    1290           1 :                 if (thisDomain.HorizInsMaterialNum == 0) {
    1291           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + "=" + state.dataIPShortCut->cAlphaArgs(6));
    1292           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1293           0 :                     ErrorsFound = true;
    1294             :                 } else {
    1295           1 :                     thisDomain.HorizInsThickness = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Thickness;
    1296           1 :                     thisDomain.HorizInsProperties.Density = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Density;
    1297           1 :                     thisDomain.HorizInsProperties.SpecificHeat = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).SpecHeat;
    1298           1 :                     thisDomain.HorizInsProperties.Conductivity = state.dataMaterial->Material(thisDomain.HorizInsMaterialNum).Conductivity;
    1299           1 :                     if (SiteGroundDomainUsingNoMassMat(state, thisDomain.HorizInsThickness, thisDomain.HorizInsMaterialNum)) {
    1300           0 :                         ErrorsFound = true;
    1301           0 :                         SiteGroundDomainNoMassMatError(
    1302           0 :                             state, state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6), thisDomain.Name);
    1303             :                     }
    1304             :                 }
    1305             : 
    1306             :                 // Set flag for horizontal insulation extents
    1307           1 :                 if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "PERIMETER")) {
    1308           1 :                     thisDomain.FullHorizInsPresent = false;
    1309             :                     // Horizontal insulation perimeter width
    1310           1 :                     if (thisDomain.HorizInsWidth <= 0.0) {
    1311           0 :                         ShowSevereError(state, "Invalid " + state.dataIPShortCut->cNumericFieldNames(10));
    1312           0 :                         ShowContinueError(state, "Found in: " + thisDomain.Name);
    1313           0 :                         ErrorsFound = true;
    1314             :                     }
    1315           0 :                 } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "FULL")) {
    1316           0 :                     thisDomain.FullHorizInsPresent = true;
    1317             :                 } else {
    1318           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(7) + "=" + state.dataIPShortCut->cAlphaArgs(7));
    1319           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1320           0 :                     ErrorsFound = true;
    1321             :                 }
    1322             :             }
    1323             : 
    1324             :             // set flag for vertical insulation
    1325           1 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "NO")) {
    1326           0 :                 thisDomain.VertInsPresentFlag = false;
    1327           1 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(9), "YES")) {
    1328           1 :                 thisDomain.VertInsPresentFlag = true;
    1329             :             } else {
    1330           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(9) + "=" + state.dataIPShortCut->cAlphaArgs(9));
    1331           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
    1332           0 :                 ErrorsFound = true;
    1333             :             }
    1334             : 
    1335             :             // Get vertical insulation material properties
    1336           1 :             if (thisDomain.VertInsPresentFlag) {
    1337             :                 // Check if vertical insulation is in domain
    1338           1 :                 if (thisDomain.VertInsDepth >= thisDomain.Extents.yMax || thisDomain.VertInsDepth <= 0.0) {
    1339           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cNumericFieldNames(12));
    1340           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1341           0 :                     ErrorsFound = true;
    1342             :                 }
    1343           3 :                 thisDomain.VertInsMaterialNum = UtilityRoutines::FindItemInList(
    1344           3 :                     state.dataIPShortCut->cAlphaArgs(10), state.dataMaterial->Material, state.dataHeatBal->TotMaterials);
    1345           1 :                 if (thisDomain.VertInsMaterialNum == 0) {
    1346           0 :                     ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(10) + "=" + state.dataIPShortCut->cAlphaArgs(10));
    1347           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1348           0 :                     ErrorsFound = true;
    1349             :                 } else {
    1350           1 :                     thisDomain.VertInsThickness = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Thickness;
    1351           1 :                     thisDomain.VertInsProperties.Density = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Density;
    1352           1 :                     thisDomain.VertInsProperties.SpecificHeat = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).SpecHeat;
    1353           1 :                     thisDomain.VertInsProperties.Conductivity = state.dataMaterial->Material(thisDomain.VertInsMaterialNum).Conductivity;
    1354           1 :                     if (SiteGroundDomainUsingNoMassMat(state, thisDomain.VertInsThickness, thisDomain.VertInsMaterialNum)) {
    1355           0 :                         ErrorsFound = true;
    1356           0 :                         SiteGroundDomainNoMassMatError(
    1357           0 :                             state, state.dataIPShortCut->cAlphaFieldNames(10), state.dataIPShortCut->cAlphaArgs(10), thisDomain.Name);
    1358             :                     }
    1359             :                 }
    1360             :             }
    1361             : 
    1362             :             // Set simulation interval flag
    1363           1 :             if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(11), "TIMESTEP")) {
    1364           1 :                 thisDomain.SimTimeStepFlag = true;
    1365           0 :             } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(11), "HOURLY")) {
    1366           0 :                 thisDomain.SimHourlyFlag = true;
    1367             :             } else {
    1368           0 :                 ShowSevereError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(11) + "=" + state.dataIPShortCut->cAlphaArgs(11));
    1369           0 :                 ShowContinueError(state, "Found in: " + thisDomain.Name);
    1370           0 :                 ErrorsFound = true;
    1371             :             }
    1372             : 
    1373             :             // Farfield ground temperature model -- note this will overwrite the DataIPShortCuts variables
    1374             :             // so any other processing below this line won't have access to the cAlphaArgs, etc., here
    1375           1 :             thisDomain.groundTempModel = GetGroundTempModelAndInit(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(3));
    1376             : 
    1377             :             // Total surface area
    1378           1 :             Real64 ThisArea = 0.0;
    1379           2 :             for (auto &z : thisDomain.ZoneCoupledSurfaces) {
    1380           1 :                 ThisArea += z.SurfaceArea;
    1381             :             }
    1382             : 
    1383             :             // Surface dimensions
    1384           1 :             thisDomain.BasementZone.Width = sqrt(ThisArea / thisAspectRatio);
    1385           1 :             thisDomain.BasementZone.Length = thisDomain.BasementZone.Width * thisAspectRatio;
    1386             : 
    1387             :             // Set ground domain dimensions
    1388             :             // get width and length from aspect ratio later
    1389           1 :             thisDomain.Extents.xMax = thisDomain.PerimeterOffset + thisDomain.BasementZone.Width / 2;
    1390           1 :             thisDomain.Extents.zMax = thisDomain.PerimeterOffset + thisDomain.BasementZone.Length / 2;
    1391             : 
    1392             :             // Check horizontal insulation width so as to prevent overlapping insulation. VertInsThickness is used here since it is used for vertical
    1393             :             // partition thickness.
    1394           1 :             if (!thisDomain.FullHorizInsPresent && ThisArea > 0.0) {
    1395           2 :                 if ((thisDomain.HorizInsWidth + thisDomain.VertInsThickness) > thisDomain.BasementZone.Width / 2.0 ||
    1396           1 :                     (thisDomain.HorizInsWidth + thisDomain.VertInsThickness) > thisDomain.BasementZone.Length / 2.0) {
    1397           0 :                     ShowContinueError(state, std::string{RoutineName} + ": Perimeter insulation width is too large.");
    1398           0 :                     ShowContinueError(state, "This would cause overlapping insulation. Check inputs.");
    1399           0 :                     ShowContinueError(state, "Defaulting to full horizontal insulation.");
    1400           0 :                     ShowContinueError(state, "Found in: " + thisDomain.Name);
    1401           0 :                     thisDomain.FullHorizInsPresent = true;
    1402             :                 }
    1403             :             }
    1404             : 
    1405             :             //******* We'll first set up the domain ********
    1406           1 :             thisDomain.IsActuallyPartOfAHorizontalTrench = false;
    1407           1 :             thisDomain.HasAPipeCircuit = false;
    1408           1 :             thisDomain.HasZoneCoupledSlab = false;
    1409           1 :             thisDomain.HasBasement = false;
    1410           1 :             thisDomain.HasZoneCoupledBasement = true;
    1411             : 
    1412             :             // setup output variables
    1413           1 :             thisDomain.SetupZoneCoupledOutputVariables(state);
    1414             :         }
    1415          11 :     }
    1416             : 
    1417          11 :     bool SiteGroundDomainUsingNoMassMat([[maybe_unused]] EnergyPlusData &state, Real64 const MaterialThickness, int const MaterialNum)
    1418             :     {
    1419             : 
    1420          11 :         if ((MaterialThickness <= 0.0) || (state.dataMaterial->Material(MaterialNum).ROnly)) {
    1421           0 :             return true;
    1422             :         } else {
    1423          11 :             return false;
    1424             :         }
    1425             :     }
    1426             : 
    1427           0 :     void SiteGroundDomainNoMassMatError(EnergyPlusData &state,
    1428             :                                         std::string_view FieldName,
    1429             :                                         std::string const &UserInputField,
    1430             :                                         std::string const &ObjectName)
    1431             :     {
    1432             : 
    1433           0 :         ShowSevereError(state, "Invalid " + std::string{FieldName} + "=" + UserInputField + " was found in: " + ObjectName);
    1434           0 :         ShowContinueError(
    1435             :             state, "The user of no mass materials or ones with no thickness are not allowed for the insulation fields of the following objects:");
    1436           0 :         ShowContinueError(state, "  " + ObjName_ZoneCoupled_Slab + " or " + ObjName_ZoneCoupled_Basement);
    1437           0 :         ShowContinueError(
    1438             :             state, "Change any insulation designations in these objects from no mass materials to regular materials that have a thickness, etc.");
    1439           0 :     }
    1440             : 
    1441           5 :     void ReadPipeCircuitInputs(EnergyPlusData &state, bool &ErrorsFound)
    1442             :     {
    1443             : 
    1444             :         // SUBROUTINE INFORMATION:
    1445             :         //       AUTHOR         Edwin Lee
    1446             :         //       DATE WRITTEN   Summer 2011
    1447             :         //       MODIFIED       na
    1448             :         //       RE-ENGINEERED  na
    1449             : 
    1450             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1451             :         static constexpr std::string_view RoutineName("ReadPipeCircuitInputs");
    1452             : 
    1453             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1454             :         int NumAlphas;
    1455             :         int NumNumbers;
    1456             :         int IOStatus;
    1457             :         int CurIndex;
    1458             : 
    1459             :         // get all of the actual generalized pipe circuit objects
    1460             : 
    1461           5 :         int NumPipeCircuits = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_Circuit);
    1462           9 :         for (int PipeCircuitCounter = 1; PipeCircuitCounter <= NumPipeCircuits; ++PipeCircuitCounter) {
    1463             : 
    1464             :             // Read all the inputs for this pipe circuit
    1465          28 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1466             :                                                                      ObjName_Circuit,
    1467             :                                                                      PipeCircuitCounter,
    1468           4 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1469             :                                                                      NumAlphas,
    1470           4 :                                                                      state.dataIPShortCut->rNumericArgs,
    1471             :                                                                      NumNumbers,
    1472             :                                                                      IOStatus,
    1473           4 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1474           4 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1475           4 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1476           4 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1477             : 
    1478           8 :             Circuit thisCircuit = Circuit();
    1479             : 
    1480             :             // Get the name, validate
    1481           4 :             thisCircuit.Name = state.dataIPShortCut->cAlphaArgs(1);
    1482           4 :             UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
    1483             : 
    1484             :             // Read pipe thermal properties, validated by IP
    1485           4 :             thisCircuit.PipeProperties.Conductivity = state.dataIPShortCut->rNumericArgs(1);
    1486           4 :             thisCircuit.PipeProperties.Density = state.dataIPShortCut->rNumericArgs(2);
    1487           4 :             thisCircuit.PipeProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(3);
    1488             : 
    1489             :             // Read pipe sizing, validated individually by IP, validated comparison here
    1490           4 :             thisCircuit.PipeSize.InnerDia = state.dataIPShortCut->rNumericArgs(4);
    1491           4 :             thisCircuit.PipeSize.OuterDia = state.dataIPShortCut->rNumericArgs(5);
    1492           4 :             if (thisCircuit.PipeSize.InnerDia >= thisCircuit.PipeSize.OuterDia) {
    1493           0 :                 CurIndex = 5;
    1494           0 :                 IssueSevereInputFieldError(state,
    1495             :                                            RoutineName,
    1496             :                                            ObjName_Circuit,
    1497           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1498           0 :                                            state.dataIPShortCut->cNumericFieldNames(CurIndex),
    1499           0 :                                            state.dataIPShortCut->rNumericArgs(CurIndex),
    1500             :                                            "Outer diameter must be greater than inner diameter.",
    1501             :                                            ErrorsFound);
    1502             :             }
    1503             : 
    1504             :             // Read design flow rate, validated positive by IP
    1505           4 :             thisCircuit.DesignVolumeFlowRate = state.dataIPShortCut->rNumericArgs(6);
    1506             : 
    1507             :             // Read inlet and outlet node names and validate them
    1508           4 :             thisCircuit.InletNodeName = state.dataIPShortCut->cAlphaArgs(2);
    1509           4 :             thisCircuit.InletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1510           4 :                                                                            state.dataIPShortCut->cAlphaArgs(2),
    1511             :                                                                            ErrorsFound,
    1512             :                                                                            DataLoopNode::ConnectionObjectType::PipingSystemUndergroundPipeCircuit,
    1513           4 :                                                                            state.dataIPShortCut->cAlphaArgs(1),
    1514             :                                                                            DataLoopNode::NodeFluidType::Water,
    1515             :                                                                            DataLoopNode::ConnectionType::Inlet,
    1516             :                                                                            NodeInputManager::CompFluidStream::Primary,
    1517           4 :                                                                            DataLoopNode::ObjectIsNotParent);
    1518           4 :             if (thisCircuit.InletNodeNum == 0) {
    1519           0 :                 CurIndex = 2;
    1520           0 :                 IssueSevereInputFieldError(state,
    1521             :                                            RoutineName,
    1522             :                                            ObjName_Circuit,
    1523           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1524           0 :                                            state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1525           0 :                                            state.dataIPShortCut->cAlphaArgs(CurIndex),
    1526             :                                            "Bad node name.",
    1527             :                                            ErrorsFound);
    1528             :             }
    1529           4 :             thisCircuit.OutletNodeName = state.dataIPShortCut->cAlphaArgs(3);
    1530           4 :             thisCircuit.OutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1531           4 :                                                                             state.dataIPShortCut->cAlphaArgs(3),
    1532             :                                                                             ErrorsFound,
    1533             :                                                                             DataLoopNode::ConnectionObjectType::PipingSystemUndergroundPipeCircuit,
    1534           4 :                                                                             state.dataIPShortCut->cAlphaArgs(1),
    1535             :                                                                             DataLoopNode::NodeFluidType::Water,
    1536             :                                                                             DataLoopNode::ConnectionType::Outlet,
    1537             :                                                                             NodeInputManager::CompFluidStream::Primary,
    1538           4 :                                                                             DataLoopNode::ObjectIsNotParent);
    1539           4 :             if (thisCircuit.OutletNodeNum == 0) {
    1540           0 :                 CurIndex = 3;
    1541           0 :                 IssueSevereInputFieldError(state,
    1542             :                                            RoutineName,
    1543             :                                            ObjName_Circuit,
    1544           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1545           0 :                                            state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1546           0 :                                            state.dataIPShortCut->cAlphaArgs(CurIndex),
    1547             :                                            "Bad node name.",
    1548             :                                            ErrorsFound);
    1549             :             }
    1550           8 :             BranchNodeConnections::TestCompSet(state,
    1551             :                                                ObjName_Circuit,
    1552           4 :                                                state.dataIPShortCut->cAlphaArgs(1),
    1553           4 :                                                state.dataIPShortCut->cAlphaArgs(2),
    1554           4 :                                                state.dataIPShortCut->cAlphaArgs(3),
    1555             :                                                "Piping System Circuit Nodes");
    1556             : 
    1557             :             // Convergence tolerance values, validated by IP
    1558           4 :             thisCircuit.Convergence_CurrentToPrevIteration = state.dataIPShortCut->rNumericArgs(7);
    1559           4 :             thisCircuit.MaxIterationsPerTS = static_cast<int>(state.dataIPShortCut->rNumericArgs(8));
    1560             : 
    1561             :             // Radial mesh inputs, validated by IP
    1562             :             // -- mesh thickness should be considered slightly dangerous until mesh dev engine can trap erroneous values
    1563           4 :             thisCircuit.NumRadialCells = static_cast<int>(state.dataIPShortCut->rNumericArgs(9));
    1564           4 :             thisCircuit.RadialMeshThickness = state.dataIPShortCut->rNumericArgs(10);
    1565             : 
    1566             :             // Read number of pipe segments for this circuit, allocate arrays
    1567           4 :             int const NumPipeSegments = static_cast<int>(state.dataIPShortCut->rNumericArgs(11));
    1568             : 
    1569             :             // Need to loop once to store the names ahead of time because calling the segment factory will override cAlphaArgs
    1570           8 :             std::vector<std::string> segmentNamesToFind;
    1571           4 :             int constexpr NumAlphasBeforeSegmentOne = 3;
    1572          16 :             for (int ThisCircuitPipeSegmentCounter = 1; ThisCircuitPipeSegmentCounter <= NumPipeSegments; ++ThisCircuitPipeSegmentCounter) {
    1573          12 :                 CurIndex = ThisCircuitPipeSegmentCounter + NumAlphasBeforeSegmentOne;
    1574          12 :                 if (state.dataIPShortCut->lAlphaFieldBlanks(CurIndex)) {
    1575           0 :                     IssueSevereInputFieldError(state,
    1576             :                                                RoutineName,
    1577             :                                                ObjName_Circuit,
    1578           0 :                                                state.dataIPShortCut->cAlphaArgs(1),
    1579           0 :                                                state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1580           0 :                                                state.dataIPShortCut->cAlphaArgs(CurIndex),
    1581             :                                                "Expected a pipe segment name, check pipe segment count input field.",
    1582             :                                                ErrorsFound);
    1583             :                 }
    1584          12 :                 segmentNamesToFind.push_back(state.dataIPShortCut->cAlphaArgs(CurIndex));
    1585             :             }
    1586             :             // then we can loop through and allow the factory to be called and carry on
    1587          16 :             for (auto &segmentNameToFind : segmentNamesToFind) {
    1588          12 :                 thisCircuit.pipeSegments.push_back(Segment::factory(state, segmentNameToFind));
    1589             :             }
    1590             : 
    1591           4 :             state.dataPlantPipingSysMgr->circuits.push_back(thisCircuit);
    1592             : 
    1593             :         } // All pipe circuits in input
    1594             : 
    1595             :         // now get all the pipe circuits related to horizontal trenches
    1596             : 
    1597           5 :         int NumHorizontalTrenches = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_HorizTrench);
    1598             : 
    1599             :         // Read in all pipe segments
    1600           6 :         for (int HorizontalGHXCtr = 1; HorizontalGHXCtr <= NumHorizontalTrenches; ++HorizontalGHXCtr) {
    1601             : 
    1602             :             // Read all inputs for this pipe segment
    1603           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1604             :                                                                      ObjName_HorizTrench,
    1605             :                                                                      HorizontalGHXCtr,
    1606           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1607             :                                                                      NumAlphas,
    1608           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    1609             :                                                                      NumNumbers,
    1610             :                                                                      IOStatus,
    1611           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1612           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1613           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1614           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1615           2 :             std::string thisTrenchName = state.dataIPShortCut->cAlphaArgs(1);
    1616             : 
    1617           2 :             Circuit thisCircuit;
    1618           1 :             thisCircuit.IsActuallyPartOfAHorizontalTrench = true;
    1619           1 :             thisCircuit.Name = thisTrenchName;
    1620             : 
    1621             :             // Read pipe thermal properties
    1622           1 :             thisCircuit.PipeProperties.Conductivity = state.dataIPShortCut->rNumericArgs(11);
    1623           1 :             thisCircuit.PipeProperties.Density = state.dataIPShortCut->rNumericArgs(12);
    1624           1 :             thisCircuit.PipeProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(13);
    1625             : 
    1626             :             // Pipe sizing
    1627           1 :             thisCircuit.PipeSize.InnerDia = state.dataIPShortCut->rNumericArgs(5);
    1628           1 :             thisCircuit.PipeSize.OuterDia = state.dataIPShortCut->rNumericArgs(6);
    1629             : 
    1630             :             // Issue a severe if Inner >= Outer diameter
    1631           1 :             if (thisCircuit.PipeSize.InnerDia >= thisCircuit.PipeSize.OuterDia) {
    1632           0 :                 ShowSevereError(state,
    1633           0 :                                 std::string{RoutineName} + ": " + ObjName_HorizTrench + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
    1634             :                                     "\" has invalid pipe diameters.");
    1635           0 :                 ShowContinueError(state,
    1636           0 :                                   format("Outer diameter [{:.3T}] must be greater than inner diameter [{:.3T}].",
    1637             :                                          thisCircuit.PipeSize.OuterDia,
    1638           0 :                                          thisCircuit.PipeSize.InnerDia));
    1639           0 :                 ErrorsFound = true;
    1640             :             }
    1641             : 
    1642             :             // Read design flow rate, validated positive by IP
    1643           1 :             thisCircuit.DesignVolumeFlowRate = state.dataIPShortCut->rNumericArgs(1);
    1644             : 
    1645             :             // Read inlet and outlet node names and validate them
    1646           1 :             thisCircuit.InletNodeName = state.dataIPShortCut->cAlphaArgs(2);
    1647           1 :             thisCircuit.InletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1648             :                                                                            thisCircuit.InletNodeName,
    1649             :                                                                            ErrorsFound,
    1650             :                                                                            DataLoopNode::ConnectionObjectType::GroundHeatExchangerHorizontalTrench,
    1651             :                                                                            thisTrenchName,
    1652             :                                                                            DataLoopNode::NodeFluidType::Water,
    1653             :                                                                            DataLoopNode::ConnectionType::Inlet,
    1654             :                                                                            NodeInputManager::CompFluidStream::Primary,
    1655           1 :                                                                            DataLoopNode::ObjectIsNotParent);
    1656           1 :             if (thisCircuit.InletNodeNum == 0) {
    1657           0 :                 CurIndex = 2;
    1658             :             }
    1659           1 :             thisCircuit.OutletNodeName = state.dataIPShortCut->cAlphaArgs(3);
    1660           1 :             thisCircuit.OutletNodeNum = NodeInputManager::GetOnlySingleNode(state,
    1661             :                                                                             thisCircuit.OutletNodeName,
    1662             :                                                                             ErrorsFound,
    1663             :                                                                             DataLoopNode::ConnectionObjectType::GroundHeatExchangerHorizontalTrench,
    1664             :                                                                             thisTrenchName,
    1665             :                                                                             DataLoopNode::NodeFluidType::Water,
    1666             :                                                                             DataLoopNode::ConnectionType::Outlet,
    1667             :                                                                             NodeInputManager::CompFluidStream::Primary,
    1668           1 :                                                                             DataLoopNode::ObjectIsNotParent);
    1669           1 :             if (thisCircuit.OutletNodeNum == 0) {
    1670           0 :                 CurIndex = 3;
    1671             :             }
    1672           1 :             BranchNodeConnections::TestCompSet(
    1673             :                 state, ObjName_HorizTrench, thisTrenchName, thisCircuit.InletNodeName, thisCircuit.OutletNodeName, "Piping System Circuit Nodes");
    1674             : 
    1675             :             // Convergence tolerance values, validated by IP
    1676           1 :             thisCircuit.Convergence_CurrentToPrevIteration = 0.001;
    1677           1 :             thisCircuit.MaxIterationsPerTS = 100;
    1678             : 
    1679             :             // Radial mesh inputs, validated by IP
    1680             :             // -- mesh thickness should be considered slightly dangerous until mesh dev engine can trap erroneous values
    1681           1 :             thisCircuit.NumRadialCells = 4;
    1682           1 :             thisCircuit.RadialMeshThickness = thisCircuit.PipeSize.InnerDia / 2.0;
    1683             : 
    1684             :             // add it to the main vector, then get a reference to it here
    1685           1 :             state.dataPlantPipingSysMgr->circuits.push_back(thisCircuit);
    1686             :         }
    1687           5 :     }
    1688             : 
    1689          12 :     Segment *Segment::factory(EnergyPlusData &state, const std::string &segmentName)
    1690             :     {
    1691          12 :         if (state.dataPlantPipingSysMgr->GetSegmentInputFlag) {
    1692           4 :             bool errorsFound = false;
    1693           4 :             ReadPipeSegmentInputs(state, errorsFound);
    1694           4 :             state.dataPlantPipingSysMgr->GetSegmentInputFlag = false;
    1695             :         }
    1696             :         // Now look for this particular segment in the list
    1697          30 :         for (auto &segment : state.dataPlantPipingSysMgr->segments) {
    1698          30 :             if (segment.Name == segmentName) {
    1699          12 :                 return &segment;
    1700             :             }
    1701             :         }
    1702             :         // If we didn't find it, fatal
    1703           0 :         ShowFatalError(state,
    1704             :                        "PipeSegmentInfoFactory: Error getting inputs for segment named: " + segmentName); // LCOV_EXCL_LINE
    1705             :         // Shut up the compiler
    1706             :         return nullptr; // LCOV_EXCL_LINE
    1707             :     }
    1708             : 
    1709           5 :     Circuit *Circuit::factory(EnergyPlusData &state, const std::string &circuitName, bool &errorsFound)
    1710             :     {
    1711           5 :         if (state.dataPlantPipingSysMgr->GetCircuitInputFlag) {
    1712           5 :             ReadPipeCircuitInputs(state, errorsFound);
    1713           5 :             state.dataPlantPipingSysMgr->GetCircuitInputFlag = false;
    1714             :         }
    1715             :         // Now look for this particular segment in the list
    1716           5 :         for (auto &circuit : state.dataPlantPipingSysMgr->circuits) {
    1717           5 :             if (circuit.Name == circuitName) {
    1718           5 :                 return &circuit;
    1719             :             }
    1720             :         }
    1721             :         // If we didn't find it, fatal
    1722           0 :         ShowFatalError(state,
    1723             :                        "PipeCircuitInfoFactory: Error getting inputs for circuit named: " + circuitName); // LCOV_EXCL_LINE
    1724             :         // Shut up the compiler
    1725             :         return nullptr; // LCOV_EXCL_LINE
    1726             :     }
    1727             : 
    1728           4 :     void ReadPipeSegmentInputs(EnergyPlusData &state, bool &ErrorsFound)
    1729             :     {
    1730             : 
    1731             :         // SUBROUTINE INFORMATION:
    1732             :         //       AUTHOR         Edwin Lee
    1733             :         //       DATE WRITTEN   Summer 2011
    1734             :         //       MODIFIED       na
    1735             :         //       RE-ENGINEERED  na
    1736             : 
    1737             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1738             :         static constexpr std::string_view RoutineName("ReadPipeSegmentInputs");
    1739             : 
    1740             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1741             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
    1742             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
    1743             :         int IOStatus;   // Used in GetObjectItem
    1744             :         int CurIndex;
    1745             : 
    1746             :         // Read in all pipe segments
    1747           4 :         int NumPipeSegmentsInInput = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_Segment);
    1748          16 :         for (int SegmentCtr = 1; SegmentCtr <= NumPipeSegmentsInInput; ++SegmentCtr) {
    1749             : 
    1750             :             // Read all inputs for this pipe segment
    1751          84 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1752             :                                                                      ObjName_Segment,
    1753             :                                                                      SegmentCtr,
    1754          12 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1755             :                                                                      NumAlphas,
    1756          12 :                                                                      state.dataIPShortCut->rNumericArgs,
    1757             :                                                                      NumNumbers,
    1758             :                                                                      IOStatus,
    1759          12 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1760          12 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1761          12 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1762          12 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1763             : 
    1764          24 :             Segment thisSegment;
    1765             : 
    1766             :             // Get the name, validate
    1767          12 :             thisSegment.Name = state.dataIPShortCut->cAlphaArgs(1);
    1768          12 :             UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
    1769             :             // Read in the pipe location, validated as positive by IP
    1770             :             // -- note that these values will be altered by the main GetInput routine in two ways:
    1771             :             //   1) shift for basement wall if selected
    1772             :             //   2) invert y direction to be measured from domain bottom surface for calculations
    1773          12 :             thisSegment.PipeLocation = PointF(state.dataIPShortCut->rNumericArgs(1), state.dataIPShortCut->rNumericArgs(2));
    1774             : 
    1775             :             // Read in the flow direction
    1776          12 :             thisSegment.FlowDirection =
    1777          24 :                 static_cast<SegmentFlow>(getEnumerationValue(flowDirectionNamesUC, stripped(state.dataIPShortCut->cAlphaArgs(2))));
    1778          12 :             if (thisSegment.FlowDirection == SegmentFlow::Invalid) {
    1779           0 :                 CurIndex = 2;
    1780           0 :                 IssueSevereInputFieldError(state,
    1781             :                                            RoutineName,
    1782             :                                            ObjName_Segment,
    1783           0 :                                            state.dataIPShortCut->cAlphaArgs(1),
    1784           0 :                                            state.dataIPShortCut->cAlphaFieldNames(CurIndex),
    1785           0 :                                            state.dataIPShortCut->cAlphaArgs(CurIndex),
    1786             :                                            "Invalid flow direction, use one of the available keys.",
    1787             :                                            ErrorsFound);
    1788             :             }
    1789             : 
    1790          12 :             state.dataPlantPipingSysMgr->segments.push_back(thisSegment);
    1791             :         }
    1792           4 :     }
    1793             : 
    1794          11 :     void ReadHorizontalTrenchInputs(EnergyPlusData &state,
    1795             :                                     int const StartingDomainNumForHorizontal,
    1796             :                                     int const StartingCircuitNumForHorizontal,
    1797             :                                     bool &ErrorsFound)
    1798             :     {
    1799             : 
    1800             :         // SUBROUTINE INFORMATION:
    1801             :         //       AUTHOR         Edwin Lee
    1802             :         //       DATE WRITTEN   September 2012
    1803             :         //       MODIFIED       na
    1804             :         //       RE-ENGINEERED  na
    1805             : 
    1806             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1807             :         int NumAlphas;  // Number of Alphas for each GetObjectItem call
    1808             :         int NumNumbers; // Number of Numbers for each GetObjectItem call
    1809             :         int IOStatus;   // Used in GetObjectItem
    1810             : 
    1811             :         // initialize these counters properly so they can be incremented within the DO loop
    1812          11 :         int DomainCtr = StartingDomainNumForHorizontal - 1;
    1813          11 :         int CircuitCtr = StartingCircuitNumForHorizontal - 1;
    1814             : 
    1815             :         // For each horizontal, we need to process the inputs into a local array of derived type,
    1816             :         //  then resolve each one, creating definitions for a pipe domain, pipe circuit, and series of pipe segments
    1817             :         // This way, the outer get input routines can handle it as though they were generalized routines
    1818             : 
    1819          11 :         int NumHorizontalTrenches = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, ObjName_HorizTrench);
    1820             : 
    1821             :         // Read in all pipe segments
    1822          12 :         for (int HorizontalGHXCtr = 1; HorizontalGHXCtr <= NumHorizontalTrenches; ++HorizontalGHXCtr) {
    1823             : 
    1824             :             // Increment the domain and circuit counters here
    1825           1 :             ++DomainCtr;
    1826           1 :             ++CircuitCtr;
    1827             : 
    1828             :             // Read all inputs for this pipe segment
    1829           7 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1830             :                                                                      ObjName_HorizTrench,
    1831             :                                                                      HorizontalGHXCtr,
    1832           1 :                                                                      state.dataIPShortCut->cAlphaArgs,
    1833             :                                                                      NumAlphas,
    1834           1 :                                                                      state.dataIPShortCut->rNumericArgs,
    1835             :                                                                      NumNumbers,
    1836             :                                                                      IOStatus,
    1837           1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
    1838           1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
    1839           1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
    1840           1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
    1841             : 
    1842           1 :             auto &thisDomain = state.dataPlantPipingSysMgr->domains[DomainCtr - 1];
    1843             : 
    1844             :             // Get the name, validate
    1845           2 :             std::string thisTrenchName = state.dataIPShortCut->cAlphaArgs(1);
    1846           1 :             UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), state.dataIPShortCut->cCurrentModuleObject, ErrorsFound);
    1847             : 
    1848           1 :             int const NumPipeSegments = static_cast<int>(state.dataIPShortCut->rNumericArgs(3));
    1849           1 :             Real64 const thisInterPipeSpacing = state.dataIPShortCut->rNumericArgs(4);
    1850           1 :             Real64 const thisBurialDepth = state.dataIPShortCut->rNumericArgs(7);
    1851             : 
    1852             :             //******* We'll first set up the domain ********
    1853             :             // the extents will be: zMax = axial length; yMax = burial depth*2; xMax = ( NumPipes+1 )*HorizontalPipeSpacing
    1854           1 :             thisDomain.IsActuallyPartOfAHorizontalTrench = true;
    1855           1 :             thisDomain.Name = format("HorizontalTrenchDomain{:4}", HorizontalGHXCtr);
    1856           1 :             thisDomain.Extents.xMax = (double(NumPipeSegments) + 1.0) * thisInterPipeSpacing;
    1857           1 :             thisDomain.Extents.yMax = 2.0 * thisBurialDepth;
    1858           1 :             thisDomain.Extents.zMax = state.dataIPShortCut->rNumericArgs(2);
    1859             : 
    1860             :             // set up the mesh with some default parameters
    1861           1 :             thisDomain.Mesh.X.RegionMeshCount = 4;
    1862           1 :             thisDomain.Mesh.X.thisMeshDistribution = MeshDistribution::Uniform;
    1863           1 :             thisDomain.Mesh.Y.RegionMeshCount = 4;
    1864           1 :             thisDomain.Mesh.Y.thisMeshDistribution = MeshDistribution::Uniform;
    1865           1 :             thisDomain.Mesh.Z.RegionMeshCount = 4;
    1866           1 :             thisDomain.Mesh.Z.thisMeshDistribution = MeshDistribution::Uniform;
    1867             : 
    1868             :             // Soil properties
    1869           1 :             thisDomain.GroundProperties.Conductivity = state.dataIPShortCut->rNumericArgs(8);
    1870           1 :             thisDomain.GroundProperties.Density = state.dataIPShortCut->rNumericArgs(9);
    1871           1 :             thisDomain.GroundProperties.SpecificHeat = state.dataIPShortCut->rNumericArgs(10);
    1872             : 
    1873             :             // Moisture properties
    1874           1 :             thisDomain.Moisture.Theta_liq = state.dataIPShortCut->rNumericArgs(14) / 100.0;
    1875           1 :             thisDomain.Moisture.Theta_sat = state.dataIPShortCut->rNumericArgs(15) / 100.0;
    1876             : 
    1877             :             // Other parameters
    1878           1 :             thisDomain.SimControls.Convergence_CurrentToPrevIteration = 0.001;
    1879           1 :             thisDomain.SimControls.MaxIterationsPerTS = 250;
    1880             : 
    1881             :             // additional evapotranspiration parameter, min/max validated by IP
    1882           1 :             thisDomain.Moisture.GroundCoverCoefficient = state.dataIPShortCut->rNumericArgs(16);
    1883             : 
    1884             :             //******* We'll next set up the circuit ********
    1885             :             // then we can loop through and allow the factory to be called and carry on
    1886           1 :             thisDomain.circuits.push_back(Circuit::factory(state, thisTrenchName, ErrorsFound));
    1887             : 
    1888             :             // Farfield model parameters -- this is pushed down pretty low because it internally calls GetObjectItem
    1889             :             // using DataIPShortCuts, so it will overwrite the cAlphaArgs and rNumericArgs values
    1890           1 :             thisDomain.groundTempModel = GetGroundTempModelAndInit(state, state.dataIPShortCut->cAlphaArgs(4), state.dataIPShortCut->cAlphaArgs(5));
    1891             : 
    1892             :             //******* Then we'll do the segments *******!
    1893           3 :             for (int ThisCircuitPipeSegmentCounter = 1; ThisCircuitPipeSegmentCounter <= NumPipeSegments; ++ThisCircuitPipeSegmentCounter) {
    1894           4 :                 Segment segment;
    1895           2 :                 segment.Name = format("HorizontalTrenchCircuit{}Segment{}", HorizontalGHXCtr, ThisCircuitPipeSegmentCounter);
    1896           2 :                 segment.IsActuallyPartOfAHorizontalTrench = true;
    1897           2 :                 segment.PipeLocation = PointF(ThisCircuitPipeSegmentCounter * thisInterPipeSpacing, thisBurialDepth);
    1898             : 
    1899           2 :                 if (mod(ThisCircuitPipeSegmentCounter, 2) != 0) {
    1900           1 :                     segment.FlowDirection = SegmentFlow::IncreasingZ;
    1901             :                 } else {
    1902           1 :                     segment.FlowDirection = SegmentFlow::DecreasingZ;
    1903             :                 }
    1904             :                 // add it to the main segment array so it has a place to live
    1905           2 :                 state.dataPlantPipingSysMgr->segments.push_back(segment);
    1906             :             }
    1907             : 
    1908             :             // now that they are in the main vector, add them here
    1909           1 :             int const newSizeSegmentVector = static_cast<int>(state.dataPlantPipingSysMgr->segments.size());
    1910           3 :             for (int segmentIndexToGrab = newSizeSegmentVector - NumPipeSegments; segmentIndexToGrab < newSizeSegmentVector; ++segmentIndexToGrab) {
    1911           2 :                 thisDomain.circuits[0]->pipeSegments.push_back(&state.dataPlantPipingSysMgr->segments[segmentIndexToGrab]);
    1912             :             }
    1913             :         }
    1914          11 :     }
    1915             : 
    1916          11 :     void SetupPipingSystemOutputVariables(EnergyPlusData &state)
    1917             :     {
    1918             : 
    1919             :         // SUBROUTINE INFORMATION:
    1920             :         //       AUTHOR         Edwin Lee
    1921             :         //       DATE WRITTEN   September 2012
    1922             :         //       MODIFIED       na
    1923             :         //       RE-ENGINEERED  na
    1924             : 
    1925          25 :         for (auto &thisSegment : state.dataPlantPipingSysMgr->segments) {
    1926             : 
    1927          14 :             if (!thisSegment.IsActuallyPartOfAHorizontalTrench) {
    1928             : 
    1929          24 :                 SetupOutputVariable(state,
    1930             :                                     "Pipe Segment Inlet Temperature",
    1931             :                                     OutputProcessor::Unit::C,
    1932             :                                     thisSegment.InletTemperature,
    1933             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1934             :                                     OutputProcessor::SOVStoreType::Average,
    1935          12 :                                     thisSegment.Name);
    1936          24 :                 SetupOutputVariable(state,
    1937             :                                     "Pipe Segment Outlet Temperature",
    1938             :                                     OutputProcessor::Unit::C,
    1939             :                                     thisSegment.OutletTemperature,
    1940             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1941             :                                     OutputProcessor::SOVStoreType::Average,
    1942          12 :                                     thisSegment.Name);
    1943             : 
    1944          24 :                 SetupOutputVariable(state,
    1945             :                                     "Pipe Segment Fluid Heat Transfer Rate",
    1946             :                                     OutputProcessor::Unit::W,
    1947             :                                     thisSegment.FluidHeatLoss,
    1948             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1949             :                                     OutputProcessor::SOVStoreType::Average,
    1950          12 :                                     thisSegment.Name);
    1951             :             }
    1952             :         }
    1953             : 
    1954          16 :         for (auto &thisCircuit : state.dataPlantPipingSysMgr->circuits) {
    1955             : 
    1956           5 :             if (!thisCircuit.IsActuallyPartOfAHorizontalTrench) {
    1957             : 
    1958           8 :                 SetupOutputVariable(state,
    1959             :                                     "Pipe Circuit Mass Flow Rate",
    1960             :                                     OutputProcessor::Unit::kg_s,
    1961             :                                     thisCircuit.CurCircuitFlowRate,
    1962             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1963             :                                     OutputProcessor::SOVStoreType::Average,
    1964           4 :                                     thisCircuit.Name);
    1965             : 
    1966           8 :                 SetupOutputVariable(state,
    1967             :                                     "Pipe Circuit Inlet Temperature",
    1968             :                                     OutputProcessor::Unit::C,
    1969             :                                     thisCircuit.InletTemperature,
    1970             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1971             :                                     OutputProcessor::SOVStoreType::Average,
    1972           4 :                                     thisCircuit.Name);
    1973           8 :                 SetupOutputVariable(state,
    1974             :                                     "Pipe Circuit Outlet Temperature",
    1975             :                                     OutputProcessor::Unit::C,
    1976             :                                     thisCircuit.OutletTemperature,
    1977             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1978             :                                     OutputProcessor::SOVStoreType::Average,
    1979           4 :                                     thisCircuit.Name);
    1980             : 
    1981           8 :                 SetupOutputVariable(state,
    1982             :                                     "Pipe Circuit Fluid Heat Transfer Rate",
    1983             :                                     OutputProcessor::Unit::W,
    1984             :                                     thisCircuit.FluidHeatLoss,
    1985             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1986             :                                     OutputProcessor::SOVStoreType::Average,
    1987           4 :                                     thisCircuit.Name);
    1988             : 
    1989             :             } else { // it is a horizontal trench
    1990             : 
    1991           2 :                 SetupOutputVariable(state,
    1992             :                                     "Ground Heat Exchanger Mass Flow Rate",
    1993             :                                     OutputProcessor::Unit::kg_s,
    1994             :                                     thisCircuit.CurCircuitFlowRate,
    1995             :                                     OutputProcessor::SOVTimeStepType::Plant,
    1996             :                                     OutputProcessor::SOVStoreType::Average,
    1997           1 :                                     thisCircuit.Name);
    1998             : 
    1999           2 :                 SetupOutputVariable(state,
    2000             :                                     "Ground Heat Exchanger Inlet Temperature",
    2001             :                                     OutputProcessor::Unit::C,
    2002             :                                     thisCircuit.InletTemperature,
    2003             :                                     OutputProcessor::SOVTimeStepType::Plant,
    2004             :                                     OutputProcessor::SOVStoreType::Average,
    2005           1 :                                     thisCircuit.Name);
    2006           2 :                 SetupOutputVariable(state,
    2007             :                                     "Ground Heat Exchanger Outlet Temperature",
    2008             :                                     OutputProcessor::Unit::C,
    2009             :                                     thisCircuit.OutletTemperature,
    2010             :                                     OutputProcessor::SOVTimeStepType::Plant,
    2011             :                                     OutputProcessor::SOVStoreType::Average,
    2012           1 :                                     thisCircuit.Name);
    2013             : 
    2014           2 :                 SetupOutputVariable(state,
    2015             :                                     "Ground Heat Exchanger Fluid Heat Transfer Rate",
    2016             :                                     OutputProcessor::Unit::W,
    2017             :                                     thisCircuit.FluidHeatLoss,
    2018             :                                     OutputProcessor::SOVTimeStepType::Plant,
    2019             :                                     OutputProcessor::SOVStoreType::Average,
    2020           1 :                                     thisCircuit.Name);
    2021             :             }
    2022             :         }
    2023          11 :     }
    2024             : 
    2025           6 :     void Domain::SetupZoneCoupledOutputVariables(EnergyPlusData &state)
    2026             :     {
    2027             : 
    2028             :         // SUBROUTINE INFORMATION:
    2029             :         //       AUTHOR         Matt Mitchell
    2030             :         //       DATE WRITTEN   August 2014
    2031             :         //       MODIFIED       na
    2032             :         //       RE-ENGINEERED  na
    2033             : 
    2034           6 :         if (this->HasZoneCoupledSlab) {
    2035             :             // Zone-coupled slab outputs
    2036          10 :             SetupOutputVariable(state,
    2037             :                                 "GroundDomain Slab Zone Coupled Surface Heat Flux",
    2038             :                                 OutputProcessor::Unit::W_m2,
    2039             :                                 this->HeatFlux,
    2040             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2041             :                                 OutputProcessor::SOVStoreType::Average,
    2042           5 :                                 this->Name);
    2043          10 :             SetupOutputVariable(state,
    2044             :                                 "GroundDomain Slab Zone Coupled Surface Temperature",
    2045             :                                 OutputProcessor::Unit::C,
    2046             :                                 this->ZoneCoupledSurfaceTemp,
    2047             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2048             :                                 OutputProcessor::SOVStoreType::Average,
    2049           5 :                                 this->Name);
    2050           1 :         } else if (this->HasZoneCoupledBasement) {
    2051             :             // Zone-coupled basement wall outputs
    2052           2 :             SetupOutputVariable(state,
    2053             :                                 "GroundDomain Basement Wall Interface Heat Flux",
    2054             :                                 OutputProcessor::Unit::W_m2,
    2055             :                                 this->WallHeatFlux,
    2056             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2057             :                                 OutputProcessor::SOVStoreType::Average,
    2058           1 :                                 this->Name);
    2059           2 :             SetupOutputVariable(state,
    2060             :                                 "GroundDomain Basement Wall Interface Temperature",
    2061             :                                 OutputProcessor::Unit::C,
    2062             :                                 this->BasementWallTemp,
    2063             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2064             :                                 OutputProcessor::SOVStoreType::Average,
    2065           1 :                                 this->Name);
    2066             :             // Zone-coupled basement floor outputs
    2067           2 :             SetupOutputVariable(state,
    2068             :                                 "GroundDomain Basement Floor Interface Heat Flux",
    2069             :                                 OutputProcessor::Unit::W_m2,
    2070             :                                 this->FloorHeatFlux,
    2071             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2072             :                                 OutputProcessor::SOVStoreType::Average,
    2073           1 :                                 this->Name);
    2074           2 :             SetupOutputVariable(state,
    2075             :                                 "GroundDomain Basement Floor Interface Temperature",
    2076             :                                 OutputProcessor::Unit::C,
    2077             :                                 this->BasementFloorTemp,
    2078             :                                 OutputProcessor::SOVTimeStepType::Zone,
    2079             :                                 OutputProcessor::SOVStoreType::Average,
    2080           1 :                                 this->Name);
    2081             :         }
    2082           6 :     }
    2083             : 
    2084       14498 :     void Domain::InitPipingSystems(EnergyPlusData &state, Circuit *thisCircuit)
    2085             :     {
    2086             : 
    2087             :         // SUBROUTINE INFORMATION:
    2088             :         //       AUTHOR         Edwin Lee
    2089             :         //       DATE WRITTEN   Summer 2011
    2090             :         //       MODIFIED       na
    2091             :         //       RE-ENGINEERED  na
    2092             : 
    2093             :         // SUBROUTINE PARAMETER DEFINITIONS:
    2094             :         static constexpr std::string_view RoutineName("InitPipingSystems");
    2095             : 
    2096             :         // Do any one-time initializations
    2097       14498 :         if (thisCircuit->NeedToFindOnPlantLoop) {
    2098             : 
    2099             :             DataPlant::PlantEquipmentType TypeToLookFor;
    2100           5 :             if (thisCircuit->IsActuallyPartOfAHorizontalTrench) {
    2101           1 :                 TypeToLookFor = DataPlant::PlantEquipmentType::GrndHtExchgHorizTrench;
    2102             :             } else {
    2103           4 :                 TypeToLookFor = DataPlant::PlantEquipmentType::PipingSystemPipeCircuit;
    2104             :             }
    2105             : 
    2106           5 :             bool errFlag = false;
    2107           5 :             PlantUtilities::ScanPlantLoopsForObject(state, thisCircuit->Name, TypeToLookFor, thisCircuit->plantLoc, errFlag, _, _, _, _, _);
    2108           5 :             if (errFlag) {
    2109           0 :                 ShowFatalError(state, "PipingSystems:" + std::string{RoutineName} + ": Program terminated due to previous condition(s).");
    2110             :             }
    2111             : 
    2112             :             // Once we find ourselves on the plant loop, we can do other things
    2113          10 :             Real64 rho = FluidProperties::GetDensityGlycol(state,
    2114           5 :                                                            state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidName,
    2115             :                                                            DataGlobalConstants::InitConvTemp,
    2116           5 :                                                            state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidIndex,
    2117           5 :                                                            RoutineName);
    2118           5 :             thisCircuit->DesignMassFlowRate = thisCircuit->DesignVolumeFlowRate * rho;
    2119           5 :             thisCircuit->NeedToFindOnPlantLoop = false;
    2120             :         }
    2121             : 
    2122       14498 :         if (this->DomainNeedsToBeMeshed) {
    2123             : 
    2124           5 :             this->developMesh(state);
    2125             : 
    2126             :             // would be OK to do some post-mesh error handling here I think
    2127          10 :             for (auto &thisDomainCircuit : this->circuits) {
    2128          19 :                 for (auto &segment : thisDomainCircuit->pipeSegments) {
    2129          14 :                     if (!segment->PipeCellCoordinatesSet) {
    2130           0 :                         ShowSevereError(state, "PipingSystems:" + std::string{RoutineName} + ":Pipe segment index not set.");
    2131           0 :                         ShowContinueError(state, "...Possibly because pipe segment was placed outside of the domain.");
    2132           0 :                         ShowContinueError(state, "...Verify piping system domain inputs, circuits, and segments.");
    2133           0 :                         ShowFatalError(state, "Preceding error causes program termination");
    2134             :                     }
    2135             :                 }
    2136             :             }
    2137             : 
    2138           5 :             this->DomainNeedsToBeMeshed = false;
    2139             :         }
    2140             : 
    2141             :         // The time init should be done here before we DoOneTimeInits because the DoOneTimeInits
    2142             :         // includes a ground temperature initialization, which is based on the Cur%CurSimTimeSeconds variable
    2143             :         // which would be carried over from the previous environment
    2144       14498 :         this->Cur.CurSimTimeStepSize = state.dataHVACGlobal->TimeStepSys * DataGlobalConstants::SecInHour;
    2145       43494 :         this->Cur.CurSimTimeSeconds = (state.dataGlobal->DayOfSim - 1) * 24 + (state.dataGlobal->HourOfDay - 1) +
    2146       28996 :                                       (state.dataGlobal->TimeStep - 1) * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    2147             : 
    2148             :         // There are also some inits that are "close to one time" inits...(one-time in standalone, each envrn in E+)
    2149       14498 :         if ((state.dataGlobal->BeginSimFlag && this->BeginSimInit) || (state.dataGlobal->BeginEnvrnFlag && this->BeginSimEnvironment)) {
    2150             : 
    2151             :             // this seemed to clean up a lot of reverse DD stuff because fluid thermal properties were
    2152             :             // being based on the inlet temperature, which wasn't updated until later
    2153          25 :             thisCircuit->CurCircuitInletTemp = state.dataLoopNodes->Node(thisCircuit->InletNodeNum).Temp;
    2154          25 :             thisCircuit->InletTemperature = thisCircuit->CurCircuitInletTemp;
    2155             : 
    2156          25 :             this->DoOneTimeInitializations(state, thisCircuit);
    2157             : 
    2158          25 :             this->BeginSimInit = false;
    2159          25 :             this->BeginSimEnvironment = false;
    2160             :         }
    2161       14498 :         if (!state.dataGlobal->BeginSimFlag) this->BeginSimInit = true;
    2162       14498 :         if (!state.dataGlobal->BeginEnvrnFlag) this->BeginSimEnvironment = true;
    2163             : 
    2164             :         // Shift history arrays only if necessary
    2165       14498 :         if (std::abs(this->Cur.CurSimTimeSeconds - this->Cur.PrevSimTimeSeconds) > 1.0e-6) {
    2166        1770 :             this->Cur.PrevSimTimeSeconds = this->Cur.CurSimTimeSeconds;
    2167        1770 :             this->ShiftTemperaturesForNewTimeStep();
    2168        1770 :             this->DomainNeedsSimulation = true;
    2169             :         }
    2170             : 
    2171             :         // Get the mass flow and inlet temperature to use for this time step
    2172       14498 :         int InletNodeNum = thisCircuit->InletNodeNum;
    2173       14498 :         int OutletNodeNum = thisCircuit->OutletNodeNum;
    2174       14498 :         thisCircuit->CurCircuitInletTemp = state.dataLoopNodes->Node(InletNodeNum).Temp;
    2175             : 
    2176             :         // request design, set component flow will decide what to give us based on restrictions and flow lock status
    2177       14498 :         thisCircuit->CurCircuitFlowRate = thisCircuit->DesignMassFlowRate;
    2178       14498 :         PlantUtilities::SetComponentFlowRate(state, thisCircuit->CurCircuitFlowRate, InletNodeNum, OutletNodeNum, thisCircuit->plantLoc);
    2179       14498 :     }
    2180             : 
    2181       14498 :     void Domain::UpdatePipingSystems(EnergyPlusData &state, Circuit *thisCircuit)
    2182             :     {
    2183             : 
    2184             :         // SUBROUTINE INFORMATION:
    2185             :         //       AUTHOR         Edwin Lee
    2186             :         //       DATE WRITTEN   Summer 2011
    2187             :         //       MODIFIED       na
    2188             :         //       RE-ENGINEERED  na
    2189             : 
    2190       14498 :         int OutletNodeNum = thisCircuit->OutletNodeNum;
    2191       14498 :         auto const &out_cell(thisCircuit->CircuitOutletCell);
    2192       14498 :         state.dataLoopNodes->Node(OutletNodeNum).Temp = this->Cells(out_cell.X, out_cell.Y, out_cell.Z).PipeCellData.Fluid.Temperature;
    2193       14498 :     }
    2194             : 
    2195           0 :     void IssueSevereInputFieldError(EnergyPlusData &state,
    2196             :                                     std::string_view const RoutineName,
    2197             :                                     std::string const &ObjectName,
    2198             :                                     std::string const &InstanceName,
    2199             :                                     std::string_view FieldName,
    2200             :                                     std::string const &FieldEntry,
    2201             :                                     std::string const &Condition,
    2202             :                                     bool &ErrorsFound)
    2203             :     {
    2204             : 
    2205             :         // SUBROUTINE INFORMATION:
    2206             :         //       AUTHOR         Edwin Lee
    2207             :         //       DATE WRITTEN   Summer 2011
    2208             :         //       MODIFIED       na
    2209             :         //       RE-ENGINEERED  na
    2210             : 
    2211           0 :         ShowSevereError(state,
    2212           0 :                         std::string{RoutineName} + ':' + ObjectName + "=\"" + InstanceName + "\", invalid " + std::string{FieldName} + "=\"" +
    2213           0 :                             FieldEntry + "\", Condition: " + Condition);
    2214           0 :         ErrorsFound = true;
    2215           0 :     }
    2216             : 
    2217           0 :     void IssueSevereInputFieldError(EnergyPlusData &state,
    2218             :                                     std::string_view const RoutineName,
    2219             :                                     std::string const &ObjectName,
    2220             :                                     std::string const &InstanceName,
    2221             :                                     std::string_view FieldName,
    2222             :                                     Real64 const FieldEntry,
    2223             :                                     std::string const &Condition,
    2224             :                                     bool &ErrorsFound)
    2225             :     {
    2226             : 
    2227             :         // SUBROUTINE INFORMATION:
    2228             :         //       AUTHOR         Edwin Lee
    2229             :         //       DATE WRITTEN   Summer 2011
    2230             :         //       MODIFIED       na
    2231             :         //       RE-ENGINEERED  na
    2232             : 
    2233           0 :         ShowSevereError(
    2234             :             state,
    2235           0 :             format(R"({}:{}="{}", invalid {}="{:.3T}", Condition: {})", RoutineName, ObjectName, InstanceName, FieldName, FieldEntry, Condition));
    2236           0 :         ErrorsFound = true;
    2237           0 :     }
    2238             : 
    2239           5 :     int GetSurfaceCountForOSCM(EnergyPlusData &state, int const OSCMIndex)
    2240             :     {
    2241             : 
    2242             :         // FUNCTION INFORMATION:
    2243             :         //       AUTHOR         Edwin Lee
    2244             :         //       DATE WRITTEN   Summer 2011
    2245             :         //       MODIFIED       na
    2246             :         //       RE-ENGINEERED  na
    2247             : 
    2248           5 :         int RetVal = 0;
    2249         139 :         for (int SurfCtr = 1; SurfCtr <= isize(state.dataSurface->Surface); ++SurfCtr) {
    2250         134 :             if (state.dataSurface->Surface(SurfCtr).OSCMPtr == OSCMIndex) ++RetVal;
    2251             :         }
    2252           5 :         return RetVal;
    2253             :     }
    2254             : 
    2255           4 :     std::vector<int> GetSurfaceIndecesForOSCM(EnergyPlusData &state, int const OSCMIndex)
    2256             :     {
    2257             : 
    2258             :         // FUNCTION INFORMATION:
    2259             :         //       AUTHOR         Edwin Lee
    2260             :         //       DATE WRITTEN   Summer 2011
    2261             :         //       MODIFIED       na
    2262             :         //       RE-ENGINEERED  na
    2263             : 
    2264           4 :         std::vector<int> retVal;
    2265          52 :         for (int SurfCtr = 1; SurfCtr <= isize(state.dataSurface->Surface); ++SurfCtr) {
    2266          48 :             if (state.dataSurface->Surface(SurfCtr).OSCMPtr == OSCMIndex) {
    2267          10 :                 retVal.push_back(SurfCtr);
    2268             :             }
    2269             :         }
    2270           4 :         return retVal;
    2271             :     }
    2272             : 
    2273           6 :     std::vector<ZoneCoupledSurfaceData> GetSurfaceDataForOSCM(EnergyPlusData &state, int const OSCMIndex)
    2274             :     {
    2275             : 
    2276             :         // FUNCTION INFORMATION:
    2277             :         //       AUTHOR         Edwin Lee
    2278             :         //       DATE WRITTEN   Summer 2011
    2279             :         //       MODIFIED       na
    2280             :         //       RE-ENGINEERED  na
    2281             : 
    2282           6 :         std::vector<ZoneCoupledSurfaceData> RetVal;
    2283         152 :         for (int SurfCtr = 1; SurfCtr <= isize(state.dataSurface->Surface); ++SurfCtr) {
    2284         146 :             if (state.dataSurface->Surface(SurfCtr).OSCMPtr == OSCMIndex) {
    2285          32 :                 ZoneCoupledSurfaceData z;
    2286          16 :                 z.IndexInSurfaceArray = SurfCtr;
    2287          16 :                 z.SurfaceArea = state.dataSurface->Surface(SurfCtr).Area;
    2288          16 :                 z.Zone = state.dataSurface->Surface(SurfCtr).Zone;
    2289          16 :                 RetVal.push_back(z);
    2290             :             }
    2291             :         }
    2292           6 :         return RetVal;
    2293             :     }
    2294             : 
    2295          80 :     void Segment::initPipeCells(int const x, int const y)
    2296             :     {
    2297             : 
    2298             :         // SUBROUTINE INFORMATION:
    2299             :         //       AUTHOR         Edwin Lee
    2300             :         //       DATE WRITTEN   Summer 2011
    2301             :         //       MODIFIED       na
    2302             :         //       RE-ENGINEERED  na
    2303             : 
    2304          80 :         this->PipeCellCoordinates.X = x;
    2305          80 :         this->PipeCellCoordinates.Y = y;
    2306          80 :         this->PipeCellCoordinatesSet = true;
    2307          80 :     }
    2308             : 
    2309           5 :     void Circuit::initInOutCells(CartesianCell const &in, CartesianCell const &out)
    2310             :     {
    2311             : 
    2312             :         // SUBROUTINE INFORMATION:
    2313             :         //       AUTHOR         Edwin Lee
    2314             :         //       DATE WRITTEN   Summer 2011
    2315             :         //       MODIFIED       na
    2316             :         //       RE-ENGINEERED  na
    2317             : 
    2318           5 :         this->CircuitInletCell = Point3DInteger(in.X_index, in.Y_index, in.Z_index);
    2319           5 :         this->CircuitOutletCell = Point3DInteger(out.X_index, out.Y_index, out.Z_index);
    2320           5 :     }
    2321           0 :     void Circuit::oneTimeInit([[maybe_unused]] EnergyPlusData &state)
    2322             :     {
    2323           0 :     }
    2324           5 :     void Circuit::oneTimeInit_new([[maybe_unused]] EnergyPlusData &state)
    2325             :     {
    2326           5 :     }
    2327             : 
    2328      125701 :     bool Domain::IsConverged_CurrentToPrevIteration()
    2329             :     {
    2330             : 
    2331             :         // FUNCTION INFORMATION:
    2332             :         //       AUTHOR         Edwin Lee
    2333             :         //       DATE WRITTEN   Summer 2011
    2334             :         //       MODIFIED       na
    2335             :         //       RE-ENGINEERED  na
    2336             : 
    2337      125701 :         Real64 LocalMax(0.0);
    2338     1836901 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    2339    30167978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    2340   329151865 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    2341   300695087 :                     auto const &cell(this->Cells(X, Y, Z));
    2342   300695087 :                     LocalMax = max(LocalMax, std::abs(cell.Temperature - cell.Temperature_PrevIteration));
    2343             :                 }
    2344             :             }
    2345             :         }
    2346      125701 :         return (LocalMax < this->SimControls.Convergence_CurrentToPrevIteration);
    2347             :     }
    2348             : 
    2349     7434584 :     bool IsConverged_PipeCurrentToPrevIteration(Circuit *thisCircuit, CartesianCell const &CellToCheck)
    2350             :     {
    2351             : 
    2352             :         // FUNCTION INFORMATION:
    2353             :         //       AUTHOR         Edwin Lee
    2354             :         //       DATE WRITTEN   Summer 2011
    2355             :         //       MODIFIED       na
    2356             :         //       RE-ENGINEERED  na
    2357             : 
    2358             :         Real64 ThisCellMax;
    2359             : 
    2360     7434584 :         Real64 MaxDivAmount = 0.0;
    2361    22678184 :         for (auto &radCell : CellToCheck.PipeCellData.Soil) {
    2362    15243600 :             ThisCellMax = std::abs(radCell.Temperature - radCell.Temperature_PrevIteration);
    2363    15243600 :             if (ThisCellMax > MaxDivAmount) {
    2364    14058590 :                 MaxDivAmount = ThisCellMax;
    2365             :             }
    2366             :         }
    2367             :         //'also do the pipe cell
    2368     7434584 :         ThisCellMax = std::abs(CellToCheck.PipeCellData.Pipe.Temperature - CellToCheck.PipeCellData.Pipe.Temperature_PrevIteration);
    2369     7434584 :         if (ThisCellMax > MaxDivAmount) {
    2370      800979 :             MaxDivAmount = ThisCellMax;
    2371             :         }
    2372             :         //'also do the water cell
    2373     7434584 :         ThisCellMax = std::abs(CellToCheck.PipeCellData.Fluid.Temperature - CellToCheck.PipeCellData.Fluid.Temperature_PrevIteration);
    2374     7434584 :         if (ThisCellMax > MaxDivAmount) {
    2375      224545 :             MaxDivAmount = ThisCellMax;
    2376             :         }
    2377             :         //'also do insulation if it exists
    2378     7434584 :         if (thisCircuit->HasInsulation) {
    2379           0 :             ThisCellMax = std::abs(CellToCheck.PipeCellData.Insulation.Temperature - CellToCheck.PipeCellData.Insulation.Temperature_PrevIteration);
    2380           0 :             if (ThisCellMax > MaxDivAmount) {
    2381           0 :                 MaxDivAmount = ThisCellMax;
    2382             :             }
    2383             :         }
    2384             : 
    2385     7434584 :         return (MaxDivAmount < thisCircuit->Convergence_CurrentToPrevIteration);
    2386             :     }
    2387             : 
    2388       15114 :     void Domain::ShiftTemperaturesForNewTimeStep()
    2389             :     {
    2390             : 
    2391             :         // SUBROUTINE INFORMATION:
    2392             :         //       AUTHOR         Edwin Lee
    2393             :         //       DATE WRITTEN   Summer 2011
    2394             :         //       MODIFIED       na
    2395             :         //       RE-ENGINEERED  na
    2396             : 
    2397      221184 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    2398     3629868 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    2399    46229298 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    2400    42805500 :                     auto &cell(this->Cells(X, Y, Z));
    2401             : 
    2402    42805500 :                     cell.Temperature_PrevTimeStep = cell.Temperature;
    2403             : 
    2404    42805500 :                     if (cell.cellType == CellType::Pipe) {
    2405             : 
    2406      162192 :                         for (auto &radCell : cell.PipeCellData.Soil) {
    2407      108672 :                             radCell.Temperature_PrevTimeStep = radCell.Temperature;
    2408             :                         }
    2409             : 
    2410       53520 :                         cell.PipeCellData.Fluid.Temperature_PrevTimeStep = cell.PipeCellData.Fluid.Temperature;
    2411             : 
    2412       53520 :                         cell.PipeCellData.Pipe.Temperature_PrevTimeStep = cell.PipeCellData.Pipe.Temperature;
    2413             : 
    2414       53520 :                         cell.PipeCellData.Insulation.Temperature_PrevTimeStep = cell.PipeCellData.Insulation.Temperature;
    2415             :                     }
    2416             :                 }
    2417             :             }
    2418             :         }
    2419       15114 :     }
    2420             : 
    2421      125701 :     void Domain::ShiftTemperaturesForNewIteration()
    2422             :     {
    2423             : 
    2424             :         // SUBROUTINE INFORMATION:
    2425             :         //       AUTHOR         Edwin Lee
    2426             :         //       DATE WRITTEN   Summer 2011
    2427             :         //       MODIFIED       na
    2428             :         //       RE-ENGINEERED  na
    2429             : 
    2430     1836901 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    2431    30167978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    2432   329151865 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    2433   300695087 :                     auto &cell(this->Cells(X, Y, Z));
    2434             : 
    2435   300695087 :                     cell.Temperature_PrevIteration = cell.Temperature;
    2436             : 
    2437   300695087 :                     if (cell.cellType == CellType::Pipe) {
    2438             : 
    2439     4222708 :                         for (auto &radCell : cell.PipeCellData.Soil) {
    2440     2827112 :                             radCell.Temperature_PrevIteration = radCell.Temperature;
    2441             :                         }
    2442             : 
    2443     1395596 :                         cell.PipeCellData.Fluid.Temperature_PrevIteration = cell.PipeCellData.Fluid.Temperature;
    2444             : 
    2445     1395596 :                         cell.PipeCellData.Pipe.Temperature_PrevIteration = cell.PipeCellData.Pipe.Temperature;
    2446             : 
    2447     1395596 :                         cell.PipeCellData.Insulation.Temperature_PrevIteration = cell.PipeCellData.Insulation.Temperature;
    2448             :                     }
    2449             :                 }
    2450             :             }
    2451             :         }
    2452      125701 :     }
    2453             : 
    2454     7434584 :     void ShiftPipeTemperaturesForNewIteration(CartesianCell &ThisPipeCell)
    2455             :     {
    2456             : 
    2457             :         // SUBROUTINE INFORMATION:
    2458             :         //       AUTHOR         Edwin Lee
    2459             :         //       DATE WRITTEN   Summer 2011
    2460             :         //       MODIFIED       na
    2461             :         //       RE-ENGINEERED  na
    2462             : 
    2463     7434584 :         if (ThisPipeCell.cellType == CellType::Pipe) { // It better be!
    2464             : 
    2465    22678184 :             for (auto &radCell : ThisPipeCell.PipeCellData.Soil) {
    2466    15243600 :                 radCell.Temperature_PrevIteration = radCell.Temperature;
    2467             :             }
    2468             : 
    2469     7434584 :             ThisPipeCell.PipeCellData.Fluid.Temperature_PrevIteration = ThisPipeCell.PipeCellData.Fluid.Temperature;
    2470             : 
    2471     7434584 :             ThisPipeCell.PipeCellData.Pipe.Temperature_PrevIteration = ThisPipeCell.PipeCellData.Pipe.Temperature;
    2472             : 
    2473     7434584 :             ThisPipeCell.PipeCellData.Insulation.Temperature_PrevIteration = ThisPipeCell.PipeCellData.Insulation.Temperature;
    2474             :         }
    2475     7434584 :     }
    2476             : 
    2477      125701 :     bool Domain::CheckForOutOfRangeTemps() const
    2478             :     {
    2479             : 
    2480             :         // FUNCTION INFORMATION:
    2481             :         //       AUTHOR         Edwin Lee
    2482             :         //       DATE WRITTEN   Summer 2011
    2483             :         //       MODIFIED       na
    2484             :         //       RE-ENGINEERED  na
    2485             : 
    2486      125701 :         Real64 const MaxLimit = this->SimControls.MaximumTemperatureLimit;
    2487      125701 :         Real64 const MinLimit = this->SimControls.MinimumTemperatureLimit;
    2488             : 
    2489   300820788 :         for (std::size_t i = 0, e = this->Cells.size(); i < e; ++i) {
    2490   300695087 :             double const Temperature(this->Cells[i].Temperature);
    2491   300695087 :             if ((Temperature > MaxLimit) || (Temperature < MinLimit)) return true;
    2492             :         }
    2493      125701 :         return false;
    2494             :     }
    2495             : 
    2496  1694250617 :     Real64 CartesianCell::normalArea(Direction const direction) const
    2497             :     {
    2498             : 
    2499             :         // FUNCTION INFORMATION:
    2500             :         //       AUTHOR         Edwin Lee
    2501             :         //       DATE WRITTEN   Summer 2011
    2502             :         //       MODIFIED       na
    2503             :         //       RE-ENGINEERED  na
    2504             : 
    2505  1694250617 :         switch (direction) {
    2506   577102193 :         case Direction::PositiveY:
    2507             :         case Direction::NegativeY:
    2508   577102193 :             return this->YNormalArea();
    2509   568117950 :         case Direction::PositiveX:
    2510             :         case Direction::NegativeX:
    2511   568117950 :             return this->XNormalArea();
    2512   549030474 :         case Direction::PositiveZ:
    2513             :         case Direction::NegativeZ:
    2514   549030474 :             return this->ZNormalArea();
    2515           0 :         default:
    2516           0 :             assert(false);
    2517             :         }
    2518             : 
    2519             :         return 0;
    2520             :     }
    2521             : 
    2522          80 :     CartesianPipeCellInformation::CartesianPipeCellInformation(Real64 const GridCellWidth,
    2523             :                                                                PlantPipingSystemsManager::RadialSizing const PipeSizes,
    2524             :                                                                int const NumRadialNodes,
    2525             :                                                                Real64 const CellDepth,
    2526             :                                                                Real64 const InsulationThickness,
    2527             :                                                                Real64 const RadialGridExtent,
    2528          80 :                                                                bool const SimHasInsulation)
    2529             :     {
    2530             : 
    2531             :         // SUBROUTINE INFORMATION:
    2532             :         //       AUTHOR         Edwin Lee
    2533             :         //       DATE WRITTEN   Summer 2011
    2534             :         //       MODIFIED       na
    2535             :         //       RE-ENGINEERED  na
    2536             : 
    2537             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2538             :         Real64 InsulationInnerRadius;
    2539             :         Real64 InsulationOuterRadius;
    2540             :         Real64 InsulationCentroid;
    2541             :         Real64 MinimumSoilRadius;
    2542             : 
    2543             :         //'calculate pipe radius
    2544          80 :         Real64 const PipeOuterRadius = PipeSizes.OuterDia / 2.0;
    2545          80 :         Real64 const PipeInnerRadius = PipeSizes.InnerDia / 2.0;
    2546             : 
    2547             :         //'--we will work from inside out, calculating dimensions and instantiating variables--
    2548             :         //'first instantiate the water cell
    2549          80 :         this->Fluid = FluidCellInformation(PipeInnerRadius, CellDepth);
    2550             : 
    2551             :         //'then the pipe cell
    2552          80 :         this->Pipe = RadialCellInformation((PipeOuterRadius + PipeInnerRadius) / 2.0, PipeInnerRadius, PipeOuterRadius);
    2553             : 
    2554             :         //'then the insulation if we have it
    2555          80 :         if (InsulationThickness > 0.0) {
    2556           0 :             InsulationInnerRadius = PipeOuterRadius;
    2557           0 :             InsulationOuterRadius = InsulationInnerRadius + InsulationThickness;
    2558           0 :             InsulationCentroid = (InsulationInnerRadius + InsulationOuterRadius) / 2.0;
    2559           0 :             this->Insulation = RadialCellInformation(InsulationCentroid, InsulationInnerRadius, InsulationOuterRadius);
    2560             :         }
    2561             : 
    2562             :         //'determine where to start applying the radial soil cells based on whether we have insulation or not
    2563          80 :         if (!SimHasInsulation) {
    2564          80 :             MinimumSoilRadius = PipeOuterRadius;
    2565             :         } else {
    2566           0 :             MinimumSoilRadius = this->Insulation.OuterRadius;
    2567             :         }
    2568             : 
    2569             :         //'the radial cells are distributed evenly throughout this region
    2570          80 :         this->RadialSliceWidth = RadialGridExtent / NumRadialNodes;
    2571             : 
    2572             :         // first set Rval to the minimum soil radius plus half a slice thickness for the innermost radial node
    2573          80 :         Real64 Rval = MinimumSoilRadius + (this->RadialSliceWidth / 2.0);
    2574          80 :         Real64 ThisSliceInnerRadius = MinimumSoilRadius;
    2575          80 :         this->Soil.emplace_back(Rval, ThisSliceInnerRadius, ThisSliceInnerRadius + this->RadialSliceWidth);
    2576             : 
    2577             :         //'then loop through the rest and assign them, each radius is simply one more slice thickness
    2578         176 :         for (int RadialCellCtr = 1; RadialCellCtr < NumRadialNodes; ++RadialCellCtr) {
    2579          96 :             Rval += this->RadialSliceWidth;
    2580          96 :             ThisSliceInnerRadius += this->RadialSliceWidth;
    2581          96 :             this->Soil.emplace_back(Rval, ThisSliceInnerRadius, ThisSliceInnerRadius + this->RadialSliceWidth);
    2582             :         }
    2583             : 
    2584             :         //'also assign the interface cell surrounding the radial system
    2585          80 :         this->InterfaceVolume = (1.0 - (DataGlobalConstants::Pi / 4.0)) * pow_2(GridCellWidth) * CellDepth;
    2586          80 :     }
    2587             : 
    2588          11 :     void Domain::developMesh(EnergyPlusData &state)
    2589             :     {
    2590             : 
    2591             :         // SUBROUTINE INFORMATION:
    2592             :         //       AUTHOR         Edwin Lee
    2593             :         //       DATE WRITTEN   Summer 2011
    2594             :         //       MODIFIED       na
    2595             :         //       RE-ENGINEERED  na
    2596             : 
    2597             :         //'****** LAYOUT PARTITIONS ******'
    2598          11 :         this->createPartitionCenterList(state);
    2599             : 
    2600          11 :         bool XPartitionsExist = !this->Partitions.X.empty();
    2601          22 :         std::vector<GridRegion> XPartitionRegions = this->createPartitionRegionList(state, this->Partitions.X, XPartitionsExist, this->Extents.xMax);
    2602             : 
    2603          11 :         bool YPartitionsExist = !this->Partitions.Y.empty();
    2604          22 :         std::vector<GridRegion> YPartitionRegions = this->createPartitionRegionList(state, this->Partitions.Y, YPartitionsExist, this->Extents.yMax);
    2605             : 
    2606          11 :         bool ZPartitionsExist = !this->Partitions.Z.empty();
    2607          22 :         std::vector<GridRegion> ZPartitionRegions = this->createPartitionRegionList(state, this->Partitions.Z, ZPartitionsExist, this->Extents.zMax);
    2608             : 
    2609             :         //'***** LAYOUT MESH REGIONS *****'
    2610             :         // Zone-coupled slab  models
    2611          11 :         if (this->HasZoneCoupledBasement) {
    2612           1 :             this->createRegionList(XRegions,
    2613             :                                    XPartitionRegions,
    2614             :                                    this->Extents.xMax,
    2615             :                                    RegionType::XDirection,
    2616             :                                    XPartitionsExist,
    2617             :                                    _,
    2618             :                                    _,
    2619             :                                    this->XIndex,
    2620             :                                    this->XWallIndex,
    2621             :                                    this->InsulationXIndex);
    2622             : 
    2623           1 :             this->createRegionList(YRegions,
    2624             :                                    YPartitionRegions,
    2625             :                                    this->Extents.yMax,
    2626             :                                    RegionType::YDirection,
    2627             :                                    YPartitionsExist,
    2628             :                                    _,
    2629             :                                    _,
    2630             :                                    _,
    2631             :                                    _,
    2632             :                                    _,
    2633             :                                    this->YIndex,
    2634             :                                    this->YFloorIndex,
    2635             :                                    this->InsulationYIndex);
    2636             : 
    2637           1 :             this->createRegionList(ZRegions,
    2638             :                                    ZPartitionRegions,
    2639             :                                    this->Extents.zMax,
    2640             :                                    RegionType::ZDirection,
    2641             :                                    ZPartitionsExist,
    2642             :                                    _,
    2643             :                                    _,
    2644             :                                    _,
    2645             :                                    _,
    2646             :                                    _,
    2647             :                                    _,
    2648             :                                    _,
    2649             :                                    _,
    2650             :                                    this->ZIndex,
    2651             :                                    this->ZWallIndex,
    2652             :                                    this->InsulationZIndex);
    2653          10 :         } else if (this->HasZoneCoupledSlab) {
    2654           5 :             this->createRegionList(XRegions,
    2655             :                                    XPartitionRegions,
    2656             :                                    this->Extents.xMax,
    2657             :                                    RegionType::XDirection,
    2658             :                                    XPartitionsExist,
    2659             :                                    _,
    2660             :                                    _,
    2661             :                                    this->XIndex,
    2662             :                                    _,
    2663             :                                    this->InsulationXIndex);
    2664             : 
    2665           5 :             this->createRegionList(YRegions,
    2666             :                                    YPartitionRegions,
    2667             :                                    this->Extents.yMax,
    2668             :                                    RegionType::YDirection,
    2669             :                                    YPartitionsExist,
    2670             :                                    _,
    2671             :                                    _,
    2672             :                                    _,
    2673             :                                    _,
    2674             :                                    _,
    2675             :                                    this->YIndex,
    2676             :                                    _,
    2677             :                                    this->InsulationYIndex);
    2678             : 
    2679           5 :             this->createRegionList(ZRegions,
    2680             :                                    ZPartitionRegions,
    2681             :                                    this->Extents.zMax,
    2682             :                                    RegionType::ZDirection,
    2683             :                                    ZPartitionsExist,
    2684             :                                    _,
    2685             :                                    _,
    2686             :                                    _,
    2687             :                                    _,
    2688             :                                    _,
    2689             :                                    _,
    2690             :                                    _,
    2691             :                                    _,
    2692             :                                    this->ZIndex,
    2693             :                                    _,
    2694             :                                    this->InsulationZIndex);
    2695             :         } else {
    2696           5 :             this->createRegionList(
    2697             :                 XRegions, XPartitionRegions, this->Extents.xMax, RegionType::XDirection, XPartitionsExist, this->BasementZone.BasementWallXIndex);
    2698             : 
    2699           5 :             this->createRegionList(
    2700             :                 YRegions, YPartitionRegions, this->Extents.yMax, RegionType::YDirection, YPartitionsExist, _, this->BasementZone.BasementFloorYIndex);
    2701             : 
    2702           5 :             this->createRegionList(ZRegions, ZPartitionRegions, this->Extents.zMax, RegionType::ZDirection, ZPartitionsExist);
    2703             :         }
    2704             : 
    2705             :         //'** MAKE REGIONS > BOUNDARIES **'
    2706          22 :         std::vector<Real64> XBoundaryPoints = CreateBoundaryList(XRegions, this->Extents.xMax, RegionType::XDirection);
    2707          22 :         std::vector<Real64> YBoundaryPoints = CreateBoundaryList(YRegions, this->Extents.yMax, RegionType::YDirection);
    2708          22 :         std::vector<Real64> ZBoundaryPoints = CreateBoundaryList(ZRegions, this->Extents.zMax, RegionType::ZDirection);
    2709             : 
    2710             :         //'****** DEVELOP CELL ARRAY *****'
    2711          11 :         this->createCellArray(XBoundaryPoints, YBoundaryPoints, ZBoundaryPoints);
    2712             : 
    2713             :         //'***** SETUP CELL NEIGHBORS ****'
    2714          11 :         this->setupCellNeighbors();
    2715             : 
    2716             :         //'** SET UP PIPE CIRCUIT CELLS **'
    2717          11 :         this->setupPipeCircuitInOutCells();
    2718          11 :     }
    2719             : 
    2720          11 :     void Domain::createPartitionCenterList([[maybe_unused]] EnergyPlusData &state)
    2721             :     {
    2722             : 
    2723             :         // SUBROUTINE INFORMATION:
    2724             :         //       AUTHOR         Edwin Lee
    2725             :         //       DATE WRITTEN   Summer 2011
    2726             :         //       MODIFIED       na
    2727             :         //       RE-ENGINEERED  na
    2728             : 
    2729             :         // SUBROUTINE PARAMETER DEFINITIONS:
    2730          11 :         Real64 constexpr BasementCellFraction(0.001); // the fraction of domain extent to use for the basement cells
    2731             :         // actual dimension shouldn't matter for calculation purposes
    2732             : 
    2733             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2734             :         Real64 BasementDistFromBottom;
    2735             :         Real64 FloorLocation;
    2736             :         Real64 UnderFloorLocation;
    2737             :         Real64 PipeCellWidth;
    2738             :         Real64 SurfCellWidth; // Basement surface...
    2739             :         Real64 SideXLocation;
    2740             :         Real64 SideXWallLocation;
    2741             :         Real64 SideXInsulationLocation;
    2742             :         Real64 SideZLocation;
    2743             :         Real64 SideZWallLocation;
    2744             :         Real64 SideZInsulationLocation;
    2745             :         Real64 SlabDistFromBottom;
    2746             :         Real64 YInsulationLocation;
    2747          11 :         Real64 CellWidth(0.0);
    2748          11 :         Real64 InterfaceCellWidth(0.008);
    2749             : 
    2750             :         // Object Data
    2751          22 :         std::vector<MeshPartition> PreviousEntries;
    2752          22 :         Segment ThisSegment;
    2753             : 
    2754             :         //'NOTE: pipe location y values have already been corrected to be measured from the bottom surface
    2755             :         //'in input they are measured by depth, but internally they are referred to by distance from y = 0, or the bottom boundary
    2756          16 :         for (auto &thisCircuit : this->circuits) {
    2757             : 
    2758             :             // set up a convenience variable here
    2759             :             //'account for the pipe and insulation if necessary
    2760           5 :             if (!thisCircuit->HasInsulation) {
    2761           5 :                 PipeCellWidth = thisCircuit->PipeSize.OuterDia;
    2762             :             } else {
    2763           0 :                 PipeCellWidth = thisCircuit->InsulationSize.OuterDia;
    2764             :             }
    2765             : 
    2766             :             //'then add the radial mesh thickness on both sides of the pipe/insulation construct
    2767           5 :             PipeCellWidth += 2 * thisCircuit->RadialMeshThickness;
    2768             : 
    2769          19 :             for (auto &segment : thisCircuit->pipeSegments) {
    2770          14 :                 if (std::find(this->Partitions.X.begin(), this->Partitions.X.end(), segment->PipeLocation.X) == this->Partitions.X.end()) {
    2771          12 :                     this->Partitions.X.emplace_back(segment->PipeLocation.X, PartitionType::Pipe, PipeCellWidth);
    2772             :                 }
    2773          14 :                 if (std::find(this->Partitions.Y.begin(), this->Partitions.Y.end(), segment->PipeLocation.Y) == this->Partitions.Y.end()) {
    2774           8 :                     this->Partitions.Y.emplace_back(segment->PipeLocation.Y, PartitionType::Pipe, PipeCellWidth);
    2775             :                 }
    2776             :             }
    2777             :         }
    2778             : 
    2779             :         // Underground Piping Systems Ground domain with basement interaction
    2780          11 :         if (!this->HasZoneCoupledBasement) {
    2781          10 :             if (this->HasBasement) { // FHX model
    2782             :                 //'NOTE: the basement depth is still a depth from the ground surface, need to correct for this here
    2783           1 :                 if (this->BasementZone.Width > 0) {
    2784           1 :                     SurfCellWidth = this->Extents.xMax * BasementCellFraction;
    2785           1 :                     if (std::find(this->Partitions.X.begin(), this->Partitions.X.end(), this->BasementZone.Width) == this->Partitions.X.end()) {
    2786           1 :                         this->Partitions.X.emplace_back(this->BasementZone.Width, PartitionType::BasementWall, SurfCellWidth);
    2787             :                     }
    2788             :                 }
    2789           1 :                 if (this->BasementZone.Depth > 0) {
    2790           1 :                     SurfCellWidth = this->Extents.yMax * BasementCellFraction;
    2791           1 :                     BasementDistFromBottom = this->Extents.yMax - this->BasementZone.Depth;
    2792           1 :                     if (std::find(this->Partitions.Y.begin(), this->Partitions.Y.end(), BasementDistFromBottom) == this->Partitions.Y.end()) {
    2793           1 :                         this->Partitions.Y.emplace_back(BasementDistFromBottom, PartitionType::BasementFloor, SurfCellWidth);
    2794             :                     }
    2795             :                 }
    2796             :             }
    2797             :         } else { // Zone-coupled basement model
    2798             :             //'NOTE: the basement depth is still a depth from the ground surface, need to correct for this here
    2799           1 :             if (this->BasementZone.Width > 0) {
    2800             :                 // Create partitions at basement walls and horizontal insulation edges
    2801           1 :                 CellWidth = this->VertInsThickness;
    2802             :                 // Side X direction - Insulation layer
    2803           1 :                 SideXLocation = this->PerimeterOffset - InterfaceCellWidth - CellWidth / 2.0;
    2804             :                 // Side X direction - Basement Wall Interface
    2805           1 :                 SideXWallLocation = this->PerimeterOffset - InterfaceCellWidth / 2.0;
    2806           1 :                 if (this->HorizInsPresentFlag && !this->FullHorizInsPresent) {
    2807             :                     // Insulation Edge in X direction
    2808           1 :                     SideXInsulationLocation = this->PerimeterOffset + this->HorizInsWidth + InterfaceCellWidth / 2.0;
    2809             :                 } else {
    2810           0 :                     SideXInsulationLocation = -1;
    2811             :                 }
    2812           1 :                 if (std::find(this->Partitions.X.begin(), this->Partitions.X.end(), this->BasementZone.Width) == this->Partitions.X.end()) {
    2813             :                     // Partition at insulation edges in the X direction, if horizontal insulation present
    2814           1 :                     if (this->HorizInsPresentFlag) {
    2815           1 :                         if (!this->FullHorizInsPresent) {
    2816             :                             // Side X direction - Insulation layer
    2817           1 :                             this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2818             :                             // Side X direction - Basement Wall interface
    2819           1 :                             this->Partitions.X.emplace_back(SideXWallLocation, PartitionType::XSideWall, InterfaceCellWidth);
    2820             :                             // Insulation Edge X direction
    2821           1 :                             this->Partitions.X.emplace_back(SideXInsulationLocation, PartitionType::HorizInsXSide, InterfaceCellWidth);
    2822             :                         } else {
    2823             :                             // Side X direction - Insulation layer
    2824           0 :                             this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2825             :                             // Side X direction -Basement Wall interface
    2826           0 :                             this->Partitions.X.emplace_back(SideXWallLocation, PartitionType::XSideWall, InterfaceCellWidth);
    2827             :                         }
    2828             :                     } else {
    2829             :                         // Side X direction - Insulation layer
    2830           0 :                         this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2831             :                         // Side X direction - Basement Wall interface
    2832           0 :                         this->Partitions.X.emplace_back(SideXWallLocation, PartitionType::XSideWall, InterfaceCellWidth);
    2833             :                     }
    2834             :                 }
    2835             :             }
    2836             :             // Zone coupled basement model
    2837           1 :             if (this->BasementZone.Depth > 0) {
    2838           1 :                 CellWidth = this->HorizInsThickness;
    2839             :                 // Distance of basement floor interface from domain bottom
    2840           1 :                 FloorLocation = this->Extents.yMax - this->BasementZone.Depth - InterfaceCellWidth / 2.0;
    2841             :                 // Distance of basement floor insulation layer from domain bottom
    2842           1 :                 UnderFloorLocation = this->Extents.yMax - this->BasementZone.Depth - InterfaceCellWidth - CellWidth / 2.0;
    2843           1 :                 if (this->VertInsPresentFlag) {
    2844           1 :                     YInsulationLocation = this->Extents.yMax - this->VertInsDepth - InterfaceCellWidth / 2.0;
    2845             :                 } else {
    2846           0 :                     YInsulationLocation = -1;
    2847             :                 }
    2848           1 :                 if (std::find(this->Partitions.Y.begin(), this->Partitions.Y.end(), FloorLocation) == this->Partitions.Y.end()) {
    2849             :                     // Partition at bottom edge of vertical insulation, if vertical insulation is present
    2850           1 :                     if (this->VertInsPresentFlag && YInsulationLocation > FloorLocation + CellWidth) {
    2851             :                         // Partition at basement floor interface
    2852           1 :                         this->Partitions.Y.emplace_back(FloorLocation, PartitionType::FloorInside, InterfaceCellWidth);
    2853             :                         // Partition under the basement floor for insulation layer
    2854           1 :                         this->Partitions.Y.emplace_back(UnderFloorLocation, PartitionType::UnderFloor, CellWidth);
    2855             :                         // Vertical-Insulation edge partition
    2856           1 :                         this->Partitions.Y.emplace_back(YInsulationLocation, PartitionType::VertInsLowerEdge, InterfaceCellWidth);
    2857             :                     } else {
    2858           0 :                         this->Partitions.Y.emplace_back(FloorLocation, PartitionType::FloorInside, InterfaceCellWidth);
    2859           0 :                         this->Partitions.Y.emplace_back(UnderFloorLocation, PartitionType::UnderFloor, CellWidth);
    2860             :                     }
    2861             :                 }
    2862             :             }
    2863           1 :             if (this->BasementZone.Width > 0) {
    2864             :                 // Create partitions at basement walls and horizontal insulation edges
    2865           1 :                 CellWidth = this->VertInsThickness;
    2866             :                 // Side Z direction - Insulation layer
    2867           1 :                 SideZLocation = this->PerimeterOffset - InterfaceCellWidth - CellWidth / 2.0;
    2868             :                 // Side Z direction - Basement Wall Interface
    2869           1 :                 SideZWallLocation = this->PerimeterOffset - InterfaceCellWidth / 2.0;
    2870           1 :                 if (this->HorizInsPresentFlag && !this->FullHorizInsPresent) {
    2871             :                     // Insulation Edge Z direction
    2872           1 :                     SideZInsulationLocation = this->PerimeterOffset + this->HorizInsWidth + InterfaceCellWidth / 2.0;
    2873             :                 } else {
    2874           0 :                     SideZInsulationLocation = -1;
    2875             :                 }
    2876           1 :                 if (std::find(this->Partitions.Z.begin(), this->Partitions.Z.end(), this->BasementZone.Width) == this->Partitions.Z.end()) {
    2877             :                     // Partition at insulation edges in the Z direction, if horizontal insulation present
    2878           1 :                     if (this->HorizInsPresentFlag) {
    2879           1 :                         if (!this->FullHorizInsPresent) {
    2880             :                             // Side Z direction - Insulation layer
    2881           1 :                             this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    2882             :                             // Side Z direction - Basement Wall interface
    2883           1 :                             this->Partitions.Z.emplace_back(SideZWallLocation, PartitionType::ZSideWall, InterfaceCellWidth);
    2884             :                             // Insulation Edge Z direction
    2885           1 :                             this->Partitions.Z.emplace_back(SideZInsulationLocation, PartitionType::HorizInsZSide, InterfaceCellWidth);
    2886             :                         } else {
    2887             :                             // Side Z direction - Insulation layer
    2888           0 :                             this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    2889             :                             // Side Z direction -Basement Wall interface
    2890           0 :                             this->Partitions.Z.emplace_back(SideZWallLocation, PartitionType::ZSideWall, InterfaceCellWidth);
    2891             :                         }
    2892             :                     } else {
    2893             :                         // Side Z direction - Insulation layer
    2894           0 :                         this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    2895             :                         // Side Z direction -Basement Wall interface
    2896           0 :                         this->Partitions.Z.emplace_back(SideZWallLocation, PartitionType::ZSideWall, InterfaceCellWidth);
    2897             :                     }
    2898             :                 }
    2899             :             }
    2900             :         }
    2901             : 
    2902             :         // Zone-coupled slab
    2903          11 :         if (this->HasZoneCoupledSlab) {
    2904             :             // NOTE: the slab depth is still a depth from the ground surface, need to correct for this here.
    2905             : 
    2906             :             // Create X-direction partitions
    2907             : 
    2908             :             // Create partition at slab edges in the X direction
    2909           5 :             CellWidth = this->VertInsThickness;
    2910             :             // Side X direction
    2911           5 :             SideXLocation = this->PerimeterOffset - CellWidth / 2.0;
    2912             :             // Insulation Edge X direction
    2913           5 :             if (this->HorizInsPresentFlag && !this->FullHorizInsPresent) {
    2914           0 :                 SideXInsulationLocation = SideXLocation + this->HorizInsWidth;
    2915             :             } else {
    2916           5 :                 SideXInsulationLocation = -1;
    2917             :             }
    2918           5 :             if (std::find(this->Partitions.X.begin(), this->Partitions.X.end(), this->SlabWidth) == this->Partitions.X.end()) {
    2919             :                 // Partition at insulation edges in the X direction, if horizontal insulation present
    2920           5 :                 if (this->HorizInsPresentFlag) {
    2921           4 :                     if (!this->FullHorizInsPresent) {
    2922             :                         // Side X direction
    2923           0 :                         this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2924             :                         // Insulation Edge X direction
    2925           0 :                         this->Partitions.X.emplace_back(SideXInsulationLocation, PartitionType::HorizInsXSide, CellWidth);
    2926             :                     } else {
    2927             :                         // Side X direction
    2928           4 :                         this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2929             :                     }
    2930             :                 } else {
    2931             :                     // Side X direction
    2932           1 :                     this->Partitions.X.emplace_back(SideXLocation, PartitionType::XSide, CellWidth);
    2933             :                 }
    2934             :             }
    2935             : 
    2936             :             // Create Y-direction partitions
    2937             : 
    2938           5 :             CellWidth = this->HorizInsThickness;
    2939             : 
    2940             :             // Partition at bottom edge of vertical insulation, if vertical insulation present
    2941           5 :             if (this->VertInsPresentFlag) {
    2942           5 :                 YInsulationLocation = this->Extents.yMax - this->VertInsDepth + CellWidth / 2.0;
    2943             :             } else {
    2944           0 :                 YInsulationLocation = -1;
    2945             :             }
    2946             : 
    2947           5 :             if (this->SlabInGradeFlag) { // Slab in-grade case
    2948             : 
    2949           4 :                 SlabDistFromBottom = this->Extents.yMax - this->SlabThickness - CellWidth / 2.0;
    2950             : 
    2951           4 :                 if (std::find(this->Partitions.Y.begin(), this->Partitions.Y.end(), SlabDistFromBottom) == this->Partitions.Y.end()) {
    2952             : 
    2953             :                     // Partition at bottom edge of vertical insulation, if vertical insulation present
    2954           4 :                     if (this->VertInsPresentFlag) {
    2955             :                         // Under-slab partition
    2956           4 :                         this->Partitions.Y.emplace_back(SlabDistFromBottom, PartitionType::UnderFloor, CellWidth);
    2957             :                         // Vertical-Insulation edge partition
    2958           4 :                         this->Partitions.Y.emplace_back(YInsulationLocation, PartitionType::VertInsLowerEdge, CellWidth);
    2959             :                     } else {
    2960             :                         // Under-slab partition
    2961           0 :                         this->Partitions.Y.emplace_back(SlabDistFromBottom, PartitionType::UnderFloor, CellWidth);
    2962             :                     }
    2963             :                 }
    2964             :             } else { // Slab on-grade case
    2965             : 
    2966           1 :                 if (std::find(this->Partitions.Y.begin(), this->Partitions.Y.end(), YInsulationLocation) == this->Partitions.Y.end()) {
    2967             :                     // Partition at bottom edge of vertical insulation, if vertical insulation present
    2968           1 :                     if (this->VertInsPresentFlag) {
    2969             :                         // Vertical-Insulation edge partition
    2970           1 :                         this->Partitions.Y.emplace_back(YInsulationLocation, PartitionType::VertInsLowerEdge, CellWidth);
    2971             :                     }
    2972             :                 }
    2973             :             }
    2974             : 
    2975             :             // Create Z-direction partitions
    2976             : 
    2977           5 :             CellWidth = this->VertInsThickness;
    2978             :             // Side Z direction
    2979           5 :             SideZLocation = this->PerimeterOffset - CellWidth / 2.0;
    2980             :             // Insulation Edge Z direction
    2981           5 :             if (this->HorizInsPresentFlag && !this->FullHorizInsPresent) {
    2982           0 :                 SideZInsulationLocation = SideZLocation + this->HorizInsWidth;
    2983             :             } else {
    2984           5 :                 SideZInsulationLocation = -1;
    2985             :             }
    2986           5 :             if (std::find(this->Partitions.Z.begin(), this->Partitions.Z.end(), this->SlabWidth) == this->Partitions.Z.end()) {
    2987             :                 // Partition at insulation edges in the Z direction, if horizontal insulation present
    2988           5 :                 if (this->HorizInsPresentFlag) {
    2989           4 :                     if (!this->FullHorizInsPresent) {
    2990             :                         // Side Z direction
    2991           0 :                         this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    2992             :                         // Insulation Edge Z direction
    2993           0 :                         this->Partitions.Z.emplace_back(SideZInsulationLocation, PartitionType::HorizInsZSide, CellWidth);
    2994             :                     } else {
    2995             :                         // Side Z direction
    2996           4 :                         this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    2997             :                     }
    2998             :                 } else {
    2999             :                     // Side Z direction
    3000           1 :                     this->Partitions.Z.emplace_back(SideZLocation, PartitionType::ZSide, CellWidth);
    3001             :                 }
    3002             :             }
    3003             :         }
    3004          65 :         auto lambda = [](MeshPartition a, MeshPartition b) { return a.rDimension < b.rDimension; };
    3005          11 :         std::sort(this->Partitions.X.begin(), this->Partitions.X.end(), lambda);
    3006          11 :         std::sort(this->Partitions.Y.begin(), this->Partitions.Y.end(), lambda);
    3007          11 :         std::sort(this->Partitions.Z.begin(), this->Partitions.Z.end(), lambda);
    3008          11 :     }
    3009             : 
    3010          33 :     std::vector<GridRegion> Domain::createPartitionRegionList(EnergyPlusData &state,
    3011             :                                                               std::vector<MeshPartition> const &ThesePartitionCenters,
    3012             :                                                               bool const PartitionsExist,
    3013             :                                                               Real64 const DirExtentMax)
    3014             :     {
    3015             : 
    3016             :         // FUNCTION INFORMATION:
    3017             :         //       AUTHOR         Edwin Lee
    3018             :         //       DATE WRITTEN   Summer 2011
    3019             :         //       MODIFIED       na
    3020             :         //       RE-ENGINEERED  na
    3021             : 
    3022             :         // Return value
    3023          33 :         std::vector<GridRegion> ThesePartitionRegions;
    3024             : 
    3025             :         // FUNCTION PARAMETER DEFINITIONS:
    3026             :         static constexpr std::string_view RoutineName("CreatePartitionRegionList");
    3027             : 
    3028          33 :         if (!PartitionsExist) {
    3029           5 :             return ThesePartitionRegions;
    3030             :         }
    3031             : 
    3032             :         //'loop across all partitions
    3033          78 :         for (int Index = 0; Index < (int)ThesePartitionCenters.size(); ++Index) {
    3034          50 :             auto &thisPartitionCenter = ThesePartitionCenters[Index];
    3035             : 
    3036          50 :             Real64 const ThisCellWidthBy2 = thisPartitionCenter.TotalWidth / 2.0;
    3037          50 :             PartitionType ThisPartitionType = thisPartitionCenter.partitionType;
    3038             : 
    3039             :             //'use this half width to validate the region and add it to the collection
    3040          50 :             Real64 CellLeft = thisPartitionCenter.rDimension - ThisCellWidthBy2;
    3041          50 :             Real64 CellRight = thisPartitionCenter.rDimension + ThisCellWidthBy2;
    3042             : 
    3043             :             // check to make sure this location is valid
    3044          50 :             if (CellLeft < 0.0 || CellRight > DirExtentMax) {
    3045           0 :                 ShowSevereError(state, "PlantPipingSystems::" + std::string{RoutineName} + ": Invalid partition location in domain.");
    3046           0 :                 ShowContinueError(state, "Occurs during mesh development for domain=" + this->Name);
    3047           0 :                 ShowContinueError(state, "A pipe or basement is located outside of the domain extents.");
    3048           0 :                 ShowFatalError(state, "Preceding error causes program termination.");
    3049             :             }
    3050             : 
    3051             :             // Scan all grid regions to make sure this range doesn't fall within an already entered range
    3052          87 :             for (int SubIndex = 0; SubIndex <= Index - 1; ++SubIndex) {
    3053          37 :                 auto &thisPartitionRegionSubIndex = ThesePartitionRegions[SubIndex];
    3054             :                 // Coupled-basement model has adjacent partitions: ThesePartitionRegions( 0 ) and ThesePartitionRegions( 1 ) - SA
    3055          37 :                 if (this->HasZoneCoupledBasement && Index == 1) {
    3056           9 :                     if (IsInRange_BasementModel(CellLeft, thisPartitionRegionSubIndex.Min, thisPartitionRegionSubIndex.Max) ||
    3057           3 :                         IsInRangeReal(CellRight, thisPartitionRegionSubIndex.Min, thisPartitionRegionSubIndex.Max)) {
    3058             : 
    3059           0 :                         ShowSevereError(state, "PlantPipingSystems::" + std::string{RoutineName} + ": Invalid partition location in domain.");
    3060           0 :                         ShowContinueError(state, "Occurs during mesh development for domain=" + this->Name);
    3061           0 :                         ShowContinueError(state, "A mesh conflict was encountered where partitions were overlapping.");
    3062           0 :                         ShowContinueError(state, "Ensure that all pipes exactly line up or are separated to allow meshing in between them");
    3063           0 :                         ShowContinueError(state, "Also verify the pipe and basement dimensions to avoid conflicts there.");
    3064           0 :                         ShowFatalError(state, "Preceding error causes program termination");
    3065             :                     }
    3066             : 
    3067             :                 } else {
    3068             : 
    3069          68 :                     if (IsInRangeReal(CellLeft, thisPartitionRegionSubIndex.Min, thisPartitionRegionSubIndex.Max) ||
    3070          34 :                         IsInRangeReal(CellRight, thisPartitionRegionSubIndex.Min, thisPartitionRegionSubIndex.Max)) {
    3071             : 
    3072           0 :                         ShowSevereError(state, "PlantPipingSystems::" + std::string{RoutineName} + ": Invalid partition location in domain.");
    3073           0 :                         ShowContinueError(state, "Occurs during mesh development for domain=" + this->Name);
    3074           0 :                         ShowContinueError(state, "A mesh conflict was encountered where partitions were overlapping.");
    3075           0 :                         ShowContinueError(state, "Ensure that all pipes exactly line up or are separated to allow meshing in between them");
    3076           0 :                         ShowContinueError(state, "Also verify the pipe and basement dimensions to avoid conflicts there.");
    3077           0 :                         ShowFatalError(state, "Preceding error causes program termination");
    3078             :                     }
    3079             :                 }
    3080             :             }
    3081             : 
    3082          50 :             ThesePartitionRegions.emplace_back();
    3083          50 :             auto &thisNewPartitionRegion = ThesePartitionRegions[Index];
    3084          50 :             thisNewPartitionRegion.Min = CellLeft;
    3085          50 :             thisNewPartitionRegion.Max = CellRight;
    3086             : 
    3087             :             // Need to map partition type into region type parameters, since they are different enumerations
    3088          50 :             if (ThisPartitionType == PartitionType::BasementWall) {
    3089           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::BasementWall;
    3090          49 :             } else if (ThisPartitionType == PartitionType::BasementFloor) {
    3091           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::BasementFloor;
    3092          48 :             } else if (ThisPartitionType == PartitionType::Pipe) {
    3093          20 :                 thisNewPartitionRegion.thisRegionType = RegionType::Pipe;
    3094          28 :             } else if (ThisPartitionType == PartitionType::XSide) {
    3095           6 :                 thisNewPartitionRegion.thisRegionType = RegionType::XSide;
    3096          22 :             } else if (ThisPartitionType == PartitionType::XSideWall) {
    3097           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::XSideWall;
    3098          21 :             } else if (ThisPartitionType == PartitionType::HorizInsXSide) {
    3099           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::HorizInsXSide;
    3100          20 :             } else if (ThisPartitionType == PartitionType::ZSide) {
    3101           6 :                 thisNewPartitionRegion.thisRegionType = RegionType::ZSide;
    3102          14 :             } else if (ThisPartitionType == PartitionType::ZSideWall) {
    3103           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::ZSideWall;
    3104          13 :             } else if (ThisPartitionType == PartitionType::HorizInsZSide) {
    3105           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::HorizInsZSide;
    3106          12 :             } else if (ThisPartitionType == PartitionType::FloorInside) {
    3107           1 :                 thisNewPartitionRegion.thisRegionType = RegionType::FloorInside;
    3108          11 :             } else if (ThisPartitionType == PartitionType::UnderFloor) {
    3109           5 :                 thisNewPartitionRegion.thisRegionType = RegionType::UnderFloor;
    3110           6 :             } else if (ThisPartitionType == PartitionType::VertInsLowerEdge) {
    3111           6 :                 thisNewPartitionRegion.thisRegionType = RegionType::VertInsLowerEdge;
    3112             :             } else {
    3113             :                 // diagnostic error
    3114             :             }
    3115             :         }
    3116             : 
    3117          28 :         return ThesePartitionRegions;
    3118             :     }
    3119             : 
    3120             : #pragma clang diagnostic push
    3121             : #pragma ide diagnostic ignored "ArgumentSelectionDefectsInspection"
    3122             : 
    3123          33 :     void Domain::createRegionList(std::vector<GridRegion> &Regions,
    3124             :                                   std::vector<GridRegion> const &ThesePartitionRegions,
    3125             :                                   Real64 const DirExtentMax,
    3126             :                                   RegionType const DirDirection,
    3127             :                                   bool const PartitionsExist,
    3128             :                                   Optional_int BasementWallXIndex,
    3129             :                                   Optional_int BasementFloorYIndex,
    3130             :                                   Optional_int XIndex,
    3131             :                                   Optional_int XWallIndex,
    3132             :                                   Optional_int InsulationXIndex,
    3133             :                                   Optional_int YIndex,
    3134             :                                   Optional_int YFloorIndex,
    3135             :                                   Optional_int InsulationYIndex,
    3136             :                                   Optional_int ZIndex,
    3137             :                                   Optional_int ZWallIndex,
    3138             :                                   Optional_int InsulationZIndex)
    3139             :     {
    3140             : 
    3141             :         // FUNCTION INFORMATION:
    3142             :         //       AUTHOR         Edwin Lee
    3143             :         //       DATE WRITTEN   Summer 2011
    3144             :         //       MODIFIED       na
    3145             :         //       RE-ENGINEERED  na
    3146             : 
    3147          33 :         int cellCountUpToNow = 0;
    3148          66 :         std::vector<Real64> tempCellWidths;
    3149             : 
    3150          33 :         if (PartitionsExist) {
    3151             : 
    3152          78 :             for (int i = 0; i < (int)ThesePartitionRegions.size(); ++i) {
    3153          50 :                 auto &thisPartition(ThesePartitionRegions[i]);
    3154             : 
    3155          50 :                 if (i == 0) { // First partition
    3156             :                     // Create region to left of partition
    3157          56 :                     GridRegion tempRegion(0.0, thisPartition.Min, DirDirection, tempCellWidths);
    3158          28 :                     int potentialCellWidthsCount = this->getCellWidthsCount(DirDirection);
    3159          28 :                     if ((thisPartition.Min - 0.0) < 0.00001) {
    3160           0 :                         cellCountUpToNow += 1; // just one cell for extremely tight regions
    3161             :                     } else {
    3162          28 :                         cellCountUpToNow += potentialCellWidthsCount;
    3163             :                     }
    3164          28 :                     this->getCellWidths(tempRegion, tempRegion.thisRegionType);
    3165          28 :                     Regions.push_back(tempRegion);
    3166          22 :                 } else if (i == 1 && this->HasZoneCoupledBasement) {
    3167           3 :                     cellCountUpToNow += 1; // don't add a left partition for partition index 1 of coupled basements
    3168             :                 } else {                   // All other partitions
    3169             :                     // Because of the way the index block below is structured, we need to update cellCount
    3170             :                     //  **after** we pass that block.  We could include logic below to do this, but this block
    3171             :                     //  already fits within the structure properly, so increment it here to account for the
    3172             :                     //  single cell partition layer that was applied at the **end** of the previous partition index
    3173          19 :                     ++cellCountUpToNow;
    3174             :                     // Create region to left of partition
    3175          19 :                     auto &leftPartition(ThesePartitionRegions[i - 1]);
    3176          38 :                     auto tempRegion(GridRegion(leftPartition.Max, thisPartition.Min, DirDirection, tempCellWidths));
    3177          19 :                     int potentialCellWidthsCount = this->getCellWidthsCount(DirDirection);
    3178          19 :                     if ((thisPartition.Min - leftPartition.Max) < 0.00001) {
    3179           0 :                         cellCountUpToNow += 1; // just one cell for extremely tight regions
    3180             :                     } else {
    3181          19 :                         cellCountUpToNow += potentialCellWidthsCount;
    3182             :                     }
    3183          19 :                     this->getCellWidths(tempRegion, tempRegion.thisRegionType);
    3184          19 :                     Regions.push_back(tempRegion);
    3185             :                 }
    3186             : 
    3187          50 :                 if (thisPartition.thisRegionType == RegionType::BasementWall) {
    3188           1 :                     if (present(BasementWallXIndex)) BasementWallXIndex = cellCountUpToNow;
    3189          49 :                 } else if (thisPartition.thisRegionType == RegionType::BasementFloor) {
    3190           1 :                     if (present(BasementFloorYIndex)) BasementFloorYIndex = cellCountUpToNow;
    3191          48 :                 } else if (thisPartition.thisRegionType == RegionType::XSide) {
    3192           6 :                     if (present(XIndex)) XIndex = cellCountUpToNow;
    3193           6 :                     this->XIndex = XIndex;
    3194          42 :                 } else if (thisPartition.thisRegionType == RegionType::XSideWall) {
    3195           1 :                     if (present(XWallIndex)) XWallIndex = cellCountUpToNow;
    3196           1 :                     this->XWallIndex = XWallIndex;
    3197          41 :                 } else if (thisPartition.thisRegionType == RegionType::ZSide) {
    3198           6 :                     if (present(ZIndex)) ZIndex = cellCountUpToNow;
    3199           6 :                     this->ZIndex = ZIndex;
    3200          35 :                 } else if (thisPartition.thisRegionType == RegionType::ZSideWall) {
    3201           1 :                     if (present(ZWallIndex)) ZWallIndex = cellCountUpToNow;
    3202           1 :                     this->ZWallIndex = ZWallIndex;
    3203          34 :                 } else if (thisPartition.thisRegionType == RegionType::HorizInsXSide) {
    3204           1 :                     if (present(InsulationXIndex)) InsulationXIndex = cellCountUpToNow;
    3205           1 :                     this->InsulationXIndex = InsulationXIndex;
    3206          33 :                 } else if (thisPartition.thisRegionType == RegionType::HorizInsZSide) {
    3207           1 :                     if (present(InsulationZIndex)) InsulationZIndex = cellCountUpToNow;
    3208           1 :                     this->InsulationZIndex = InsulationZIndex;
    3209          32 :                 } else if (thisPartition.thisRegionType == RegionType::FloorInside) {
    3210           1 :                     if (present(YFloorIndex)) YFloorIndex = cellCountUpToNow;
    3211           1 :                     this->YFloorIndex = YFloorIndex;
    3212          31 :                 } else if (thisPartition.thisRegionType == RegionType::UnderFloor) {
    3213           5 :                     if (present(YIndex)) YIndex = cellCountUpToNow;
    3214           5 :                     this->YIndex = YIndex;
    3215          26 :                 } else if (thisPartition.thisRegionType == RegionType::VertInsLowerEdge) {
    3216           6 :                     if (present(InsulationYIndex)) InsulationYIndex = cellCountUpToNow;
    3217           6 :                     this->InsulationYIndex = InsulationYIndex;
    3218             :                 }
    3219             : 
    3220             :                 // Create region for this partition
    3221         100 :                 auto tempRegion(GridRegion(thisPartition.Min, thisPartition.Max, thisPartition.thisRegionType, tempCellWidths));
    3222          50 :                 this->getCellWidths(tempRegion, tempRegion.thisRegionType);
    3223          50 :                 Regions.push_back(tempRegion);
    3224             :             }
    3225             : 
    3226             :             // Create final region
    3227          28 :             auto &thisPartition(ThesePartitionRegions[ThesePartitionRegions.size() - 1]);
    3228          56 :             auto tempRegion(GridRegion(thisPartition.Max, DirExtentMax, DirDirection, tempCellWidths));
    3229          28 :             this->getCellWidths(tempRegion, tempRegion.thisRegionType);
    3230          28 :             Regions.push_back(tempRegion);
    3231             : 
    3232             :         } else {
    3233             :             // Need to create a region anyway if no partitions exist
    3234          10 :             auto tempRegion(GridRegion(0.0, DirExtentMax, DirDirection, tempCellWidths));
    3235           5 :             this->getCellWidths(tempRegion, tempRegion.thisRegionType);
    3236           5 :             Regions.push_back(tempRegion);
    3237             :         }
    3238          33 :     }
    3239             : 
    3240             : #pragma clang diagnostic pop
    3241             : 
    3242          33 :     std::vector<Real64> CreateBoundaryList(std::vector<GridRegion> const &RegionList, Real64 const DirExtentMax, RegionType const DirDirection)
    3243             :     {
    3244             : 
    3245             :         // FUNCTION INFORMATION:
    3246             :         //       AUTHOR         Edwin Lee
    3247             :         //       DATE WRITTEN   Summer 2011
    3248             :         //       MODIFIED       na
    3249             :         //       RE-ENGINEERED  na
    3250             : 
    3251          33 :         std::vector<Real64> RetVal;
    3252         163 :         for (auto const &thisRegion : RegionList) {
    3253         130 :             switch (thisRegion.thisRegionType) {
    3254          50 :             case RegionType::Pipe:
    3255             :             case RegionType::BasementFloor:
    3256             :             case RegionType::BasementWall:
    3257             :             case RegionType::XSide:
    3258             :             case RegionType::XSideWall:
    3259             :             case RegionType::ZSide:
    3260             :             case RegionType::ZSideWall:
    3261             :             case RegionType::HorizInsXSide:
    3262             :             case RegionType::HorizInsZSide:
    3263             :             case RegionType::FloorInside:
    3264             :             case RegionType::UnderFloor:
    3265             :             case RegionType::VertInsLowerEdge:
    3266          50 :                 RetVal.push_back(thisRegion.Min);
    3267          50 :                 break;
    3268          80 :             default:
    3269          80 :                 if (thisRegion.thisRegionType == DirDirection) {
    3270          80 :                     Real64 StartingPointCounter = thisRegion.Min;
    3271         422 :                     for (auto &cellWidth : thisRegion.CellWidths) {
    3272         342 :                         RetVal.push_back(StartingPointCounter);
    3273         342 :                         StartingPointCounter += cellWidth;
    3274             :                     }
    3275             :                 }
    3276             :             }
    3277             :         }
    3278          33 :         RetVal.push_back(DirExtentMax);
    3279          33 :         return RetVal;
    3280             :     }
    3281             : 
    3282          11 :     void Domain::createCellArray(std::vector<Real64> const &XBoundaryPoints,
    3283             :                                  std::vector<Real64> const &YBoundaryPoints,
    3284             :                                  std::vector<Real64> const &ZBoundaryPoints)
    3285             :     {
    3286             : 
    3287             :         // SUBROUTINE INFORMATION:
    3288             :         //       AUTHOR         Edwin Lee
    3289             :         //       DATE WRITTEN   Summer 2011
    3290             :         //       MODIFIED       na
    3291             :         //       RE-ENGINEERED  na
    3292             : 
    3293          11 :         int TotNumCells = 0;
    3294          11 :         int NumCutawayBasementCells = 0;
    3295          11 :         int NumInsulationCells = 0;
    3296          11 :         int NumGroundSurfaceCells = 0;
    3297             : 
    3298             :         //'subtract 2 in each dimension:
    3299             :         //'     one for zero based array
    3300             :         //'     one because the boundary points contain one entry more than the number of cells WITHIN the domain
    3301          11 :         this->x_max_index = XBoundaryPoints.size() - 2;
    3302          11 :         this->y_max_index = YBoundaryPoints.size() - 2;
    3303          11 :         this->z_max_index = ZBoundaryPoints.size() - 2;
    3304          11 :         this->Cells.allocate({0, this->x_max_index}, {0, this->y_max_index}, {0, this->z_max_index});
    3305             : 
    3306          11 :         int MaxBasementXNodeIndex = this->BasementZone.BasementWallXIndex;
    3307          11 :         int MinBasementYNodeIndex = this->BasementZone.BasementFloorYIndex;
    3308          11 :         int MinXIndex = this->XIndex;
    3309          11 :         int YIndex = this->YIndex;
    3310          11 :         int MinZIndex = this->ZIndex;
    3311          11 :         int XWallIndex = this->XWallIndex;
    3312          11 :         int YFloorIndex = this->YFloorIndex;
    3313          11 :         int ZWallIndex = this->ZWallIndex;
    3314          11 :         int InsulationXIndex = this->InsulationXIndex;
    3315          11 :         int InsulationYIndex = this->InsulationYIndex;
    3316          11 :         int InsulationZIndex = this->InsulationZIndex;
    3317             : 
    3318          11 :         auto &cells(this->Cells);
    3319         146 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    3320        2104 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    3321       24019 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    3322       22050 :                     auto &cell(cells(X, Y, Z));
    3323             : 
    3324             :                     //'set up x-direction variables
    3325       22050 :                     int CellXIndex = X;                            //'zero based index
    3326       22050 :                     Real64 CellXMinValue = XBoundaryPoints[X];     //'left wall x-value
    3327       22050 :                     Real64 CellXMaxValue = XBoundaryPoints[X + 1]; //'right wall x-value
    3328       22050 :                     Real64 CellXCenter = (CellXMinValue + CellXMaxValue) / 2;
    3329       22050 :                     Real64 CellWidth = CellXMaxValue - CellXMinValue;
    3330             : 
    3331             :                     //'set up y-direction variables
    3332       22050 :                     int CellYIndex = Y;                            //'zero based index
    3333       22050 :                     Real64 CellYMinValue = YBoundaryPoints[Y];     //'bottom wall y-value
    3334       22050 :                     Real64 CellYMaxValue = YBoundaryPoints[Y + 1]; //'top wall y-value
    3335       22050 :                     Real64 CellYCenter = (CellYMinValue + CellYMaxValue) / 2;
    3336       22050 :                     Real64 CellHeight = CellYMaxValue - CellYMinValue;
    3337             : 
    3338             :                     //'set up z-direction variables
    3339       22050 :                     int CellZIndex = Z;                            //'zero based index
    3340       22050 :                     Real64 CellZMinValue = ZBoundaryPoints[Z];     //'lower z value
    3341       22050 :                     Real64 CellZMaxValue = ZBoundaryPoints[Z + 1]; //'higher z value
    3342       22050 :                     Real64 CellZCenter = (CellZMinValue + CellZMaxValue) / 2;
    3343             : 
    3344             :                     //'set up an extent class for this cell
    3345             :                     CellExtents theseCellExtents =
    3346       22050 :                         CellExtents(CellXMaxValue, CellYMaxValue, CellZMaxValue, CellXMinValue, CellYMinValue, CellZMinValue);
    3347             : 
    3348             :                     //'set up centroid, index, and overall size
    3349       22050 :                     Point3DReal Centroid = Point3DReal(CellXCenter, CellYCenter, CellZCenter);
    3350       22050 :                     Point3DInteger CellIndeces = Point3DInteger(CellXIndex, CellYIndex, CellZIndex);
    3351       22050 :                     RectangleF XYRectangle = RectangleF(CellXMinValue, CellYMinValue, CellWidth, CellHeight);
    3352             : 
    3353             :                     //'determine cell type
    3354       22050 :                     CellType cellType = CellType::Invalid;
    3355             : 
    3356             :                     //'if this is a pipe node, some flags are needed
    3357       22050 :                     bool pipeCell = false;
    3358       22050 :                     int NumRadialCells = -1;
    3359             : 
    3360             :                     // Adiabatic behavior is now achieved in the SetupCellNeighbors routine, these are simply farfield for now.
    3361       22050 :                     CellType const ZWallCellType = CellType::FarfieldBoundary;
    3362       22050 :                     CellType const UnderBasementBoundary = CellType::FarfieldBoundary;
    3363             : 
    3364             :                     //'apply boundary conditions
    3365             : 
    3366             :                     // For zone-coupled ground domain
    3367       22050 :                     if (this->HasZoneCoupledSlab) {
    3368             : 
    3369             :                         // Assign all cells common between on-grade and in-grade cases first
    3370             :                         // This should be all X/Z-side interface, vertical insulation, far-field,
    3371             :                         // ground surface, and ground/zone interface cells
    3372       15717 :                         if (CellXIndex == MinXIndex && CellZIndex >= MinZIndex) { // Z side interface
    3373             :                             // Check if vertical insulation present
    3374        1302 :                             if (this->VertInsPresentFlag) {
    3375         651 :                                 if (CellYIndex <= this->y_max_index && CellYIndex >= InsulationYIndex) { // Check depth of vertical insulation
    3376         441 :                                     cellType = CellType::VertInsulation;
    3377         441 :                                     ++NumInsulationCells;
    3378             :                                 }
    3379           0 :                             } else if (CellYIndex == this->y_max_index) {
    3380           0 :                                 cellType = CellType::GroundSurface;
    3381           0 :                                 ++NumGroundSurfaceCells;
    3382             :                             }
    3383       15066 :                         } else if (CellZIndex == MinZIndex && CellXIndex >= MinXIndex) {                 // X side interface
    3384        1116 :                             if (this->VertInsPresentFlag) {                                              // Check if vertical insulation present
    3385         558 :                                 if (CellYIndex <= this->y_max_index && CellYIndex >= InsulationYIndex) { // Check depth of vertical insulation
    3386         378 :                                     cellType = CellType::VertInsulation;
    3387         378 :                                     ++NumInsulationCells;
    3388             :                                 }
    3389           0 :                             } else if (CellYIndex == this->y_max_index) {
    3390           0 :                                 cellType = CellType::GroundSurface;
    3391           0 :                                 ++NumGroundSurfaceCells;
    3392             :                             }
    3393       14508 :                         } else if (CellYIndex == y_max_index) {
    3394         780 :                             if (CellXIndex <= MinXIndex || CellZIndex <= MinZIndex) { // Ground surface
    3395         600 :                                 cellType = CellType::GroundSurface;
    3396         600 :                                 ++NumGroundSurfaceCells;
    3397         180 :                             } else if (CellXIndex >= MinXIndex || CellZIndex >= MinZIndex) { // Zone-ground interface
    3398         180 :                                 cellType = CellType::ZoneGroundInterface;
    3399             :                             }
    3400             :                         }
    3401             : 
    3402       15717 :                         if (CellYIndex == 0 || CellXIndex == 0 || CellZIndex == 0) { // Farfield boundary
    3403        3045 :                             cellType = CellType::FarfieldBoundary;
    3404             :                         }
    3405             : 
    3406             :                         // Assign different cells between in-grade and on-grade cases
    3407       15717 :                         if (this->SlabInGradeFlag) { // In-grade case
    3408             :                             // This will assign the slab cells and horizontal insulation
    3409             : 
    3410       13520 :                             if (CellZIndex > MinZIndex && CellXIndex > MinXIndex) {     // Cells inside bounds of slab
    3411        2880 :                                 if (CellYIndex >= YIndex && CellYIndex < y_max_index) { // Slab cells
    3412         864 :                                     cellType = CellType::Slab;
    3413        2016 :                                 } else if (CellYIndex == (YIndex - 1)) {
    3414         144 :                                     if (this->HorizInsPresentFlag && this->FullHorizInsPresent) { // Full under-slab insulation
    3415         144 :                                         cellType = CellType::HorizInsulation;
    3416           0 :                                     } else if (this->HorizInsPresentFlag && !this->FullHorizInsPresent) { // Perimeter only under-slab insulation
    3417           0 :                                         if (CellZIndex < InsulationZIndex || CellXIndex < InsulationXIndex) {
    3418           0 :                                             cellType = CellType::HorizInsulation;
    3419             :                                         }
    3420             :                                     }
    3421             :                                 }
    3422             :                             }
    3423             : 
    3424             :                         } else { // Slab-on grade
    3425             :                             // Nothing should happen. Interface cells should already be set.
    3426             :                             // Under that are 'General' field cells that should be caught later.
    3427             :                         }
    3428             : 
    3429        6333 :                     } else if (this->HasZoneCoupledBasement) { // basement model, zone-coupled
    3430             :                         // Set the appropriate cell type
    3431        3375 :                         if (CellYIndex == 0) { // Farfield cells
    3432         225 :                             cellType = CellType::FarfieldBoundary;
    3433        3150 :                         } else if (CellXIndex > XWallIndex && CellZIndex > ZWallIndex) {       // Basement cutaway
    3434        2268 :                             if (CellYIndex <= this->y_max_index && CellYIndex > YFloorIndex) { // General basement cells
    3435         729 :                                 cellType = CellType::BasementCutaway;
    3436             :                                 // Not counting basement cutaway cells.
    3437         405 :                             } else if (CellYIndex == YFloorIndex) { // Basement Floor cells
    3438          81 :                                 cellType = CellType::BasementFloor;
    3439         324 :                             } else if (CellYIndex == YIndex) {
    3440             :                                 // Check if horizontal insulation present
    3441          81 :                                 if (this->HorizInsPresentFlag) {
    3442          81 :                                     if (this->FullHorizInsPresent) { // Entire underfloor insulated
    3443           0 :                                         cellType = CellType::HorizInsulation;
    3444           0 :                                         ++NumInsulationCells;
    3445             :                                     } else { // Perimeter insulation
    3446          81 :                                         if (CellXIndex < InsulationXIndex || CellZIndex < InsulationZIndex) {
    3447          56 :                                             cellType = CellType::HorizInsulation;
    3448          56 :                                             ++NumInsulationCells;
    3449             :                                         }
    3450             :                                     }
    3451             :                                 }
    3452             :                             }
    3453        2016 :                         } else if ((CellXIndex == XWallIndex && CellZIndex > ZWallIndex) ||
    3454         210 :                                    (CellZIndex == ZWallIndex && CellXIndex > XWallIndex)) { // Basement Walls
    3455         504 :                             if (CellYIndex <= this->y_max_index && CellYIndex > YFloorIndex) {
    3456         162 :                                 cellType = CellType::BasementWall;
    3457             :                             }
    3458        1764 :                         } else if ((CellXIndex == MinXIndex && CellZIndex > ZWallIndex) ||
    3459         210 :                                    (CellZIndex == MinZIndex && CellXIndex > XWallIndex)) { // Insulation cells
    3460         504 :                             if (CellYIndex <= this->y_max_index && CellYIndex > YFloorIndex) {
    3461             :                                 // Check if vertical insulation present
    3462         162 :                                 if (this->VertInsPresentFlag) {
    3463         162 :                                     if (InsulationYIndex != 0) { // Partial vertical insulation
    3464         162 :                                         if (CellYIndex <= this->y_max_index && CellYIndex > InsulationYIndex) {
    3465          72 :                                             cellType = CellType::VertInsulation;
    3466          72 :                                             ++NumInsulationCells;
    3467             :                                         }
    3468             :                                     } else { // Vertical insulation extends to depth of basement floor
    3469           0 :                                         if (CellYIndex <= this->y_max_index && CellYIndex > YFloorIndex) {
    3470           0 :                                             cellType = CellType::VertInsulation;
    3471           0 :                                             ++NumInsulationCells;
    3472             :                                         }
    3473             :                                     }
    3474             :                                 }
    3475             :                             }
    3476        1512 :                         } else if (CellYIndex == this->y_max_index) { // Surface cells
    3477         108 :                             cellType = CellType::GroundSurface;
    3478         108 :                             ++NumGroundSurfaceCells;
    3479        1404 :                         } else if (CellYIndex == 0 || CellXIndex == 0 || CellZIndex == 0) { // Farfield boundary
    3480         377 :                             cellType = CellType::FarfieldBoundary;
    3481             :                         }
    3482        2958 :                     } else if (CellXIndex == MaxBasementXNodeIndex && CellYIndex == MinBasementYNodeIndex) {
    3483           6 :                         cellType = CellType::BasementCorner;
    3484        2952 :                     } else if (CellXIndex == MaxBasementXNodeIndex && CellYIndex > MinBasementYNodeIndex) {
    3485          84 :                         cellType = CellType::BasementWall;
    3486        2868 :                     } else if (CellXIndex < MaxBasementXNodeIndex && CellYIndex == MinBasementYNodeIndex) {
    3487          12 :                         cellType = CellType::BasementFloor;
    3488        2856 :                     } else if (CellXIndex < MaxBasementXNodeIndex && CellYIndex > MinBasementYNodeIndex) {
    3489         168 :                         cellType = CellType::BasementCutaway;
    3490             :                         // Not counting basement cutaway cells
    3491        2688 :                     } else if (CellYIndex == Y_end) {
    3492         284 :                         cellType = CellType::GroundSurface;
    3493         284 :                         ++NumGroundSurfaceCells;
    3494        2404 :                     } else if (CellXIndex == 0) {
    3495         116 :                         if (this->HasBasement && Y > 0) {
    3496           6 :                             cellType = UnderBasementBoundary; //'this must come after the basement cutaway ELSEIF branch
    3497             :                         } else {
    3498         110 :                             cellType = CellType::FarfieldBoundary;
    3499             :                         }
    3500        2288 :                     } else if (CellXIndex == X_end || CellYIndex == 0) {
    3501         446 :                         cellType = CellType::FarfieldBoundary;
    3502        1842 :                     } else if (CellZIndex == 0 || CellZIndex == Z_end) {
    3503         670 :                         cellType = ZWallCellType;
    3504             :                     }
    3505             : 
    3506             :                     //'check to see if this is a pipe node...
    3507       22050 :                     Real64 InsulationThickness(0.0);
    3508       22050 :                     Real64 RadialMeshThickness(0.0);
    3509       22050 :                     bool HasInsulation(false);
    3510       22050 :                     RadialSizing PipeSizing;
    3511       22050 :                     Circuit *circuitReference = nullptr;
    3512       24928 :                     for (auto &thisCircuit : this->circuits) {
    3513       15618 :                         for (auto &segment : thisCircuit->pipeSegments) {
    3514       12740 :                             if (XYRectangle.contains(segment->PipeLocation)) {
    3515             :                                 //'inform the cell that it is a pipe node
    3516          80 :                                 cellType = CellType::Pipe;
    3517             :                                 //'inform the cell of which pipe it contains
    3518          80 :                                 pipeCell = true;
    3519             :                                 //'inform the cell of which pipe circuit contains it
    3520          80 :                                 circuitReference = thisCircuit;
    3521             :                                 //'inform the pipe of what cell it is inside
    3522          80 :                                 segment->initPipeCells(CellXIndex, CellYIndex);
    3523             :                                 //'set the number of cells to be generated in this near-pipe region
    3524          80 :                                 NumRadialCells = thisCircuit->NumRadialCells;
    3525             :                                 //'exit the pipe counter loop
    3526          80 :                                 goto CircuitLoop_exit;
    3527             :                             }
    3528             :                         }
    3529             :                     }
    3530       22050 :                 CircuitLoop_exit:;
    3531             : 
    3532             :                     //'if it still isn't anything, then it is just an interior node
    3533       22050 :                     switch (cellType) {
    3534         897 :                     case CellType::BasementCutaway:
    3535         897 :                         ++NumCutawayBasementCells;
    3536         897 :                         break;
    3537       12875 :                     case CellType::Invalid:
    3538       12875 :                         cellType = CellType::GeneralField;
    3539             :                         // fallthrough
    3540       21153 :                     default:
    3541       21153 :                         ++TotNumCells;
    3542             :                     }
    3543             : 
    3544             :                     // if we were found on a pipe circuit, get some things for convenience
    3545       22050 :                     if (circuitReference) {
    3546          80 :                         if (circuitReference->HasInsulation) {
    3547           0 :                             InsulationThickness = circuitReference->InsulationSize.thickness();
    3548             :                         }
    3549          80 :                         PipeSizing = circuitReference->PipeSize;
    3550          80 :                         RadialMeshThickness = circuitReference->RadialMeshThickness;
    3551          80 :                         HasInsulation = circuitReference->HasInsulation;
    3552             :                     }
    3553             : 
    3554             :                     //'instantiate the cell class
    3555       22050 :                     cell.X_min = theseCellExtents.Xmin;
    3556       22050 :                     cell.X_max = theseCellExtents.xMax;
    3557       22050 :                     cell.Y_min = theseCellExtents.Ymin;
    3558       22050 :                     cell.Y_max = theseCellExtents.yMax;
    3559       22050 :                     cell.Z_min = theseCellExtents.Zmin;
    3560       22050 :                     cell.Z_max = theseCellExtents.zMax;
    3561       22050 :                     cell.X_index = CellIndeces.X;
    3562       22050 :                     cell.Y_index = CellIndeces.Y;
    3563       22050 :                     cell.Z_index = CellIndeces.Z;
    3564       22050 :                     cell.Centroid = Centroid;
    3565       22050 :                     cell.cellType = cellType;
    3566             : 
    3567       22050 :                     if (pipeCell) {
    3568         160 :                         cell.PipeCellData = CartesianPipeCellInformation(cell.X_max - cell.X_min,
    3569             :                                                                          PipeSizing,
    3570             :                                                                          NumRadialCells,
    3571             :                                                                          cell.depth(),
    3572             :                                                                          InsulationThickness,
    3573             :                                                                          RadialMeshThickness,
    3574          80 :                                                                          HasInsulation);
    3575             :                     }
    3576             : 
    3577             :                 } //'z
    3578             :             }     //'y
    3579             :         }         //'x
    3580             : 
    3581          11 :         this->NumDomainCells = TotNumCells;
    3582          11 :         this->NumGroundSurfCells = NumGroundSurfaceCells;
    3583          11 :         this->NumInsulationCells = NumInsulationCells;
    3584          11 :     }
    3585             : 
    3586          11 :     void Domain::setupCellNeighbors()
    3587             :     {
    3588             : 
    3589             :         // SUBROUTINE INFORMATION:
    3590             :         //       AUTHOR         Edwin Lee
    3591             :         //       DATE WRITTEN   Summer 2011
    3592             :         //       MODIFIED       na
    3593             :         //       RE-ENGINEERED  na
    3594             : 
    3595             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3596             :         Real64 CellRightCentroidX;
    3597             :         Real64 CellRightLeftWallX;
    3598             :         Real64 CellLeftCentroidX;
    3599             :         Real64 CellLeftRightWallX;
    3600             :         Real64 LeftCellCentroidX;
    3601             :         Real64 LeftCellRightWallX;
    3602             :         Real64 RightCellCentroidX;
    3603             :         Real64 RightCellLeftWallX;
    3604             :         Real64 UpperCellCentroidY;
    3605             :         Real64 UpperCellLowerWallY;
    3606             :         Real64 LowerCellCentroidY;
    3607             :         Real64 LowerCellUpperWallY;
    3608             :         Real64 UpperZCellCentroidZ;
    3609             :         Real64 UpperZCellLowerWallZ;
    3610             :         Real64 LowerZCellCentroidZ;
    3611             :         Real64 LowerZCellUpperWallZ;
    3612             : 
    3613          11 :         auto const &cells(this->Cells);
    3614         146 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    3615        2104 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    3616       24019 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    3617       22050 :                     auto const &cell(cells(X, Y, Z));
    3618             : 
    3619             :                     //'for convenience
    3620       22050 :                     Real64 const &ThisCellCentroidX = cell.Centroid.X;
    3621       22050 :                     Real64 const &ThisCellCentroidY = cell.Centroid.Y;
    3622       22050 :                     Real64 const &ThisCellCentroidZ = cell.Centroid.Z;
    3623       22050 :                     Real64 ThisAdiabaticMultiplier = 1.0;
    3624       22050 :                     Real64 ThisAdiabaticMultiplierMirror = 1.0;
    3625             : 
    3626             :                     //'setup east/west cell neighbors
    3627       22050 :                     if (X == 0) {
    3628        1662 :                         CellRightCentroidX = cells(X + 1, Y, Z).Centroid.X;
    3629        1662 :                         CellRightLeftWallX = cells(X + 1, Y, Z).X_min;
    3630             :                         // on the X=0 face, the only adiabatic cases are:
    3631             :                         //   1) For a non-zone-coupled basement simulation, where the under basement X=0 cells are adiabatic -- cutaways will also get
    3632             :                         //   adiabatic, but who cares?
    3633        1662 :                         if (((!this->HasZoneCoupledSlab) && (!this->HasZoneCoupledBasement) && (this->HasBasement))) {
    3634         102 :                             ThisAdiabaticMultiplier = 2.0;
    3635         102 :                             ThisAdiabaticMultiplierMirror = 0.0;
    3636             :                         }
    3637        3324 :                         this->addNeighborInformation(X,
    3638             :                                                      Y,
    3639             :                                                      Z,
    3640             :                                                      Direction::PositiveX,
    3641        1662 :                                                      CellRightLeftWallX - ThisCellCentroidX,
    3642             :                                                      CellRightCentroidX - CellRightLeftWallX,
    3643             :                                                      ThisAdiabaticMultiplier);
    3644        1662 :                         this->addNeighborInformation(X, Y, Z, Direction::NegativeX, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3645       20388 :                     } else if (X == this->x_max_index) {
    3646             :                         // on the X=XMAX face, the adiabatic cases are:
    3647             :                         //   1) if we are doing a zone coupled slab/basement simulation where we quartered the domain
    3648        1662 :                         if (this->HasZoneCoupledSlab || this->HasZoneCoupledBasement) {
    3649        1434 :                             ThisAdiabaticMultiplier = 2.0;
    3650        1434 :                             ThisAdiabaticMultiplierMirror = 0.0;
    3651             :                         }
    3652        1662 :                         CellLeftCentroidX = cells(X - 1, Y, Z).Centroid.X;
    3653        1662 :                         CellLeftRightWallX = cells(X - 1, Y, Z).X_max;
    3654        3324 :                         this->addNeighborInformation(X,
    3655             :                                                      Y,
    3656             :                                                      Z,
    3657             :                                                      Direction::NegativeX,
    3658        1662 :                                                      ThisCellCentroidX - CellLeftRightWallX,
    3659             :                                                      CellLeftRightWallX - CellLeftCentroidX,
    3660             :                                                      ThisAdiabaticMultiplier);
    3661        1662 :                         this->addNeighborInformation(X, Y, Z, Direction::PositiveX, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3662             :                     } else {
    3663       18726 :                         LeftCellCentroidX = cells(X - 1, Y, Z).Centroid.X;
    3664       18726 :                         LeftCellRightWallX = cells(X - 1, Y, Z).X_max;
    3665       18726 :                         RightCellCentroidX = cells(X + 1, Y, Z).Centroid.X;
    3666       18726 :                         RightCellLeftWallX = cells(X + 1, Y, Z).X_min;
    3667       37452 :                         this->addNeighborInformation(X,
    3668             :                                                      Y,
    3669             :                                                      Z,
    3670             :                                                      Direction::NegativeX,
    3671       18726 :                                                      ThisCellCentroidX - LeftCellRightWallX,
    3672             :                                                      LeftCellRightWallX - LeftCellCentroidX,
    3673             :                                                      ThisAdiabaticMultiplier);
    3674       37452 :                         this->addNeighborInformation(X,
    3675             :                                                      Y,
    3676             :                                                      Z,
    3677             :                                                      Direction::PositiveX,
    3678       18726 :                                                      RightCellLeftWallX - ThisCellCentroidX,
    3679             :                                                      RightCellCentroidX - RightCellLeftWallX,
    3680             :                                                      ThisAdiabaticMultiplier);
    3681             :                     }
    3682             : 
    3683             :                     // Reset for the Y direction assignments
    3684       22050 :                     ThisAdiabaticMultiplier = 1.0;
    3685       22050 :                     ThisAdiabaticMultiplierMirror = 1.0;
    3686             : 
    3687             :                     //'setup north/south cell neighbors
    3688       22050 :                     if (Y == 0) {
    3689        1372 :                         UpperCellCentroidY = cells(X, Y + 1, Z).Centroid.Y;
    3690        1372 :                         UpperCellLowerWallY = cells(X, Y + 1, Z).Y_min;
    3691             :                         // on the Y=0 face, the only adiabatic cases are:
    3692             :                         //   1) NONE
    3693        2744 :                         this->addNeighborInformation(X,
    3694             :                                                      Y,
    3695             :                                                      Z,
    3696             :                                                      Direction::PositiveY,
    3697        1372 :                                                      UpperCellLowerWallY - ThisCellCentroidY,
    3698             :                                                      UpperCellCentroidY - UpperCellLowerWallY,
    3699             :                                                      ThisAdiabaticMultiplier);
    3700        1372 :                         this->addNeighborInformation(X, Y, Z, Direction::NegativeY, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3701       20678 :                     } else if (Y == this->y_max_index) {
    3702        1372 :                         LowerCellCentroidY = cells(X, Y - 1, Z).Centroid.Y;
    3703        1372 :                         LowerCellUpperWallY = cells(X, Y - 1, Z).Y_max;
    3704             :                         // on the Y=YMAX face, the only adiabatic cases are:
    3705             :                         //   1) NONE
    3706        2744 :                         this->addNeighborInformation(X,
    3707             :                                                      Y,
    3708             :                                                      Z,
    3709             :                                                      Direction::NegativeY,
    3710        1372 :                                                      ThisCellCentroidY - LowerCellUpperWallY,
    3711             :                                                      LowerCellUpperWallY - LowerCellCentroidY,
    3712             :                                                      ThisAdiabaticMultiplier);
    3713        1372 :                         this->addNeighborInformation(X, Y, Z, Direction::PositiveY, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3714             :                     } else {
    3715       19306 :                         UpperCellCentroidY = cells(X, Y + 1, Z).Centroid.Y;
    3716       19306 :                         LowerCellCentroidY = cells(X, Y - 1, Z).Centroid.Y;
    3717       19306 :                         UpperCellLowerWallY = cells(X, Y + 1, Z).Y_min;
    3718       19306 :                         LowerCellUpperWallY = cells(X, Y - 1, Z).Y_max;
    3719       38612 :                         this->addNeighborInformation(X,
    3720             :                                                      Y,
    3721             :                                                      Z,
    3722             :                                                      Direction::NegativeY,
    3723       19306 :                                                      ThisCellCentroidY - LowerCellUpperWallY,
    3724             :                                                      LowerCellUpperWallY - LowerCellCentroidY,
    3725             :                                                      ThisAdiabaticMultiplier);
    3726       38612 :                         this->addNeighborInformation(X,
    3727             :                                                      Y,
    3728             :                                                      Z,
    3729             :                                                      Direction::PositiveY,
    3730       19306 :                                                      UpperCellLowerWallY - ThisCellCentroidY,
    3731             :                                                      UpperCellCentroidY - UpperCellLowerWallY,
    3732             :                                                      ThisAdiabaticMultiplier);
    3733             :                     }
    3734             : 
    3735             :                     // Reset for the Z direction assignments
    3736       22050 :                     ThisAdiabaticMultiplier = 1.0;
    3737       22050 :                     ThisAdiabaticMultiplierMirror = 1.0;
    3738             : 
    3739             :                     //'setup forward/backward cell neighbors
    3740       22050 :                     if (Z == 0) {
    3741        1969 :                         UpperZCellCentroidZ = cells(X, Y, Z + 1).Centroid.Z;
    3742        1969 :                         UpperZCellLowerWallZ = cells(X, Y, Z + 1).Z_min;
    3743             :                         // on the Z=0 face, the only adiabatic cases are:
    3744             :                         //   1) for a non-zone-related simulation, such as for a standalone ground HX, or if we have the regular HasBasement
    3745             :                         //   simulation
    3746        1969 :                         if (((!this->HasZoneCoupledSlab) && (!this->HasZoneCoupledBasement))) {
    3747         535 :                             ThisAdiabaticMultiplier = 2.0;
    3748         535 :                             ThisAdiabaticMultiplierMirror = 0.0;
    3749             :                         }
    3750        3938 :                         this->addNeighborInformation(X,
    3751             :                                                      Y,
    3752             :                                                      Z,
    3753             :                                                      Direction::PositiveZ,
    3754        1969 :                                                      UpperZCellLowerWallZ - ThisCellCentroidZ,
    3755             :                                                      UpperZCellCentroidZ - UpperZCellLowerWallZ,
    3756             :                                                      ThisAdiabaticMultiplier);
    3757        1969 :                         this->addNeighborInformation(X, Y, Z, Direction::NegativeZ, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3758       20081 :                     } else if (Z == this->z_max_index) {
    3759        1969 :                         LowerZCellCentroidZ = cells(X, Y, Z - 1).Centroid.Z;
    3760        1969 :                         LowerZCellUpperWallZ = cells(X, Y, Z - 1).Z_max;
    3761             :                         // on the Z=ZMAX face, the only adiabatic cases are:
    3762             :                         //   1) this face is always adiabatic?
    3763             :                         // if (  ) {
    3764        1969 :                         ThisAdiabaticMultiplier = 2.0;
    3765        1969 :                         ThisAdiabaticMultiplierMirror = 0.0;
    3766             :                         //}
    3767        3938 :                         this->addNeighborInformation(X,
    3768             :                                                      Y,
    3769             :                                                      Z,
    3770             :                                                      Direction::NegativeZ,
    3771        1969 :                                                      ThisCellCentroidZ - LowerZCellUpperWallZ,
    3772             :                                                      LowerZCellUpperWallZ - LowerZCellCentroidZ,
    3773             :                                                      ThisAdiabaticMultiplier);
    3774        1969 :                         this->addNeighborInformation(X, Y, Z, Direction::PositiveZ, 0.0, 0.0, ThisAdiabaticMultiplierMirror);
    3775             :                     } else {
    3776       18112 :                         LowerZCellCentroidZ = cells(X, Y, Z - 1).Centroid.Z;
    3777       18112 :                         UpperZCellCentroidZ = cells(X, Y, Z + 1).Centroid.Z;
    3778       18112 :                         UpperZCellLowerWallZ = cells(X, Y, Z + 1).Z_min;
    3779       18112 :                         LowerZCellUpperWallZ = cells(X, Y, Z - 1).Z_max;
    3780       36224 :                         this->addNeighborInformation(X,
    3781             :                                                      Y,
    3782             :                                                      Z,
    3783             :                                                      Direction::NegativeZ,
    3784       18112 :                                                      ThisCellCentroidZ - LowerZCellUpperWallZ,
    3785             :                                                      LowerZCellUpperWallZ - LowerZCellCentroidZ,
    3786             :                                                      ThisAdiabaticMultiplier);
    3787       36224 :                         this->addNeighborInformation(X,
    3788             :                                                      Y,
    3789             :                                                      Z,
    3790             :                                                      Direction::PositiveZ,
    3791       18112 :                                                      UpperZCellLowerWallZ - ThisCellCentroidZ,
    3792             :                                                      UpperZCellCentroidZ - UpperZCellLowerWallZ,
    3793             :                                                      ThisAdiabaticMultiplier);
    3794             :                     }
    3795             :                 }
    3796             :             }
    3797             :         }
    3798          11 :     }
    3799             : 
    3800      132300 :     void Domain::addNeighborInformation(int const X,
    3801             :                                         int const Y,
    3802             :                                         int const Z,
    3803             :                                         Direction const direction,
    3804             :                                         Real64 const ThisCentroidToNeighborWall,
    3805             :                                         Real64 const ThisWallToNeighborCentroid,
    3806             :                                         Real64 const ThisAdiabaticMultiplier)
    3807             :     {
    3808             :         // SUBROUTINE INFORMATION:
    3809             :         //       AUTHOR         Edwin Lee
    3810             :         //       DATE WRITTEN   Summer 2011
    3811             :         //       MODIFIED       na
    3812             :         //       RE-ENGINEERED  na
    3813      132300 :         auto &thisNeighborInfo = this->Cells(X, Y, Z).NeighborInfo[direction];
    3814      132300 :         thisNeighborInfo.direction = direction;
    3815      132300 :         thisNeighborInfo.ThisCentroidToNeighborWall = ThisCentroidToNeighborWall;
    3816      132300 :         thisNeighborInfo.ThisWallToNeighborCentroid = ThisWallToNeighborCentroid;
    3817      132300 :         thisNeighborInfo.adiabaticMultiplier = ThisAdiabaticMultiplier;
    3818      132300 :     }
    3819             : 
    3820          11 :     void Domain::setupPipeCircuitInOutCells()
    3821             :     {
    3822             : 
    3823             :         // SUBROUTINE INFORMATION:
    3824             :         //       AUTHOR         Edwin Lee
    3825             :         //       DATE WRITTEN   Summer 2011
    3826             :         //       MODIFIED       na
    3827             :         //       RE-ENGINEERED  na
    3828             : 
    3829          11 :         auto const &cells(this->Cells);
    3830          16 :         for (auto &thisCircuit : this->circuits) {
    3831             : 
    3832           5 :             int SegmentInletCellX = 0;
    3833           5 :             int SegmentInletCellY = 0;
    3834           5 :             int SegmentInletCellZ = 0;
    3835           5 :             int SegmentOutletCellX = 0;
    3836           5 :             int SegmentOutletCellY = 0;
    3837           5 :             int SegmentOutletCellZ = 0;
    3838           5 :             int CircuitInletCellX = 0;
    3839           5 :             int CircuitInletCellY = 0;
    3840           5 :             int CircuitInletCellZ = 0;
    3841           5 :             int CircuitOutletCellX = 0;
    3842           5 :             int CircuitOutletCellY = 0;
    3843           5 :             int CircuitOutletCellZ = 0;
    3844             : 
    3845           5 :             bool CircuitInletCellSet = false;
    3846             : 
    3847          19 :             for (auto &segment : thisCircuit->pipeSegments) {
    3848          14 :                 switch (segment->FlowDirection) {
    3849           7 :                 case SegmentFlow::IncreasingZ:
    3850           7 :                     SegmentInletCellX = segment->PipeCellCoordinates.X;
    3851           7 :                     SegmentInletCellY = segment->PipeCellCoordinates.Y;
    3852           7 :                     SegmentInletCellZ = 0;
    3853           7 :                     SegmentOutletCellX = segment->PipeCellCoordinates.X;
    3854           7 :                     SegmentOutletCellY = segment->PipeCellCoordinates.Y;
    3855           7 :                     SegmentOutletCellZ = this->z_max_index;
    3856           7 :                     break;
    3857           7 :                 case SegmentFlow::DecreasingZ:
    3858           7 :                     SegmentInletCellX = segment->PipeCellCoordinates.X;
    3859           7 :                     SegmentInletCellY = segment->PipeCellCoordinates.Y;
    3860           7 :                     SegmentInletCellZ = this->z_max_index;
    3861           7 :                     SegmentOutletCellX = segment->PipeCellCoordinates.X;
    3862           7 :                     SegmentOutletCellY = segment->PipeCellCoordinates.Y;
    3863           7 :                     SegmentOutletCellZ = 0;
    3864           7 :                     break;
    3865           0 :                 default:
    3866           0 :                     assert(false);
    3867             :                 }
    3868          14 :                 if (!CircuitInletCellSet) {
    3869           5 :                     CircuitInletCellX = SegmentInletCellX;
    3870           5 :                     CircuitInletCellY = SegmentInletCellY;
    3871           5 :                     CircuitInletCellZ = SegmentInletCellZ;
    3872           5 :                     CircuitInletCellSet = true;
    3873             :                 }
    3874          14 :                 CircuitOutletCellX = SegmentOutletCellX;
    3875          14 :                 CircuitOutletCellY = SegmentOutletCellY;
    3876          14 :                 CircuitOutletCellZ = SegmentOutletCellZ;
    3877             :             }
    3878             : 
    3879           5 :             thisCircuit->initInOutCells(cells(CircuitInletCellX, CircuitInletCellY, CircuitInletCellZ),
    3880             :                                         cells(CircuitOutletCellX, CircuitOutletCellY, CircuitOutletCellZ));
    3881             :         }
    3882          11 :     }
    3883             : 
    3884          47 :     int Domain::getCellWidthsCount(RegionType const dir) const
    3885             :     {
    3886             : 
    3887             :         // FUNCTION INFORMATION:
    3888             :         //       AUTHOR         Edwin Lee
    3889             :         //       DATE WRITTEN   Summer 2011
    3890             :         //       MODIFIED       na
    3891             :         //       RE-ENGINEERED  na
    3892             : 
    3893          47 :         if (dir == RegionType::XDirection) {
    3894          20 :             return this->Mesh.X.RegionMeshCount;
    3895          27 :         } else if (dir == RegionType::YDirection) {
    3896          20 :             return this->Mesh.Y.RegionMeshCount;
    3897           7 :         } else if (dir == RegionType::ZDirection) {
    3898           7 :             return this->Mesh.Z.RegionMeshCount;
    3899             :         } else {
    3900           0 :             return 1; // it's either a mesh region (X,Y,ZDirection), or it is some form of partition -- so 1
    3901             :         }
    3902             :         return 0;
    3903             :     }
    3904             : 
    3905         130 :     void Domain::getCellWidths(GridRegion &g, RegionType const direction) const
    3906             :     {
    3907             : 
    3908             :         // FUNCTION INFORMATION:
    3909             :         //       AUTHOR         Edwin Lee
    3910             :         //       DATE WRITTEN   Summer 2011
    3911             :         //       MODIFIED       na
    3912             :         //       RE-ENGINEERED  na
    3913             : 
    3914             :         // Object Data
    3915         130 :         DistributionStructure ThisMesh;
    3916         130 :         ThisMesh.RegionMeshCount = 0;
    3917         130 :         ThisMesh.GeometricSeriesCoefficient = 0.0;
    3918             : 
    3919         130 :         switch (direction) {
    3920          31 :         case RegionType::XDirection:
    3921          31 :             ThisMesh = this->Mesh.X;
    3922          31 :             break;
    3923          31 :         case RegionType::YDirection:
    3924          31 :             ThisMesh = this->Mesh.Y;
    3925          31 :             break;
    3926          18 :         case RegionType::ZDirection:
    3927          18 :             ThisMesh = this->Mesh.Z;
    3928          18 :             break;
    3929          50 :         default:
    3930          50 :             ThisMesh.RegionMeshCount = 1; // it must be a partition type or something
    3931          50 :             ThisMesh.thisMeshDistribution = MeshDistribution::Uniform;
    3932             :             // ShowSevereError(state,  "Invalid RegionType passed to PlantPipingSystems::Domain::getCellWidths; should be x, y, or z
    3933             :             // direction only." );  ShowContinueError(state,  "This is a developer problem, as the code should never reach this point." );
    3934             :             // ShowFatalError(state, "EnergyPlus aborts due to the previous severe error" );
    3935             :         }
    3936             : 
    3937             :         // just one cell for extremely tight regions
    3938         130 :         if ((g.Max - g.Min) < 0.00001) {
    3939           0 :             ThisMesh.RegionMeshCount = 1;
    3940           0 :             ThisMesh.thisMeshDistribution = MeshDistribution::Uniform;
    3941             :         }
    3942         130 :         assert(g.Max > g.Min);
    3943             : 
    3944         130 :         Real64 GridWidth = g.Max - g.Min;
    3945             : 
    3946         130 :         if (ThisMesh.thisMeshDistribution == MeshDistribution::Uniform) {
    3947          96 :             if (this->HasZoneCoupledSlab && g.thisRegionType == RegionType::YDirection && g.Max == this->Extents.yMax) { // Slab region
    3948           0 :                 Real64 const CellWidth = GridWidth / this->NumSlabCells;
    3949           0 :                 for (int I = 0; I <= this->NumSlabCells - 1; ++I) {
    3950           0 :                     g.CellWidths.push_back(CellWidth);
    3951           0 :                 }
    3952             :             } else {
    3953             :                 // we have it quite simple
    3954          96 :                 assert(ThisMesh.RegionMeshCount > 0);
    3955          96 :                 Real64 const CellWidth = GridWidth / ThisMesh.RegionMeshCount;
    3956         284 :                 for (int I = 0; I <= ThisMesh.RegionMeshCount - 1; ++I) {
    3957         188 :                     g.CellWidths.push_back(CellWidth);
    3958             :                 }
    3959             :             }
    3960          34 :         } else if (ThisMesh.thisMeshDistribution == MeshDistribution::SymmetricGeometric) {
    3961             : 
    3962             :             //'then apply this "direction"'s conditions to generate a cell width array
    3963             :             //'first get the total number of cells on this half of the region
    3964          34 :             int NumCellsOnEachSide = ThisMesh.RegionMeshCount / 2; // Already validated to be an even #
    3965             :             //'calculate geometric series
    3966          34 :             Real64 SummationTerm = 0.0;
    3967         136 :             for (int I = 1; I <= NumCellsOnEachSide; ++I) {
    3968         102 :                 SummationTerm += std::pow(ThisMesh.GeometricSeriesCoefficient, I - 1);
    3969             :             }
    3970             :             //'set up a list of cell widths for this region
    3971          34 :             Real64 CellWidth = (GridWidth / 2) / SummationTerm;
    3972          34 :             g.CellWidths.push_back(CellWidth);
    3973         102 :             for (int I = 1; I <= NumCellsOnEachSide - 1; ++I) {
    3974          68 :                 CellWidth *= ThisMesh.GeometricSeriesCoefficient;
    3975          68 :                 g.CellWidths.push_back(CellWidth);
    3976             :             }
    3977         136 :             for (int I = NumCellsOnEachSide - 1; I >= 0; --I) {
    3978         102 :                 g.CellWidths.push_back(g.CellWidths[I]);
    3979             :             }
    3980             : 
    3981           0 :         } else if (ThisMesh.thisMeshDistribution == MeshDistribution::Geometric) {
    3982             : 
    3983           0 :             int NumCells = ThisMesh.RegionMeshCount;
    3984           0 :             if (g.thisRegionType == RegionType::XDirection || g.thisRegionType == RegionType::ZDirection) {
    3985             :                 //'calculate geometric series
    3986           0 :                 Real64 SummationTerm = 0.0;
    3987           0 :                 for (int I = 1; I <= NumCells; ++I) {
    3988           0 :                     SummationTerm += std::pow(ThisMesh.GeometricSeriesCoefficient, I - 1);
    3989             :                 }
    3990           0 :                 Real64 CellWidth = GridWidth / SummationTerm;
    3991           0 :                 if (g.Min == 0) {
    3992             :                     // Ground region to the left of the slab will have cells expanding to the left
    3993             :                     // adding them here moving forward, then reversing it to get this effect
    3994             :                     // Possible spot for diffs
    3995           0 :                     g.CellWidths.push_back(CellWidth);
    3996           0 :                     for (int I = 0; I < NumCells; ++I) {
    3997           0 :                         CellWidth *= ThisMesh.GeometricSeriesCoefficient;
    3998           0 :                         g.CellWidths.push_back(CellWidth);
    3999             :                     }
    4000           0 :                     std::reverse(g.CellWidths.begin(), g.CellWidths.end());
    4001             :                 } else {
    4002             :                     // Slab region will have cells expanding to the right
    4003           0 :                     g.CellWidths.push_back(CellWidth);
    4004           0 :                     for (int I = 1; I <= NumCells - 1; ++I) {
    4005           0 :                         CellWidth *= ThisMesh.GeometricSeriesCoefficient;
    4006           0 :                         g.CellWidths.push_back(CellWidth);
    4007             :                     }
    4008           0 :                 }
    4009           0 :             } else if (g.thisRegionType == RegionType::YDirection) {
    4010             :                 // Assign uniform cell thickness to the slab cells.
    4011           0 :                 if (g.Max == this->Extents.yMax) {
    4012           0 :                     NumCells = this->NumSlabCells;
    4013           0 :                     Real64 CellWidth = GridWidth / NumCells;
    4014           0 :                     for (int I = 0; I <= NumCells - 1; ++I) {
    4015           0 :                         g.CellWidths.push_back(CellWidth);
    4016             :                     }
    4017             :                 } else {
    4018             :                     //'calculate geometric series
    4019           0 :                     Real64 SummationTerm = 0.0;
    4020           0 :                     for (int I = 1; I <= NumCells; ++I) {
    4021           0 :                         SummationTerm += std::pow(ThisMesh.GeometricSeriesCoefficient, I - 1);
    4022             :                     }
    4023           0 :                     Real64 CellWidth = GridWidth / SummationTerm;
    4024             :                     // Ground region under the slab will have cells expanding as we go down
    4025             :                     // adding them here moving forward, then reversing it to get this effect
    4026             :                     // Possible spot for diffs
    4027           0 :                     g.CellWidths.push_back(CellWidth);
    4028           0 :                     for (int I = 1; I < NumCells; ++I) {
    4029           0 :                         CellWidth *= ThisMesh.GeometricSeriesCoefficient;
    4030           0 :                         g.CellWidths.push_back(CellWidth);
    4031             :                     }
    4032           0 :                     std::reverse(g.CellWidths.begin(), g.CellWidths.end());
    4033             :                 }
    4034             :             }
    4035             :         }
    4036         130 :     }
    4037             : 
    4038       13344 :     void Domain::PerformIterationLoop(EnergyPlusData &state)
    4039             :     {
    4040             : 
    4041             :         // SUBROUTINE INFORMATION:
    4042             :         //       AUTHOR         Edwin Lee
    4043             :         //       DATE WRITTEN   Summer 2011
    4044             :         //       MODIFIED       na
    4045             :         //       RE-ENGINEERED  na
    4046             : 
    4047             :         // Always do start of time step inits
    4048       13344 :         this->DoStartOfTimeStepInitializations(state);
    4049             : 
    4050             :         // Begin iterating for this time step
    4051       74811 :         for (int IterationIndex = 1; IterationIndex <= this->SimControls.MaxIterationsPerTS; ++IterationIndex) {
    4052       74811 :             this->ShiftTemperaturesForNewIteration();
    4053       74811 :             if (this->DomainNeedsSimulation) this->PerformTemperatureFieldUpdate(state);
    4054       74811 :             bool FinishedIterationLoop = false;
    4055       74811 :             this->DoEndOfIterationOperations(state, FinishedIterationLoop);
    4056       74811 :             if (FinishedIterationLoop) break;
    4057             :         }
    4058             : 
    4059             :         // Update the basement surface temperatures, if any
    4060       13344 :         if (this->HasBasement || this->HasZoneCoupledBasement) {
    4061        2784 :             this->UpdateBasementSurfaceTemperatures(state);
    4062             :         }
    4063             : 
    4064             :         // Update the slab surface temperatures, if any
    4065       13344 :         if (this->HasZoneCoupledSlab) {
    4066       10560 :             this->UpdateZoneSurfaceTemperatures(state);
    4067             :         }
    4068       13344 :     }
    4069             : 
    4070       14498 :     void Domain::PerformIterationLoop(EnergyPlusData &state, Circuit *thisCircuit)
    4071             :     {
    4072             : 
    4073             :         // SUBROUTINE INFORMATION:
    4074             :         //       AUTHOR         Edwin Lee
    4075             :         //       DATE WRITTEN   Summer 2011
    4076             :         //       MODIFIED       na
    4077             :         //       RE-ENGINEERED  na
    4078             : 
    4079             :         // Always do start of time step inits
    4080       14498 :         this->DoStartOfTimeStepInitializations(state, thisCircuit);
    4081             : 
    4082             :         // Prepare the pipe circuit for calculations, but we'll actually do calcs at the iteration level
    4083       14498 :         if (this->HasAPipeCircuit) {
    4084       14498 :             this->PreparePipeCircuitSimulation(thisCircuit);
    4085             :         }
    4086             : 
    4087             :         // Begin iterating for this time step
    4088       50890 :         for (int IterationIndex = 1; IterationIndex <= this->SimControls.MaxIterationsPerTS; ++IterationIndex) {
    4089             : 
    4090       50890 :             this->ShiftTemperaturesForNewIteration();
    4091             : 
    4092       50890 :             if (this->HasAPipeCircuit) {
    4093       50890 :                 this->PerformPipeCircuitSimulation(state, thisCircuit);
    4094             :             }
    4095             : 
    4096       50890 :             if (this->DomainNeedsSimulation) this->PerformTemperatureFieldUpdate(state);
    4097       50890 :             bool FinishedIterationLoop = false;
    4098       50890 :             this->DoEndOfIterationOperations(state, FinishedIterationLoop);
    4099             : 
    4100       50890 :             if (FinishedIterationLoop) break;
    4101             :         }
    4102             : 
    4103             :         // Update the basement surface temperatures, if any
    4104       14498 :         if (this->HasBasement || this->HasZoneCoupledBasement) {
    4105       10982 :             this->UpdateBasementSurfaceTemperatures(state);
    4106             :         }
    4107             : 
    4108             :         // Update the slab surface temperatures, if any
    4109       14498 :         if (this->HasZoneCoupledSlab) {
    4110           0 :             this->UpdateZoneSurfaceTemperatures(state);
    4111             :         }
    4112       14498 :     }
    4113             : 
    4114      125701 :     void Domain::PerformTemperatureFieldUpdate(EnergyPlusData &state)
    4115             :     {
    4116             : 
    4117             :         // SUBROUTINE INFORMATION:
    4118             :         //       AUTHOR         Edwin Lee
    4119             :         //       DATE WRITTEN   Summer 2011
    4120             :         //       MODIFIED       na
    4121             :         //       RE-ENGINEERED  na
    4122             : 
    4123     1836901 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    4124    30167978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    4125   329151865 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    4126   300695087 :                     auto &cell(this->Cells(X, Y, Z));
    4127             : 
    4128   300695087 :                     switch (cell.cellType) {
    4129     1395596 :                     case CellType::Pipe:
    4130             :                         //'pipes are simulated separately
    4131     1395596 :                         break;
    4132   200017095 :                     case CellType::GeneralField:
    4133             :                     case CellType::Slab:
    4134             :                     case CellType::HorizInsulation:
    4135             :                     case CellType::VertInsulation:
    4136   200017095 :                         cell.Temperature = this->EvaluateFieldCellTemperature(cell);
    4137   200017095 :                         break;
    4138    10890883 :                     case CellType::GroundSurface:
    4139    10890883 :                         cell.Temperature = this->EvaluateGroundSurfaceTemperature(state, cell);
    4140    10890883 :                         break;
    4141    67240379 :                     case CellType::FarfieldBoundary:
    4142    67240379 :                         cell.Temperature = this->EvaluateFarfieldBoundaryTemperature(state, cell);
    4143    67240379 :                         break;
    4144     5847312 :                     case CellType::BasementWall:
    4145             :                     case CellType::BasementCorner:
    4146             :                     case CellType::BasementFloor:
    4147             :                         // basement model, zone-coupled. Call EvaluateZoneInterfaceTemperature routine to handle timestep/hourly simulation.
    4148     5847312 :                         if (this->HasZoneCoupledBasement) {
    4149     2473254 :                             cell.Temperature = this->EvaluateZoneInterfaceTemperature(cell);
    4150             :                         } else { // FHX model
    4151     3374058 :                             cell.Temperature = this->EvaluateBasementCellTemperature(state, cell);
    4152             :                         }
    4153     5847312 :                         break;
    4154     2326788 :                     case CellType::ZoneGroundInterface:
    4155     2326788 :                         cell.Temperature = this->EvaluateZoneInterfaceTemperature(cell);
    4156     2326788 :                         break;
    4157    12977034 :                     case CellType::BasementCutaway:
    4158             :                         // it's ok to not simulate this one
    4159    12977034 :                         break;
    4160           0 :                     default:
    4161           0 :                         assert(false);
    4162             :                     }
    4163             :                 }
    4164             :             }
    4165             :         }
    4166      125701 :     }
    4167             : 
    4168   200017095 :     Real64 Domain::EvaluateFieldCellTemperature(CartesianCell &cell)
    4169             :     {
    4170             : 
    4171             :         // FUNCTION INFORMATION:
    4172             :         //       AUTHOR         Edwin Lee
    4173             :         //       DATE WRITTEN   Summer 2011
    4174             :         //       MODIFIED       na
    4175             :         //       RE-ENGINEERED  na
    4176             : 
    4177             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4178   200017095 :         Real64 Numerator = 0.0;
    4179   200017095 :         Real64 Denominator = 0.0;
    4180   200017095 :         Real64 AdiabaticMultiplier = 1.0;
    4181             : 
    4182             :         // add effect from cell history
    4183   200017095 :         Numerator += cell.Temperature_PrevTimeStep;
    4184   200017095 :         ++Denominator;
    4185             : 
    4186             :         // determine the neighbor types based on cell location
    4187   200017095 :         int NumFieldCells = 0, NumBoundaryCells = 0;
    4188   200017095 :         this->EvaluateCellNeighborDirections(cell, NumFieldCells, NumBoundaryCells);
    4189             : 
    4190             :         // loop across each direction in the simulation
    4191  1371168710 :         for (int DirectionCounter = 0; DirectionCounter <= NumFieldCells; ++DirectionCounter) {
    4192             : 
    4193  1171151615 :             Real64 NeighborTemp = 0.0;
    4194  1171151615 :             Real64 Resistance = 0.0;
    4195  1171151615 :             Direction CurDirection = this->NeighborFieldCells[DirectionCounter];
    4196             : 
    4197             :             //'evaluate the transient expression terms
    4198  1171151615 :             this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4199             : 
    4200  1171151615 :             Numerator += AdiabaticMultiplier * (cell.Beta / Resistance) * NeighborTemp;
    4201  1171151615 :             Denominator += AdiabaticMultiplier * (cell.Beta / Resistance);
    4202             :         }
    4203             : 
    4204             :         //'now that we have passed all directions, update the temperature
    4205   200017095 :         return Numerator / Denominator;
    4206             :     }
    4207             : 
    4208    10890883 :     Real64 Domain::EvaluateGroundSurfaceTemperature(EnergyPlusData &state, CartesianCell &cell)
    4209             :     {
    4210             : 
    4211             :         // FUNCTION INFORMATION:
    4212             :         //       AUTHOR         Edwin Lee
    4213             :         //       DATE WRITTEN   Summer 2011
    4214             :         //       MODIFIED       na
    4215             :         //       RE-ENGINEERED  na
    4216             : 
    4217             :         // FUNCTION PARAMETER DEFINITIONS:
    4218    10890883 :         Real64 constexpr AirDensity(1.22521);   // '[kg/m3]
    4219    10890883 :         Real64 constexpr AirSpecificHeat(1003); // '[J/kg-K]
    4220             :         // evapotranspiration parameters
    4221    10890883 :         Real64 constexpr MeanSolarConstant(0.08196); // 1367 [W/m2], entered in [MJ/m2-minute]
    4222    10890883 :         Real64 constexpr A_s(0.25);                  // ?
    4223    10890883 :         Real64 constexpr B_s(0.5);                   // ?
    4224    10890883 :         Real64 constexpr Absor_Corrected(0.77);
    4225    10890883 :         Real64 const Convert_Wm2_To_MJhrmin(3600.0 / 1000000.0);
    4226    10890883 :         Real64 const Convert_MJhrmin_To_Wm2(1.0 / Convert_Wm2_To_MJhrmin);
    4227    10890883 :         Real64 constexpr Rho_water(998.0); // [kg/m3]
    4228             : 
    4229             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4230    10890883 :         Real64 NeighborTemp = 0.0;
    4231             :         Real64 IncidentHeatGain;
    4232             :         Real64 Latitude_Degrees;   // Latitude, degrees N
    4233             :         Real64 StMeridian_Degrees; // Standard meridian, degrees W -- note it is degrees E in DataEnvironment
    4234             :         Real64 Longitude_Degrees;  // Longitude, degrees W -- note it is degrees E in DataEnvironment
    4235             :         // evapotranspiration calculated values
    4236             :         Real64 Latitude_Radians;
    4237             :         Real64 DayOfYear;
    4238             :         Real64 HourOfDay;
    4239             :         Real64 CurSecondsIntoToday;
    4240             :         Real64 dr;
    4241             :         Real64 Declination;
    4242             :         Real64 b_SC;
    4243             :         Real64 Sc;
    4244             :         Real64 Hour_Angle;
    4245             :         Real64 X_sunset;
    4246             :         Real64 Sunset_Angle;
    4247             :         Real64 Solar_Angle_1;
    4248             :         Real64 Solar_Angle_2;
    4249             :         Real64 QRAD_A;
    4250             :         Real64 QRAD_SO;
    4251             :         Real64 Ratio_SO;
    4252             :         Real64 IncidentSolar_MJhrmin;
    4253             :         Real64 AbsorbedIncidentSolar_MJhrmin;
    4254             :         Real64 VaporPressureSaturated_kPa;
    4255             :         Real64 VaporPressureActual_kPa;
    4256             :         Real64 QRAD_NL;
    4257             :         Real64 NetIncidentRadiation_MJhr; // [MJ/hr]
    4258             :         Real64 NetIncidentRadiation_Wm2;  // [W/m2]
    4259             :         Real64 CN;
    4260             :         Real64 G_hr;
    4261             :         Real64 Cd;
    4262             :         Real64 Slope_S;
    4263             :         Real64 Pressure;
    4264             :         Real64 PsychrometricConstant;
    4265             :         Real64 EvapotransFluidLoss_mmhr;
    4266             :         Real64 EvapotransFluidLoss_mhr;
    4267             :         Real64 LatentHeatVaporization;
    4268             :         Real64 EvapotransHeatLoss_MJhrmin; // [MJ/m2-hr]
    4269             :         Real64 EvapotransHeatLoss_Wm2;     // [W/m2]
    4270             :         Real64 CurAirTempK;
    4271             :         Real64 GroundCoverCoefficient;
    4272             : 
    4273             :         // retrieve information from E+ globals
    4274    10890883 :         Latitude_Degrees = state.dataEnvrn->Latitude;
    4275    10890883 :         StMeridian_Degrees = -state.dataEnvrn->TimeZoneMeridian; // Standard meridian, degrees W
    4276    10890883 :         Longitude_Degrees = -state.dataEnvrn->Longitude;         // Longitude, degrees W
    4277             : 
    4278             :         // retrieve any information from input data structure
    4279    10890883 :         GroundCoverCoefficient = this->Moisture.GroundCoverCoefficient;
    4280             : 
    4281             :         // initialize values
    4282    10890883 :         Real64 AdiabaticMultiplier = 1.0;
    4283    10890883 :         Real64 Numerator = 0.0;
    4284    10890883 :         Real64 Denominator = 0.0;
    4285    10890883 :         Real64 Resistance = 0.0;
    4286    10890883 :         Real64 Beta = cell.Beta;
    4287    10890883 :         Real64 ThisNormalArea = cell.normalArea(Direction::PositiveY);
    4288             : 
    4289             :         //'add effect from previous time step
    4290    10890883 :         Numerator += cell.Temperature_PrevTimeStep;
    4291    10890883 :         ++Denominator;
    4292             : 
    4293             :         // now that we aren't infinitesimal, we need to determine the neighbor types based on cell location
    4294    10890883 :         int NumFieldCells = 0, NumBoundaryCells = 0;
    4295    10890883 :         this->EvaluateCellNeighborDirections(cell, NumFieldCells, NumBoundaryCells);
    4296             : 
    4297             :         // loop over all regular neighbor cells, check if we have adiabatic on opposite surface
    4298    62670850 :         for (int DirectionCounter = 0; DirectionCounter <= NumFieldCells; ++DirectionCounter) {
    4299    51779967 :             Direction CurDirection = this->NeighborFieldCells[DirectionCounter];
    4300             : 
    4301             :             // Use the multiplier ( either 1 or 2 ) to calculate the neighbor cell effects
    4302    51779967 :             this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4303    51779967 :             Numerator = AdiabaticMultiplier * Numerator + (Beta / Resistance) * NeighborTemp;
    4304    51779967 :             Denominator = AdiabaticMultiplier * Denominator + (Beta / Resistance);
    4305             :         }
    4306             : 
    4307             :         // do all non-adiabatic boundary types here
    4308    24456214 :         for (int DirectionCounter = 0; DirectionCounter <= NumBoundaryCells; ++DirectionCounter) {
    4309    13565331 :             Direction CurDirection = this->NeighborBoundaryCells[DirectionCounter];
    4310             : 
    4311             :             // For Zone-coupled slab or basement configuration
    4312    13565331 :             if (this->HasZoneCoupledSlab || this->HasZoneCoupledBasement) {
    4313             :                 //-x-direction will always be a farfield boundary
    4314             :                 //-z will also be a farfield boundary
    4315             :                 //+x and +z will be handled above
    4316             :                 //-y will always be a neighbor cell, so it is handled above
    4317             :                 //+y will always be the outdoor air
    4318    16544906 :                 if (CurDirection == Direction::NegativeX || CurDirection == Direction::NegativeZ) {
    4319             :                     // always farfield
    4320      305340 :                     this->EvaluateFarfieldCharacteristics(state, cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4321      305340 :                     Numerator += (Beta / Resistance) * NeighborTemp;
    4322      305340 :                     Denominator += (Beta / Resistance);
    4323     7967113 :                 } else if (CurDirection == Direction::PositiveY) {
    4324             :                     // convection at the surface
    4325     7239359 :                     if (state.dataEnvrn->WindSpeed > 0.1) {
    4326     7239359 :                         Resistance = 208.0 / (AirDensity * AirSpecificHeat * state.dataEnvrn->WindSpeed * ThisNormalArea);
    4327     7239359 :                         Numerator += (Beta / Resistance) * this->Cur.CurAirTemp;
    4328     7239359 :                         Denominator += (Beta / Resistance);
    4329             :                     }
    4330      727754 :                 } else if (CurDirection == Direction::NegativeY) {
    4331           0 :                     assert(false); // debug error, can't get here!
    4332             :                 }
    4333             :             } else { // FHX model
    4334             :                 // x-direction will always be a farfield boundary
    4335             :                 // z-direction will be handled above -- adiabatic
    4336             :                 //-y we don't handle here because -y will always be a neighbor cell, so handled above
    4337             :                 //+y will always be the outdoor air
    4338     5292878 :                 if ((CurDirection == Direction::PositiveX) || (CurDirection == Direction::NegativeX)) {
    4339             :                     // always farfield
    4340      403226 :                     this->EvaluateFarfieldCharacteristics(state, cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4341      403226 :                     Numerator += (Beta / Resistance) * NeighborTemp;
    4342      403226 :                     Denominator += (Beta / Resistance);
    4343     4889652 :                 } else if ((CurDirection == Direction::PositiveZ) || (CurDirection == Direction::NegativeZ)) {
    4344             :                     // debug error, can't get here
    4345     3651524 :                 } else if (CurDirection == Direction::PositiveY) {
    4346             :                     // convection at the surface
    4347     3651524 :                     if (state.dataEnvrn->WindSpeed > 0.1) {
    4348     3599692 :                         Resistance = 208.0 / (AirDensity * AirSpecificHeat * state.dataEnvrn->WindSpeed * ThisNormalArea);
    4349     3599692 :                         Numerator += (Beta / Resistance) * this->Cur.CurAirTemp;
    4350     3599692 :                         Denominator += (Beta / Resistance);
    4351             :                     } else {
    4352             :                         // Future development should include additional natural convection effects here
    4353             :                     }
    4354           0 :                 } else if (CurDirection == Direction::NegativeY) {
    4355           0 :                     assert(false); // debug error, can't get here!
    4356             :                 }
    4357             :             }
    4358             :         }
    4359             : 
    4360             :         // Latitude, converted to radians...positive for northern hemisphere, [radians]
    4361    10890883 :         Latitude_Radians = DataGlobalConstants::Pi / 180.0 * Latitude_Degrees;
    4362             : 
    4363             :         // The day of year at this point in the simulation
    4364    10890883 :         DayOfYear = int(this->Cur.CurSimTimeSeconds / DataGlobalConstants::SecsInDay);
    4365             : 
    4366             :         // The number of seconds into the current day
    4367    10890883 :         CurSecondsIntoToday = int(mod(this->Cur.CurSimTimeSeconds, DataGlobalConstants::SecsInDay));
    4368             : 
    4369             :         // The number of hours into today
    4370    10890883 :         HourOfDay = int(CurSecondsIntoToday / DataGlobalConstants::SecInHour);
    4371             : 
    4372             :         // For convenience convert to Kelvin once
    4373    10890883 :         CurAirTempK = this->Cur.CurAirTemp + 273.15;
    4374             : 
    4375             :         // Calculate some angles
    4376    10890883 :         dr = 1.0 + 0.033 * std::cos(2.0 * DataGlobalConstants::Pi * DayOfYear / 365.0);
    4377    10890883 :         Declination = 0.409 * std::sin(2.0 * DataGlobalConstants::Pi / 365.0 * DayOfYear - 1.39);
    4378    10890883 :         b_SC = 2.0 * DataGlobalConstants::Pi * (DayOfYear - 81.0) / 364.0;
    4379    10890883 :         Sc = 0.1645 * std::sin(2.0 * b_SC) - 0.1255 * std::cos(b_SC) - 0.025 * std::sin(b_SC);
    4380    10890883 :         Hour_Angle = DataGlobalConstants::Pi / 12.0 * (((HourOfDay - 0.5) + 0.06667 * (StMeridian_Degrees - Longitude_Degrees) + Sc) - 12.0);
    4381             : 
    4382             :         // Calculate sunset something, and constrain to a minimum of 0.000001
    4383    10890883 :         X_sunset = 1.0 - pow_2(std::tan(Latitude_Radians)) * pow_2(std::tan(Declination));
    4384    10890883 :         X_sunset = max(X_sunset, 0.000001);
    4385             : 
    4386             :         // Find sunset angle
    4387    10890883 :         Sunset_Angle = DataGlobalConstants::Pi / 2.0 - std::atan(-std::tan(Latitude_Radians) * std::tan(Declination) / std::sqrt(X_sunset));
    4388             : 
    4389             :         // Find solar angles
    4390    10890883 :         Solar_Angle_1 = Hour_Angle - DataGlobalConstants::Pi / 24.0;
    4391    10890883 :         Solar_Angle_2 = Hour_Angle + DataGlobalConstants::Pi / 24.0;
    4392             : 
    4393             :         // Constrain solar angles
    4394    10890883 :         if (Solar_Angle_1 < -Sunset_Angle) Solar_Angle_1 = -Sunset_Angle;
    4395    10890883 :         if (Solar_Angle_2 < -Sunset_Angle) Solar_Angle_2 = -Sunset_Angle;
    4396    10890883 :         if (Solar_Angle_1 > Sunset_Angle) Solar_Angle_1 = Sunset_Angle;
    4397    10890883 :         if (Solar_Angle_2 > Sunset_Angle) Solar_Angle_2 = Sunset_Angle;
    4398    10890883 :         if (Solar_Angle_1 > Solar_Angle_2) Solar_Angle_1 = Solar_Angle_2;
    4399             : 
    4400             :         // Convert input solar radiation [w/m2] into units for ET model, [MJ/hr-min]
    4401    10890883 :         IncidentSolar_MJhrmin = this->Cur.CurIncidentSolar * Convert_Wm2_To_MJhrmin;
    4402             : 
    4403             :         // Calculate another Q term...
    4404    21781766 :         QRAD_A = 12.0 * 60.0 / DataGlobalConstants::Pi * MeanSolarConstant * dr *
    4405    21781766 :                  ((Solar_Angle_2 - Solar_Angle_1) * std::sin(Latitude_Radians) * std::sin(Declination) +
    4406    10890883 :                   std::cos(Latitude_Radians) * std::cos(Declination) * (std::sin(Solar_Angle_2) - std::sin(Solar_Angle_1)));
    4407             : 
    4408             :         // Calculate another Q term...
    4409    10890883 :         QRAD_SO = (A_s + B_s + 0.00002 * state.dataEnvrn->Elevation) * QRAD_A;
    4410             : 
    4411             :         // Correct the Qrad term ... better way??
    4412    10890883 :         if (IncidentSolar_MJhrmin < 0.01) {
    4413     7162573 :             Ratio_SO = 0.0;
    4414             :         } else {
    4415     3728310 :             if (QRAD_SO != 0.0) {
    4416     2105561 :                 Ratio_SO = IncidentSolar_MJhrmin / QRAD_SO;
    4417             :             } else {
    4418             :                 // I used logic below to choose value, divide by 0 = infinity, so value = 1, not sure if correct...
    4419     1622749 :                 Ratio_SO = 1.0;
    4420             :             }
    4421             :         }
    4422             : 
    4423             :         // Constrain Ratio_SO
    4424    10890883 :         Ratio_SO = min(Ratio_SO, 1.0);
    4425    10890883 :         Ratio_SO = max(Ratio_SO, 0.3);
    4426             : 
    4427             :         // Calculate another Q term, [MJ/hr-min]
    4428    10890883 :         AbsorbedIncidentSolar_MJhrmin = Absor_Corrected * IncidentSolar_MJhrmin;
    4429             : 
    4430             :         // Calculate saturated vapor pressure, [kPa]
    4431    10890883 :         VaporPressureSaturated_kPa = 0.6108 * std::exp(17.27 * this->Cur.CurAirTemp / (this->Cur.CurAirTemp + 237.3));
    4432             : 
    4433             :         // Calculate actual vapor pressure, [kPa]
    4434    10890883 :         VaporPressureActual_kPa = VaporPressureSaturated_kPa * this->Cur.CurRelativeHumidity / 100.0;
    4435             : 
    4436             :         // Calculate another Q term, [MJ/m2-hr]
    4437    10890883 :         QRAD_NL = 2.042E-10 * pow_4(CurAirTempK) * (0.34 - 0.14 * std::sqrt(VaporPressureActual_kPa)) * (1.35 * Ratio_SO - 0.35);
    4438             : 
    4439             :         // Calculate another Q term, [MJ/hr]
    4440    10890883 :         NetIncidentRadiation_MJhr = AbsorbedIncidentSolar_MJhrmin - QRAD_NL;
    4441             : 
    4442             :         // ?
    4443    10890883 :         CN = 37.0;
    4444             : 
    4445             :         // Check whether there was sun
    4446    10890883 :         if (NetIncidentRadiation_MJhr < 0.0) {
    4447     7558885 :             G_hr = 0.5 * NetIncidentRadiation_MJhr;
    4448     7558885 :             Cd = 0.96;
    4449             :         } else {
    4450     3331998 :             G_hr = 0.1 * NetIncidentRadiation_MJhr;
    4451     3331998 :             Cd = 0.24;
    4452             :         }
    4453             : 
    4454             :         // Just For Check
    4455             :         // Lu Xing Sep 22 2009
    4456             : 
    4457    10890883 :         Slope_S = 2503.0 * std::exp(17.27 * this->Cur.CurAirTemp / (this->Cur.CurAirTemp + 237.3)) / pow_2(this->Cur.CurAirTemp + 237.3);
    4458    10890883 :         Pressure = 98.0;
    4459    10890883 :         PsychrometricConstant = 0.665e-3 * Pressure;
    4460             : 
    4461             :         // Evapotranspiration constant, [mm/hr]
    4462    10890883 :         EvapotransFluidLoss_mmhr =
    4463    21781766 :             (GroundCoverCoefficient * Slope_S * (NetIncidentRadiation_MJhr - G_hr) +
    4464    10890883 :              PsychrometricConstant * (CN / CurAirTempK) * this->Cur.CurWindSpeed * (VaporPressureSaturated_kPa - VaporPressureActual_kPa)) /
    4465    10890883 :             (Slope_S + PsychrometricConstant * (1 + Cd * this->Cur.CurWindSpeed));
    4466             : 
    4467             :         // Convert units, [m/hr]
    4468    10890883 :         EvapotransFluidLoss_mhr = EvapotransFluidLoss_mmhr / 1000.0;
    4469             : 
    4470             :         // Calculate latent heat, [MJ/kg]
    4471             :         // Full formulation is cubic: L(T) = -0.0000614342 * T**3 + 0.00158927 * T**2 - 2.36418 * T + 2500.79[5]
    4472             :         // In: Cubic fit to Table 2.1,p.16, Textbook: R.R.Rogers & M.K. Yau, A Short Course in Cloud Physics, 3e,(1989), Pergamon press
    4473             :         // But a linear relation should suffice;
    4474             :         // note-for now using the previous time step temperature as an approximation to help ensure stability
    4475    10890883 :         LatentHeatVaporization = 2.501 - 2.361e-3 * cell.Temperature_PrevTimeStep;
    4476             : 
    4477             :         // Calculate evapotranspiration heat loss, [MJ/m2-hr]
    4478    10890883 :         EvapotransHeatLoss_MJhrmin = Rho_water * EvapotransFluidLoss_mhr * LatentHeatVaporization;
    4479             : 
    4480             :         // Convert net incident solar units, [W/m2]
    4481    10890883 :         NetIncidentRadiation_Wm2 = NetIncidentRadiation_MJhr * Convert_MJhrmin_To_Wm2;
    4482             : 
    4483             :         // Convert evapotranspiration units, [W/m2]
    4484    10890883 :         EvapotransHeatLoss_Wm2 = EvapotransHeatLoss_MJhrmin * Convert_MJhrmin_To_Wm2;
    4485             : 
    4486             :         // Calculate overall net heat ?gain? into the cell, [W]
    4487    10890883 :         IncidentHeatGain = (NetIncidentRadiation_Wm2 - EvapotransHeatLoss_Wm2) * ThisNormalArea;
    4488             : 
    4489             :         // Add any solar/evapotranspiration heat gain here
    4490    10890883 :         Numerator += Beta * IncidentHeatGain;
    4491             : 
    4492             :         // Calculate the return temperature and leave
    4493    10890883 :         return Numerator / Denominator;
    4494             :     }
    4495             : 
    4496     3374058 :     Real64 Domain::EvaluateBasementCellTemperature(EnergyPlusData &state, CartesianCell &cell)
    4497             :     {
    4498             : 
    4499             :         // FUNCTION INFORMATION:
    4500             :         //       AUTHOR         Edwin Lee
    4501             :         //       DATE WRITTEN   Summer 2011
    4502             :         //       MODIFIED       na
    4503             :         //       RE-ENGINEERED  na
    4504             : 
    4505             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4506             :         Real64 Beta;
    4507     3374058 :         Real64 NeighborTemp = 0.0;
    4508             :         Real64 HeatFlux;
    4509     3374058 :         Real64 Numerator = 0.0;
    4510     3374058 :         Real64 Denominator = 0.0;
    4511     3374058 :         Real64 Resistance = 0.0;
    4512     3374058 :         Real64 AdiabaticMultiplier = 1.0;
    4513             : 
    4514             :         // add effect from previous time step
    4515     3374058 :         Numerator += cell.Temperature_PrevTimeStep;
    4516     3374058 :         ++Denominator;
    4517             : 
    4518     3374058 :         switch (cell.cellType) {
    4519     2778636 :         case CellType::BasementWall:
    4520             : 
    4521             :             // we will only have heat flux from the basement wall and heat conduction to the +x cell
    4522             : 
    4523             :             // This is actually only a half-cell since the basement wall slices right through the middle in one direction
    4524     2778636 :             Beta = cell.Beta / 2.0;
    4525             : 
    4526             :             // get the average basement wall heat flux and add it to the tally
    4527     2778636 :             HeatFlux = this->GetBasementWallHeatFlux(state);
    4528     2778636 :             Numerator += Beta * HeatFlux * cell.height();
    4529             : 
    4530             :             // then get the +x conduction to continue the heat balance
    4531     2778636 :             this->EvaluateNeighborCharacteristics(cell, Direction::PositiveX, NeighborTemp, Resistance, AdiabaticMultiplier);
    4532     2778636 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4533     2778636 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4534             : 
    4535     2778636 :             break;
    4536             : 
    4537      396948 :         case CellType::BasementFloor:
    4538             : 
    4539             :             // we will only have heat flux from the basement floor and heat conduction to the lower cell
    4540             : 
    4541             :             // This is actually only a half-cell since the basement wall slices right through the middle in one direction
    4542      396948 :             Beta = cell.Beta / 2.0;
    4543             : 
    4544             :             // get the average basement floor heat flux and add it to the tally
    4545      396948 :             HeatFlux = this->GetBasementFloorHeatFlux(state);
    4546      396948 :             Numerator += Beta * HeatFlux * cell.width();
    4547             : 
    4548             :             // then get the -y conduction to continue the heat balance
    4549      396948 :             this->EvaluateNeighborCharacteristics(cell, Direction::NegativeY, NeighborTemp, Resistance, AdiabaticMultiplier);
    4550      396948 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4551      396948 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4552             : 
    4553      396948 :             break;
    4554             : 
    4555      198474 :         case CellType::BasementCorner:
    4556             : 
    4557             :             // This is actually only a three-quarter-cell since the basement wall slices right through the middle in both directions
    4558      198474 :             Beta = cell.Beta * 3.0 / 4.0;
    4559             : 
    4560             :             // we will only have heat conduction to the +x and -y cells
    4561      198474 :             this->EvaluateNeighborCharacteristics(cell, Direction::PositiveX, NeighborTemp, Resistance, AdiabaticMultiplier);
    4562      198474 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4563      198474 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4564             : 
    4565      198474 :             this->EvaluateNeighborCharacteristics(cell, Direction::NegativeY, NeighborTemp, Resistance, AdiabaticMultiplier);
    4566      198474 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4567      198474 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4568             : 
    4569      198474 :             break;
    4570             : 
    4571           0 :         default:
    4572             :             // other cell types are not calculated here
    4573           0 :             break;
    4574             :         }
    4575             : 
    4576     3374058 :         return Numerator / Denominator;
    4577             :     }
    4578             : 
    4579    67240379 :     Real64 Domain::EvaluateFarfieldBoundaryTemperature(EnergyPlusData &state, CartesianCell &cell)
    4580             :     {
    4581             : 
    4582             :         // FUNCTION INFORMATION:
    4583             :         //       AUTHOR         Edwin Lee
    4584             :         //       DATE WRITTEN   Summer 2011
    4585             :         //       MODIFIED       na
    4586             :         //       RE-ENGINEERED  na
    4587             : 
    4588             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4589    67240379 :         Real64 Numerator = 0.0;
    4590    67240379 :         Real64 Denominator = 0.0;
    4591    67240379 :         Real64 Resistance = 0.0;
    4592    67240379 :         Real64 AdiabaticMultiplier = 1.0;
    4593    67240379 :         Real64 Beta = cell.Beta;
    4594             : 
    4595             :         // add effect from previous time step
    4596    67240379 :         Numerator += cell.Temperature_PrevTimeStep;
    4597    67240379 :         ++Denominator;
    4598             : 
    4599             :         // now that we aren't infinitesimal, we need to determine the neighbor types based on cell location
    4600    67240379 :         int NumFieldCells = 0, NumBoundaryCells = 0;
    4601    67240379 :         this->EvaluateCellNeighborDirections(cell, NumFieldCells, NumBoundaryCells);
    4602             : 
    4603             :         // Do all neighbor cells
    4604   390681931 :         for (int DirectionCounter = 0; DirectionCounter <= NumFieldCells; ++DirectionCounter) {
    4605   323441552 :             Direction CurDirection = this->NeighborFieldCells[DirectionCounter];
    4606   323441552 :             Real64 NeighborTemp = 0.0;
    4607   323441552 :             this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4608   323441552 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4609   323441552 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4610             :         }
    4611             : 
    4612             :         // Then all farfield boundaries
    4613   147241101 :         for (int DirectionCounter = 0; DirectionCounter <= NumBoundaryCells; ++DirectionCounter) {
    4614    80000722 :             Direction CurDirection = this->NeighborBoundaryCells[DirectionCounter];
    4615    80000722 :             Real64 NeighborTemp = 0.0;
    4616    80000722 :             this->EvaluateFarfieldCharacteristics(state, cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4617    80000722 :             Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4618    80000722 :             Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4619             :         }
    4620             : 
    4621    67240379 :         return Numerator / Denominator;
    4622             :     }
    4623             : 
    4624     4800042 :     Real64 Domain::EvaluateZoneInterfaceTemperature(CartesianCell &cell)
    4625             :     {
    4626             : 
    4627             :         // FUNCTION INFORMATION:
    4628             :         //       AUTHOR         Edwin Lee
    4629             :         //       DATE WRITTEN   Summer 2011
    4630             :         //       MODIFIED       na
    4631             :         //       RE-ENGINEERED  na
    4632             : 
    4633             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4634             :         Real64 HeatFlux;
    4635             :         Real64 ConductionArea;
    4636     4800042 :         Real64 Numerator = 0.0;
    4637     4800042 :         Real64 Denominator = 0.0;
    4638     4800042 :         Real64 Resistance = 0.0;
    4639     4800042 :         Real64 AdiabaticMultiplier = 1.0;
    4640     4800042 :         Real64 Beta = cell.Beta;
    4641             : 
    4642             :         // add effect from previous time step
    4643     4800042 :         Numerator += cell.Temperature_PrevTimeStep;
    4644     4800042 :         ++Denominator;
    4645             : 
    4646     4800042 :         if (cell.cellType == CellType::BasementWall) {
    4647             :             // Get the average basement wall heat flux and add it to the tally
    4648     1648836 :             HeatFlux = this->WallHeatFlux;
    4649     1648836 :             if (cell.X_index == this->XWallIndex) {
    4650      824418 :                 ConductionArea = cell.depth() * cell.height();
    4651      824418 :                 Numerator += Beta * HeatFlux * ConductionArea;
    4652      824418 :             } else if (cell.Z_index == this->ZWallIndex) {
    4653      824418 :                 ConductionArea = cell.width() * cell.height();
    4654      824418 :                 Numerator += Beta * HeatFlux * ConductionArea;
    4655             :             }
    4656     3151206 :         } else if (cell.cellType == CellType::BasementFloor) {
    4657             :             // Get the average basement floor heat flux and add it to the tally
    4658      824418 :             HeatFlux = this->FloorHeatFlux;
    4659      824418 :             ConductionArea = cell.width() * cell.depth();
    4660      824418 :             Numerator += Beta * HeatFlux * ConductionArea;
    4661     2326788 :         } else if (cell.cellType == CellType::ZoneGroundInterface) {
    4662             :             // Get the average slab heat flux and add it to the tally
    4663     2326788 :             HeatFlux = this->WeightedHeatFlux(cell.X_index, cell.Z_index);
    4664     2326788 :             ConductionArea = cell.width() * cell.depth();
    4665     2326788 :             Numerator += Beta * HeatFlux * ConductionArea;
    4666             :         }
    4667             : 
    4668             :         // determine the neighbor types based on cell location
    4669     4800042 :         int NumFieldCells = 0, NumBoundaryCells = 0;
    4670     4800042 :         this->EvaluateCellNeighborDirections(cell, NumFieldCells, NumBoundaryCells);
    4671             : 
    4672             :         // loop across each direction in the simulation
    4673    29948298 :         for (int DirectionCounter = 0; DirectionCounter <= NumFieldCells; ++DirectionCounter) {
    4674             : 
    4675    25148256 :             Real64 NeighborTemp = 0.0;
    4676    25148256 :             Direction CurDirection = this->NeighborFieldCells[DirectionCounter];
    4677             : 
    4678             :             // Have to be careful here to make sure heat conduction happens only in the appropriate directions
    4679    25148256 :             if (cell.cellType == CellType::BasementWall) {
    4680             :                 // No heat conduction from the X-side basement wall cell to the +x cell ( basement cutaway )
    4681     9526608 :                 if (cell.X_index == this->XWallIndex && CurDirection != Direction::PositiveX) {
    4682             :                     // Evaluate the transient expression terms
    4683     3938886 :                     this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4684     3938886 :                     Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4685     3938886 :                     Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4686             :                 }
    4687             :                 // No heat conduction from the Z-side basement wall cell to the +z cell ( basement cutaway )
    4688     9526608 :                 if (cell.Z_index == this->ZWallIndex && CurDirection != Direction::PositiveZ) {
    4689             :                     // Evaluate the transient expression terms
    4690     3938886 :                     this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4691     3938886 :                     Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4692     3938886 :                     Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4693             :                 }
    4694    15621648 :             } else if (cell.cellType == CellType::BasementFloor) {
    4695             :                 // No heat conduction from the basement floor cell to the +y cell ( basement cutaway )
    4696     4763304 :                 if (CurDirection != Direction::PositiveY) {
    4697             :                     // Evaluate the transient expression terms
    4698     3938886 :                     this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4699     3938886 :                     Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4700     3938886 :                     Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4701             :                 }
    4702    10858344 :             } else if (cell.cellType == CellType::ZoneGroundInterface || cell.cellType == CellType::BasementCorner) {
    4703             :                 // Heat conduction in all directions
    4704             :                 // Evaluate the transient expression terms
    4705    10858344 :                 this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    4706    10858344 :                 Numerator += AdiabaticMultiplier * (Beta / Resistance) * NeighborTemp;
    4707    10858344 :                 Denominator += AdiabaticMultiplier * (Beta / Resistance);
    4708             :             }
    4709             :         }
    4710             : 
    4711     4800042 :         return Numerator / Denominator;
    4712             :     }
    4713             : 
    4714     2784204 :     Real64 Domain::GetBasementWallHeatFlux(EnergyPlusData &state)
    4715             :     {
    4716             : 
    4717             :         // FUNCTION INFORMATION:
    4718             :         //       AUTHOR         Edwin Lee
    4719             :         //       DATE WRITTEN   Summer 2011
    4720             :         //       MODIFIED       na
    4721             :         //       RE-ENGINEERED  na
    4722             : 
    4723     2784204 :         Real64 RunningSummation = 0.0;
    4724     2784204 :         auto const &numSurfaces = static_cast<unsigned int>(this->BasementZone.WallSurfacePointers.size());
    4725    13921020 :         for (auto &surfaceIndex : this->BasementZone.WallSurfacePointers) {
    4726    11136816 :             RunningSummation += state.dataHeatBalSurf->SurfQdotConvOutPerArea(surfaceIndex);
    4727             :         }
    4728     2784204 :         return -RunningSummation / numSurfaces; // heat flux is negative here
    4729             :     }
    4730             : 
    4731      402516 :     Real64 Domain::GetBasementFloorHeatFlux(EnergyPlusData &state)
    4732             :     {
    4733             : 
    4734             :         // FUNCTION INFORMATION:
    4735             :         //       AUTHOR         Edwin Lee
    4736             :         //       DATE WRITTEN   Summer 2011
    4737             :         //       MODIFIED       na
    4738             :         //       RE-ENGINEERED  na
    4739             : 
    4740      402516 :         Real64 RunningSummation = 0.0;
    4741      402516 :         auto const &numSurfaces = static_cast<unsigned int>(this->BasementZone.FloorSurfacePointers.size());
    4742      805032 :         for (auto &surfaceIndex : this->BasementZone.FloorSurfacePointers) {
    4743      402516 :             RunningSummation += state.dataHeatBalSurf->SurfQdotConvOutPerArea(surfaceIndex);
    4744             :         }
    4745      402516 :         return -RunningSummation / numSurfaces; // heat flux is negative here
    4746             :     }
    4747             : 
    4748       13766 :     void Domain::UpdateBasementSurfaceTemperatures(EnergyPlusData &state)
    4749             :     {
    4750             : 
    4751             :         // SUBROUTINE INFORMATION:
    4752             :         //       AUTHOR         Edwin Lee
    4753             :         //       DATE WRITTEN   Summer 2011
    4754             :         //       MODIFIED       na
    4755             :         //       RE-ENGINEERED  na
    4756             : 
    4757             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4758       13766 :         Real64 constexpr BigNumber(10000.0);
    4759             : 
    4760             :         // First the wall
    4761       13766 :         this->BasementWallTemp = this->GetAverageTempByType(state, CellType::BasementWall);
    4762       13766 :         int OSCMIndex = this->BasementZone.WallBoundaryOSCMIndex;
    4763       13766 :         state.dataSurface->OSCM(OSCMIndex).TConv = this->BasementWallTemp;
    4764       13766 :         state.dataSurface->OSCM(OSCMIndex).HConv = BigNumber;
    4765       13766 :         state.dataSurface->OSCM(OSCMIndex).TRad = this->BasementWallTemp;
    4766       13766 :         state.dataSurface->OSCM(OSCMIndex).HRad = 0.0;
    4767             : 
    4768             :         // Then the floor
    4769       13766 :         this->BasementFloorTemp = this->GetAverageTempByType(state, CellType::BasementFloor);
    4770       13766 :         OSCMIndex = this->BasementZone.FloorBoundaryOSCMIndex;
    4771       13766 :         state.dataSurface->OSCM(OSCMIndex).TConv = this->BasementFloorTemp;
    4772       13766 :         state.dataSurface->OSCM(OSCMIndex).HConv = BigNumber;
    4773       13766 :         state.dataSurface->OSCM(OSCMIndex).TRad = this->BasementFloorTemp;
    4774       13766 :         state.dataSurface->OSCM(OSCMIndex).HRad = 0.0;
    4775       13766 :     }
    4776             : 
    4777       21120 :     Real64 Domain::GetZoneInterfaceHeatFlux(EnergyPlusData &state)
    4778             :     {
    4779             : 
    4780             :         // FUNCTION INFORMATION:
    4781             :         //       AUTHOR         Edwin Lee
    4782             :         //       DATE WRITTEN   Summer 2011
    4783             :         //       MODIFIED       na
    4784             :         //       RE-ENGINEERED  na
    4785             : 
    4786       21120 :         Real64 RunningSummation = 0.0;
    4787       21120 :         auto const &NumSurfaces = this->ZoneCoupledSurfaces.size();
    4788       78336 :         for (auto &z : this->ZoneCoupledSurfaces) {
    4789       57216 :             RunningSummation += state.dataHeatBalSurf->SurfQdotConvOutPerArea(z.IndexInSurfaceArray);
    4790             :         }
    4791       21120 :         return -RunningSummation / NumSurfaces; // heat flux is negative here
    4792             :     }
    4793             : 
    4794       10560 :     void Domain::UpdateZoneSurfaceTemperatures(EnergyPlusData &state)
    4795             :     {
    4796             : 
    4797             :         // SUBROUTINE INFORMATION:
    4798             :         //       AUTHOR
    4799             :         //       DATE WRITTEN
    4800             :         //       MODIFIED       na
    4801             :         //       RE-ENGINEERED  na
    4802             : 
    4803             :         // SUBROUTINE PARAMETER DEFINITIONS:
    4804       10560 :         Real64 constexpr BigNumber(10000.0);
    4805             : 
    4806       10560 :         this->ZoneCoupledSurfaceTemp = this->GetAverageTempByType(state, CellType::ZoneGroundInterface);
    4807       10560 :         int OSCMIndex = this->ZoneCoupledOSCMIndex;
    4808       10560 :         state.dataSurface->OSCM(OSCMIndex).TConv = this->ZoneCoupledSurfaceTemp;
    4809       10560 :         state.dataSurface->OSCM(OSCMIndex).HConv = BigNumber;
    4810       10560 :         state.dataSurface->OSCM(OSCMIndex).TRad = this->ZoneCoupledSurfaceTemp;
    4811       10560 :         state.dataSurface->OSCM(OSCMIndex).HRad = 0.0;
    4812             : 
    4813             :         // Reset the interface heat flux after iteration
    4814       10560 :         this->ResetHeatFluxFlag = true;
    4815       10560 :     }
    4816             : 
    4817       48652 :     Real64 Domain::GetAverageTempByType(EnergyPlusData &state, CellType const cellType) const
    4818             :     {
    4819             : 
    4820             :         // FUNCTION INFORMATION:
    4821             :         //       AUTHOR         Edwin Lee
    4822             :         //       DATE WRITTEN   Summer 2011
    4823             :         //       MODIFIED       na
    4824             :         //       RE-ENGINEERED  na
    4825             : 
    4826             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    4827       48652 :         Real64 RunningSummation = 0.0;
    4828       48652 :         Real64 RunningVolume = 0.0;
    4829             : 
    4830       48652 :         auto const &cells(Cells);
    4831      780120 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    4832    13089240 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    4833   131081236 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    4834   118723464 :                     auto const &cell(cells(X, Y, Z));
    4835   118723464 :                     if (cell.cellType == cellType) {
    4836     2491104 :                         Real64 CellVolume = cell.volume();
    4837     2491104 :                         RunningVolume += CellVolume;
    4838     2491104 :                         RunningSummation += CellVolume * cell.Temperature;
    4839             :                     }
    4840             :                 }
    4841             :             }
    4842             :         }
    4843             : 
    4844       48652 :         if (RunningVolume <= 0.0) {
    4845           0 :             ShowFatalError(state, "Domain::GetAverageTempByType calculated zero volume, program aborts");
    4846             :         }
    4847             : 
    4848       48652 :         return RunningSummation / RunningVolume;
    4849             :     }
    4850             : 
    4851    80709288 :     void Domain::EvaluateFarfieldCharacteristics(
    4852             :         EnergyPlusData &state, CartesianCell &cell, Direction const direction, Real64 &neighbortemp, Real64 &resistance, Real64 &adiabaticMultiplier)
    4853             :     {
    4854             : 
    4855             :         // SUBROUTINE INFORMATION:
    4856             :         //       AUTHOR         Edwin Lee
    4857             :         //       DATE WRITTEN   Summer 2011
    4858             :         //       MODIFIED       na
    4859             :         //       RE-ENGINEERED  na
    4860             : 
    4861             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4862    80709288 :         Real64 distance(0.0);
    4863             : 
    4864    80709288 :         switch (direction) {
    4865    25126422 :         case Direction::NegativeX:
    4866             :         case Direction::PositiveX:
    4867    25126422 :             distance = (cell.width() / 2.0);
    4868    25126422 :             break;
    4869    19075798 :         case Direction::NegativeY:
    4870             :         case Direction::PositiveY:
    4871    19075798 :             distance = (cell.height() / 2.0);
    4872    19075798 :             break;
    4873    36507068 :         case Direction::NegativeZ:
    4874             :         case Direction::PositiveZ:
    4875    36507068 :             distance = (cell.depth() / 2.0);
    4876    36507068 :             break;
    4877           0 :         default:
    4878           0 :             assert(false);
    4879             :         }
    4880             : 
    4881    80709288 :         resistance = (distance / 2.0) / (cell.Properties.Conductivity * cell.normalArea(direction));
    4882    80709288 :         neighbortemp = this->GetFarfieldTemp(state, cell);
    4883             : 
    4884    80709288 :         adiabaticMultiplier = cell.NeighborInfo[direction].adiabaticMultiplier;
    4885    80709288 :     }
    4886             : 
    4887    80762262 :     Real64 Domain::GetFarfieldTemp(EnergyPlusData &state, CartesianCell const &cell)
    4888             :     {
    4889             : 
    4890             :         // FUNCTION INFORMATION:
    4891             :         //       AUTHOR         Edwin Lee
    4892             :         //       DATE WRITTEN   Summer 2011
    4893             :         //       MODIFIED       na
    4894             :         //       RE-ENGINEERED  na
    4895             : 
    4896    80762262 :         Real64 CurTime = this->Cur.CurSimTimeSeconds;
    4897    80762262 :         Real64 z = this->Extents.yMax - cell.Centroid.Y;
    4898    80762262 :         return this->groundTempModel->getGroundTempAtTimeInSeconds(state, z, CurTime);
    4899             :     }
    4900             : 
    4901       14498 :     void Domain::PreparePipeCircuitSimulation(Circuit *thisCircuit)
    4902             :     {
    4903             : 
    4904             :         // SUBROUTINE INFORMATION:
    4905             :         //       AUTHOR         Edwin Lee
    4906             :         //       DATE WRITTEN   Summer 2011
    4907             :         //       MODIFIED       na
    4908             :         //       RE-ENGINEERED  na
    4909             : 
    4910             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    4911       14498 :         Real64 constexpr StagnantFluidConvCoeff(200.0);
    4912             : 
    4913             :         // Setup circuit flow conditions -- convection coefficient
    4914       14498 :         int const CellX = thisCircuit->CircuitInletCell.X;
    4915       14498 :         int const CellY = thisCircuit->CircuitInletCell.Y;
    4916       14498 :         int const CellZ = thisCircuit->CircuitInletCell.Z;
    4917             : 
    4918             :         // Look up current fluid properties
    4919       14498 :         Real64 const Density = thisCircuit->CurFluidPropertySet.Density;
    4920       14498 :         Real64 const Viscosity = thisCircuit->CurFluidPropertySet.Viscosity;
    4921       14498 :         Real64 const Conductivity = thisCircuit->CurFluidPropertySet.Conductivity;
    4922       14498 :         Real64 const Prandtl = thisCircuit->CurFluidPropertySet.Prandtl;
    4923             : 
    4924             :         // Flow calculations
    4925       14498 :         Real64 const Area_c = (DataGlobalConstants::Pi / 4.0) * pow_2(thisCircuit->PipeSize.InnerDia);
    4926       14498 :         Real64 const Velocity = thisCircuit->CurCircuitFlowRate / (Density * Area_c);
    4927             : 
    4928             :         // Determine convection coefficient based on flow conditions
    4929             :         Real64 ConvCoefficient;
    4930       14498 :         if (Velocity > 0) {
    4931       14426 :             Real64 Reynolds = Density * thisCircuit->PipeSize.InnerDia * Velocity / Viscosity;
    4932             :             Real64 ExponentTerm;
    4933       14426 :             if (this->Cells(CellX, CellY, CellZ).PipeCellData.Fluid.Temperature > this->Cells(CellX, CellY, CellZ).PipeCellData.Pipe.Temperature) {
    4934        3719 :                 ExponentTerm = 0.3;
    4935             :             } else {
    4936       10707 :                 ExponentTerm = 0.4;
    4937             :             }
    4938       14426 :             Real64 const Nusselt = 0.023 * std::pow(Reynolds, 4.0 / 5.0) * std::pow(Prandtl, ExponentTerm);
    4939       14426 :             ConvCoefficient = Nusselt * Conductivity / thisCircuit->PipeSize.InnerDia;
    4940             :         } else {
    4941          72 :             ConvCoefficient = StagnantFluidConvCoeff;
    4942             :         }
    4943             : 
    4944             :         // Assign the convection coefficient
    4945       14498 :         thisCircuit->CurCircuitConvectionCoefficient = ConvCoefficient;
    4946       14498 :     }
    4947             : 
    4948       50890 :     void Domain::PerformPipeCircuitSimulation(EnergyPlusData &state, Circuit *thisCircuit)
    4949             :     {
    4950             : 
    4951             :         // SUBROUTINE INFORMATION:
    4952             :         //       AUTHOR         Edwin Lee
    4953             :         //       DATE WRITTEN   Summer 2011
    4954             :         //       MODIFIED       na
    4955             :         //       RE-ENGINEERED  na
    4956             : 
    4957             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4958       50890 :         Real64 CircuitCrossTemp = 0.0;
    4959             : 
    4960             :         // retrieve initial conditions from the data structure
    4961             :         // these have been set either by the init routine or by the heat pump routine
    4962       50890 :         Real64 const FlowRate = thisCircuit->CurCircuitFlowRate;
    4963       50890 :         Real64 const EnteringTemp = thisCircuit->CurCircuitInletTemp;
    4964             : 
    4965             :         // initialize
    4966       50890 :         int SegmentCellCtr = 0;
    4967       50890 :         unsigned long const NumSegments = thisCircuit->pipeSegments.size();
    4968       50890 :         unsigned long segmentNum = 0;
    4969             : 
    4970             :         //'loop across all segments (pipes) of the circuit
    4971       50890 :         auto &cells(this->Cells);
    4972      284986 :         for (auto &segment : thisCircuit->pipeSegments) {
    4973             : 
    4974      234096 :             segmentNum++;
    4975      234096 :             int StartingZ = 0;
    4976      234096 :             int EndingZ = 0;
    4977      234096 :             int Increment = 0;
    4978             : 
    4979             :             //'set simulation flow direction
    4980      234096 :             switch (segment->FlowDirection) {
    4981      117048 :             case SegmentFlow::IncreasingZ:
    4982      117048 :                 StartingZ = 0;
    4983      117048 :                 EndingZ = this->z_max_index;
    4984      117048 :                 Increment = 1;
    4985      117048 :                 break;
    4986      117048 :             case SegmentFlow::DecreasingZ:
    4987      117048 :                 StartingZ = this->z_max_index;
    4988      117048 :                 EndingZ = 0;
    4989      117048 :                 Increment = -1;
    4990      117048 :                 break;
    4991           0 :             default:
    4992           0 :                 ShowFatalError(state, "Debug error: invalid flow direction on piping system segment");
    4993             :             }
    4994             : 
    4995             :             //'find the cell we are working on in order to retrieve cell and neighbor information
    4996      234096 :             int PipeX = segment->PipeCellCoordinates.X;
    4997      234096 :             int PipeY = segment->PipeCellCoordinates.Y;
    4998             : 
    4999             :             //'loop across all z-direction indeces
    5000      234096 :             int const Zindex_stop(floop_end(StartingZ, EndingZ, Increment));
    5001     1629692 :             for (int Zindex = StartingZ; Zindex != Zindex_stop; Zindex += Increment) {
    5002             : 
    5003             :                 //'overall cell segment counter
    5004     1395596 :                 ++SegmentCellCtr;
    5005             : 
    5006     1395596 :                 if (SegmentCellCtr == 1) {
    5007             :                     //'we have the very first cell, need to pass in circuiting entering temperature
    5008       50890 :                     this->PerformPipeCellSimulation(thisCircuit, cells(PipeX, PipeY, Zindex), FlowRate, EnteringTemp);
    5009             :                 } else {
    5010             :                     //'we don't have the first cell so just normal simulation
    5011     1344706 :                     if (Zindex == EndingZ) {
    5012             :                         // simulate current cell using upstream as entering conditions
    5013      234096 :                         this->PerformPipeCellSimulation(thisCircuit,
    5014             :                                                         cells(PipeX, PipeY, Zindex),
    5015             :                                                         FlowRate,
    5016      234096 :                                                         cells(PipeX, PipeY, Zindex - Increment).PipeCellData.Fluid.Temperature);
    5017             :                         // store this outlet condition to be passed to the next segment
    5018      234096 :                         CircuitCrossTemp = cells(PipeX, PipeY, Zindex).PipeCellData.Fluid.Temperature;
    5019     1110610 :                     } else if (Zindex == StartingZ) {
    5020             :                         // we are starting another segment, use the previous cross temperature
    5021      183206 :                         this->PerformPipeCellSimulation(thisCircuit, cells(PipeX, PipeY, Zindex), FlowRate, CircuitCrossTemp);
    5022             :                     } else {
    5023             :                         // we are in an interior node, so just get the upstream cell and use the main simulation
    5024      927404 :                         this->PerformPipeCellSimulation(thisCircuit,
    5025             :                                                         cells(PipeX, PipeY, Zindex),
    5026             :                                                         FlowRate,
    5027      927404 :                                                         cells(PipeX, PipeY, Zindex - Increment).PipeCellData.Fluid.Temperature);
    5028             :                     }
    5029             :                 }
    5030             : 
    5031             :                 // Bookkeeping: segment fluid temperature updates
    5032     1395596 :                 if (Zindex == StartingZ) {
    5033      234096 :                     if (segmentNum == 1) {
    5034       50890 :                         segment->InletTemperature = EnteringTemp;
    5035             :                     } else {
    5036      183206 :                         segment->InletTemperature = CircuitCrossTemp;
    5037             :                     }
    5038     1161500 :                 } else if (Zindex == EndingZ) {
    5039      234096 :                     segment->OutletTemperature = cells(PipeX, PipeY, Zindex).PipeCellData.Fluid.Temperature;
    5040      468192 :                     segment->FluidHeatLoss =
    5041      468192 :                         FlowRate * thisCircuit->CurFluidPropertySet.SpecificHeat * (segment->InletTemperature - segment->OutletTemperature);
    5042             :                 }
    5043             : 
    5044             :                 // Bookkeeping: circuit fluid temperature updates
    5045     1395596 :                 if ((segmentNum == 1) && (Zindex == StartingZ)) {
    5046       50890 :                     thisCircuit->InletTemperature = EnteringTemp;
    5047     1344706 :                 } else if ((segmentNum == NumSegments) && (Zindex == EndingZ)) {
    5048       50890 :                     thisCircuit->OutletTemperature = cells(PipeX, PipeY, Zindex).PipeCellData.Fluid.Temperature;
    5049       50890 :                     thisCircuit->FluidHeatLoss =
    5050       50890 :                         FlowRate * thisCircuit->CurFluidPropertySet.SpecificHeat * (thisCircuit->InletTemperature - thisCircuit->OutletTemperature);
    5051             :                 }
    5052             :             }
    5053             :         }
    5054       50890 :     }
    5055             : 
    5056     1395596 :     void Domain::PerformPipeCellSimulation(Circuit *thisCircuit, CartesianCell &ThisCell, Real64 const FlowRate, Real64 const EnteringTemp)
    5057             :     {
    5058             : 
    5059             :         // SUBROUTINE INFORMATION:
    5060             :         //       AUTHOR         Edwin Lee
    5061             :         //       DATE WRITTEN   Summer 2011
    5062             :         //       MODIFIED       na
    5063             :         //       RE-ENGINEERED  na
    5064             : 
    5065     7434910 :         for (int Iter = 1; Iter <= thisCircuit->MaxIterationsPerTS; ++Iter) {
    5066             : 
    5067             :             //'shift all the pipe related temperatures for the next internal pipe iteration
    5068     7434584 :             ShiftPipeTemperaturesForNewIteration(ThisCell);
    5069             : 
    5070             :             //'simulate the funny interface soil cell between the radial and cartesian systems
    5071     7434584 :             this->SimulateRadialToCartesianInterface(ThisCell);
    5072             : 
    5073             :             //'simulate the outermost radial slice
    5074     7434584 :             SimulateOuterMostRadialSoilSlice(thisCircuit, ThisCell);
    5075             : 
    5076             :             //'we only need to simulate these if they actually exist!
    5077     7434584 :             if (!ThisCell.PipeCellData.Soil.empty()) {
    5078             : 
    5079             :                 //'simulate all interior radial slices
    5080     7434584 :                 SimulateAllInteriorRadialSoilSlices(ThisCell);
    5081             : 
    5082             :                 //'simulate the innermost radial soil slice
    5083     7434584 :                 SimulateInnerMostRadialSoilSlice(thisCircuit, ThisCell);
    5084             :             }
    5085             : 
    5086     7434584 :             if (thisCircuit->HasInsulation) {
    5087           0 :                 SimulateRadialInsulationCell(ThisCell);
    5088             :             }
    5089             : 
    5090             :             //'simulate the pipe cell
    5091     7434584 :             SimulateRadialPipeCell(thisCircuit, ThisCell);
    5092             : 
    5093             :             //'simulate the water cell
    5094     7434584 :             SimulateFluidCell(thisCircuit, ThisCell, FlowRate, EnteringTemp);
    5095             : 
    5096             :             //'check convergence
    5097     7434584 :             if (IsConverged_PipeCurrentToPrevIteration(thisCircuit, ThisCell)) break; // potential diff source
    5098             :         }
    5099     1395596 :     }
    5100             : 
    5101     7434584 :     void Domain::SimulateRadialToCartesianInterface(CartesianCell &cell)
    5102             :     {
    5103             : 
    5104             :         // SUBROUTINE INFORMATION:
    5105             :         //       AUTHOR         Edwin Lee
    5106             :         //       DATE WRITTEN   Summer 2011
    5107             :         //       MODIFIED       na
    5108             :         //       RE-ENGINEERED  na
    5109             : 
    5110             :         // SUBROUTINE PARAMETER DEFINITIONS:
    5111     7434584 :         static std::vector<Direction> const Directions = {Direction::NegativeX, Direction::NegativeY, Direction::PositiveX, Direction::PositiveY};
    5112             : 
    5113             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5114     7434584 :         Real64 Numerator = 0.0;
    5115     7434584 :         Real64 Denominator = 0.0;
    5116             : 
    5117             :         //'add effects from this cell history
    5118     7434584 :         Numerator += cell.Temperature_PrevTimeStep;
    5119     7434584 :         ++Denominator;
    5120             : 
    5121             :         //'add effects from outermost radial cell
    5122     7434584 :         auto &outerRadialCell = cell.PipeCellData.Soil.back();
    5123     7434584 :         Real64 OutermostRadialCellOuterRadius = outerRadialCell.OuterRadius;
    5124     7434584 :         Real64 OutermostRadialCellRadialCentroid = outerRadialCell.RadialCentroid;
    5125     7434584 :         Real64 OutermostRadialCellTemperature = outerRadialCell.Temperature;
    5126    14869168 :         Real64 Resistance = std::log(OutermostRadialCellOuterRadius / OutermostRadialCellRadialCentroid) /
    5127    14869168 :                             (2.0 * DataGlobalConstants::Pi * cell.depth() * cell.Properties.Conductivity);
    5128     7434584 :         Numerator += (cell.Beta / Resistance) * OutermostRadialCellTemperature;
    5129     7434584 :         Denominator += (cell.Beta / Resistance);
    5130             : 
    5131             :         //'add effects from neighboring Cartesian cells
    5132    37172920 :         for (auto &curDirection : Directions) {
    5133    29738336 :             Real64 AdiabaticMultiplier = 1.0;
    5134    29738336 :             Real64 NeighborTemp = 0.0;
    5135    29738336 :             this->EvaluateNeighborCharacteristics(cell, curDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    5136    29738336 :             Numerator += AdiabaticMultiplier * (cell.Beta / Resistance) * NeighborTemp;
    5137    29738336 :             Denominator += AdiabaticMultiplier * (cell.Beta / Resistance);
    5138             :         }
    5139             : 
    5140             :         //'calculate the new temperature
    5141     7434584 :         cell.Temperature = Numerator / Denominator;
    5142     7434584 :     }
    5143             : 
    5144     7434584 :     void SimulateOuterMostRadialSoilSlice(Circuit *thisCircuit, CartesianCell &cell)
    5145             :     {
    5146             : 
    5147             :         // SUBROUTINE INFORMATION:
    5148             :         //       AUTHOR         Edwin Lee
    5149             :         //       DATE WRITTEN   Summer 2011
    5150             :         //       MODIFIED       na
    5151             :         //       RE-ENGINEERED  na
    5152             : 
    5153             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5154             :         Real64 NextOuterRadialCellOuterRadius;
    5155             :         Real64 NextOuterRadialCellRadialCentroid;
    5156             :         Real64 NextOuterRadialCellConductivity;
    5157             :         Real64 NextOuterRadialCellTemperature;
    5158             : 
    5159     7434584 :         Real64 Numerator = 0.0;
    5160     7434584 :         Real64 Denominator = 0.0;
    5161             : 
    5162             :         //'convenience variables
    5163     7434584 :         int const numSoilCells = static_cast<int>(cell.PipeCellData.Soil.size());
    5164     7434584 :         auto &outerMostSoilCell = cell.PipeCellData.Soil[numSoilCells - 1];
    5165     7434584 :         Real64 ThisRadialCellOuterRadius = outerMostSoilCell.OuterRadius;
    5166     7434584 :         Real64 ThisRadialCellRadialCentroid = outerMostSoilCell.RadialCentroid;
    5167     7434584 :         Real64 ThisRadialCellConductivity = outerMostSoilCell.Properties.Conductivity;
    5168     7434584 :         Real64 ThisRadialCellInnerRadius = outerMostSoilCell.InnerRadius;
    5169     7434584 :         Real64 ThisRadialCellTemperature_PrevTimeStep = outerMostSoilCell.Temperature_PrevTimeStep;
    5170     7434584 :         if (numSoilCells == 1) {
    5171           0 :             if (thisCircuit->HasInsulation) {
    5172           0 :                 NextOuterRadialCellOuterRadius = cell.PipeCellData.Insulation.OuterRadius;
    5173           0 :                 NextOuterRadialCellRadialCentroid = cell.PipeCellData.Insulation.RadialCentroid;
    5174           0 :                 NextOuterRadialCellConductivity = cell.PipeCellData.Insulation.Properties.Conductivity;
    5175           0 :                 NextOuterRadialCellTemperature = cell.PipeCellData.Insulation.Temperature;
    5176             :             } else {
    5177           0 :                 NextOuterRadialCellOuterRadius = cell.PipeCellData.Pipe.OuterRadius;
    5178           0 :                 NextOuterRadialCellRadialCentroid = cell.PipeCellData.Pipe.RadialCentroid;
    5179           0 :                 NextOuterRadialCellConductivity = cell.PipeCellData.Pipe.Properties.Conductivity;
    5180           0 :                 NextOuterRadialCellTemperature = cell.PipeCellData.Pipe.Temperature;
    5181             :             }
    5182             :         } else {
    5183     7434584 :             auto &nextOuterMostSoilCell = cell.PipeCellData.Soil[numSoilCells - 2];
    5184     7434584 :             NextOuterRadialCellOuterRadius = nextOuterMostSoilCell.OuterRadius;
    5185     7434584 :             NextOuterRadialCellRadialCentroid = nextOuterMostSoilCell.RadialCentroid;
    5186     7434584 :             NextOuterRadialCellConductivity = nextOuterMostSoilCell.Properties.Conductivity;
    5187     7434584 :             NextOuterRadialCellTemperature = nextOuterMostSoilCell.Temperature;
    5188             :         }
    5189             : 
    5190             :         //'any broadly defined variables
    5191     7434584 :         Real64 Beta = outerMostSoilCell.Beta;
    5192             : 
    5193             :         //'add effects from this cell history
    5194     7434584 :         Numerator += ThisRadialCellTemperature_PrevTimeStep;
    5195     7434584 :         ++Denominator;
    5196             : 
    5197             :         //'add effects from interface cell
    5198     7434584 :         Real64 Resistance = std::log(ThisRadialCellOuterRadius / ThisRadialCellRadialCentroid) /
    5199     7434584 :                             (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity);
    5200     7434584 :         Numerator += (Beta / Resistance) * cell.Temperature;
    5201     7434584 :         Denominator += (Beta / Resistance);
    5202             : 
    5203             :         //'add effects from inner radial cell
    5204    22303752 :         Resistance = (std::log(ThisRadialCellRadialCentroid / ThisRadialCellInnerRadius) /
    5205     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity)) +
    5206    14869168 :                      (std::log(NextOuterRadialCellOuterRadius / NextOuterRadialCellRadialCentroid) /
    5207     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * NextOuterRadialCellConductivity));
    5208     7434584 :         Numerator += (Beta / Resistance) * NextOuterRadialCellTemperature;
    5209     7434584 :         Denominator += (Beta / Resistance);
    5210             : 
    5211             :         //'calculate the new temperature
    5212     7434584 :         outerMostSoilCell.Temperature = Numerator / Denominator;
    5213     7434584 :     }
    5214             : 
    5215     7434584 :     void SimulateAllInteriorRadialSoilSlices(CartesianCell &cell)
    5216             :     {
    5217             : 
    5218             :         // SUBROUTINE INFORMATION:
    5219             :         //       AUTHOR         Edwin Lee
    5220             :         //       DATE WRITTEN   Summer 2011
    5221             :         //       MODIFIED       na
    5222             :         //       RE-ENGINEERED  na
    5223             : 
    5224     7809016 :         for (int rCtr = (int)cell.PipeCellData.Soil.size() - 2; rCtr >= 1; --rCtr) {
    5225             : 
    5226      374432 :             Real64 Numerator = 0.0;
    5227      374432 :             Real64 Denominator = 0.0;
    5228             : 
    5229             :             //'convenience variables
    5230      374432 :             auto &thisSoilCell = cell.PipeCellData.Soil[rCtr];
    5231      374432 :             Real64 ThisRadialCellOuterRadius = thisSoilCell.OuterRadius;
    5232      374432 :             Real64 ThisRadialCellRadialCentroid = thisSoilCell.RadialCentroid;
    5233      374432 :             Real64 ThisRadialCellConductivity = thisSoilCell.Properties.Conductivity;
    5234      374432 :             Real64 ThisRadialCellInnerRadius = thisSoilCell.InnerRadius;
    5235      374432 :             Real64 ThisRadialCellTemperature_PrevTimeStep = thisSoilCell.Temperature_PrevTimeStep;
    5236             : 
    5237      374432 :             auto const &minusSoilCell = cell.PipeCellData.Soil[rCtr - 1];
    5238      374432 :             Real64 InnerRadialCellOuterRadius = minusSoilCell.OuterRadius;
    5239      374432 :             Real64 InnerRadialCellRadialCentroid = minusSoilCell.RadialCentroid;
    5240      374432 :             Real64 InnerRadialCellConductivity = minusSoilCell.Properties.Conductivity;
    5241      374432 :             Real64 InnerRadialCellTemperature = minusSoilCell.Temperature;
    5242             : 
    5243      374432 :             auto const &plusSoilCell = cell.PipeCellData.Soil[rCtr + 1];
    5244      374432 :             Real64 OuterRadialCellRadialCentroid = plusSoilCell.RadialCentroid;
    5245      374432 :             Real64 OuterRadialCellConductivity = plusSoilCell.Properties.Conductivity;
    5246      374432 :             Real64 OuterRadialCellInnerRadius = plusSoilCell.InnerRadius;
    5247      374432 :             Real64 OuterRadialCellTemperature = plusSoilCell.Temperature;
    5248             : 
    5249             :             //'add effects from this cell history
    5250      374432 :             Numerator += ThisRadialCellTemperature_PrevTimeStep;
    5251      374432 :             ++Denominator;
    5252             : 
    5253             :             //'add effects from outer cell
    5254      748864 :             Real64 Resistance = (std::log(OuterRadialCellRadialCentroid / OuterRadialCellInnerRadius) /
    5255      374432 :                                  (2 * DataGlobalConstants::Pi * cell.depth() * OuterRadialCellConductivity)) +
    5256      748864 :                                 (std::log(ThisRadialCellOuterRadius / ThisRadialCellRadialCentroid) /
    5257      748864 :                                  (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity));
    5258      374432 :             Numerator += (thisSoilCell.Beta / Resistance) * OuterRadialCellTemperature;
    5259      374432 :             Denominator += (thisSoilCell.Beta / Resistance);
    5260             : 
    5261             :             //'add effects from inner cell
    5262     1123296 :             Resistance = (std::log(ThisRadialCellRadialCentroid / ThisRadialCellInnerRadius) /
    5263      374432 :                           (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity)) +
    5264      748864 :                          (std::log(InnerRadialCellOuterRadius / InnerRadialCellRadialCentroid) /
    5265      374432 :                           (2 * DataGlobalConstants::Pi * cell.depth() * InnerRadialCellConductivity));
    5266      374432 :             Numerator += (thisSoilCell.Beta / Resistance) * InnerRadialCellTemperature;
    5267      374432 :             Denominator += (thisSoilCell.Beta / Resistance);
    5268             : 
    5269             :             //'calculate the new temperature
    5270      374432 :             thisSoilCell.Temperature = Numerator / Denominator;
    5271             :         }
    5272     7434584 :     }
    5273             : 
    5274     7434584 :     void SimulateInnerMostRadialSoilSlice(Circuit *thisCircuit, CartesianCell &cell)
    5275             :     {
    5276             : 
    5277             :         // SUBROUTINE INFORMATION:
    5278             :         //       AUTHOR         Edwin Lee
    5279             :         //       DATE WRITTEN   Summer 2011
    5280             :         //       MODIFIED       na
    5281             :         //       RE-ENGINEERED  na
    5282             : 
    5283             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5284             :         Real64 Resistance;
    5285             :         Real64 InnerNeighborRadialCellOuterRadius;
    5286             :         Real64 InnerNeighborRadialCellRadialCentroid;
    5287             :         Real64 InnerNeighborRadialCellConductivity;
    5288             :         Real64 InnerNeighborRadialCellTemperature;
    5289             : 
    5290     7434584 :         Real64 Numerator = 0.0;
    5291     7434584 :         Real64 Denominator = 0.0;
    5292             : 
    5293             :         //'convenience variables
    5294     7434584 :         if (thisCircuit->HasInsulation) {
    5295           0 :             InnerNeighborRadialCellOuterRadius = cell.PipeCellData.Insulation.OuterRadius;
    5296           0 :             InnerNeighborRadialCellRadialCentroid = cell.PipeCellData.Insulation.RadialCentroid;
    5297           0 :             InnerNeighborRadialCellConductivity = cell.PipeCellData.Insulation.Properties.Conductivity;
    5298           0 :             InnerNeighborRadialCellTemperature = cell.PipeCellData.Insulation.Temperature;
    5299             :         } else {
    5300     7434584 :             InnerNeighborRadialCellOuterRadius = cell.PipeCellData.Pipe.OuterRadius;
    5301     7434584 :             InnerNeighborRadialCellRadialCentroid = cell.PipeCellData.Pipe.RadialCentroid;
    5302     7434584 :             InnerNeighborRadialCellConductivity = cell.PipeCellData.Pipe.Properties.Conductivity;
    5303     7434584 :             InnerNeighborRadialCellTemperature = cell.PipeCellData.Pipe.Temperature;
    5304             :         }
    5305             : 
    5306     7434584 :         auto &soilZero = cell.PipeCellData.Soil[0];
    5307     7434584 :         Real64 ThisRadialCellOuterRadius = soilZero.OuterRadius;
    5308     7434584 :         Real64 ThisRadialCellRadialCentroid = soilZero.RadialCentroid;
    5309     7434584 :         Real64 ThisRadialCellConductivity = soilZero.Properties.Conductivity;
    5310     7434584 :         Real64 ThisRadialCellInnerRadius = soilZero.InnerRadius;
    5311     7434584 :         Real64 ThisRadialCellTemperature_PrevTimeStep = soilZero.Temperature_PrevTimeStep;
    5312             : 
    5313     7434584 :         auto const &soilOne = cell.PipeCellData.Soil[1];
    5314     7434584 :         Real64 OuterNeighborRadialCellRadialCentroid = soilOne.RadialCentroid;
    5315     7434584 :         Real64 OuterNeighborRadialCellConductivity = soilOne.Properties.Conductivity;
    5316     7434584 :         Real64 OuterNeighborRadialCellInnerRadius = soilOne.InnerRadius;
    5317     7434584 :         Real64 OuterNeighborRadialCellTemperature = soilOne.Temperature;
    5318             : 
    5319             :         //'add effects from this cell history
    5320     7434584 :         Numerator += ThisRadialCellTemperature_PrevTimeStep;
    5321     7434584 :         ++Denominator;
    5322             : 
    5323             :         //'add effects from outer radial cell
    5324    22303752 :         Resistance = (std::log(OuterNeighborRadialCellRadialCentroid / OuterNeighborRadialCellInnerRadius) /
    5325     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * OuterNeighborRadialCellConductivity)) +
    5326    14869168 :                      (std::log(ThisRadialCellOuterRadius / ThisRadialCellRadialCentroid) /
    5327     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity));
    5328     7434584 :         Numerator += (soilZero.Beta / Resistance) * OuterNeighborRadialCellTemperature;
    5329     7434584 :         Denominator += (soilZero.Beta / Resistance);
    5330             : 
    5331             :         //'add effects from pipe cell
    5332    22303752 :         Resistance = (std::log(ThisRadialCellRadialCentroid / ThisRadialCellInnerRadius) /
    5333     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * ThisRadialCellConductivity)) +
    5334    14869168 :                      (std::log(InnerNeighborRadialCellOuterRadius / InnerNeighborRadialCellRadialCentroid) /
    5335     7434584 :                       (2 * DataGlobalConstants::Pi * cell.depth() * InnerNeighborRadialCellConductivity));
    5336     7434584 :         Numerator += (soilZero.Beta / Resistance) * InnerNeighborRadialCellTemperature;
    5337     7434584 :         Denominator += (soilZero.Beta / Resistance);
    5338             : 
    5339             :         //'calculate the new temperature
    5340     7434584 :         soilZero.Temperature = Numerator / Denominator;
    5341     7434584 :     }
    5342             : 
    5343           0 :     void SimulateRadialInsulationCell(CartesianCell &cell)
    5344             :     {
    5345             : 
    5346             :         // SUBROUTINE INFORMATION:
    5347             :         //       AUTHOR         Edwin Lee
    5348             :         //       DATE WRITTEN   Summer 2011
    5349             :         //       MODIFIED       na
    5350             :         //       RE-ENGINEERED  na
    5351             : 
    5352             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5353           0 :         Real64 Numerator = 0.0;
    5354           0 :         Real64 Denominator = 0.0;
    5355             : 
    5356             :         //'convenience variables
    5357           0 :         auto const &PipeCell = cell.PipeCellData.Pipe;
    5358           0 :         auto const &ThisInsulationCell = cell.PipeCellData.Insulation;
    5359           0 :         auto const &NextInnerRadialCell = cell.PipeCellData.Soil[0];
    5360             : 
    5361             :         //'add effects from this cell history
    5362           0 :         Numerator += ThisInsulationCell.Temperature_PrevTimeStep;
    5363           0 :         ++Denominator;
    5364             : 
    5365             :         //'add effects from outer radial cell
    5366           0 :         Real64 Resistance = (std::log(NextInnerRadialCell.RadialCentroid / NextInnerRadialCell.InnerRadius) /
    5367           0 :                              (2 * DataGlobalConstants::Pi * cell.depth() * NextInnerRadialCell.Properties.Conductivity)) +
    5368           0 :                             (std::log(ThisInsulationCell.OuterRadius / ThisInsulationCell.RadialCentroid) /
    5369           0 :                              (2 * DataGlobalConstants::Pi * cell.depth() * ThisInsulationCell.Properties.Conductivity));
    5370           0 :         Numerator += (ThisInsulationCell.Beta / Resistance) * NextInnerRadialCell.Temperature;
    5371           0 :         Denominator += (ThisInsulationCell.Beta / Resistance);
    5372             : 
    5373             :         //'add effects from pipe cell
    5374           0 :         Resistance = (std::log(ThisInsulationCell.RadialCentroid / ThisInsulationCell.InnerRadius) /
    5375           0 :                       (2 * DataGlobalConstants::Pi * cell.depth() * ThisInsulationCell.Properties.Conductivity)) +
    5376           0 :                      (std::log(PipeCell.OuterRadius / PipeCell.RadialCentroid) /
    5377           0 :                       (2 * DataGlobalConstants::Pi * cell.depth() * PipeCell.Properties.Conductivity));
    5378           0 :         Numerator += (ThisInsulationCell.Beta / Resistance) * PipeCell.Temperature;
    5379           0 :         Denominator += (ThisInsulationCell.Beta / Resistance);
    5380             : 
    5381             :         //'calculate the new temperature
    5382           0 :         cell.PipeCellData.Insulation.Temperature = Numerator / Denominator;
    5383           0 :     }
    5384             : 
    5385     7434584 :     void SimulateRadialPipeCell(Circuit *thisCircuit, CartesianCell &cell)
    5386             :     {
    5387             : 
    5388             :         // SUBROUTINE INFORMATION:
    5389             :         //       AUTHOR         Edwin Lee
    5390             :         //       DATE WRITTEN   Summer 2011
    5391             :         //       MODIFIED       na
    5392             :         //       RE-ENGINEERED  na
    5393             : 
    5394             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5395             :         Real64 OuterNeighborRadialCellRadialCentroid;
    5396             :         Real64 OuterNeighborRadialCellConductivity;
    5397             :         Real64 OuterNeighborRadialCellInnerRadius;
    5398             :         Real64 OuterNeighborRadialCellTemperature;
    5399             : 
    5400     7434584 :         Real64 Numerator = 0.0;
    5401     7434584 :         Real64 Denominator = 0.0;
    5402             : 
    5403             :         //'convenience variables
    5404     7434584 :         if (thisCircuit->HasInsulation) {
    5405           0 :             OuterNeighborRadialCellRadialCentroid = cell.PipeCellData.Insulation.RadialCentroid;
    5406           0 :             OuterNeighborRadialCellConductivity = cell.PipeCellData.Insulation.Properties.Conductivity;
    5407           0 :             OuterNeighborRadialCellInnerRadius = cell.PipeCellData.Insulation.InnerRadius;
    5408           0 :             OuterNeighborRadialCellTemperature = cell.PipeCellData.Insulation.Temperature;
    5409             :         } else {
    5410     7434584 :             auto const &soilZero = cell.PipeCellData.Soil[0];
    5411     7434584 :             OuterNeighborRadialCellRadialCentroid = soilZero.RadialCentroid;
    5412     7434584 :             OuterNeighborRadialCellConductivity = soilZero.Properties.Conductivity;
    5413     7434584 :             OuterNeighborRadialCellInnerRadius = soilZero.InnerRadius;
    5414     7434584 :             OuterNeighborRadialCellTemperature = soilZero.Temperature;
    5415             :         }
    5416             : 
    5417     7434584 :         Real64 const ThisPipeCellOuterRadius = cell.PipeCellData.Pipe.OuterRadius;
    5418     7434584 :         Real64 const ThisPipeCellRadialCentroid = cell.PipeCellData.Pipe.RadialCentroid;
    5419     7434584 :         Real64 const ThisPipeCellConductivity = cell.PipeCellData.Pipe.Properties.Conductivity;
    5420     7434584 :         Real64 const ThisPipeCellInnerRadius = cell.PipeCellData.Pipe.InnerRadius;
    5421     7434584 :         Real64 const ThisPipeCellTemperature_PrevTimeStep = cell.PipeCellData.Pipe.Temperature_PrevTimeStep;
    5422             : 
    5423     7434584 :         Real64 const FluidCellTemperature = cell.PipeCellData.Fluid.Temperature;
    5424             : 
    5425             :         //'add effects from this cell history
    5426     7434584 :         Numerator += ThisPipeCellTemperature_PrevTimeStep;
    5427     7434584 :         ++Denominator;
    5428             : 
    5429             :         //'add effects from outer radial cell
    5430    14869168 :         Real64 Resistance = (std::log(OuterNeighborRadialCellRadialCentroid / OuterNeighborRadialCellInnerRadius) /
    5431     7434584 :                              (2 * DataGlobalConstants::Pi * cell.depth() * OuterNeighborRadialCellConductivity)) +
    5432    14869168 :                             (std::log(ThisPipeCellOuterRadius / ThisPipeCellRadialCentroid) /
    5433    14869168 :                              (2 * DataGlobalConstants::Pi * cell.depth() * ThisPipeCellConductivity));
    5434     7434584 :         Numerator += (cell.PipeCellData.Pipe.Beta / Resistance) * OuterNeighborRadialCellTemperature;
    5435     7434584 :         Denominator += (cell.PipeCellData.Pipe.Beta / Resistance);
    5436             : 
    5437             :         //'add effects from water cell
    5438             :         Real64 PipeConductionResistance =
    5439     7434584 :             std::log(ThisPipeCellRadialCentroid / ThisPipeCellInnerRadius) / (2 * DataGlobalConstants::Pi * cell.depth() * ThisPipeCellConductivity);
    5440             :         Real64 ConvectiveResistance =
    5441     7434584 :             1.0 / (thisCircuit->CurCircuitConvectionCoefficient * 2 * DataGlobalConstants::Pi * ThisPipeCellInnerRadius * cell.depth());
    5442     7434584 :         Resistance = PipeConductionResistance + ConvectiveResistance;
    5443     7434584 :         Numerator += (cell.PipeCellData.Pipe.Beta / Resistance) * FluidCellTemperature;
    5444     7434584 :         Denominator += (cell.PipeCellData.Pipe.Beta / Resistance);
    5445             : 
    5446             :         //'calculate new temperature
    5447     7434584 :         cell.PipeCellData.Pipe.Temperature = Numerator / Denominator;
    5448     7434584 :     }
    5449             : 
    5450     7434584 :     void SimulateFluidCell(Circuit *thisCircuit, CartesianCell &cell, Real64 const FlowRate, Real64 const EnteringFluidTemp)
    5451             :     {
    5452             : 
    5453             :         // SUBROUTINE INFORMATION:
    5454             :         //       AUTHOR         Edwin Lee
    5455             :         //       DATE WRITTEN   Summer 2011
    5456             :         //       MODIFIED       na
    5457             :         //       RE-ENGINEERED  na
    5458             : 
    5459             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5460     7434584 :         Real64 Numerator = 0.0;
    5461     7434584 :         Real64 Denominator = 0.0;
    5462             : 
    5463             :         //'convenience variables
    5464     7434584 :         Real64 const FluidCellTemperature_PrevTimeStep = cell.PipeCellData.Fluid.Temperature_PrevTimeStep;
    5465     7434584 :         Real64 const FluidCellSpecificHeat = cell.PipeCellData.Fluid.Properties.SpecificHeat;
    5466             : 
    5467     7434584 :         Real64 const PipeCellRadialCentroid = cell.PipeCellData.Pipe.RadialCentroid;
    5468     7434584 :         Real64 const PipeCellConductivity = cell.PipeCellData.Pipe.Properties.Conductivity;
    5469     7434584 :         Real64 const PipeCellInnerRadius = cell.PipeCellData.Pipe.InnerRadius;
    5470     7434584 :         Real64 const PipeCellTemperature = cell.PipeCellData.Pipe.Temperature;
    5471             : 
    5472             :         //'add effects from this cell history
    5473     7434584 :         Numerator += FluidCellTemperature_PrevTimeStep;
    5474     7434584 :         ++Denominator;
    5475             : 
    5476             :         //'add effects from outer pipe cell
    5477             :         Real64 PipeConductionResistance =
    5478     7434584 :             std::log(PipeCellRadialCentroid / PipeCellInnerRadius) / (2 * DataGlobalConstants::Pi * cell.depth() * PipeCellConductivity);
    5479             :         Real64 ConvectiveResistance =
    5480     7434584 :             1.0 / (thisCircuit->CurCircuitConvectionCoefficient * 2 * DataGlobalConstants::Pi * PipeCellInnerRadius * cell.depth());
    5481     7434584 :         Real64 TotalPipeResistance = PipeConductionResistance + ConvectiveResistance;
    5482     7434584 :         Numerator += (cell.PipeCellData.Fluid.Beta / TotalPipeResistance) * PipeCellTemperature;
    5483     7434584 :         Denominator += (cell.PipeCellData.Fluid.Beta / TotalPipeResistance);
    5484             : 
    5485             :         //'add effects from upstream flow
    5486     7434584 :         if (FlowRate > 0.0) {
    5487     7389980 :             Real64 UpstreamResistance = 1 / (FlowRate * FluidCellSpecificHeat);
    5488     7389980 :             Numerator += (cell.PipeCellData.Fluid.Beta / UpstreamResistance) * EnteringFluidTemp;
    5489     7389980 :             Denominator += (cell.PipeCellData.Fluid.Beta / UpstreamResistance);
    5490             :         }
    5491             : 
    5492             :         //'calculate new temperature
    5493     7434584 :         cell.PipeCellData.Fluid.Temperature = Numerator / Denominator;
    5494     7434584 :     }
    5495             : 
    5496          37 :     void Domain::DoOneTimeInitializations(EnergyPlusData &state, Circuit *thisCircuit)
    5497             :     {
    5498             : 
    5499             :         // SUBROUTINE INFORMATION:
    5500             :         //       AUTHOR         Edwin Lee
    5501             :         //       DATE WRITTEN   Summer 2011
    5502             :         //       MODIFIED       na
    5503             :         //       RE-ENGINEERED  na
    5504             : 
    5505             :         //'initialize cell properties
    5506         472 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    5507        5978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    5508       58517 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    5509       52974 :                     auto &cell(this->Cells(X, Y, Z));
    5510       52974 :                     switch (cell.cellType) {
    5511         400 :                     case CellType::Pipe:
    5512         400 :                         cell.Properties = this->GroundProperties;
    5513        1280 :                         for (auto &soilCell : cell.PipeCellData.Soil) {
    5514         880 :                             soilCell.Properties = this->GroundProperties;
    5515         400 :                         }
    5516         400 :                         if (thisCircuit) {
    5517         400 :                             cell.PipeCellData.Pipe.Properties = thisCircuit->PipeProperties;
    5518         400 :                             if (thisCircuit->HasInsulation) {
    5519           0 :                                 cell.PipeCellData.Insulation.Properties = thisCircuit->InsulationProperties;
    5520             :                             }
    5521             :                         }
    5522         400 :                         break;
    5523       45010 :                     case CellType::GeneralField:
    5524             :                     case CellType::GroundSurface:
    5525             :                     case CellType::FarfieldBoundary:
    5526       45010 :                         cell.Properties = this->GroundProperties;
    5527       45010 :                         break;
    5528         996 :                     case CellType::BasementWall:
    5529             :                     case CellType::BasementFloor:
    5530             :                     case CellType::BasementCorner:
    5531         996 :                         if (this->HasZoneCoupledBasement) { // Basement interface layer
    5532         486 :                             cell.Properties = this->BasementInterfaceProperties;
    5533             :                         } else { // Basement cells are partially ground, give them some props
    5534         510 :                             cell.Properties = this->GroundProperties;
    5535             :                         }
    5536         996 :                         break;
    5537        1728 :                     case CellType::Slab:
    5538        1728 :                         cell.Properties = this->SlabProperties;
    5539        1728 :                         break;
    5540         400 :                     case CellType::HorizInsulation:
    5541         400 :                         cell.Properties = this->HorizInsProperties;
    5542         400 :                         break;
    5543        1782 :                     case CellType::VertInsulation:
    5544        1782 :                         cell.Properties = this->VertInsProperties;
    5545        1782 :                         break;
    5546         360 :                     case CellType::ZoneGroundInterface:
    5547         360 :                         if (this->SlabInGradeFlag) {
    5548         288 :                             cell.Properties = this->SlabProperties;
    5549             :                         } else {
    5550          72 :                             cell.Properties = this->GroundProperties;
    5551             :                         }
    5552         360 :                         break;
    5553        2298 :                     case CellType::BasementCutaway:
    5554        2298 :                         break;
    5555           0 :                     default:
    5556           0 :                         assert(false);
    5557             :                     }
    5558             :                 }
    5559             :             }
    5560             :         }
    5561             : 
    5562             :         //'calculate one-time resistance terms for cartesian cells
    5563         472 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    5564        5978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    5565       58517 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    5566       52974 :                     auto &cell(this->Cells(X, Y, Z));
    5567       52974 :                     int NumFieldCells = 0, NumBoundaryCells = 0;
    5568       52974 :                     this->EvaluateCellNeighborDirections(cell, NumFieldCells, NumBoundaryCells);
    5569      344416 :                     for (int DirectionCtr = 0; DirectionCtr <= NumFieldCells; ++DirectionCtr) {
    5570      291442 :                         Direction CurDirection = this->NeighborFieldCells[DirectionCtr];
    5571      291442 :                         Real64 AdiabaticMultiplier = 1.0, NeighborTemp = 0.0, Resistance = 0.0;
    5572      291442 :                         this->EvaluateNeighborCharacteristics(cell, CurDirection, NeighborTemp, Resistance, AdiabaticMultiplier);
    5573      291442 :                         int NX = 0, NY = 0, NZ = 0;
    5574      291442 :                         cell.EvaluateNeighborCoordinates(CurDirection, NX, NY, NZ);
    5575             :                     }
    5576             :                 }
    5577             :             }
    5578             :         }
    5579             : 
    5580             :         //'initialize freezing calculation variables
    5581          37 :         this->InitializeSoilMoistureCalcs();
    5582             : 
    5583             :         //'we can also initialize the domain based on the farfield temperature here
    5584         472 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    5585        5978 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    5586       58517 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    5587       52974 :                     auto &cell(this->Cells(X, Y, Z));
    5588             : 
    5589             :                     // On OneTimeInit, the cur sim time should be zero, so this will be OK
    5590       52974 :                     Real64 ThisCellTemp = this->GetFarfieldTemp(state, cell);
    5591       52974 :                     cell.Temperature = ThisCellTemp;
    5592       52974 :                     cell.Temperature_PrevIteration = ThisCellTemp;
    5593       52974 :                     cell.Temperature_PrevTimeStep = ThisCellTemp;
    5594             : 
    5595       52974 :                     if (cell.cellType == CellType::Pipe) {
    5596             : 
    5597        1280 :                         for (auto &soilCell : cell.PipeCellData.Soil) {
    5598         880 :                             soilCell.Temperature = ThisCellTemp;
    5599         880 :                             soilCell.Temperature_PrevIteration = ThisCellTemp;
    5600         880 :                             soilCell.Temperature_PrevTimeStep = ThisCellTemp;
    5601             :                         }
    5602         400 :                         cell.PipeCellData.Pipe.Temperature = ThisCellTemp;
    5603         400 :                         cell.PipeCellData.Pipe.Temperature_PrevIteration = ThisCellTemp;
    5604         400 :                         cell.PipeCellData.Pipe.Temperature_PrevTimeStep = ThisCellTemp;
    5605         400 :                         if (thisCircuit) {
    5606         400 :                             if (thisCircuit->HasInsulation) {
    5607           0 :                                 cell.PipeCellData.Insulation.Temperature = ThisCellTemp;
    5608           0 :                                 cell.PipeCellData.Insulation.Temperature_PrevIteration = ThisCellTemp;
    5609           0 :                                 cell.PipeCellData.Insulation.Temperature_PrevTimeStep = ThisCellTemp;
    5610             :                             }
    5611             :                         }
    5612         400 :                         cell.PipeCellData.Fluid.Temperature = ThisCellTemp;
    5613         400 :                         cell.PipeCellData.Fluid.Temperature_PrevIteration = ThisCellTemp;
    5614         400 :                         cell.PipeCellData.Fluid.Temperature_PrevTimeStep = ThisCellTemp;
    5615             :                     }
    5616             :                 }
    5617             :             }
    5618             :         }
    5619          37 :     }
    5620             : 
    5621       27842 :     void Domain::DoStartOfTimeStepInitializations(EnergyPlusData &state)
    5622             :     {
    5623             :         // Update environmental conditions
    5624       27842 :         this->Cur.CurAirTemp = state.dataEnvrn->OutDryBulbTemp;
    5625       27842 :         this->Cur.CurWindSpeed = state.dataEnvrn->WindSpeed;
    5626       27842 :         this->Cur.CurRelativeHumidity = state.dataEnvrn->OutRelHum;
    5627       27842 :         this->Cur.CurIncidentSolar = state.dataEnvrn->BeamSolarRad * max(state.dataEnvrn->SOLCOS(3), 0.0);
    5628             : 
    5629             :         //'now update cell properties
    5630       27842 :         auto &cells(this->Cells);
    5631      426870 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    5632     6792600 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    5633    66826448 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    5634    60432876 :                     auto &cell(cells(X, Y, Z));
    5635    60432876 :                     switch (cell.cellType) {
    5636    52187688 :                     case CellType::GeneralField:
    5637             :                     case CellType::FarfieldBoundary:
    5638             :                     case CellType::GroundSurface:
    5639             :                     case CellType::BasementCorner:
    5640             :                     case CellType::BasementFloor:
    5641             :                     case CellType::BasementWall:
    5642             :                         // UPDATE CELL PROPERTY SETS
    5643             :                         //'main ground cells, update with soil properties
    5644             :                         Real64 CellRhoCp;
    5645    52187688 :                         this->EvaluateSoilRhoCp(cell.Temperature, CellRhoCp);
    5646    52187688 :                         cell.Properties.SpecificHeat = CellRhoCp / cell.Properties.Density;
    5647             :                         // UPDATE BETA VALUE
    5648             :                         //'these are basic cartesian calculation cells
    5649    52187688 :                         cell.Beta = this->Cur.CurSimTimeStepSize / (cell.Properties.Density * cell.volume() * cell.Properties.SpecificHeat);
    5650    52187688 :                         break;
    5651     3936576 :                     case CellType::HorizInsulation:
    5652             :                     case CellType::VertInsulation:
    5653             :                     case CellType::Slab:
    5654             :                     case CellType::ZoneGroundInterface:
    5655     3936576 :                         this->Cells(X, Y, Z).Beta =
    5656     3936576 :                             this->Cur.CurSimTimeStepSize / (cell.Properties.Density * cell.volume() * cell.Properties.SpecificHeat);
    5657     3936576 :                         break;
    5658      434100 :                     case CellType::Pipe:
    5659             :                         // No pipe circuit with this call
    5660      434100 :                         break;
    5661     3874512 :                     case CellType::BasementCutaway:
    5662     3874512 :                         break;
    5663           0 :                     default:
    5664           0 :                         assert(false);
    5665             :                     }
    5666             :                 }
    5667             :             }
    5668             :         }
    5669       27842 :     }
    5670             : 
    5671       14498 :     void Domain::DoStartOfTimeStepInitializations(EnergyPlusData &state, Circuit *thisCircuit)
    5672             :     {
    5673             : 
    5674             :         // SUBROUTINE INFORMATION:
    5675             :         //       AUTHOR         Edwin Lee
    5676             :         //       DATE WRITTEN   Summer 2011
    5677             :         //       MODIFIED       na
    5678             :         //       RE-ENGINEERED  na
    5679             : 
    5680             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5681             :         static constexpr std::string_view RoutineName("PipingSystemCircuit::DoStartOfTimeStepInitializations");
    5682             :         Real64 CellTemp;
    5683             :         Real64 CellRhoCp;
    5684             :         Real64 FluidCp;
    5685             :         Real64 FluidDensity;
    5686             :         Real64 FluidConductivity;
    5687             :         Real64 FluidViscosity;
    5688             :         Real64 FluidPrandtl;
    5689             : 
    5690             :         // do the regular, non-circuit related inits
    5691       14498 :         this->DoStartOfTimeStepInitializations(state);
    5692             : 
    5693             :         // retrieve fluid properties based on the circuit inlet temperature -- which varies during the simulation
    5694             :         // but need to verify the value of inlet temperature during warm up, etc.
    5695       28996 :         FluidCp = FluidProperties::GetSpecificHeatGlycol(state,
    5696       14498 :                                                          state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidName,
    5697             :                                                          thisCircuit->InletTemperature,
    5698       14498 :                                                          state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidIndex,
    5699             :                                                          RoutineName);
    5700       28996 :         FluidDensity = FluidProperties::GetDensityGlycol(state,
    5701       14498 :                                                          state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidName,
    5702             :                                                          thisCircuit->InletTemperature,
    5703       14498 :                                                          state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidIndex,
    5704             :                                                          RoutineName);
    5705       28996 :         FluidConductivity = FluidProperties::GetConductivityGlycol(state,
    5706       14498 :                                                                    state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidName,
    5707             :                                                                    thisCircuit->InletTemperature,
    5708       14498 :                                                                    state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidIndex,
    5709             :                                                                    RoutineName);
    5710       28996 :         FluidViscosity = FluidProperties::GetViscosityGlycol(state,
    5711       14498 :                                                              state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidName,
    5712             :                                                              thisCircuit->InletTemperature,
    5713       14498 :                                                              state.dataPlnt->PlantLoop(thisCircuit->plantLoc.loopNum).FluidIndex,
    5714             :                                                              RoutineName);
    5715             : 
    5716             :         // Doesn't anyone care about poor Ludwig Prandtl?
    5717       14498 :         FluidPrandtl = 3.0;
    5718             : 
    5719             :         // then assign these fluid properties to the current fluid property set for easy lookup as needed
    5720       14498 :         thisCircuit->CurFluidPropertySet.Conductivity = FluidConductivity;
    5721       14498 :         thisCircuit->CurFluidPropertySet.Density = FluidDensity;
    5722       14498 :         thisCircuit->CurFluidPropertySet.SpecificHeat = FluidCp;
    5723       14498 :         thisCircuit->CurFluidPropertySet.Viscosity = FluidViscosity;
    5724       14498 :         thisCircuit->CurFluidPropertySet.Prandtl = FluidPrandtl;
    5725             : 
    5726             :         //'now update cell properties
    5727       14498 :         auto &cells(this->Cells);
    5728      234486 :         for (int X = 0, X_end = this->x_max_index; X <= X_end; ++X) {
    5729     3608472 :             for (int Y = 0, Y_end = this->y_max_index; Y <= Y_end; ++Y) {
    5730    23502416 :                 for (int Z = 0, Z_end = this->z_max_index; Z <= Z_end; ++Z) {
    5731    20113932 :                     auto &cell(cells(X, Y, Z));
    5732    20113932 :                     if (cell.cellType == CellType::Pipe) {
    5733             :                         // UPDATE CELL PROPERTY SETS
    5734             :                         //'first update the outer cell itself
    5735      434100 :                         CellTemp = cell.Temperature;
    5736      434100 :                         this->EvaluateSoilRhoCp(CellTemp, CellRhoCp);
    5737      434100 :                         cell.Properties.SpecificHeat = CellRhoCp / cell.Properties.Density;
    5738             :                         //'then update all the soil radial cells
    5739     1316076 :                         for (auto &soilCell : cell.PipeCellData.Soil) {
    5740      881976 :                             CellTemp = soilCell.Temperature;
    5741      881976 :                             this->EvaluateSoilRhoCp(CellTemp, CellRhoCp);
    5742      881976 :                             soilCell.Properties.SpecificHeat = CellRhoCp / soilCell.Properties.Density;
    5743             :                         }
    5744             : 
    5745             :                         // UPDATE BETA VALUES
    5746             :                         //'set the interface cell
    5747      868200 :                         cell.Beta = this->Cur.CurSimTimeStepSize /
    5748      434100 :                                     (cell.Properties.Density * cell.PipeCellData.InterfaceVolume * cell.Properties.SpecificHeat);
    5749             : 
    5750             :                         //'set the radial soil cells
    5751     1316076 :                         for (auto &soilCell : cell.PipeCellData.Soil) {
    5752     1763952 :                             soilCell.Beta = this->Cur.CurSimTimeStepSize / (soilCell.Properties.Density * soilCell.XY_CrossSectArea() * cell.depth() *
    5753      881976 :                                                                             soilCell.Properties.SpecificHeat);
    5754             :                         }
    5755             : 
    5756             :                         //'then insulation if it exists
    5757      434100 :                         if (thisCircuit->HasInsulation) {
    5758           0 :                             cell.PipeCellData.Insulation.Beta =
    5759           0 :                                 this->Cur.CurSimTimeStepSize /
    5760           0 :                                 (cell.PipeCellData.Insulation.Properties.Density * cell.PipeCellData.Insulation.XY_CrossSectArea() * cell.depth() *
    5761           0 :                                  cell.PipeCellData.Insulation.Properties.SpecificHeat);
    5762             :                         }
    5763             : 
    5764             :                         //'set the pipe cell
    5765      434100 :                         cell.PipeCellData.Pipe.Beta =
    5766     1302300 :                             this->Cur.CurSimTimeStepSize / (cell.PipeCellData.Pipe.Properties.Density * cell.PipeCellData.Pipe.XY_CrossSectArea() *
    5767      868200 :                                                             cell.depth() * cell.PipeCellData.Pipe.Properties.SpecificHeat);
    5768             : 
    5769             :                         // now the fluid cell also
    5770      434100 :                         cell.PipeCellData.Fluid.Properties = thisCircuit->CurFluidPropertySet;
    5771      434100 :                         cell.PipeCellData.Fluid.Beta =
    5772      868200 :                             this->Cur.CurSimTimeStepSize / (cell.PipeCellData.Fluid.Properties.Density * cell.PipeCellData.Fluid.Volume *
    5773      434100 :                                                             cell.PipeCellData.Fluid.Properties.SpecificHeat);
    5774             :                     }
    5775             :                 }
    5776             :             }
    5777             :         }
    5778       14498 :     }
    5779             : 
    5780      125701 :     void Domain::DoEndOfIterationOperations(EnergyPlusData &state, bool &Finished)
    5781             :     {
    5782             : 
    5783             :         // SUBROUTINE INFORMATION:
    5784             :         //       AUTHOR         Edwin Lee
    5785             :         //       DATE WRITTEN   Summer 2011
    5786             :         //       MODIFIED       na
    5787             :         //       RE-ENGINEERED  na
    5788             : 
    5789             :         // SUBROUTINE PARAMETER DEFINITIONS:
    5790             :         static constexpr std::string_view RoutineName("DoEndOfIterationOperations");
    5791             : 
    5792             :         //'check if we have converged for this iteration
    5793      125701 :         Finished = this->IsConverged_CurrentToPrevIteration();
    5794             : 
    5795             :         //'check for out of range temperatures here so they aren't plotted
    5796             :         //'this routine should be *much* more restrictive than the exceptions, so we should be safe with this location
    5797      125701 :         bool OutOfRange = this->CheckForOutOfRangeTemps();
    5798      125701 :         if (OutOfRange) {
    5799           0 :             if (this->HasZoneCoupledSlab) {
    5800           0 :                 ShowSevereError(state,
    5801           0 :                                 "Site:GroundDomain:Slab" + std::string{RoutineName} + ": Out of range temperatures detected in the ground domain.");
    5802           0 :                 ShowContinueError(state, "This could be due to the size of the loads on the domain.");
    5803           0 :                 ShowContinueError(state, "Verify inputs are correct. If problem persists, notify EnergyPlus support.");
    5804           0 :                 ShowFatalError(state, "Preceding error(s) cause program termination");
    5805           0 :             } else if (this->HasZoneCoupledBasement) {
    5806           0 :                 ShowSevereError(
    5807           0 :                     state, "Site:GroundDomain:Basement" + std::string{RoutineName} + ": Out of range temperatures detected in the ground domain.");
    5808           0 :                 ShowContinueError(state, "This could be due to the size of the loads on the domain.");
    5809           0 :                 ShowContinueError(state, "Verify inputs are correct. If problem persists, notify EnergyPlus support.");
    5810           0 :                 ShowFatalError(state, "Preceding error(s) cause program termination");
    5811             :             } else {
    5812           0 :                 ShowSevereError(state,
    5813           0 :                                 "PipingSystems:" + std::string{RoutineName} + ": Out of range temperatures detected in piping system simulation.");
    5814           0 :                 ShowContinueError(state, "This could be due to the size of the pipe circuit in relation to the loads being imposed.");
    5815           0 :                 ShowContinueError(state, "Try increasing the size of the pipe circuit and investigate sizing effects.");
    5816           0 :                 ShowFatalError(state, "Preceding error(s) cause program termination");
    5817             :             }
    5818             :         }
    5819      125701 :     }
    5820             : 
    5821          37 :     void Domain::InitializeSoilMoistureCalcs()
    5822             :     {
    5823             : 
    5824             :         // These vary by domain now, so we must be careful to retrieve them every time
    5825          37 :         Real64 const Theta_liq = this->Moisture.Theta_liq;
    5826          37 :         Real64 const Theta_sat = this->Moisture.Theta_sat;
    5827             : 
    5828             :         // Assumption
    5829          37 :         Real64 const Theta_ice = Theta_liq;
    5830             : 
    5831             :         //'Cp (freezing) calculations
    5832          37 :         Real64 constexpr rho_ice = 917.0;  //'Kg / m3
    5833          37 :         Real64 constexpr rho_liq = 1000.0; //'kg / m3
    5834             : 
    5835             :         //'from( " An improved model for predicting soil thermal conductivity from water content at room temperature, Fig 4" )
    5836          37 :         Real64 constexpr CP_liq = 4180.0;    //'J / KgK
    5837          37 :         Real64 constexpr CP_ice = 2066.0;    //'J / KgK
    5838          37 :         Real64 constexpr Lat_fus = 334000.0; //'J / Kg
    5839          37 :         Real64 const Cp_transient = Lat_fus / 0.4 + (0.5 * CP_ice - (CP_liq + CP_ice) / 2.0 * 0.1) / 0.4;
    5840             : 
    5841             :         //'from( " Numerical and experimental investigation of melting and freezing processes in phase change material storage" )
    5842          37 :         this->Moisture.rhoCp_soil_liq_1 = 1225000.0 / (1.0 - Theta_sat); //'J/m3K
    5843          37 :         this->Moisture.rhoCP_soil_liq = this->Moisture.rhoCp_soil_liq_1 * (1.0 - Theta_sat) + rho_liq * CP_liq * Theta_liq;
    5844          37 :         this->Moisture.rhoCP_soil_transient =
    5845          37 :             this->Moisture.rhoCp_soil_liq_1 * (1.0 - Theta_sat) + ((rho_liq + rho_ice) / 2.0) * Cp_transient * Theta_ice;
    5846          37 :         this->Moisture.rhoCP_soil_ice = this->Moisture.rhoCp_soil_liq_1 * (1.0 - Theta_sat) + rho_ice * CP_ice * Theta_ice; //'!J / m3K
    5847          37 :     }
    5848             : 
    5849    53503764 :     void Domain::EvaluateSoilRhoCp(Real64 const CellTemp, Real64 &rhoCp) const
    5850             :     {
    5851             : 
    5852             :         // SUBROUTINE INFORMATION:
    5853             :         //       AUTHOR         Edwin Lee
    5854             :         //       DATE WRITTEN   Summer 2011
    5855             :         //       MODIFIED       na
    5856             :         //       RE-ENGINEERED  na
    5857             : 
    5858             :         //'set some temperatures here for generalization -- these could be set in the input file
    5859    53503764 :         Real64 constexpr frzAllIce = -0.5;
    5860    53503764 :         Real64 constexpr frzIceTrans = -0.4;
    5861    53503764 :         Real64 constexpr frzLiqTrans = -0.1;
    5862    53503764 :         Real64 constexpr frzAllLiq = 0.0;
    5863             : 
    5864             :         //'calculate this cell's new Cp value based on the cell temperature
    5865    53503764 :         if (CellTemp <= frzAllIce) { // totally frozen
    5866     2683878 :             rhoCp = this->Moisture.rhoCP_soil_ice;
    5867    50819886 :         } else if ((CellTemp > frzAllIce) && (CellTemp < frzIceTrans)) { // in between totally frozen and ice transition
    5868      121192 :             rhoCp = this->Moisture.rhoCP_soil_ice +
    5869       60596 :                     (this->Moisture.rhoCP_soil_transient - this->Moisture.rhoCP_soil_ice) / (frzIceTrans - frzAllIce) * (CellTemp - frzAllIce);
    5870    50759290 :         } else if ((CellTemp >= frzIceTrans) && (CellTemp <= frzLiqTrans)) { // in between ice transition and liquid transition
    5871      470924 :             rhoCp = this->Moisture.rhoCP_soil_transient;
    5872    50288366 :         } else if ((CellTemp > frzLiqTrans) && (CellTemp < frzAllLiq)) { // in between liquid transition and all liquid
    5873      356678 :             rhoCp = this->Moisture.rhoCp_soil_liq_1 +
    5874      178339 :                     (this->Moisture.rhoCP_soil_transient - this->Moisture.rhoCP_soil_liq) / (frzAllLiq - frzLiqTrans) * (frzAllLiq - CellTemp);
    5875             :         } else { // ( CellTemp >= frzAllLiq ) --- greater than or equal to all liquid
    5876    50110027 :             rhoCp = this->Moisture.rhoCp_soil_liq_1;
    5877             :         }
    5878    53503764 :     }
    5879             : 
    5880  1602941888 :     void CartesianCell::EvaluateNeighborCoordinates(Direction const CurDirection, int &NX, int &NY, int &NZ) const
    5881             :     {
    5882             : 
    5883             :         // SUBROUTINE INFORMATION:
    5884             :         //       AUTHOR         Edwin Lee
    5885             :         //       DATE WRITTEN   Summer 2011
    5886             :         //       MODIFIED       na
    5887             :         //       RE-ENGINEERED  na
    5888             : 
    5889  1602941888 :         int const X = this->X_index;
    5890  1602941888 :         int const Y = this->Y_index;
    5891  1602941888 :         int const Z = this->Z_index;
    5892             : 
    5893  1602941888 :         switch (CurDirection) {
    5894   273617080 :         case Direction::PositiveY:
    5895   273617080 :             NX = X;
    5896   273617080 :             NY = Y + 1;
    5897   273617080 :             NZ = Z;
    5898   273617080 :             break;
    5899   273617080 :         case Direction::NegativeY:
    5900   273617080 :             NX = X;
    5901   273617080 :             NY = Y - 1;
    5902   273617080 :             NZ = Z;
    5903   273617080 :             break;
    5904   271544730 :         case Direction::PositiveX:
    5905   271544730 :             NX = X + 1;
    5906   271544730 :             NY = Y;
    5907   271544730 :             NZ = Z;
    5908   271544730 :             break;
    5909   271544730 :         case Direction::NegativeX:
    5910   271544730 :             NX = X - 1;
    5911   271544730 :             NY = Y;
    5912   271544730 :             NZ = Z;
    5913   271544730 :             break;
    5914   256309134 :         case Direction::PositiveZ:
    5915   256309134 :             NX = X;
    5916   256309134 :             NY = Y;
    5917   256309134 :             NZ = Z + 1;
    5918   256309134 :             break;
    5919   256309134 :         case Direction::NegativeZ:
    5920   256309134 :             NX = X;
    5921   256309134 :             NY = Y;
    5922   256309134 :             NZ = Z - 1;
    5923   256309134 :             break;
    5924           0 :         default:
    5925           0 :             assert(false);
    5926             :         }
    5927  1602941888 :     }
    5928             : 
    5929  1602650446 :     void Domain::EvaluateNeighborCharacteristics(
    5930             :         CartesianCell &ThisCell, Direction const CurDirection, Real64 &NeighborTemp, Real64 &Resistance, Real64 &AdiabaticMultiplier)
    5931             :     {
    5932             : 
    5933             :         // SUBROUTINE INFORMATION:
    5934             :         //       AUTHOR         Edwin Lee
    5935             :         //       DATE WRITTEN   Summer 2011
    5936             :         //       MODIFIED       na
    5937             :         //       RE-ENGINEERED  na
    5938             : 
    5939  1602650446 :         int NX = 0, NY = 0, NZ = 0;
    5940  1602650446 :         ThisCell.EvaluateNeighborCoordinates(CurDirection, NX, NY, NZ);
    5941             : 
    5942             :         //'split effects between the two cells so we can carefully calculate resistance values
    5943             :         Real64 ThisCellLength;
    5944             :         Real64 NeighborCellLength;
    5945  1602650446 :         Real64 ThisCellConductivity = 10000.0;
    5946  1602650446 :         if (ThisCell.Properties.Conductivity > 0.0) ThisCellConductivity = ThisCell.Properties.Conductivity;
    5947  1602650446 :         Real64 NeighborConductivity = 10000.0;
    5948  1602650446 :         auto const &cell(this->Cells(NX, NY, NZ));
    5949  1602650446 :         if (cell.Properties.Conductivity > 0.0) NeighborConductivity = cell.Properties.Conductivity;
    5950             : 
    5951             :         //'calculate normal surface area
    5952  1602650446 :         Real64 const ThisNormalArea = ThisCell.normalArea(CurDirection);
    5953             : 
    5954             :         //'set distance based on cell types
    5955  1602650446 :         auto const &TempNeighborInfo = ThisCell.NeighborInfo[CurDirection];
    5956  1602650446 :         if (ThisCell.cellType == CellType::Pipe) {
    5957             :             //'we need to be a bit careful with pipes, as they are full centroid to centroid in the z direction,
    5958             :             //' but only centroid to wall in the x and y directions
    5959    29740596 :             if (CurDirection == Direction::NegativeZ || CurDirection == Direction::PositiveZ) {
    5960         660 :                 ThisCellLength = TempNeighborInfo.ThisCentroidToNeighborWall;
    5961         660 :                 NeighborCellLength = TempNeighborInfo.ThisWallToNeighborCentroid;
    5962             :             } else {
    5963    29739936 :                 ThisCellLength = 0.0;
    5964    29739936 :                 NeighborCellLength = TempNeighborInfo.ThisWallToNeighborCentroid;
    5965             :             }
    5966  1572909850 :         } else if (cell.cellType == CellType::Pipe) {
    5967     5583984 :             ThisCellLength = TempNeighborInfo.ThisCentroidToNeighborWall;
    5968     5583984 :             NeighborCellLength = 0.0;
    5969             :         } else {
    5970  1567325866 :             ThisCellLength = TempNeighborInfo.ThisCentroidToNeighborWall;
    5971  1567325866 :             NeighborCellLength = TempNeighborInfo.ThisWallToNeighborCentroid;
    5972             :         }
    5973             : 
    5974             :         //'calculate resistance based on different conductivities between the two cells
    5975  1602650446 :         Resistance = (ThisCellLength / (ThisNormalArea * ThisCellConductivity)) + (NeighborCellLength / (ThisNormalArea * NeighborConductivity));
    5976             : 
    5977             :         //'return proper temperature for the given simulation type
    5978  1602650446 :         NeighborTemp = cell.Temperature;
    5979             : 
    5980             :         //'return the adiabatic multiplier
    5981  1602650446 :         AdiabaticMultiplier = TempNeighborInfo.adiabaticMultiplier;
    5982  1602650446 :     }
    5983             : 
    5984   283001373 :     void Domain::EvaluateCellNeighborDirections(CartesianCell const &cell, int &NumFieldCells, int &NumBoundaryCells)
    5985             :     {
    5986             : 
    5987             :         // SUBROUTINE INFORMATION:
    5988             :         //       AUTHOR         Edwin Lee
    5989             :         //       DATE WRITTEN   Summer 2011
    5990             :         //       MODIFIED       na
    5991             :         //       RE-ENGINEERED  na
    5992             : 
    5993   283001373 :         NumFieldCells = -1;
    5994   283001373 :         NumBoundaryCells = -1;
    5995             : 
    5996   283001373 :         if (cell.X_index < this->x_max_index) {
    5997   261908488 :             ++NumFieldCells;
    5998   261908488 :             this->NeighborFieldCells[NumFieldCells] = Direction::PositiveX;
    5999             :         } else {
    6000    21092885 :             ++NumBoundaryCells;
    6001    21092885 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::PositiveX;
    6002             :         }
    6003             : 
    6004   283001373 :         if (cell.X_index > 0) {
    6005   264061180 :             ++NumFieldCells;
    6006   264061180 :             this->NeighborFieldCells[NumFieldCells] = Direction::NegativeX;
    6007             :         } else {
    6008    18940193 :             ++NumBoundaryCells;
    6009    18940193 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::NegativeX;
    6010             :         }
    6011             : 
    6012   283001373 :         if (cell.Y_index < this->y_max_index) {
    6013   266957590 :             ++NumFieldCells;
    6014   266957590 :             this->NeighborFieldCells[NumFieldCells] = Direction::PositiveY;
    6015             :         } else {
    6016    16043783 :             ++NumBoundaryCells;
    6017    16043783 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::PositiveY;
    6018             :         }
    6019             : 
    6020   283001373 :         if (cell.Y_index > 0) {
    6021   265537750 :             ++NumFieldCells;
    6022   265537750 :             this->NeighborFieldCells[NumFieldCells] = Direction::NegativeY;
    6023             :         } else {
    6024    17463623 :             ++NumBoundaryCells;
    6025    17463623 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::NegativeY;
    6026             :         }
    6027             : 
    6028   283001373 :         if (cell.Z_index < this->z_max_index) {
    6029   257086121 :             ++NumFieldCells;
    6030   257086121 :             this->NeighborFieldCells[NumFieldCells] = Direction::PositiveZ;
    6031             :         } else {
    6032    25915252 :             ++NumBoundaryCells;
    6033    25915252 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::PositiveZ;
    6034             :         }
    6035             : 
    6036   283001373 :         if (cell.Z_index > 0) {
    6037   256261703 :             ++NumFieldCells;
    6038   256261703 :             this->NeighborFieldCells[NumFieldCells] = Direction::NegativeZ;
    6039             :         } else {
    6040    26739670 :             ++NumBoundaryCells;
    6041    26739670 :             this->NeighborBoundaryCells[NumBoundaryCells] = Direction::NegativeZ;
    6042             :         }
    6043   283001373 :     }
    6044             : 
    6045             : } // namespace PlantPipingSystemsManager
    6046             : 
    6047        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13