LCOV - code coverage report
Current view: top level - EnergyPlus - DElightManagerF.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 71.0 % 331 235
Test Date: 2025-06-02 07:23:51 Functions: 87.5 % 8 7

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

Generated by: LCOV version 2.0-1