LCOV - code coverage report
Current view: top level - EnergyPlus/PhaseChangeModeling - HysteresisModel.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 50.7 % 221 112
Test Date: 2025-06-02 07:23:51 Functions: 100.0 % 6 6

            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              : #include <ObjexxFCL/Array1D.hh>
      49              : 
      50              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      51              : #include <EnergyPlus/DataHeatBalance.hh>
      52              : #include <EnergyPlus/DataIPShortCuts.hh>
      53              : #include <EnergyPlus/EnergyPlus.hh>
      54              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      55              : #include <EnergyPlus/PhaseChangeModeling/HysteresisModel.hh>
      56              : #include <EnergyPlus/UtilityRoutines.hh>
      57              : 
      58              : namespace EnergyPlus {
      59              : 
      60              : namespace Material {
      61              : 
      62      1099700 :     Real64 MaterialPhaseChange::getEnthalpy(Real64 T, Real64 Tc, Real64 tau1, Real64 tau2) const
      63              :     {
      64              :         // Looks up the enthalpy on the characteristic curve defined by the parameters Tc, tau1, and tau2,
      65              :         // and the position on that curve defined by T.
      66      1099700 :         Real64 eta1 = (this->totalLatentHeat / 2) * exp(-2 * std::abs(T - Tc) / tau1);
      67      1099700 :         Real64 eta2 = (this->totalLatentHeat / 2) * exp(-2 * std::abs(T - Tc) / tau2);
      68      1099700 :         if (T <= Tc) {
      69       899914 :             return (this->specificHeatSolid * T) + eta1;
      70              :         } else {
      71       199786 :             return (this->specificHeatSolid * Tc) + this->totalLatentHeat + this->specificHeatLiquid * (T - Tc) - eta2;
      72              :         }
      73              :     }
      74              : 
      75       549850 :     Real64 MaterialPhaseChange::getCurrentSpecificHeat(
      76              :         Real64 prevTempTD, Real64 updatedTempTDT, Real64 phaseChangeTempReverse, Phase prevPhaseChangeState, Phase &phaseChangeState)
      77              :     {
      78              :         // Main public facing function; returns the current specific heat based on input properties, and current and previous conditions.
      79              :         // In a future version, this could be compartmentalized to track all states and histories, but it would require some further modification to
      80              :         // the HBFDManager
      81       549850 :         Real64 TempLowPCM = this->peakTempMelting - this->deltaTempMeltingLow;
      82       549850 :         Real64 TempHighPCM = this->peakTempMelting + this->deltaTempMeltingHigh;
      83              :         Real64 Tc;   // assigned later
      84              :         Real64 Tau1; // assigned later
      85              :         Real64 Tau2; // assigned later
      86       549850 :         Real64 TempLowPCF = this->peakTempFreezing - this->deltaTempFreezingLow;
      87       549850 :         Real64 TempHighPCF = this->peakTempFreezing + this->deltaTempFreezingHigh;
      88              :         Real64 Cp;
      89       549850 :         Real64 phaseChangeDeltaT = prevTempTD - updatedTempTDT;
      90              : 
      91              :         // determine phase change state and curve characteristics based on delta T direction, updated temp, and previous state
      92       549850 :         if (phaseChangeDeltaT <= 0) {
      93       169781 :             Tc = this->peakTempMelting;
      94       169781 :             Tau1 = this->deltaTempMeltingLow;
      95       169781 :             Tau2 = this->deltaTempMeltingHigh;
      96       169781 :             if (updatedTempTDT < TempLowPCM) {
      97        55442 :                 phaseChangeState = Phase::Crystallized;
      98       114339 :             } else if (updatedTempTDT <= TempHighPCM) {
      99       114339 :                 phaseChangeState = Phase::Melting;
     100       114339 :                 if (prevPhaseChangeState == Phase::Freezing || prevPhaseChangeState == Phase::Transition) {
     101         4271 :                     phaseChangeState = Phase::Transition;
     102              :                 }
     103              :             } else {
     104            0 :                 phaseChangeState = Phase::Liquid;
     105              :             }
     106              :         } else { // phaseChangeDeltaT > 0
     107       380069 :             Tc = this->peakTempFreezing;
     108       380069 :             Tau1 = this->deltaTempFreezingLow;
     109       380069 :             Tau2 = this->deltaTempFreezingHigh;
     110       380069 :             if (updatedTempTDT < TempLowPCF) {
     111       286070 :                 phaseChangeState = Phase::Crystallized;
     112        93999 :             } else if (updatedTempTDT <= TempHighPCF) {
     113        14390 :                 phaseChangeState = Phase::Freezing;
     114        14390 :                 if (prevPhaseChangeState == Phase::Melting || prevPhaseChangeState == Phase::Transition) {
     115            0 :                     phaseChangeState = Phase::Transition;
     116              :                 }
     117              :             } else {
     118        79609 :                 phaseChangeState = Phase::Liquid;
     119              :             }
     120              :         }
     121              : 
     122              :         // Why is phaseChangeTransition a state variable of the material and not the surface?
     123              :         // determine if we are transitioning or not
     124       549850 :         if (prevPhaseChangeState == Phase::Transition && phaseChangeState == Phase::Crystallized) {
     125            0 :             this->phaseChangeTransition = true;
     126       549850 :         } else if (prevPhaseChangeState == Phase::Transition && phaseChangeState == Phase::Freezing) {
     127            0 :             this->phaseChangeTransition = true;
     128              :             // this->phaseChangeState = 0; ?????
     129       549850 :         } else if (prevPhaseChangeState == Phase::Freezing && phaseChangeState == Phase::Transition) {
     130            0 :             this->phaseChangeTransition = true;
     131       549850 :         } else if (prevPhaseChangeState == Phase::Crystallized && phaseChangeState == Phase::Transition) {
     132            0 :             this->phaseChangeTransition = true;
     133              :         } else {
     134       549850 :             this->phaseChangeTransition = false;
     135              :         }
     136              : 
     137              :         // now calculate the enthalpy appropriately
     138       549850 :         if (!this->phaseChangeTransition) {
     139       549850 :             this->enthOld = this->getEnthalpy(prevTempTD, Tc, Tau1, Tau2);
     140       549850 :             this->enthNew = this->getEnthalpy(updatedTempTDT, Tc, Tau1, Tau2);
     141              :         } else {
     142            0 :             if (prevPhaseChangeState == Phase::Freezing && phaseChangeState == Phase::Transition) {
     143            0 :                 this->enthRev =
     144            0 :                     this->getEnthalpy(phaseChangeTempReverse, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     145            0 :                 this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthOld - (this->specHeatTransition * prevTempTD));
     146            0 :                 this->enthalpyM = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     147            0 :                 this->enthalpyF = this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     148            0 :                 if (this->enthNew < this->enthRev && this->enthNew >= this->enthalpyF && updatedTempTDT <= prevTempTD) {
     149            0 :                     phaseChangeState = Phase::Freezing;
     150            0 :                     this->enthNew =
     151            0 :                         this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     152            0 :                 } else if ((this->enthNew < this->enthalpyF) && (this->enthNew > this->enthalpyM)) {
     153            0 :                     phaseChangeState = Phase::Transition;
     154            0 :                     this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthOld - (this->specHeatTransition * prevTempTD));
     155            0 :                 } else if ((this->enthNew < this->enthalpyF) && (updatedTempTDT > phaseChangeTempReverse)) {
     156            0 :                     phaseChangeState = Phase::Transition;
     157            0 :                     this->enthNew =
     158            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     159            0 :                 } else if ((this->enthNew <= this->enthalpyM) && (updatedTempTDT <= phaseChangeTempReverse)) {
     160            0 :                     phaseChangeState = Phase::Transition;
     161            0 :                     this->enthNew =
     162            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     163              :                 }
     164            0 :             } else if (prevPhaseChangeState == Phase::Transition && phaseChangeState == Phase::Transition) {
     165            0 :                 if (updatedTempTDT < phaseChangeTempReverse) {
     166            0 :                     Tc = this->peakTempMelting;
     167            0 :                     Tau1 = this->deltaTempMeltingLow;
     168            0 :                     Tau2 = this->deltaTempMeltingHigh;
     169            0 :                 } else if (updatedTempTDT > phaseChangeTempReverse) {
     170            0 :                     Tc = this->peakTempFreezing;
     171            0 :                     Tau1 = this->deltaTempFreezingLow;
     172            0 :                     Tau2 = this->deltaTempFreezingHigh;
     173              :                 }
     174            0 :                 this->enthRev = this->getEnthalpy(phaseChangeTempReverse, Tc, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     175            0 :                 this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthOld - (this->specHeatTransition * prevTempTD));
     176            0 :                 this->enthalpyM = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     177            0 :                 this->enthalpyF = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     178            0 :                 if ((updatedTempTDT < phaseChangeTempReverse) && (this->enthNew > this->enthalpyF)) {
     179            0 :                     phaseChangeState = Phase::Freezing;
     180            0 :                     this->enthNew =
     181            0 :                         this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     182            0 :                 } else if ((this->enthNew < this->enthalpyF) && (this->enthNew > this->enthalpyM) &&
     183            0 :                            (updatedTempTDT < prevTempTD || updatedTempTDT > prevTempTD)) {
     184            0 :                     phaseChangeState = Phase::Transition;
     185            0 :                     this->enthNew =
     186            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     187            0 :                 } else if (this->enthNew <= this->enthalpyM && updatedTempTDT >= prevTempTD && this->enthNew > this->enthOld) {
     188            0 :                     phaseChangeState = Phase::Melting;
     189            0 :                     this->enthNew =
     190            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     191              :                 }
     192            0 :             } else if (prevPhaseChangeState == Phase::Transition && phaseChangeState == Phase::Crystallized) {
     193            0 :                 this->enthRev =
     194            0 :                     this->getEnthalpy(phaseChangeTempReverse, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     195            0 :                 this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     196            0 :                 this->enthalpyM = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     197            0 :                 this->enthalpyF = this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     198            0 :                 if ((this->enthNew < this->enthalpyF) && (this->enthNew > this->enthalpyM)) {
     199            0 :                     phaseChangeState = Phase::Transition;
     200            0 :                     this->enthNew =
     201            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     202            0 :                 } else if (this->enthNew <= this->enthalpyM && updatedTempTDT >= prevTempTD) {
     203            0 :                     phaseChangeState = Phase::Melting;
     204            0 :                     this->enthNew = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     205              :                 }
     206            0 :             } else if (prevPhaseChangeState == Phase::Melting && phaseChangeState == Phase::Transition) {
     207            0 :                 this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthOld - (this->specHeatTransition * prevTempTD));
     208            0 :                 this->enthalpyM = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     209            0 :                 this->enthalpyF = this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     210            0 :                 if ((this->enthNew < this->enthOld) && (updatedTempTDT < prevTempTD)) {
     211            0 :                     phaseChangeState = Phase::Transition;
     212            0 :                     this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthOld - (this->specHeatTransition * prevTempTD));
     213            0 :                 } else if ((this->enthNew < this->enthalpyF) && (this->enthNew > this->enthalpyM) && (updatedTempTDT < prevTempTD)) {
     214            0 :                     phaseChangeState = Phase::Transition;
     215            0 :                     this->enthNew =
     216            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     217            0 :                 } else if ((this->enthNew >= this->enthalpyF) && (updatedTempTDT <= phaseChangeTempReverse)) {
     218            0 :                     phaseChangeState = Phase::Transition;
     219            0 :                     this->enthNew =
     220            0 :                         (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     221              :                 }
     222            0 :             } else if (prevPhaseChangeState == Phase::Transition && phaseChangeState == Phase::Freezing) {
     223            0 :                 this->enthalpyM = this->getEnthalpy(updatedTempTDT, this->peakTempMelting, this->deltaTempMeltingLow, this->deltaTempMeltingHigh);
     224            0 :                 this->enthalpyF = this->getEnthalpy(updatedTempTDT, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     225            0 :                 this->enthRev =
     226            0 :                     this->getEnthalpy(phaseChangeTempReverse, this->peakTempFreezing, this->deltaTempFreezingLow, this->deltaTempFreezingHigh);
     227            0 :                 this->enthNew = (this->specHeatTransition * updatedTempTDT) + (this->enthRev - (this->specHeatTransition * phaseChangeTempReverse));
     228              :             }
     229              :         }
     230              : 
     231              :         // then calculate the specific heat and return it
     232       549850 :         if (!this->phaseChangeTransition) {
     233       549850 :             if (this->enthNew == this->enthOld) {
     234        74919 :                 Cp = this->CpOld;
     235              :             } else {
     236       474931 :                 Cp = this->specHeat(prevTempTD, updatedTempTDT, Tc, Tau1, Tau2, this->enthOld, this->enthNew);
     237              :             }
     238              :         } else {
     239            0 :             Cp = this->specHeatTransition;
     240              :         }
     241       549850 :         this->CpOld = Cp;
     242       549850 :         return Cp;
     243              :     }
     244              : 
     245       474931 :     Real64 MaterialPhaseChange::specHeat(Real64 temperaturePrev,
     246              :                                          Real64 temperatureCurrent,
     247              :                                          Real64 criticalTemperature,
     248              :                                          Real64 tau1,
     249              :                                          Real64 tau2,
     250              :                                          Real64 EnthalpyOld,
     251              :                                          Real64 EnthalpyNew) const
     252              :     {
     253              : 
     254              :         //    Tc                  ! Critical (Melting/Freezing) Temperature of PCM
     255              :         //    Tau1                ! Width of Melting Zone low
     256              :         //    Tau2                ! Width of Melting Zone high
     257              :         //    EnthalpyOld         ! Previous Timestep Nodal Enthalpy
     258              :         //    EnthalpyNew         ! Current Timestep Nodal Enthalpy
     259              : 
     260       474931 :         Real64 T = temperatureCurrent;
     261              : 
     262       474931 :         if (T < criticalTemperature) {
     263       376132 :             Real64 DEta1 = -(this->totalLatentHeat * (T - criticalTemperature) * exp(-2 * std::abs(T - criticalTemperature) / tau1)) /
     264       376132 :                            (tau1 * std::abs(T - criticalTemperature));
     265       376132 :             Real64 Cp1 = this->specificHeatSolid;
     266       376132 :             return (Cp1 + DEta1);
     267        98799 :         } else if (T == criticalTemperature) {
     268            0 :             return (EnthalpyNew - EnthalpyOld) / (temperatureCurrent - temperaturePrev);
     269              :         } else {
     270        98799 :             Real64 DEta2 = (this->totalLatentHeat * (T - criticalTemperature) * exp(-2 * std::abs(T - criticalTemperature) / tau2)) /
     271        98799 :                            (tau2 * std::abs(T - criticalTemperature));
     272        98799 :             Real64 Cp2 = this->specificHeatLiquid;
     273        98799 :             return Cp2 + DEta2;
     274              :         }
     275              :     }
     276              : 
     277      1209670 :     Real64 MaterialPhaseChange::getConductivity(Real64 T) const
     278              :     {
     279      1209670 :         if (T < this->peakTempMelting) {
     280      1154717 :             return this->fullySolidThermalConductivity;
     281        54953 :         } else if (T > this->peakTempFreezing) {
     282        54953 :             return this->fullyLiquidThermalConductivity;
     283              :         } else {
     284            0 :             return (this->fullySolidThermalConductivity + this->fullyLiquidThermalConductivity) / 2.0;
     285              :         }
     286              :     }
     287              : 
     288       549850 :     Real64 MaterialPhaseChange::getDensity(Real64 T) const
     289              :     {
     290       549850 :         if (T < this->peakTempMelting) {
     291       520422 :             return this->fullySolidDensity;
     292        29428 :         } else if (T > this->peakTempFreezing) {
     293        29428 :             return this->fullyLiquidDensity;
     294              :         } else {
     295            0 :             return (this->fullySolidDensity + this->fullyLiquidDensity) / 2.0;
     296              :         }
     297              :     }
     298              : 
     299          801 :     void GetHysteresisData(EnergyPlusData &state, bool &ErrorsFound)
     300              :     {
     301              :         static constexpr std::string_view routineName = "GetHysteresisData";
     302              : 
     303          801 :         auto &s_ipsc = state.dataIPShortCut;
     304          801 :         auto &s_ip = state.dataInputProcessing->inputProcessor;
     305          801 :         auto &s_mat = state.dataMaterial;
     306              : 
     307              :         // convenience variables
     308          801 :         s_ipsc->cCurrentModuleObject = "MaterialProperty:PhaseChangeHysteresis";
     309          801 :         int numPhaseChangeModels = s_ip->getNumObjectsFound(state, s_ipsc->cCurrentModuleObject);
     310              : 
     311              :         // loop over all hysteresis input instances, if zero, this will simply not do anything
     312          802 :         for (int hmNum = 1; hmNum <= numPhaseChangeModels; ++hmNum) {
     313              : 
     314              :             // just a few vars to pass in and out to GetObjectItem
     315              :             int ioStatus;
     316              :             int numAlphas;
     317              :             int numNumbers;
     318              : 
     319              :             // get the input data and store it in the Shortcuts structures
     320            2 :             s_ip->getObjectItem(state,
     321            1 :                                 s_ipsc->cCurrentModuleObject,
     322              :                                 hmNum,
     323            1 :                                 s_ipsc->cAlphaArgs,
     324              :                                 numAlphas,
     325            1 :                                 s_ipsc->rNumericArgs,
     326              :                                 numNumbers,
     327              :                                 ioStatus,
     328            1 :                                 s_ipsc->lNumericFieldBlanks,
     329            1 :                                 s_ipsc->lAlphaFieldBlanks,
     330            1 :                                 s_ipsc->cAlphaFieldNames,
     331            1 :                                 s_ipsc->cNumericFieldNames);
     332              : 
     333            1 :             ErrorObjectHeader eoh{routineName, s_ipsc->cCurrentModuleObject, s_ipsc->cAlphaArgs(1)};
     334              :             // the input processor validates the numeric inputs based on the IDD definition
     335              :             // still validate the name to make sure there aren't any duplicates or blanks
     336              :             // blanks are easy: fatal if blank
     337              : 
     338            1 :             if (s_ipsc->lAlphaFieldBlanks(1)) {
     339            0 :                 ShowSevereEmptyField(state, eoh, s_ipsc->cAlphaFieldNames(1), s_ipsc->cAlphaArgs(1));
     340            0 :                 ErrorsFound = true;
     341            0 :                 continue;
     342              :             }
     343              : 
     344            1 :             int matNum = GetMaterialNum(state, s_ipsc->cAlphaArgs(1));
     345            1 :             if (matNum == 0) {
     346            0 :                 ShowSevereItemNotFound(state, eoh, s_ipsc->cAlphaFieldNames(1), s_ipsc->cAlphaArgs(1));
     347            0 :                 ErrorsFound = true;
     348            0 :                 continue;
     349              :             }
     350              : 
     351            1 :             auto *mat = s_mat->materials(matNum);
     352            1 :             if (mat->group != Group::Regular) {
     353            0 :                 ShowSevereCustom(state, eoh, format("Material {} is not a Regular material.", mat->Name));
     354            0 :                 ErrorsFound = true;
     355            0 :                 continue;
     356              :             }
     357              : 
     358            1 :             if (mat->hasPCM) {
     359            0 :                 ShowSevereCustom(state, eoh, format("Material {} already has {} properties defined.", mat->Name, s_ipsc->cCurrentModuleObject));
     360            0 :                 ErrorsFound = true;
     361            0 :                 continue;
     362              :             }
     363              : 
     364            1 :             if (mat->hasEMPD) {
     365            0 :                 ShowSevereCustom(state, eoh, format("Material {} already has EMPD properties defined.", mat->Name));
     366            0 :                 ErrorsFound = true;
     367            0 :                 continue;
     368              :             }
     369              : 
     370            1 :             if (mat->hasHAMT) {
     371            0 :                 ShowSevereCustom(state, eoh, format("Material {} already has HAMT properties defined.", mat->Name));
     372            0 :                 ErrorsFound = true;
     373            0 :                 continue;
     374              :             }
     375              : 
     376              :             // Need to upgrade this object to MaterialPhaseChange
     377            1 :             auto *matPC = new MaterialPhaseChange;
     378            1 :             matPC->MaterialBase::operator=(*mat); // Deep copy the parent object
     379              : 
     380            1 :             delete mat;
     381            1 :             s_mat->materials(matNum) = matPC;
     382              : 
     383              :             // now build out a new hysteresis instance and add it to the vector
     384            1 :             matPC->totalLatentHeat = s_ipsc->rNumericArgs(1);
     385            1 :             matPC->fullyLiquidThermalConductivity = s_ipsc->rNumericArgs(2);
     386            1 :             matPC->fullyLiquidDensity = s_ipsc->rNumericArgs(3);
     387            1 :             matPC->specificHeatLiquid = s_ipsc->rNumericArgs(4);
     388            1 :             matPC->deltaTempMeltingHigh = s_ipsc->rNumericArgs(5);
     389            1 :             matPC->peakTempMelting = s_ipsc->rNumericArgs(6);
     390            1 :             matPC->deltaTempMeltingLow = s_ipsc->rNumericArgs(7);
     391            1 :             matPC->fullySolidThermalConductivity = s_ipsc->rNumericArgs(8);
     392            1 :             matPC->fullySolidDensity = s_ipsc->rNumericArgs(9);
     393            1 :             matPC->specificHeatSolid = s_ipsc->rNumericArgs(10);
     394            1 :             matPC->deltaTempFreezingHigh = s_ipsc->rNumericArgs(11);
     395            1 :             matPC->peakTempFreezing = s_ipsc->rNumericArgs(12);
     396            1 :             matPC->deltaTempFreezingLow = s_ipsc->rNumericArgs(13);
     397            1 :             matPC->specHeatTransition = (matPC->specificHeatSolid + matPC->specificHeatLiquid) / 2.0;
     398            1 :             matPC->CpOld = matPC->specificHeatSolid;
     399            1 :             matPC->hasPCM = true;
     400              :         }
     401          801 :     }
     402              : 
     403              : } // namespace Material
     404              : 
     405              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1