LCOV - code coverage report
Current view: top level - EnergyPlus - DElightManagerF.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 6.8 % 323 22
Test Date: 2025-05-22 16:09:37 Functions: 12.5 % 8 1

            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            0 :     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            0 :         Vector3<Real64> RefPt_WCS_Coord;
     153            0 :         Array1D_int iWndoConstIndexes(100);
     154              :         bool lWndoConstFound;      // Flag for non-unique window const index
     155            0 :         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            0 :         ErrorsFound = false;
     206              : 
     207            0 :         GetInputDElightComplexFenestration(state, ErrorsFound);
     208              : 
     209            0 :         CheckForGeometricTransform(state, ldoTransform, roldAspectRatio, rnewAspectRatio);
     210              : 
     211              :         // Init the counter for Thermal Zones with hosted Daylighting:DElight objects
     212            0 :         iNumDElightZones = 0;
     213              : 
     214              :         // Init the counter for Window Construction types for writing to Library Data section of DElight input file
     215            0 :         int iNumWndoConsts = 0;
     216              : 
     217              :         // Open a file for writing DElight input from EnergyPlus data
     218            0 :         auto delightInFile = state.files.delightIn.open(state, "DElightInputGenerator", state.files.outputControl.delightin); // (THIS_AUTO_OK)
     219              : 
     220              :         // Start of DElight input file
     221            0 :         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            0 :         cNameWOBlanks = ReplaceBlanksWithUnderscores(state.dataHeatBal->BuildingName);
     226            0 :         print(delightInFile,
     227              :               Format_902,
     228              :               cNameWOBlanks,
     229            0 :               state.dataEnvrn->Latitude,
     230            0 :               state.dataEnvrn->Longitude,
     231            0 :               state.dataEnvrn->Elevation * M2FT,
     232            0 :               state.dataHeatBal->BuildingAzimuth,
     233            0 :               state.dataEnvrn->TimeZoneNumber);
     234              : 
     235              :         // Calc cos and sin of Building Relative North values for later use in transforming Reference Point coordinates
     236            0 :         CosBldgRelNorth = std::cos(-state.dataHeatBal->BuildingAzimuth * Constant::DegToRad);
     237            0 :         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            0 :         for (auto &znDayl : state.dataDayltg->daylightControl) {
     241            0 :             if (znDayl.DaylightMethod == Dayltg::DaylightingMethod::DElight) {
     242              : 
     243              :                 // Register Error if 0 DElight RefPts have been input for valid DElight object
     244            0 :                 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            0 :                 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            0 :                 assert((int)znDayl.refPts.size() == znDayl.TotalDaylRefPoints);
     259            0 :                 for (auto &refPt : znDayl.refPts) {
     260            0 :                     refPt.absCoords = {0.0, 0.0, 0.0};
     261            0 :                     refPt.lums[(int)Lum::Illum] = 0.0;
     262            0 :                     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            0 :                 ++iNumDElightZones;
     274              :             }
     275              :         } // traverse ZoneDaylight array
     276              : 
     277              :         // Zone Data Section
     278            0 :         print(delightInFile, Format_903, iNumDElightZones);
     279              : 
     280              :         // Loop through the Daylighting:DElight objects searching for a match to the current Zone
     281              : 
     282            0 :         for (auto &znDayl : state.dataDayltg->daylightControl) {
     283            0 :             if (znDayl.DaylightMethod == Dayltg::DaylightingMethod::DElight) {
     284            0 :                 int const izone = Util::FindItemInList(znDayl.ZoneName, state.dataHeatBal->Zone);
     285            0 :                 if (izone != 0) {
     286              : 
     287            0 :                     rLightLevel = GetDesignLightingLevelForZone(state, izone);
     288            0 :                     CheckLightsReplaceableMinMaxForZone(state, izone);
     289            0 :                     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            0 :                     cNameWOBlanks = ReplaceBlanksWithUnderscores(zn.Name);
     294            0 :                     print(delightInFile,
     295              :                           Format_904,
     296              :                           cNameWOBlanks,
     297            0 :                           zn.OriginX * M2FT,
     298            0 :                           zn.OriginY * M2FT,
     299            0 :                           zn.OriginZ * M2FT,
     300            0 :                           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            0 :                           znDayl.MinPowerFraction,
     306            0 :                           znDayl.MinLightFraction,
     307            0 :                           znDayl.LightControlSteps,
     308            0 :                           znDayl.LightControlProbability,
     309            0 :                           znDayl.DElightGriddingResolution * M22FT2);
     310              : 
     311              :                     // Calc cos and sin of Zone Relative North values for later use in transforming Reference Point coordinates
     312            0 :                     CosZoneRelNorth = std::cos(-zn.RelNorth * Constant::DegToRad);
     313            0 :                     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            0 :                     print(delightInFile, Format_905);
     318              : 
     319              :                     // Zone Surface Data Section
     320              :                     // Count the number of opaque surfaces bounding the current zone
     321            0 :                     iNumOpaqueSurfs = 0;
     322            0 :                     for (int spaceNum : zn.spaceIndexes) {
     323            0 :                         auto const &thisSpace = state.dataHeatBal->space(spaceNum);
     324            0 :                         for (int isurf = thisSpace.HTSurfaceFirst; isurf <= thisSpace.HTSurfaceLast; ++isurf) {
     325            0 :                             auto const &surf(state.dataSurface->Surface(isurf));
     326            0 :                             if (surf.Class == SurfaceClass::Wall) ++iNumOpaqueSurfs;
     327            0 :                             if (surf.Class == SurfaceClass::Roof) ++iNumOpaqueSurfs;
     328            0 :                             if (surf.Class == SurfaceClass::Floor) ++iNumOpaqueSurfs;
     329              :                         }
     330              :                     } // Zone Opaque Surface loop
     331              : 
     332            0 :                     print(delightInFile, Format_906, iNumOpaqueSurfs);
     333              : 
     334              :                     // Write each opaque bounding Surface to the DElight input file
     335            0 :                     for (int spaceNum : zn.spaceIndexes) {
     336            0 :                         auto const &thisSpace = state.dataHeatBal->space(spaceNum);
     337            0 :                         int const iSurfaceFirst = thisSpace.HTSurfaceFirst;
     338            0 :                         int const iSurfaceLast = thisSpace.HTSurfaceLast;
     339            0 :                         for (int isurf = iSurfaceFirst; isurf <= iSurfaceLast; ++isurf) {
     340              : 
     341            0 :                             auto &surf(state.dataSurface->Surface(isurf));
     342              : 
     343              :                             // Only process "opaque bounding" surface types
     344            0 :                             if ((surf.Class == SurfaceClass::Wall) || (surf.Class == SurfaceClass::Roof) || (surf.Class == SurfaceClass::Floor)) {
     345              : 
     346              :                                 // Get the Construction index for this Surface
     347            0 :                                 iconstruct = surf.Construction;
     348              : 
     349              :                                 // Is this Surface exposed to the exterior?
     350            0 :                                 if (surf.ExtSolar) {
     351              :                                     // Get the index for the outside (i.e., 1st) Material Layer for this Construction
     352            0 :                                     iMatlLayer = state.dataConstruction->Construct(iconstruct).LayerPoint(1);
     353              :                                     // Get the outside visible reflectance of this material layer
     354              :                                     // (since Construct(iconstruct)%ReflectVisDiffFront always appears to == 0.0)
     355            0 :                                     rExtVisRefl = 1.0 - state.dataMaterial->materials(iMatlLayer)->AbsorpVisible;
     356              :                                 } else {
     357            0 :                                     rExtVisRefl = 0.0;
     358              :                                 }
     359              : 
     360              :                                 // Remove any blanks from the Surface Name for ease of input to DElight
     361            0 :                                 cNameWOBlanks = ReplaceBlanksWithUnderscores(surf.Name);
     362            0 :                                 print(delightInFile,
     363              :                                       Format_907,
     364              :                                       cNameWOBlanks,
     365            0 :                                       surf.Azimuth,
     366            0 :                                       surf.Tilt,
     367            0 :                                       state.dataConstruction->Construct(iconstruct).ReflectVisDiffBack,
     368              :                                       rExtVisRefl,
     369            0 :                                       surf.Sides);
     370              : 
     371              :                                 // Write out the vertex coordinates for each vertex
     372            0 :                                 for (int ivert = 1; ivert <= surf.Sides; ++ivert) {
     373            0 :                                     print(delightInFile,
     374              :                                           Format_908,
     375            0 :                                           surf.Vertex(ivert).x * M2FT,
     376            0 :                                           surf.Vertex(ivert).y * M2FT,
     377            0 :                                           surf.Vertex(ivert).z * M2FT);
     378              :                                 }
     379              : 
     380              :                                 // Count each Window hosted by the current opaque bounding Surface
     381            0 :                                 iNumWindows = 0;
     382            0 :                                 for (int iwndo = iSurfaceFirst; iwndo <= iSurfaceLast; ++iwndo) {
     383            0 :                                     if (state.dataSurface->Surface(iwndo).Class == SurfaceClass::Window) {
     384            0 :                                         auto &wndo(state.dataSurface->Surface(iwndo));
     385            0 :                                         if (wndo.BaseSurfName == surf.Name) {
     386              : 
     387              :                                             // Error if window has multiplier > 1 since this causes incorrect illuminance calc
     388            0 :                                             if (wndo.Multiplier > 1.0) {
     389            0 :                                                 ShowSevereError(
     390              :                                                     state,
     391            0 :                                                     format(
     392              :                                                         "Multiplier > 1.0 for window {} not allowed since it is in a zone with DElight daylighting.",
     393            0 :                                                         wndo.Name));
     394            0 :                                                 ErrorsFound = true;
     395              :                                             }
     396              : 
     397              :                                             // Error if window has a shading device (blind/shade/screen) since
     398              :                                             // DElight cannot perform dynamic shading device deployment
     399            0 :                                             if (wndo.HasShadeControl) {
     400            0 :                                                 ShowSevereError(state,
     401            0 :                                                                 format("Shading Device on window {} dynamic control is not supported in a zone with "
     402              :                                                                        "DElight daylighting.",
     403            0 :                                                                        wndo.Name));
     404            0 :                                                 ErrorsFound = true;
     405              :                                             }
     406              : 
     407              :                                             // Loop through all Doppelganger Surface Names to ignore these Windows
     408            0 :                                             lWndoIsDoppelganger = false;
     409            0 :                                             for (auto const &cfs : state.dataDayltg->DElightComplexFene) {
     410              : 
     411              :                                                 // Is the current Window Surface a Doppelganger?
     412            0 :                                                 if (wndo.Name == cfs.wndwName) {
     413              :                                                     // Ignore this Doppelganger Window
     414            0 :                                                     lWndoIsDoppelganger = true;
     415              :                                                 }
     416              : 
     417              :                                             } // CFS object loop A
     418              : 
     419            0 :                                             if (!lWndoIsDoppelganger) {
     420            0 :                                                 ++iNumWindows;
     421              :                                             }
     422              : 
     423              :                                         } // Surface hosts Window test
     424              :                                     }     // Window test
     425              :                                 }         // Window loop
     426              : 
     427            0 :                                 print(delightInFile, Format_909, iNumWindows);
     428              : 
     429              :                                 // If the current opaque bounding Surface hosts Windows,
     430              :                                 // then write each hosted Window to the DElight input file
     431              :                                 // and track the Window Construction type for later writing
     432            0 :                                 if (iNumWindows > 0) {
     433            0 :                                     for (int iwndo2 = iSurfaceFirst; iwndo2 <= iSurfaceLast; ++iwndo2) {
     434            0 :                                         if (state.dataSurface->Surface(iwndo2).Class == SurfaceClass::Window) {
     435              : 
     436            0 :                                             auto &wndo2(state.dataSurface->Surface(iwndo2));
     437              : 
     438            0 :                                             if (wndo2.BaseSurfName == surf.Name) {
     439              : 
     440              :                                                 // Loop through all Doppelganger Surface Names to ignore these Windows
     441            0 :                                                 lWndoIsDoppelganger = false;
     442              : 
     443            0 :                                                 for (auto const &cfs : state.dataDayltg->DElightComplexFene) {
     444              : 
     445              :                                                     // Is the current Window Surface a Doppelganger?
     446            0 :                                                     if (wndo2.Name == cfs.wndwName) {
     447              :                                                         // Ignore this Doppelganger Window
     448            0 :                                                         lWndoIsDoppelganger = true;
     449              :                                                     }
     450              : 
     451              :                                                 } // CFS object loop A
     452              : 
     453            0 :                                                 if (!lWndoIsDoppelganger) {
     454              : 
     455              :                                                     // Track unique window construction types here for later writing to
     456              :                                                     // the library section of DElight input file
     457              : 
     458              :                                                     // Get the Construction index for this Window Surface
     459            0 :                                                     iconstruct = wndo2.Construction;
     460              : 
     461              :                                                     // Has the current Construction index been encountered before?
     462            0 :                                                     lWndoConstFound = false;
     463            0 :                                                     for (int iconst = 1; iconst <= iNumWndoConsts; ++iconst) {
     464            0 :                                                         if (iconstruct == iWndoConstIndexes(iconst)) lWndoConstFound = true;
     465              :                                                     }
     466            0 :                                                     if (!lWndoConstFound) {
     467            0 :                                                         ++iNumWndoConsts;
     468            0 :                                                         iWndoConstIndexes(iNumWndoConsts) = iconstruct;
     469              :                                                     }
     470              : 
     471              :                                                     // Write this Window to the DElight input file
     472              :                                                     // Remove any blanks from the Window Surface Name for ease of input to DElight
     473            0 :                                                     cNameWOBlanks = ReplaceBlanksWithUnderscores(wndo2.Name);
     474            0 :                                                     print(delightInFile, Format_910, cNameWOBlanks, iconstruct + 10000, wndo2.Sides);
     475              :                                                     // Use WndoConstIndex + 10000 as the Glass Type Name
     476              :                                                     // to differentiate EPlus glass types within DElight
     477              : 
     478              :                                                     // Write out the vertex coordinates for each vertex
     479            0 :                                                     for (int ivert = 1; ivert <= wndo2.Sides; ++ivert) {
     480            0 :                                                         print(delightInFile,
     481              :                                                               Format_908,
     482            0 :                                                               wndo2.Vertex(ivert).x * M2FT,
     483            0 :                                                               wndo2.Vertex(ivert).y * M2FT,
     484            0 :                                                               wndo2.Vertex(ivert).z * M2FT);
     485              :                                                     }
     486              :                                                 } //! lWndoIsDoppelganger
     487              :                                             }     // Surface hosts Window2 test
     488              :                                         }         // Window2 Class test
     489              :                                     }             // Window2 loop
     490              :                                 }                 // Hosted Windows test
     491              : 
     492              :                                 // Write the number of CFS hosted by the current Opaque Bounding Surface
     493            0 :                                 iHostedCFS = 0;
     494              : 
     495              :                                 // Loop through the input CFS objects searching for a match to the current Opaque Bounding Surface
     496            0 :                                 for (auto const &cfs : state.dataDayltg->DElightComplexFene) {
     497              : 
     498              :                                     // Does the current Opaque Bounding Surface host the current CFS object?
     499            0 :                                     if (surf.Name == cfs.surfName) {
     500              :                                         // Count this hosted CFS
     501            0 :                                         ++iHostedCFS;
     502              :                                     }
     503              :                                 } // CFS object loop 1
     504              : 
     505            0 :                                 print(delightInFile, Format_911, iHostedCFS);
     506              : 
     507              :                                 // Now write each of the hosted CFS data
     508              :                                 // Loop through the input CFS objects searching for a match to the current Opaque Bounding Surface
     509            0 :                                 for (auto const &cfs : state.dataDayltg->DElightComplexFene) {
     510              : 
     511              :                                     // Does the current Opaque Bounding Surface host the current CFS object?
     512            0 :                                     if (surf.Name == cfs.surfName) {
     513              : 
     514              :                                         // Get the Doppelganger surface for this CFS
     515            0 :                                         iDoppelganger = 0;
     516            0 :                                         for (int iwndo3 = iSurfaceFirst; iwndo3 <= iSurfaceLast; ++iwndo3) {
     517              : 
     518            0 :                                             auto const &wndo3(state.dataSurface->Surface(iwndo3));
     519              : 
     520            0 :                                             if (wndo3.Class == SurfaceClass::Window) {
     521              : 
     522              :                                                 // Is the current Window Surface the Doppelganger for the current CFS?
     523            0 :                                                 if (wndo3.Name == cfs.wndwName) {
     524              :                                                     // Store the window surface index for future reference
     525            0 :                                                     iDoppelganger = iwndo3;
     526              :                                                 }
     527              :                                             }
     528              :                                         }
     529              : 
     530              :                                         // Make sure that a valid Doppelganger surface exists
     531            0 :                                         if (iDoppelganger > 0) {
     532              : 
     533              :                                             // Write the data for this hosted CFS
     534            0 :                                             auto &doppelgangerSurf(state.dataSurface->Surface(iDoppelganger));
     535              : 
     536              :                                             // Remove any blanks from the CFS Name for ease of input to DElight
     537            0 :                                             cNameWOBlanks = ReplaceBlanksWithUnderscores(cfs.Name);
     538            0 :                                             print(
     539            0 :                                                 delightInFile, Format_915, cNameWOBlanks, cfs.ComplexFeneType, cfs.feneRota, doppelgangerSurf.Sides);
     540              : 
     541              :                                             // Write out the vertex coordinates for each vertex
     542            0 :                                             for (int ivert = 1; ivert <= doppelgangerSurf.Sides; ++ivert) {
     543            0 :                                                 print(delightInFile,
     544              :                                                       Format_908,
     545            0 :                                                       doppelgangerSurf.Vertex(ivert).x * M2FT,
     546            0 :                                                       doppelgangerSurf.Vertex(ivert).y * M2FT,
     547            0 :                                                       doppelgangerSurf.Vertex(ivert).z * M2FT);
     548              :                                             }
     549              :                                         }
     550              :                                         // Register Error if there is no valid Doppelganger for current Complex Fenestration
     551            0 :                                         if (iDoppelganger == 0) {
     552            0 :                                             ShowSevereError(state,
     553            0 :                                                             format("No Doppelganger Window Surface found for Complex Fenestration ={}", cfs.Name));
     554            0 :                                             ErrorsFound = true;
     555              :                                         }
     556              :                                     } // The current Opaque Bounding Surface hosts the current CFS object?
     557              :                                 }     // CFS object loop 2
     558              :                             }         // Opaque Bounding Surface test
     559              :                         }
     560              :                     } // Zone Surface loop
     561              : 
     562              :                     // Write ZONE REFERENCE POINTS
     563            0 :                     print(delightInFile, Format_912, znDayl.TotalDaylRefPoints);
     564              : 
     565              :                     // Loop through the Daylighting:DElight:Reference Point objects checking for the current DElight Zone host
     566            0 :                     for (auto &refPt : state.dataDayltg->DaylRefPt) {
     567              : 
     568              :                         // Is this RefPt hosted by current DElight Zone?
     569            0 :                         if (izone == refPt.ZoneNum) {
     570            0 :                             auto &thisZone = state.dataHeatBal->Zone(izone);
     571              : 
     572              :                             // Limit to maximum of 100 RefPts
     573            0 :                             if (znDayl.TotalDaylRefPoints <= 100) {
     574              : 
     575            0 :                                 if (state.dataSurface->DaylRefWorldCoordSystem) {
     576            0 :                                     RefPt_WCS_Coord = refPt.coords;
     577              :                                 } else {
     578              :                                     // Transform reference point coordinates into building coordinate system
     579            0 :                                     Xb = refPt.coords.x * CosZoneRelNorth - refPt.coords.y * SinZoneRelNorth + thisZone.OriginX;
     580            0 :                                     Yb = refPt.coords.x * SinZoneRelNorth + refPt.coords.y * CosZoneRelNorth + thisZone.OriginY;
     581              :                                     // Transform into World Coordinate System
     582            0 :                                     RefPt_WCS_Coord.x = Xb * CosBldgRelNorth - Yb * SinBldgRelNorth;
     583            0 :                                     RefPt_WCS_Coord.y = Xb * SinBldgRelNorth + Yb * CosBldgRelNorth;
     584            0 :                                     RefPt_WCS_Coord.z = refPt.coords.z + thisZone.OriginZ;
     585            0 :                                     if (ldoTransform) {         // Geometry transform
     586            0 :                                         Xo = RefPt_WCS_Coord.x; // world coordinates.... shifted by relative north angle...
     587            0 :                                         Yo = RefPt_WCS_Coord.y;
     588              :                                         // next derotate the building
     589            0 :                                         XnoRot = Xo * CosBldgRelNorth + Yo * SinBldgRelNorth;
     590            0 :                                         YnoRot = Yo * CosBldgRelNorth - Xo * SinBldgRelNorth;
     591              :                                         // translate
     592            0 :                                         Xtrans = XnoRot * std::sqrt(rnewAspectRatio / roldAspectRatio);
     593            0 :                                         Ytrans = YnoRot * std::sqrt(roldAspectRatio / rnewAspectRatio);
     594              :                                         // rerotate
     595            0 :                                         RefPt_WCS_Coord.x = Xtrans * CosBldgRelNorth - Ytrans * SinBldgRelNorth;
     596              : 
     597            0 :                                         RefPt_WCS_Coord.y = Xtrans * SinBldgRelNorth + Ytrans * CosBldgRelNorth;
     598              :                                     }
     599              :                                 }
     600            0 :                                 znDayl.refPts(refPt.indexToFracAndIllum).absCoords = RefPt_WCS_Coord;
     601              : 
     602              :                                 // Validate that Reference Point coordinates are within the host Zone
     603            0 :                                 if (RefPt_WCS_Coord.x < thisZone.MinimumX || RefPt_WCS_Coord.x > thisZone.MaximumX) {
     604            0 :                                     ShowSevereError(state,
     605            0 :                                                     format("DElightInputGenerator:Reference point X Value outside Zone Min/Max X, Zone={}", zn.Name));
     606            0 :                                     ShowContinueError(state,
     607            0 :                                                       format("...X Reference Point= {:.2R}, Zone Minimum X= {:.2R}, Zone Maximum X= {:.2R}",
     608            0 :                                                              thisZone.MinimumX,
     609              :                                                              RefPt_WCS_Coord.x,
     610            0 :                                                              thisZone.MaximumX));
     611            0 :                                     ErrorsFound = true;
     612              :                                 }
     613            0 :                                 if (RefPt_WCS_Coord.y < thisZone.MinimumY || RefPt_WCS_Coord.y > thisZone.MaximumY) {
     614            0 :                                     ShowSevereError(state,
     615            0 :                                                     format("DElightInputGenerator:Reference point Y Value outside Zone Min/Max Y, Zone={}", zn.Name));
     616            0 :                                     ShowContinueError(state,
     617            0 :                                                       format("...Y Reference Point= {:.2R}, Zone Minimum Y= {:.2R}, Zone Maximum Y= {:.2R}",
     618            0 :                                                              thisZone.MinimumY,
     619              :                                                              RefPt_WCS_Coord.y,
     620            0 :                                                              thisZone.MaximumY));
     621            0 :                                     ErrorsFound = true;
     622              :                                 }
     623            0 :                                 if (RefPt_WCS_Coord.z < state.dataHeatBal->Zone(izone).MinimumZ || RefPt_WCS_Coord.z > thisZone.MaximumZ) {
     624            0 :                                     ShowSevereError(
     625              :                                         state,
     626            0 :                                         format("DElightInputGenerator:Reference point Z Value outside Zone Min/Max Z, Zone={}", thisZone.Name));
     627            0 :                                     ShowContinueError(state,
     628            0 :                                                       format("...Z Reference Point= {:.2R}, Zone Minimum Z= {:.2R}, Zone Maximum Z= {:.2R}",
     629            0 :                                                              thisZone.MinimumZ,
     630              :                                                              RefPt_WCS_Coord.z,
     631            0 :                                                              thisZone.MaximumZ));
     632            0 :                                     ErrorsFound = true;
     633              :                                 }
     634              : 
     635              :                                 // Write this RefPt to the DElight input file
     636              : 
     637              :                                 // Remove any blanks from the RefPt Name for ease of input to DElight
     638            0 :                                 cNameWOBlanks = ReplaceBlanksWithUnderscores(refPt.Name);
     639            0 :                                 if (refPt.indexToFracAndIllum != 0) {
     640            0 :                                     print(delightInFile,
     641              :                                           Format_913,
     642              :                                           cNameWOBlanks,
     643            0 :                                           RefPt_WCS_Coord.x * M2FT,
     644            0 :                                           RefPt_WCS_Coord.y * M2FT,
     645            0 :                                           RefPt_WCS_Coord.z * M2FT,
     646            0 :                                           znDayl.refPts(refPt.indexToFracAndIllum).fracZoneDaylit,
     647            0 :                                           znDayl.refPts(refPt.indexToFracAndIllum).illumSetPoint * LUX2FC,
     648            0 :                                           znDayl.LightControlType);
     649              :                                     // RJH 2008-03-07: Set up DaylIllumAtRefPt for output for this DElight zone RefPt
     650            0 :                                     SetupOutputVariable(state,
     651              :                                                         "Daylighting Reference Point Illuminance",
     652              :                                                         Constant::Units::lux,
     653            0 :                                                         znDayl.refPts(refPt.indexToFracAndIllum).lums[(int)Lum::Illum],
     654              :                                                         OutputProcessor::TimeStepType::Zone,
     655              :                                                         OutputProcessor::StoreType::Average,
     656            0 :                                                         refPt.Name);
     657              :                                 } else {
     658            0 :                                     print(delightInFile,
     659              :                                           Format_913,
     660              :                                           cNameWOBlanks,
     661            0 :                                           RefPt_WCS_Coord.x * M2FT,
     662            0 :                                           RefPt_WCS_Coord.y * M2FT,
     663            0 :                                           RefPt_WCS_Coord.z * M2FT,
     664            0 :                                           0.0,
     665            0 :                                           0.0 * LUX2FC,
     666            0 :                                           znDayl.LightControlType); // should never happen but just in case send zero fraction and illuminance
     667              :                                 }
     668              :                             } // Max 100 RefPt test
     669              :                         }     // RefPt in current DElight Zone test
     670              :                     }         // traverse reference points loop
     671              :                 }             // if in a zone
     672              :             }                 // Zone hosts DElight object test
     673              :         }                     // traverse ZoneDayLight object loop
     674              : 
     675              :         // Write BUILDING SHADES
     676            0 :         print(delightInFile, Format_914);
     677              : 
     678              :         // Write LIBRARY DATA
     679            0 :         print(delightInFile, Format_920, iNumWndoConsts);
     680              : 
     681              :         // Write GLASS TYPES
     682              :         // VisBeamCoeffs are processed in EPlus by POLYF() function
     683              :         // Use WndoConstIndex + 10000 as the Glass Type Name to differentiate EPlus glass types within DElight
     684            0 :         for (int iconst = 1; iconst <= iNumWndoConsts; ++iconst) {
     685            0 :             print(delightInFile,
     686              :                   Format_921,
     687            0 :                   iWndoConstIndexes(iconst) + 10000,
     688            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransDiffVis,
     689            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).ReflectVisDiffBack,
     690            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[0],
     691            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[1],
     692            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[2],
     693            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[3],
     694            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[4],
     695            0 :                   state.dataConstruction->Construct(iWndoConstIndexes(iconst)).TransVisBeamCoef[5]);
     696              : 
     697              :         } // Glass Type loop
     698              : 
     699            0 :         if (ErrorsFound) ShowFatalError(state, "Problems with Daylighting:DElight input, see previous error messages");
     700            0 :     }
     701              : 
     702            0 :     void GenerateDElightDaylightCoefficients(Real64 &dLatitude, int &iErrorFlag)
     703              :     {
     704              : 
     705              :         // SUBROUTINE INFORMATION:
     706              :         //       AUTHOR         Linda Lawrie
     707              :         //       DATE WRITTEN   September 2012
     708              :         //       MODIFIED       na
     709              :         //       RE-ENGINEERED  na
     710              : 
     711              :         // PURPOSE OF THIS SUBROUTINE:
     712              :         // The purpose of this subroutine is to provide an envelop to the DElightDaylightCoefficients routine
     713              : 
     714            0 :         delightdaylightcoefficients(dLatitude, &iErrorFlag);
     715            0 :     }
     716              : 
     717            1 :     void GetInputDElightComplexFenestration(EnergyPlusData &state, bool &ErrorsFound)
     718              :     {
     719              :         // Perform GetInput function for the Daylighting:DELight:ComplexFenestration object
     720              :         // Glazer - July 2016
     721              : 
     722              :         int NumAlpha;
     723              :         int NumNumber;
     724              :         int IOStat;
     725            1 :         int CFSNum = 0;
     726              : 
     727            1 :         constexpr std::string_view cCurrentModuleObject("Daylighting:DELight:ComplexFenestration");
     728              : 
     729            1 :         int TotDElightCFS = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
     730            1 :         state.dataDayltg->DElightComplexFene.allocate(TotDElightCFS);
     731            2 :         for (auto &cfs : state.dataDayltg->DElightComplexFene) {
     732            2 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     733              :                                                                      cCurrentModuleObject,
     734              :                                                                      ++CFSNum,
     735            1 :                                                                      state.dataIPShortCut->cAlphaArgs,
     736              :                                                                      NumAlpha,
     737            1 :                                                                      state.dataIPShortCut->rNumericArgs,
     738              :                                                                      NumNumber,
     739              :                                                                      IOStat,
     740            1 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     741            1 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     742            1 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     743            1 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     744            1 :             cfs.Name = state.dataIPShortCut->cAlphaArgs(1);
     745            1 :             cfs.ComplexFeneType = state.dataIPShortCut->cAlphaArgs(2);
     746            1 :             cfs.surfName = state.dataIPShortCut->cAlphaArgs(3);
     747            1 :             if (Util::FindItemInList(cfs.surfName, state.dataSurface->Surface) == 0) {
     748            0 :                 ShowSevereError(state,
     749            0 :                                 format("{}{}",
     750              :                                        cCurrentModuleObject,
     751            0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + cfs.surfName + "\"."));
     752            0 :                 ErrorsFound = true;
     753              :             }
     754            1 :             cfs.wndwName = state.dataIPShortCut->cAlphaArgs(4);
     755            1 :             if (Util::FindItemInList(cfs.surfName, state.dataSurface->Surface) == 0) {
     756            0 :                 ShowSevereError(state,
     757            0 :                                 format("{}{}",
     758              :                                        cCurrentModuleObject,
     759            0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + cfs.wndwName + "\"."));
     760            0 :                 ErrorsFound = true;
     761              :             }
     762            1 :             cfs.feneRota = state.dataIPShortCut->rNumericArgs(1);
     763            1 :             if (cfs.feneRota < 0. || cfs.feneRota > 360.) {
     764            0 :                 ShowSevereError(state,
     765            0 :                                 format("{}{}",
     766              :                                        cCurrentModuleObject,
     767            0 :                                        ": " + cfs.Name + ", invalid " + state.dataIPShortCut->cNumericFieldNames(1) + " outside of range 0 to 360."));
     768            0 :                 ErrorsFound = true;
     769              :             }
     770              :         }
     771            1 :     }
     772              : 
     773            0 :     void CheckForGeometricTransform(EnergyPlusData &state, bool &doTransform, Real64 &OldAspectRatio, Real64 &NewAspectRatio)
     774              :     {
     775              : 
     776              :         // SUBROUTINE INFORMATION:
     777              :         //       AUTHOR         Linda Lawrie
     778              :         //       DATE WRITTEN   February 2009
     779              :         //       MODIFIED       na
     780              :         //       RE-ENGINEERED  na
     781              : 
     782              :         // PURPOSE OF THIS SUBROUTINE:
     783              :         // check for geometrytransform in the daylighting access for reference points
     784              : 
     785              :         // METHODOLOGY EMPLOYED:
     786              :         // once reference points  have been converted to WCS,
     787              :         //  change them to reflect a different aspect
     788              :         // ratio for the entire building based on user input.
     789              : 
     790              :         // SUBROUTINE PARAMETER DEFINITIONS:
     791            0 :         constexpr std::string_view CurrentModuleObject("GeometryTransform");
     792              : 
     793              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     794            0 :         Array1D_string cAlphas(1);
     795            0 :         Array1D<Real64> rNumerics(2);
     796              : 
     797              :         // begin execution
     798              :         // get user input...
     799            0 :         doTransform = false;
     800            0 :         OldAspectRatio = 1.0;
     801            0 :         NewAspectRatio = 1.0;
     802              : 
     803            0 :         if (state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject) == 1) {
     804              :             int NAlphas;
     805              :             int NNum;
     806              :             int IOStat;
     807            0 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     808              :                                                                      CurrentModuleObject,
     809              :                                                                      1,
     810              :                                                                      cAlphas,
     811              :                                                                      NAlphas,
     812              :                                                                      rNumerics,
     813              :                                                                      NNum,
     814              :                                                                      IOStat,
     815            0 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     816            0 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     817            0 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     818            0 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     819            0 :             OldAspectRatio = rNumerics(1);
     820            0 :             NewAspectRatio = rNumerics(2);
     821            0 :             if (cAlphas(1) != "XY") {
     822            0 :                 ShowWarningError(
     823              :                     state,
     824            0 :                     format("{}{}", CurrentModuleObject, ": invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + "=" + cAlphas(1) + "...ignored."));
     825              :             }
     826            0 :             doTransform = true;
     827            0 :             state.dataSurface->AspectTransform = true;
     828              :         }
     829            0 :         if (state.dataSurface->WorldCoordSystem) {
     830            0 :             doTransform = false;
     831            0 :             state.dataSurface->AspectTransform = false;
     832              :         }
     833            0 :     }
     834              : 
     835            0 :     std::string ReplaceBlanksWithUnderscores(std::string const &InputString) // Input String
     836              :     {
     837              : 
     838              :         // FUNCTION INFORMATION:
     839              :         //       AUTHOR         Robert J. Hitchcock
     840              :         //       DATE WRITTEN   August 2003
     841              : 
     842              :         // PURPOSE OF THIS SUBROUTINE:
     843              :         // This function returns a representation of the InputString with blanks replaced with underscores.
     844              : 
     845              :         // METHODOLOGY EMPLOYED:
     846              :         // Uses the std::replace function from the C++ library
     847              : 
     848              :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
     849              : 
     850            0 :         std::string ResultString(trimmed(InputString));
     851            0 :         std::replace(ResultString.begin(), ResultString.end(), ' ', '_');
     852            0 :         return ResultString;
     853              :     }
     854              : 
     855            0 :     void DElightElecLtgCtrl(int iNameLength,
     856              :                             std::string const &cZoneName,
     857              :                             Real64 dBldgLat,
     858              :                             Real64 dHISKF,
     859              :                             Real64 dHISUNF,
     860              :                             Real64 dCloudFraction,
     861              :                             Real64 dSOLCOSX,
     862              :                             Real64 dSOLCOSY,
     863              :                             Real64 dSOLCOSZ,
     864              :                             Real64 &pdPowerReducFac,
     865              :                             int piErrorFlag)
     866              :     {
     867            0 :         std::vector<char> zoneNameArr(getCharArrayFromString(cZoneName));
     868            0 :         delightelecltgctrl(
     869            0 :             iNameLength, &zoneNameArr[0], dBldgLat, dHISKF, dHISUNF, dCloudFraction, dSOLCOSX, dSOLCOSY, dSOLCOSZ, &pdPowerReducFac, &piErrorFlag);
     870            0 :     }
     871              : 
     872            0 :     std::vector<char> getCharArrayFromString(std::string const &originalString)
     873              :     {
     874            0 :         std::vector<char> returnVal(originalString.begin(), originalString.end());
     875            0 :         returnVal.push_back('\0'); // get null terminated string of chars
     876            0 :         return returnVal;
     877            0 :     }
     878              : 
     879            0 :     std::string getStringFromCharArray(std::vector<char> const &originalCharArray)
     880              :     {
     881            0 :         return std::string(originalCharArray.begin(), originalCharArray.end());
     882              :     }
     883              : 
     884              : } // namespace DElightManagerF
     885              : 
     886              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1