LCOV - code coverage report
Current view: top level - EnergyPlus - DElightManagerF.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 234 307 76.2 %
Date: 2023-01-17 19:17:23 Functions: 9 10 90.0 %

          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 <algorithm>
      50             : #include <cmath>
      51             : #include <fstream>
      52             : #include <ostream>
      53             : 
      54             : // ObjexxFCL Headers
      55             : #include <ObjexxFCL/Array1D.hh>
      56             : #include <ObjexxFCL/string.functions.hh>
      57             : 
      58             : // EnergyPlus Headers
      59             : #include <EnergyPlus/Construction.hh>
      60             : #include <EnergyPlus/DElightManagerF.hh>
      61             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      62             : #include <EnergyPlus/DataDElight.hh>
      63             : #include <EnergyPlus/DataDaylighting.hh>
      64             : #include <EnergyPlus/DataEnvironment.hh>
      65             : #include <EnergyPlus/DataGlobals.hh>
      66             : #include <EnergyPlus/DataHeatBalance.hh>
      67             : #include <EnergyPlus/DataIPShortCuts.hh>
      68             : #include <EnergyPlus/DataStringGlobals.hh>
      69             : #include <EnergyPlus/DataSurfaces.hh>
      70             : #include <EnergyPlus/General.hh>
      71             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      72             : #include <EnergyPlus/InternalHeatGains.hh>
      73             : #include <EnergyPlus/Material.hh>
      74             : #include <EnergyPlus/OutputProcessor.hh>
      75             : #include <EnergyPlus/UtilityRoutines.hh>
      76             : 
      77             : extern "C" {
      78             : #include <DElight/DElightManagerC.h>
      79             : }
      80             : 
      81             : namespace EnergyPlus {
      82             : 
      83             : namespace DElightManagerF {
      84             : 
      85             :     // MODULE INFORMATION
      86             :     //       AUTHOR         Robert J. Hitchcock
      87             :     //       DATE WRITTEN   August 2003
      88             :     //       MODIFIED       January 2004
      89             :     //       RE-ENGINEERED  na
      90             : 
      91             :     // PURPOSE OF THIS MODULE:
      92             : 
      93             :     // Defines INTERFACE Statements for Fortran calls to the DElightManagerC.cpp module.
      94             :     // The DElightManager.cpp module in turn defines the C/C++ calls to the DElight DLL.
      95             :     // Also, contains subroutines for performing associated operations.
      96             : 
      97             :     // METHODOLOGY EMPLOYED:
      98             : 
      99             :     // C Language Implementation of DOE2.1d and Superlite 3.0
     100             :     // Daylighting Algorithms with new Complex Fenestration System
     101             :     // analysis algorithms.
     102             :     // The original DOE2 daylighting algorithms and implementation
     103             :     // in FORTRAN were developed by F.C. Winkelmann at the
     104             :     // Lawrence Berkeley National Laboratory.
     105             :     // The original Superlite algorithms and implementation in FORTRAN
     106             :     // were developed by Michael Modest and Jong-Jin Kim
     107             :     // under contract with Lawrence Berkeley National Laboratory.
     108             :     // REFERENCES:
     109             : 
     110             :     // "Daylighting Calculation in DOE-2," F.C.Winkelmann, LBL-11353, May 1983
     111             :     // "Daylighting Simulation in the DOE-2 Building Energy Analysis Program,"
     112             :     // F.C. Winkelmann and S. Selkowitz, Energy and Buildings 8(1985)271-286
     113             : 
     114             :     // USE STATEMENTS:
     115             :     using namespace DataDElight;
     116             : 
     117           3 :     void DElightInputGenerator(EnergyPlusData &state)
     118             :     {
     119             : 
     120             :         // SUBROUTINE INFORMATION:
     121             :         //       AUTHOR         Robert J. Hitchcock
     122             :         //       DATE WRITTEN   August 2003
     123             :         //       MODIFIED       February 2004 - Changes to accommodate mods in DElight IDD
     124             :         //       RE-ENGINEERED  na
     125             : 
     126             :         // PURPOSE OF THIS SUBROUTINE:
     127             :         // This subroutine creates a DElight input file from EnergyPlus processed input.
     128             : 
     129             :         // USE STATEMENTS:
     130             :         using namespace DataHeatBalance;   // Gives access to Building, Zone and Lights data
     131             :         using namespace DataEnvironment;   // Gives access to Site data
     132             :         using namespace DataSurfaces;      // Gives access to Surface data
     133             :         using namespace DataStringGlobals; // Gives access to Program Path and Current Time/Date
     134             :         using InternalHeatGains::CheckLightsReplaceableMinMaxForZone;
     135             :         using InternalHeatGains::GetDesignLightingLevelForZone;
     136             : 
     137             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     138             :         int iNumDElightZones;   // Counter for Thermal Zones with hosted Daylighting:DElight objects
     139             :         int iNumOpaqueSurfs;    // Counter for opaque surfaces in each zone
     140             :         int iNumWindows;        // Counter for windows hosted in each surface
     141             :         int iconstruct;         // Index for construction type of surfaces
     142             :         int iMatlLayer;         // Index for the outside (i.e., 1st) Material Layer for a Construction
     143             :         Real64 rExtVisRefl;     // Exterior visible reflectance of a material
     144             :         Real64 rLightLevel;     // installed lighting level for current zone
     145             :         Real64 CosBldgRelNorth; // Cosine of Building rotation
     146             :         Real64 SinBldgRelNorth; // Sine of Building rotation
     147             :         Real64 CosZoneRelNorth; // Cosine of Zone rotation
     148             :         Real64 SinZoneRelNorth; // Sine of Zone rotation
     149             :         Real64 Xb;              // temp var for transformation calc
     150             :         Real64 Yb;              // temp var for transformation calc
     151           6 :         Array1D<Real64> RefPt_WCS_Coord(3);
     152           6 :         Array1D_int iWndoConstIndexes(100);
     153             :         bool lWndoConstFound;      // Flag for non-unique window const index
     154           6 :         std::string cNameWOBlanks; // Name without blanks
     155             :         bool ErrorsFound;
     156             :         int iHostedCFS;
     157             :         bool lWndoIsDoppelganger; // Flag for doppelganger window test
     158             :         int iDoppelganger;
     159             :         bool ldoTransform;
     160             :         Real64 roldAspectRatio;
     161             :         Real64 rnewAspectRatio;
     162             :         Real64 Xo;
     163             :         Real64 XnoRot;
     164             :         Real64 Xtrans;
     165             :         Real64 Yo;
     166             :         Real64 YnoRot;
     167             :         Real64 Ytrans;
     168             : 
     169             :         // Formats
     170             :         static constexpr std::string_view Format_901("Version EPlus : DElight input generated from EnergyPlus processed input {}\n");
     171             :         static constexpr std::string_view Format_902(
     172             :             "\nBuilding_Name {}\nSite_Latitude  {:12.4F}\nSite_Longitude {:12.4F}\nSite_Altitude  {:12.4F}\nBldg_Azimuth   {:12.4F}\nSite_Time_Zone "
     173             :             "{:12.4F}\nAtm_Moisture  0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07 0.07\nAtm_Turbidity 0.12 0.12 0.12 0.12 0.12 0.12 0.12 "
     174             :             "0.12 0.12 0.12 0.12 0.12\n");
     175             :         static constexpr std::string_view Format_903("\nZONES\nN_Zones {:4}\n");
     176             :         static constexpr std::string_view Format_904(
     177             :             "\nZONE DATA\nZone {}\nBldgSystem_Zone_Origin {:12.4F}{:12.4F}{:12.4F}\nZone_Azimuth    {:12.4F}\nZone_Multiplier {:5}\nZone_Floor_Area "
     178             :             "{:12.4F}\nZone_Volume     {:12.4F}\nZone_Installed_Lighting {:12.4F}\nMin_Input_Power    {:12.4F}\nMin_Light_Fraction "
     179             :             "{:12.4F}\nLight_Ctrl_Steps   {:3}\nLight_Ctrl_Prob    {:12.4F}\nView_Azimuth  0.0\nMax_Grid_Node_Area {:12.4F}\n");
     180             :         static constexpr std::string_view Format_905("\nZONE LIGHTING SCHEDULES\nN_Lt_Scheds 0\n");
     181             :         static constexpr std::string_view Format_906("\nZONE SURFACES\nN_Surfaces {:4}\n");
     182             :         static constexpr std::string_view Format_907("\nZONE SURFACE DATA\nSurface {}\nWCS_Azimuth {:12.4F}\nWCS_Tilt    {:12.4F}\nVis_Refl    "
     183             :                                                      "{:12.4F}\nExt_Refl    {:12.4F}\nGnd_Refl     0.2\nN_WCS_Vertices {:6}\n");
     184             :         static constexpr std::string_view Format_908("Vertex {:12.4F}{:12.4F}{:12.4F}\n");
     185             :         static constexpr std::string_view Format_909("\nSURFACE WINDOWS\nN_Windows {:6}\n");
     186             :         static constexpr std::string_view Format_910(
     187             :             "\nSURFACE WINDOW DATA\nWindow     {}\nGlass_Type {:8}\nShade_Flag   0\nOverhang_Fin_Depth    0.0 0.0 "
     188             :             "0.0\nOverhang_Fin_Distance 0.0 0.0 0.0\nN_WCS_Vertices {:4}\n");
     189             :         static constexpr std::string_view Format_911("\nSURFACE CFS\nN_CFS {:6}\n");
     190             :         static constexpr std::string_view Format_915(
     191             :             "\nCOMPLEX FENESTRATION DATA\nCFS_Name   {}\nCFS_Type   {}\nFenestration_Rotation {:12.4F}\nN_WCS_Vertices {:4}\n");
     192             :         static constexpr std::string_view Format_912("\nZONE REFERENCE POINTS\nN_Ref_Pts {:4}\n");
     193             :         static constexpr std::string_view Format_913(
     194             :             "\nZONE REFERENCE POINT DATA\nReference_Point {}\nRefPt_WCS_Coords {:12.4F}{:12.4F}{:12.4F}\nZone_Fraction "
     195             :             "{:12.4F}\nLight_Set_Pt {:12.4F}\nLight_Ctrl_Type {:4}\n");
     196             :         static constexpr std::string_view Format_914("\nBUILDING SHADES\nN_BShades 0\n");
     197             :         static constexpr std::string_view Format_920("\nLIBRARY DATA\nGLASS TYPES\nN_Glass_Types {:4}\n");
     198             :         static constexpr std::string_view Format_921(
     199             :             "\nGLASS TYPE DATA\nName {:6}\nEPlusDiffuse_Transmittance   {:12.4F}\nEPlusDiffuse_Int_Reflectance "
     200             :             "{:12.4F}\nEPlus_Vis_Trans_Coeff_1 {:17.9F}\nEPlus_Vis_Trans_Coeff_2 {:17.9F}\nEPlus_Vis_Trans_Coeff_3 "
     201             :             "{:17.9F}\nEPlus_Vis_Trans_Coeff_4 {:17.9F}\nEPlus_Vis_Trans_Coeff_5 {:17.9F}\nEPlus_Vis_Trans_Coeff_6 {:17.9F}\n");
     202             : 
     203             :         // Init the ErrorsFound flag
     204           3 :         ErrorsFound = false;
     205             : 
     206           3 :         GetInputDElightComplexFenestration(state, ErrorsFound);
     207             : 
     208           3 :         CheckForGeometricTransform(state, ldoTransform, roldAspectRatio, rnewAspectRatio);
     209             : 
     210             :         // Init the counter for Thermal Zones with hosted Daylighting:DElight objects
     211           3 :         iNumDElightZones = 0;
     212             : 
     213             :         // Init the counter for Window Construction types for writing to Library Data section of DElight input file
     214           3 :         int iNumWndoConsts = 0;
     215             : 
     216             :         // Open a file for writing DElight input from EnergyPlus data
     217           6 :         auto delightInFile = state.files.delightIn.open(state, "DElightInputGenerator", state.files.outputControl.delightin);
     218             : 
     219             :         // Start of DElight input file
     220           3 :         print(delightInFile, Format_901, state.dataStrGlobals->CurrentDateTime);
     221             : 
     222             :         // Building Data Section retrieved from DataHeatBalance and DataEnvironment modules
     223             :         // Remove any blanks from the Building Name for ease of input to DElight
     224           3 :         cNameWOBlanks = ReplaceBlanksWithUnderscores(state.dataHeatBal->BuildingName);
     225          12 :         print(delightInFile,
     226             :               Format_902,
     227             :               cNameWOBlanks,
     228           3 :               state.dataEnvrn->Latitude,
     229           3 :               state.dataEnvrn->Longitude,
     230           6 :               state.dataEnvrn->Elevation * M2FT,
     231           3 :               state.dataHeatBal->BuildingAzimuth,
     232           3 :               state.dataEnvrn->TimeZoneNumber);
     233             : 
     234             :         // Calc cos and sin of Building Relative North values for later use in transforming Reference Point coordinates
     235           3 :         CosBldgRelNorth = std::cos(-state.dataHeatBal->BuildingAzimuth * DataGlobalConstants::DegToRadians);
     236           3 :         SinBldgRelNorth = std::sin(-state.dataHeatBal->BuildingAzimuth * DataGlobalConstants::DegToRadians);
     237             : 
     238             :         // Loop through the Daylighting:Controls objects that use DElight checking for a host Zone
     239           9 :         for (auto &znDayl : state.dataDaylightingData->daylightControl) {
     240           6 :             if (znDayl.DaylightMethod == DataDaylighting::DaylightingMethod::DElight) {
     241             : 
     242             :                 // Register Error if 0 DElight RefPts have been input for valid DElight object
     243           3 :                 if (znDayl.TotalDaylRefPoints == 0) {
     244           0 :                     ShowSevereError(state, "No Reference Points input for daylighting zone using DElight =" + znDayl.Name);
     245           0 :                     ErrorsFound = true;
     246             :                 }
     247             : 
     248             :                 // Register Warning if more than 100 DElight RefPts have been input for valid DElight object
     249           3 :                 if (znDayl.TotalDaylRefPoints > 100) {
     250             :                     // Restrict to 100 Ref Pt maximum
     251           0 :                     znDayl.TotalDaylRefPoints = 100;
     252           0 :                     ShowWarningError(state, "Maximum of 100 Reference Points exceeded for daylighting zone using DElight =" + znDayl.Name);
     253           0 :                     ShowWarningError(state, "  Only first 100 Reference Points included in DElight analysis");
     254             :                 }
     255           3 :                 znDayl.DaylRefPtAbsCoord.allocate(3, znDayl.TotalDaylRefPoints);
     256           3 :                 znDayl.DaylRefPtAbsCoord = 0.0;
     257             : 
     258             :                 // RJH 2008-03-07: Allocate and Init DaylIllumAtRefPt array for this DElight zone
     259           3 :                 znDayl.DaylIllumAtRefPt.allocate(znDayl.TotalDaylRefPoints);
     260           3 :                 znDayl.DaylIllumAtRefPt = 0.0;
     261             :                 // following not used in DElight but allocated for convenience
     262           3 :                 znDayl.GlareIndexAtRefPt.allocate(znDayl.TotalDaylRefPoints);
     263           3 :                 znDayl.GlareIndexAtRefPt = 0.0;
     264             : 
     265             :                 // Increment counter of Thermal Zones with valid hosted DElight object
     266           3 :                 ++iNumDElightZones;
     267             :             }
     268             :         } // traverse ZoneDaylight array
     269             : 
     270             :         // Zone Data Section
     271           3 :         print(delightInFile, Format_903, iNumDElightZones);
     272             : 
     273             :         // Loop through the Daylighting:DElight objects searching for a match to the current Zone
     274             : 
     275           9 :         for (auto &znDayl : state.dataDaylightingData->daylightControl) {
     276           6 :             if (znDayl.DaylightMethod == DataDaylighting::DaylightingMethod::DElight) {
     277           3 :                 int const izone = UtilityRoutines::FindItemInList(znDayl.ZoneName, state.dataHeatBal->Zone);
     278           3 :                 if (izone != 0) {
     279             : 
     280           3 :                     rLightLevel = GetDesignLightingLevelForZone(state, izone);
     281           3 :                     CheckLightsReplaceableMinMaxForZone(state, izone);
     282           3 :                     auto &zn(state.dataHeatBal->Zone(izone));
     283             : 
     284             :                     // Write this Zone to the DElight input file
     285             :                     // Remove any blanks from the Zone Name for ease of input to DElight
     286           3 :                     cNameWOBlanks = ReplaceBlanksWithUnderscores(zn.Name);
     287           9 :                     print(delightInFile,
     288             :                           Format_904,
     289             :                           cNameWOBlanks,
     290           6 :                           zn.OriginX * M2FT,
     291           6 :                           zn.OriginY * M2FT,
     292           6 :                           zn.OriginZ * M2FT,
     293             :                           zn.RelNorth,
     294           6 :                           zn.Multiplier * zn.ListMultiplier,
     295           6 :                           zn.FloorArea * M22FT2,
     296           6 :                           zn.Volume * M32FT3,
     297           6 :                           rLightLevel / (zn.FloorArea * M22FT2 + 0.00001),
     298             :                           znDayl.MinPowerFraction,
     299             :                           znDayl.MinLightFraction,
     300             :                           znDayl.LightControlSteps,
     301             :                           znDayl.LightControlProbability,
     302           6 :                           znDayl.DElightGriddingResolution * M22FT2);
     303             : 
     304             :                     // Calc cos and sin of Zone Relative North values for later use in transforming Reference Point coordinates
     305           3 :                     CosZoneRelNorth = std::cos(-zn.RelNorth * DataGlobalConstants::DegToRadians);
     306           3 :                     SinZoneRelNorth = std::sin(-zn.RelNorth * DataGlobalConstants::DegToRadians);
     307             : 
     308             :                     // Zone Lighting Schedule Data Section
     309             :                     // NOTE: Schedules are not required since hourly values are retrieved from EnergyPlus as needed
     310           3 :                     print(delightInFile, Format_905);
     311             : 
     312             :                     // Zone Surface Data Section
     313             :                     // Count the number of opaque surfaces bounding the current zone
     314           3 :                     iNumOpaqueSurfs = 0;
     315           6 :                     for (int spaceNum : zn.spaceIndexes) {
     316           3 :                         auto &thisSpace = state.dataHeatBal->space(spaceNum);
     317          24 :                         for (int isurf = thisSpace.HTSurfaceFirst; isurf <= thisSpace.HTSurfaceLast; ++isurf) {
     318          21 :                             auto &surf(state.dataSurface->Surface(isurf));
     319          21 :                             if (surf.Class == SurfaceClass::Wall) ++iNumOpaqueSurfs;
     320          21 :                             if (surf.Class == SurfaceClass::Roof) ++iNumOpaqueSurfs;
     321          21 :                             if (surf.Class == SurfaceClass::Floor) ++iNumOpaqueSurfs;
     322             :                         }
     323             :                     } // Zone Opaque Surface loop
     324             : 
     325           3 :                     print(delightInFile, Format_906, iNumOpaqueSurfs);
     326             : 
     327             :                     // Write each opaque bounding Surface to the DElight input file
     328           6 :                     for (int spaceNum : zn.spaceIndexes) {
     329           3 :                         auto &thisSpace = state.dataHeatBal->space(spaceNum);
     330           3 :                         int const iSurfaceFirst = thisSpace.HTSurfaceFirst;
     331           3 :                         int const iSurfaceLast = thisSpace.HTSurfaceLast;
     332          24 :                         for (int isurf = iSurfaceFirst; isurf <= iSurfaceLast; ++isurf) {
     333             : 
     334          21 :                             auto &surf(state.dataSurface->Surface(isurf));
     335             : 
     336             :                             // Only process "opaque bounding" surface types
     337          21 :                             if ((surf.Class == SurfaceClass::Wall) || (surf.Class == SurfaceClass::Roof) || (surf.Class == SurfaceClass::Floor)) {
     338             : 
     339             :                                 // Get the Construction index for this Surface
     340          18 :                                 iconstruct = surf.Construction;
     341             : 
     342             :                                 // Is this Surface exposed to the exterior?
     343          18 :                                 if (surf.ExtSolar) {
     344             :                                     // Get the index for the outside (i.e., 1st) Material Layer for this Construction
     345          12 :                                     iMatlLayer = state.dataConstruction->Construct(iconstruct).LayerPoint(1);
     346             :                                     // Get the outside visible reflectance of this material layer
     347             :                                     // (since Construct(iconstruct)%ReflectVisDiffFront always appears to == 0.0)
     348          12 :                                     rExtVisRefl = 1.0 - state.dataMaterial->Material(iMatlLayer).AbsorpVisible;
     349             :                                 } else {
     350           6 :                                     rExtVisRefl = 0.0;
     351             :                                 }
     352             : 
     353             :                                 // Remove any blanks from the Surface Name for ease of input to DElight
     354          18 :                                 cNameWOBlanks = ReplaceBlanksWithUnderscores(surf.Name);
     355          36 :                                 print(delightInFile,
     356             :                                       Format_907,
     357             :                                       cNameWOBlanks,
     358             :                                       surf.Azimuth,
     359             :                                       surf.Tilt,
     360          18 :                                       state.dataConstruction->Construct(iconstruct).ReflectVisDiffBack,
     361             :                                       rExtVisRefl,
     362             :                                       surf.Sides);
     363             : 
     364             :                                 // Write out the vertex coordinates for each vertex
     365          18 :                                 int const iNumVertices = surf.Sides; // Counter for surface vertices
     366          90 :                                 for (int ivert = 1; ivert <= iNumVertices; ++ivert) {
     367          72 :                                     print(delightInFile,
     368             :                                           Format_908,
     369         144 :                                           surf.Vertex(ivert).x * M2FT,
     370         144 :                                           surf.Vertex(ivert).y * M2FT,
     371         144 :                                           surf.Vertex(ivert).z * M2FT);
     372             :                                 }
     373             : 
     374             :                                 // Count each Window hosted by the current opaque bounding Surface
     375          18 :                                 iNumWindows = 0;
     376         144 :                                 for (int iwndo = iSurfaceFirst; iwndo <= iSurfaceLast; ++iwndo) {
     377         126 :                                     if (state.dataSurface->Surface(iwndo).Class == SurfaceClass::Window) {
     378          18 :                                         auto &wndo(state.dataSurface->Surface(iwndo));
     379          18 :                                         if (wndo.BaseSurfName == surf.Name) {
     380             : 
     381             :                                             // Error if window has multiplier > 1 since this causes incorrect illuminance calc
     382           3 :                                             if (wndo.Multiplier > 1.0) {
     383           0 :                                                 ShowSevereError(state,
     384           0 :                                                                 "Multiplier > 1.0 for window " + wndo.Name +
     385             :                                                                     " not allowed since it is in a zone with DElight daylighting.");
     386           0 :                                                 ErrorsFound = true;
     387             :                                             }
     388             : 
     389             :                                             // Error if window has a shading device (blind/shade/screen) since
     390             :                                             // DElight cannot perform dynamic shading device deployment
     391           3 :                                             if (wndo.HasShadeControl) {
     392           0 :                                                 ShowSevereError(state,
     393           0 :                                                                 "Shading Device on window " + wndo.Name +
     394             :                                                                     " dynamic control is not supported in a zone with DElight daylighting.");
     395           0 :                                                 ErrorsFound = true;
     396             :                                             }
     397             : 
     398             :                                             // Loop through all Doppelganger Surface Names to ignore these Windows
     399           3 :                                             lWndoIsDoppelganger = false;
     400           5 :                                             for (auto &cfs : state.dataDaylightingData->DElightComplexFene) {
     401             : 
     402             :                                                 // Is the current Window Surface a Doppelganger?
     403           2 :                                                 if (wndo.Name == cfs.wndwName) {
     404             :                                                     // Ignore this Doppelganger Window
     405           2 :                                                     lWndoIsDoppelganger = true;
     406             :                                                 }
     407             : 
     408             :                                             } // CFS object loop A
     409             : 
     410           3 :                                             if (!lWndoIsDoppelganger) {
     411           1 :                                                 ++iNumWindows;
     412             :                                             }
     413             : 
     414             :                                         } // Surface hosts Window test
     415             :                                     }     // Window test
     416             :                                 }         // Window loop
     417             : 
     418          18 :                                 print(delightInFile, Format_909, iNumWindows);
     419             : 
     420             :                                 // If the current opaque bounding Surface hosts Windows,
     421             :                                 // then write each hosted Window to the DElight input file
     422             :                                 // and track the Window Construction type for later writing
     423          18 :                                 if (iNumWindows > 0) {
     424           8 :                                     for (int iwndo2 = iSurfaceFirst; iwndo2 <= iSurfaceLast; ++iwndo2) {
     425           7 :                                         if (state.dataSurface->Surface(iwndo2).Class == SurfaceClass::Window) {
     426             : 
     427           1 :                                             auto &wndo2(state.dataSurface->Surface(iwndo2));
     428             : 
     429           1 :                                             if (wndo2.BaseSurfName == surf.Name) {
     430             : 
     431             :                                                 // Loop through all Doppelganger Surface Names to ignore these Windows
     432           1 :                                                 lWndoIsDoppelganger = false;
     433             : 
     434           1 :                                                 for (auto &cfs : state.dataDaylightingData->DElightComplexFene) {
     435             : 
     436             :                                                     // Is the current Window Surface a Doppelganger?
     437           0 :                                                     if (wndo2.Name == cfs.wndwName) {
     438             :                                                         // Ignore this Doppelganger Window
     439           0 :                                                         lWndoIsDoppelganger = true;
     440             :                                                     }
     441             : 
     442             :                                                 } // CFS object loop A
     443             : 
     444           1 :                                                 if (!lWndoIsDoppelganger) {
     445             : 
     446             :                                                     // Track unique window construction types here for later writing to
     447             :                                                     // the library section of DElight input file
     448             : 
     449             :                                                     // Get the Construction index for this Window Surface
     450           1 :                                                     iconstruct = wndo2.Construction;
     451             : 
     452             :                                                     // Has the current Construction index been encountered before?
     453           1 :                                                     lWndoConstFound = false;
     454           1 :                                                     for (int iconst = 1; iconst <= iNumWndoConsts; ++iconst) {
     455           0 :                                                         if (iconstruct == iWndoConstIndexes(iconst)) lWndoConstFound = true;
     456             :                                                     }
     457           1 :                                                     if (!lWndoConstFound) {
     458           1 :                                                         ++iNumWndoConsts;
     459           1 :                                                         iWndoConstIndexes(iNumWndoConsts) = iconstruct;
     460             :                                                     }
     461             : 
     462             :                                                     // Write this Window to the DElight input file
     463             :                                                     // Remove any blanks from the Window Surface Name for ease of input to DElight
     464           1 :                                                     cNameWOBlanks = ReplaceBlanksWithUnderscores(wndo2.Name);
     465           1 :                                                     print(delightInFile, Format_910, cNameWOBlanks, iconstruct + 10000, wndo2.Sides);
     466             :                                                     // Use WndoConstIndex + 10000 as the Glass Type Name
     467             :                                                     // to differentiate EPlus glass types within DElight
     468             : 
     469             :                                                     // Write out the vertex coordinates for each vertex
     470           1 :                                                     int const iNumVertices = wndo2.Sides; // Counter for surface vertices
     471           5 :                                                     for (int ivert = 1; ivert <= iNumVertices; ++ivert) {
     472           4 :                                                         print(delightInFile,
     473             :                                                               Format_908,
     474           8 :                                                               wndo2.Vertex(ivert).x * M2FT,
     475           8 :                                                               wndo2.Vertex(ivert).y * M2FT,
     476           8 :                                                               wndo2.Vertex(ivert).z * M2FT);
     477             :                                                     }
     478             :                                                 } //! lWndoIsDoppelganger
     479             :                                             }     // Surface hosts Window2 test
     480             :                                         }         // Window2 Class test
     481             :                                     }             // Window2 loop
     482             :                                 }                 // Hosted Windows test
     483             : 
     484             :                                 // Write the number of CFS hosted by the current Opaque Bounding Surface
     485          18 :                                 iHostedCFS = 0;
     486             : 
     487             :                                 // Loop through the input CFS objects searching for a match to the current Opaque Bounding Surface
     488          30 :                                 for (auto &cfs : state.dataDaylightingData->DElightComplexFene) {
     489             : 
     490             :                                     // Does the current Opaque Bounding Surface host the current CFS object?
     491          12 :                                     if (surf.Name == cfs.surfName) {
     492             :                                         // Count this hosted CFS
     493           2 :                                         ++iHostedCFS;
     494             :                                     }
     495             :                                 } // CFS object loop 1
     496             : 
     497          18 :                                 print(delightInFile, Format_911, iHostedCFS);
     498             : 
     499             :                                 // Now write each of the hosted CFS data
     500             :                                 // Loop through the input CFS objects searching for a match to the current Opaque Bounding Surface
     501          30 :                                 for (auto &cfs : state.dataDaylightingData->DElightComplexFene) {
     502             : 
     503             :                                     // Does the current Opaque Bounding Surface host the current CFS object?
     504          12 :                                     if (surf.Name == cfs.surfName) {
     505             : 
     506             :                                         // Get the Doppelganger surface for this CFS
     507           2 :                                         iDoppelganger = 0;
     508          16 :                                         for (int iwndo3 = iSurfaceFirst; iwndo3 <= iSurfaceLast; ++iwndo3) {
     509             : 
     510          14 :                                             auto &wndo3(state.dataSurface->Surface(iwndo3));
     511             : 
     512          14 :                                             if (wndo3.Class == SurfaceClass::Window) {
     513             : 
     514             :                                                 // Is the current Window Surface the Doppelganger for the current CFS?
     515           2 :                                                 if (wndo3.Name == cfs.wndwName) {
     516             :                                                     // Store the window surface index for future reference
     517           2 :                                                     iDoppelganger = iwndo3;
     518             :                                                 }
     519             :                                             }
     520             :                                         }
     521             : 
     522             :                                         // Make sure that a valid Doppelganger surface exists
     523           2 :                                         if (iDoppelganger > 0) {
     524             : 
     525             :                                             // Write the data for this hosted CFS
     526           2 :                                             auto &doppelgangerSurf(state.dataSurface->Surface(iDoppelganger));
     527             : 
     528             :                                             // Remove any blanks from the CFS Name for ease of input to DElight
     529           2 :                                             cNameWOBlanks = ReplaceBlanksWithUnderscores(cfs.Name);
     530           2 :                                             int const iNumVertices = doppelgangerSurf.Sides; // Counter for surface vertices
     531           2 :                                             print(delightInFile, Format_915, cNameWOBlanks, cfs.ComplexFeneType, cfs.feneRota, iNumVertices);
     532             : 
     533             :                                             // Write out the vertex coordinates for each vertex
     534          10 :                                             for (int ivert = 1; ivert <= iNumVertices; ++ivert) {
     535           8 :                                                 print(delightInFile,
     536             :                                                       Format_908,
     537          16 :                                                       doppelgangerSurf.Vertex(ivert).x * M2FT,
     538          16 :                                                       doppelgangerSurf.Vertex(ivert).y * M2FT,
     539          16 :                                                       doppelgangerSurf.Vertex(ivert).z * M2FT);
     540             :                                             }
     541             :                                         }
     542             :                                         // Register Error if there is no valid Doppelganger for current Complex Fenestration
     543           2 :                                         if (iDoppelganger == 0) {
     544           0 :                                             ShowSevereError(state, "No Doppelganger Window Surface found for Complex Fenestration =" + cfs.Name);
     545           0 :                                             ErrorsFound = true;
     546             :                                         }
     547             :                                     } // The current Opaque Bounding Surface hosts the current CFS object?
     548             :                                 }     // CFS object loop 2
     549             :                             }         // Opaque Bounding Surface test
     550             :                         }
     551             :                     } // Zone Surface loop
     552             : 
     553             :                     // Write ZONE REFERENCE POINTS
     554           3 :                     print(delightInFile, Format_912, znDayl.TotalDaylRefPoints);
     555             : 
     556             :                     // Loop through the Daylighting:DElight:Reference Point objects checking for the current DElight Zone host
     557          15 :                     for (auto &refPt : state.dataDaylightingData->DaylRefPt) {
     558             : 
     559             :                         // Is this RefPt hosted by current DElight Zone?
     560          12 :                         if (izone == refPt.ZoneNum) {
     561           6 :                             auto &zn(state.dataHeatBal->Zone(izone));
     562             : 
     563             :                             // Limit to maximum of 100 RefPts
     564           6 :                             if (znDayl.TotalDaylRefPoints <= 100) {
     565             : 
     566           6 :                                 if (state.dataSurface->DaylRefWorldCoordSystem) {
     567           0 :                                     RefPt_WCS_Coord(1) = refPt.x;
     568           0 :                                     RefPt_WCS_Coord(2) = refPt.y;
     569           0 :                                     RefPt_WCS_Coord(3) = refPt.z;
     570             :                                 } else {
     571             :                                     // Transform reference point coordinates into building coordinate system
     572           6 :                                     Xb = refPt.x * CosZoneRelNorth - refPt.y * SinZoneRelNorth + zn.OriginX;
     573           6 :                                     Yb = refPt.x * SinZoneRelNorth + refPt.y * CosZoneRelNorth + zn.OriginY;
     574             :                                     // Transform into World Coordinate System
     575           6 :                                     RefPt_WCS_Coord(1) = Xb * CosBldgRelNorth - Yb * SinBldgRelNorth;
     576           6 :                                     RefPt_WCS_Coord(2) = Xb * SinBldgRelNorth + Yb * CosBldgRelNorth;
     577           6 :                                     RefPt_WCS_Coord(3) = refPt.z + zn.OriginZ;
     578           6 :                                     if (ldoTransform) {          // Geometry transform
     579           0 :                                         Xo = RefPt_WCS_Coord(1); // world coordinates.... shifted by relative north angle...
     580           0 :                                         Yo = RefPt_WCS_Coord(2);
     581             :                                         // next derotate the building
     582           0 :                                         XnoRot = Xo * CosBldgRelNorth + Yo * SinBldgRelNorth;
     583           0 :                                         YnoRot = Yo * CosBldgRelNorth - Xo * SinBldgRelNorth;
     584             :                                         // translate
     585           0 :                                         Xtrans = XnoRot * std::sqrt(rnewAspectRatio / roldAspectRatio);
     586           0 :                                         Ytrans = YnoRot * std::sqrt(roldAspectRatio / rnewAspectRatio);
     587             :                                         // rerotate
     588           0 :                                         RefPt_WCS_Coord(1) = Xtrans * CosBldgRelNorth - Ytrans * SinBldgRelNorth;
     589             : 
     590           0 :                                         RefPt_WCS_Coord(2) = Xtrans * SinBldgRelNorth + Ytrans * CosBldgRelNorth;
     591             :                                     }
     592             :                                 }
     593           6 :                                 znDayl.DaylRefPtAbsCoord({1, 3}, refPt.indexToFracAndIllum) = RefPt_WCS_Coord({1, 3});
     594             : 
     595             :                                 // Validate that Reference Point coordinates are within the host Zone
     596           6 :                                 if (RefPt_WCS_Coord(1) < zn.MinimumX || RefPt_WCS_Coord(1) > zn.MaximumX) {
     597           0 :                                     ShowWarningError(state, "DElightInputGenerator:Reference point X Value outside Zone Min/Max X, Zone=" + zn.Name);
     598           0 :                                     ShowSevereError(state,
     599           0 :                                                     format("...X Reference Point= {:.2R}, Zone Minimum X= {:.2R}, Zone Maximum X= {:.2R}",
     600             :                                                            zn.MinimumX,
     601             :                                                            RefPt_WCS_Coord(1),
     602           0 :                                                            zn.MaximumX));
     603           0 :                                     ErrorsFound = true;
     604             :                                 }
     605           6 :                                 if (RefPt_WCS_Coord(2) < zn.MinimumY || RefPt_WCS_Coord(2) > zn.MaximumY) {
     606           0 :                                     ShowWarningError(state, "DElightInputGenerator:Reference point Y Value outside Zone Min/Max Y, Zone=" + zn.Name);
     607           0 :                                     ShowSevereError(state,
     608           0 :                                                     format("...Y Reference Point= {:.2R}, Zone Minimum Y= {:.2R}, Zone Maximum Y= {:.2R}",
     609             :                                                            zn.MinimumY,
     610             :                                                            RefPt_WCS_Coord(2),
     611           0 :                                                            zn.MaximumY));
     612           0 :                                     ErrorsFound = true;
     613             :                                 }
     614           6 :                                 if (RefPt_WCS_Coord(3) < state.dataHeatBal->Zone(izone).MinimumZ || RefPt_WCS_Coord(3) > zn.MaximumZ) {
     615           0 :                                     ShowWarningError(state, "DElightInputGenerator:Reference point Z Value outside Zone Min/Max Z, Zone=" + zn.Name);
     616           0 :                                     ShowSevereError(state,
     617           0 :                                                     format("...Z Reference Point= {:.2R}, Zone Minimum Z= {:.2R}, Zone Maximum Z= {:.2R}",
     618             :                                                            zn.MinimumZ,
     619             :                                                            RefPt_WCS_Coord(3),
     620           0 :                                                            zn.MaximumZ));
     621           0 :                                     ErrorsFound = true;
     622             :                                 }
     623             : 
     624             :                                 // Write this RefPt to the DElight input file
     625             : 
     626             :                                 // Remove any blanks from the RefPt Name for ease of input to DElight
     627           6 :                                 cNameWOBlanks = ReplaceBlanksWithUnderscores(refPt.Name);
     628           6 :                                 if (refPt.indexToFracAndIllum != 0) {
     629          18 :                                     print(delightInFile,
     630             :                                           Format_913,
     631             :                                           cNameWOBlanks,
     632          12 :                                           RefPt_WCS_Coord(1) * M2FT,
     633          12 :                                           RefPt_WCS_Coord(2) * M2FT,
     634          12 :                                           RefPt_WCS_Coord(3) * M2FT,
     635             :                                           znDayl.FracZoneDaylit(refPt.indexToFracAndIllum),
     636          12 :                                           znDayl.IllumSetPoint(refPt.indexToFracAndIllum) * LUX2FC,
     637             :                                           znDayl.LightControlType);
     638             :                                     // RJH 2008-03-07: Set up DaylIllumAtRefPt for output for this DElight zone RefPt
     639          12 :                                     SetupOutputVariable(state,
     640             :                                                         "Daylighting Reference Point Illuminance",
     641             :                                                         OutputProcessor::Unit::lux,
     642           6 :                                                         znDayl.DaylIllumAtRefPt(refPt.indexToFracAndIllum),
     643             :                                                         OutputProcessor::SOVTimeStepType::Zone,
     644             :                                                         OutputProcessor::SOVStoreType::Average,
     645           6 :                                                         refPt.Name);
     646             :                                 } else {
     647           0 :                                     print(delightInFile,
     648             :                                           Format_913,
     649             :                                           cNameWOBlanks,
     650           0 :                                           RefPt_WCS_Coord(1) * M2FT,
     651           0 :                                           RefPt_WCS_Coord(2) * M2FT,
     652           0 :                                           RefPt_WCS_Coord(3) * M2FT,
     653             :                                           0.0,
     654           0 :                                           0.0 * LUX2FC,
     655             :                                           znDayl.LightControlType); // should never happen but just in case send zero fraction and illuminance
     656             :                                 }
     657             :                             } // Max 100 RefPt test
     658             :                         }     // RefPt in current DElight Zone test
     659             :                     }         // traverse reference points loop
     660             :                 }             // if in a zone
     661             :             }                 // Zone hosts DElight object test
     662             :         }                     // traverse ZoneDayLight object loop
     663             : 
     664             :         // Write BUILDING SHADES
     665           3 :         print(delightInFile, Format_914);
     666             : 
     667             :         // Write LIBRARY DATA
     668           3 :         print(delightInFile, Format_920, iNumWndoConsts);
     669             : 
     670             :         // Write GLASS TYPES
     671             :         // VisBeamCoeffs are processed in EPlus by POLYF() function
     672             :         // Use WndoConstIndex + 10000 as the Glass Type Name to differentiate EPlus glass types within DElight
     673           4 :         for (int iconst = 1; iconst <= iNumWndoConsts; ++iconst) {
     674           9 :             print(delightInFile,
     675             :                   Format_921,
     676           2 :                   iWndoConstIndexes(iconst) + 10000,
     677           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransDiffVis,
     678           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).ReflectVisDiffBack,
     679           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(1),
     680           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(2),
     681           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(3),
     682           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(4),
     683           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(5),
     684           1 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef(6));
     685             : 
     686             :         } // Glass Type loop
     687             : 
     688           3 :         if (ErrorsFound) ShowFatalError(state, "Problems with Daylighting:DElight input, see previous error messages");
     689           3 :     }
     690             : 
     691           3 :     void GenerateDElightDaylightCoefficients(Real64 &dLatitude, int &iErrorFlag)
     692             :     {
     693             : 
     694             :         // SUBROUTINE INFORMATION:
     695             :         //       AUTHOR         Linda Lawrie
     696             :         //       DATE WRITTEN   September 2012
     697             :         //       MODIFIED       na
     698             :         //       RE-ENGINEERED  na
     699             : 
     700             :         // PURPOSE OF THIS SUBROUTINE:
     701             :         // The purpose of this subroutine is to provide an envelop to the DElightDaylightCoefficients routine
     702             : 
     703           3 :         delightdaylightcoefficients(dLatitude, &iErrorFlag);
     704           3 :     }
     705             : 
     706           3 :     void GetInputDElightComplexFenestration(EnergyPlusData &state, bool &ErrorsFound)
     707             :     {
     708             :         // Perform GetInput function for the Daylighting:DELight:ComplexFenestration object
     709             :         // Glazer - July 2016
     710             : 
     711             :         int NumAlpha;
     712             :         int NumNumber;
     713             :         int IOStat;
     714           3 :         int CFSNum = 0;
     715             : 
     716           3 :         constexpr auto cCurrentModuleObject("Daylighting:DELight:ComplexFenestration");
     717             : 
     718           3 :         int TotDElightCFS = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     719           3 :         state.dataDaylightingData->DElightComplexFene.allocate(TotDElightCFS);
     720           5 :         for (auto &cfs : state.dataDaylightingData->DElightComplexFene) {
     721          16 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     722             :                                                                      cCurrentModuleObject,
     723             :                                                                      ++CFSNum,
     724           2 :                                                                      state.dataIPShortCut->cAlphaArgs,
     725             :                                                                      NumAlpha,
     726           2 :                                                                      state.dataIPShortCut->rNumericArgs,
     727             :                                                                      NumNumber,
     728             :                                                                      IOStat,
     729           2 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     730           2 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     731           2 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     732           4 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     733           2 :             cfs.Name = state.dataIPShortCut->cAlphaArgs(1);
     734           2 :             cfs.ComplexFeneType = state.dataIPShortCut->cAlphaArgs(2);
     735           2 :             cfs.surfName = state.dataIPShortCut->cAlphaArgs(3);
     736           2 :             if (UtilityRoutines::FindItemInList(cfs.surfName, state.dataSurface->Surface) == 0) {
     737           0 :                 ShowSevereError(state,
     738           0 :                                 format("{}{}",
     739             :                                        cCurrentModuleObject,
     740           0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + cfs.surfName + "\"."));
     741           0 :                 ErrorsFound = true;
     742             :             }
     743           2 :             cfs.wndwName = state.dataIPShortCut->cAlphaArgs(4);
     744           2 :             if (UtilityRoutines::FindItemInList(cfs.surfName, state.dataSurface->Surface) == 0) {
     745           0 :                 ShowSevereError(state,
     746           0 :                                 format("{}{}",
     747             :                                        cCurrentModuleObject,
     748           0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + cfs.wndwName + "\"."));
     749           0 :                 ErrorsFound = true;
     750             :             }
     751           2 :             cfs.feneRota = state.dataIPShortCut->rNumericArgs(1);
     752           2 :             if (cfs.feneRota < 0. || cfs.feneRota > 360.) {
     753           0 :                 ShowSevereError(state,
     754           0 :                                 format("{}{}",
     755             :                                        cCurrentModuleObject,
     756           0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cNumericFieldNames(1) + " outside of range 0 to 360."));
     757           0 :                 ErrorsFound = true;
     758             :             }
     759             :         }
     760           3 :     }
     761             : 
     762           3 :     void CheckForGeometricTransform(EnergyPlusData &state, bool &doTransform, Real64 &OldAspectRatio, Real64 &NewAspectRatio)
     763             :     {
     764             : 
     765             :         // SUBROUTINE INFORMATION:
     766             :         //       AUTHOR         Linda Lawrie
     767             :         //       DATE WRITTEN   February 2009
     768             :         //       MODIFIED       na
     769             :         //       RE-ENGINEERED  na
     770             : 
     771             :         // PURPOSE OF THIS SUBROUTINE:
     772             :         // check for geometrytransform in the daylighting access for reference points
     773             : 
     774             :         // METHODOLOGY EMPLOYED:
     775             :         // once reference points  have been converted to WCS,
     776             :         //  change them to reflect a different aspect
     777             :         // ratio for the entire building based on user input.
     778             : 
     779             :         // SUBROUTINE PARAMETER DEFINITIONS:
     780           3 :         constexpr auto CurrentModuleObject("GeometryTransform");
     781             : 
     782             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     783           6 :         Array1D_string cAlphas(1);
     784           6 :         Array1D<Real64> rNumerics(2);
     785             :         int NAlphas;
     786             :         int NNum;
     787             :         int IOStat;
     788             : 
     789             :         // begin execution
     790             :         // get user input...
     791           3 :         doTransform = false;
     792           3 :         OldAspectRatio = 1.0;
     793           3 :         NewAspectRatio = 1.0;
     794             : 
     795           3 :         if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject) == 1) {
     796           0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     797             :                                                                      CurrentModuleObject,
     798             :                                                                      1,
     799             :                                                                      cAlphas,
     800             :                                                                      NAlphas,
     801             :                                                                      rNumerics,
     802             :                                                                      NNum,
     803             :                                                                      IOStat,
     804           0 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     805           0 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     806           0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     807           0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     808           0 :             OldAspectRatio = rNumerics(1);
     809           0 :             NewAspectRatio = rNumerics(2);
     810           0 :             if (cAlphas(1) != "XY") {
     811           0 :                 ShowWarningError(
     812             :                     state,
     813           0 :                     format("{}{}", CurrentModuleObject, ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=" + cAlphas(1) + "...ignored."));
     814             :             }
     815           0 :             doTransform = true;
     816           0 :             state.dataSurface->AspectTransform = true;
     817             :         }
     818           3 :         if (state.dataSurface->WorldCoordSystem) {
     819           3 :             doTransform = false;
     820           3 :             state.dataSurface->AspectTransform = false;
     821             :         }
     822           3 :     }
     823             : 
     824          33 :     std::string ReplaceBlanksWithUnderscores(std::string const &InputString) // Input String
     825             :     {
     826             : 
     827             :         // FUNCTION INFORMATION:
     828             :         //       AUTHOR         Robert J. Hitchcock
     829             :         //       DATE WRITTEN   August 2003
     830             :         //       MODIFIED       From UtilityRoutines::MakeUPPERCase( function by Linda K. Lawrie
     831             :         //       RE-ENGINEERED  na
     832             : 
     833             :         // PURPOSE OF THIS SUBROUTINE:
     834             :         // This function returns a representation of the InputString with blanks replaced with underscores.
     835             : 
     836             :         // METHODOLOGY EMPLOYED:
     837             :         // Uses the std::replace function from the C++ library
     838             : 
     839             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     840             : 
     841          33 :         std::string ResultString(trimmed(InputString));
     842          33 :         std::replace(ResultString.begin(), ResultString.end(), ' ', '_');
     843          33 :         return ResultString;
     844             :     }
     845             : 
     846        2037 :     void DElightElecLtgCtrl(int iNameLength,
     847             :                             std::string cZoneName,
     848             :                             Real64 dBldgLat,
     849             :                             Real64 dHISKF,
     850             :                             Real64 dHISUNF,
     851             :                             Real64 dCloudFraction,
     852             :                             Real64 dSOLCOSX,
     853             :                             Real64 dSOLCOSY,
     854             :                             Real64 dSOLCOSZ,
     855             :                             Real64 &pdPowerReducFac,
     856             :                             int piErrorFlag)
     857             :     {
     858        4074 :         auto zoneNameArr(getCharArrayFromString(cZoneName));
     859        2037 :         delightelecltgctrl(
     860        2037 :             iNameLength, &zoneNameArr[0], dBldgLat, dHISKF, dHISUNF, dCloudFraction, dSOLCOSX, dSOLCOSY, dSOLCOSZ, &pdPowerReducFac, &piErrorFlag);
     861        2037 :     }
     862             : 
     863        2037 :     std::vector<char> getCharArrayFromString(std::string const &originalString)
     864             :     {
     865        2037 :         std::vector<char> returnVal(originalString.begin(), originalString.end());
     866        2037 :         returnVal.push_back('\0'); // get null terminated string of chars
     867        2037 :         return returnVal;
     868             :     }
     869             : 
     870           0 :     std::string getStringFromCharArray(std::vector<char> const &originalCharArray)
     871             :     {
     872           0 :         return std::string(originalCharArray.begin(), originalCharArray.end());
     873             :     }
     874             : 
     875             : } // namespace DElightManagerF
     876             : 
     877        2313 : } // namespace EnergyPlus

Generated by: LCOV version 1.13