LCOV - code coverage report
Current view: top level - EnergyPlus - DElightManagerF.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 234 328 71.3 %
Date: 2024-08-23 23:50:59 Functions: 7 8 87.5 %

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

Generated by: LCOV version 1.14