Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cassert>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 : #include <ObjexxFCL/numeric.hh>
55 : #include <ObjexxFCL/string.functions.hh>
56 :
57 : // EnergyPlus Headers
58 : #include <EnergyPlus/CostEstimateManager.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataEnvironment.hh>
61 : #include <EnergyPlus/DataGlobalConstants.hh>
62 : #include <EnergyPlus/DataIPShortCuts.hh>
63 : #include <EnergyPlus/DisplayRoutines.hh>
64 : #include <EnergyPlus/EconomicTariff.hh>
65 : #include <EnergyPlus/General.hh>
66 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
67 : #include <EnergyPlus/OutputProcessor.hh>
68 : #include <EnergyPlus/OutputReportPredefined.hh>
69 : #include <EnergyPlus/OutputReportTabular.hh>
70 : #include <EnergyPlus/ResultsFramework.hh>
71 : #include <EnergyPlus/SQLiteProcedures.hh>
72 : #include <EnergyPlus/ScheduleManager.hh>
73 : #include <EnergyPlus/UtilityRoutines.hh>
74 :
75 : namespace EnergyPlus::EconomicTariff {
76 :
77 : // MODULE INFORMATION:
78 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
79 : // DATE WRITTEN May 2004
80 :
81 : // Compute utility bills for a building based on energy
82 : // use estimate.
83 : using ScheduleManager::GetScheduleIndex;
84 :
85 299088 : void UpdateUtilityBills(EnergyPlusData &state)
86 : {
87 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
88 : // DATE WRITTEN September 2003
89 :
90 : // Single routine used to call all get input
91 : // routines for economics.
92 :
93 299088 : bool ErrorsFound(false);
94 :
95 299088 : if (state.dataEconTariff->Update_GetInput) {
96 769 : GetInputEconomicsTariff(state, ErrorsFound);
97 : // do rest of GetInput only if at least one tariff is defined.
98 769 : GetInputEconomicsCurrencyType(state, ErrorsFound);
99 769 : if (state.dataEconTariff->numTariff >= 1) {
100 95 : if (!ErrorsFound && state.dataOutRptTab->displayEconomicResultSummary)
101 28 : OutputReportTabular::AddTOCEntry(state, "Economics Results Summary Report", "Entire Facility");
102 95 : CreateCategoryNativeVariables(state);
103 95 : GetInputEconomicsQualify(state, ErrorsFound);
104 95 : GetInputEconomicsChargeSimple(state, ErrorsFound);
105 95 : GetInputEconomicsChargeBlock(state, ErrorsFound);
106 95 : GetInputEconomicsRatchet(state, ErrorsFound);
107 95 : GetInputEconomicsVariable(state, ErrorsFound);
108 95 : GetInputEconomicsComputation(state, ErrorsFound);
109 95 : CreateDefaultComputation(state);
110 : }
111 769 : state.dataEconTariff->Update_GetInput = false;
112 769 : if (ErrorsFound) ShowFatalError(state, "UpdateUtilityBills: Preceding errors cause termination.");
113 : }
114 299088 : if (state.dataGlobal->DoOutputReporting && (state.dataGlobal->KindOfSim == DataGlobalConstants::KindOfSim::RunPeriodWeather)) {
115 70176 : GatherForEconomics(state);
116 : }
117 299088 : }
118 :
119 : //======================================================================================================================
120 : //======================================================================================================================
121 :
122 : // GET INPUT ROUTINES
123 :
124 : //======================================================================================================================
125 : //======================================================================================================================
126 :
127 769 : void GetInputEconomicsTariff(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
128 : {
129 : // SUBROUTINE INFORMATION:
130 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
131 : // DATE WRITTEN May 2004
132 : // MODIFIED Aug. 2017, Julien Marrec of EffiBEM. Handled conversions factor based on meter resources
133 : //
134 : // PURPOSE OF THIS SUBROUTINE:
135 : // This subroutine reads the input file for "UtilityCost:Tariff" objects
136 : // It will be the right conversion factors based on the associated meter resource type
137 : // meaning if "CCF" is picked, the conversion factor isn't the same whether it's a water meter or a fuel meter.
138 :
139 : static constexpr std::string_view RoutineName("GetInputEconomicsTariff: ");
140 : int NumAlphas; // Number of elements in the alpha array
141 : int NumNums; // Number of elements in the numeric array
142 : int IOStat; // IO Status when calling get input subroutine
143 : bool isNotNumeric;
144 : // variables for getting report variable/meter index
145 : int KeyCount;
146 : OutputProcessor::VariableType TypeVar;
147 : OutputProcessor::StoreType AvgSumVar;
148 : OutputProcessor::TimeStepType StepTypeVar;
149 769 : OutputProcessor::Unit UnitsVar(OutputProcessor::Unit::None); // Units sting, may be blank
150 1538 : Array1D_string NamesOfKeys; // Specific key name
151 1538 : Array1D_int IndexesForKeyVar; // Array index
152 :
153 769 : auto &tariff(state.dataEconTariff->tariff);
154 :
155 769 : std::string_view CurrentModuleObject = "UtilityCost:Tariff";
156 769 : state.dataEconTariff->numTariff = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
157 769 : tariff.allocate(state.dataEconTariff->numTariff);
158 1057 : for (int iInObj = 1; iInObj <= state.dataEconTariff->numTariff; ++iInObj) {
159 2016 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
160 : CurrentModuleObject,
161 : iInObj,
162 288 : state.dataIPShortCut->cAlphaArgs,
163 : NumAlphas,
164 288 : state.dataIPShortCut->rNumericArgs,
165 : NumNums,
166 : IOStat,
167 288 : state.dataIPShortCut->lNumericFieldBlanks,
168 288 : state.dataIPShortCut->lAlphaFieldBlanks,
169 288 : state.dataIPShortCut->cAlphaFieldNames,
170 288 : state.dataIPShortCut->cNumericFieldNames);
171 : // check to make sure none of the values are another economic object
172 3642 : for (int jFld = 1; jFld <= NumAlphas; ++jFld) {
173 : // args are always turned to upper case but this is okay...
174 3354 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
175 0 : ShowWarningError(state, format("{}{}=\"{}\".", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
176 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
177 : }
178 : }
179 : // name of the tariff
180 288 : tariff(iInObj).tariffName = state.dataIPShortCut->cAlphaArgs(1);
181 : // check if tariff name is unique
182 288 : int found = 0;
183 681 : for (int jObj = 1; jObj <= iInObj - 1; ++jObj) {
184 393 : if (tariff(iInObj).tariffName == tariff(jObj).tariffName) {
185 0 : found = jObj;
186 0 : break;
187 : }
188 : }
189 288 : if (found > 0) {
190 0 : ShowSevereError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
191 0 : ShowContinueError(state, "...Duplicate name. Name has already been used.");
192 0 : ErrorsFound = true;
193 : }
194 : // name of the report meter
195 288 : tariff(iInObj).reportMeter = state.dataIPShortCut->cAlphaArgs(2);
196 : // call the key count function but only need count during this pass
197 288 : GetVariableKeyCountandType(state, tariff(iInObj).reportMeter, KeyCount, TypeVar, AvgSumVar, StepTypeVar, UnitsVar);
198 : // if no meters found for that name
199 288 : if (KeyCount == 0) {
200 0 : ShowWarningError(state, format("{}{}=\"{}\" missing meter", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
201 0 : ShowContinueError(state,
202 0 : format("Meter referenced is not present due to a lack of equipment that uses that energy source/meter:\"{}\".",
203 0 : tariff(iInObj).reportMeter));
204 0 : tariff(iInObj).reportMeterIndx = 0;
205 : } else {
206 288 : NamesOfKeys.allocate(KeyCount);
207 288 : IndexesForKeyVar.allocate(KeyCount);
208 288 : GetVariableKeys(state, tariff(iInObj).reportMeter, TypeVar, NamesOfKeys, IndexesForKeyVar);
209 : // although this retrieves all keys for a variable, we only need one so the first one is chosen
210 288 : if (KeyCount > 1) {
211 0 : ShowWarningError(state, format("{}{}=\"{}\" multiple keys", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
212 0 : ShowContinueError(state, "... Multiple keys for variable select. First key will be used.");
213 : }
214 : // assign the index
215 288 : tariff(iInObj).reportMeterIndx = IndexesForKeyVar(1);
216 : // get rid of the arrays used to get the variable number
217 288 : NamesOfKeys.deallocate();
218 288 : IndexesForKeyVar.deallocate();
219 : }
220 :
221 : // Start by checking what type of meter we do have, some units can be used for several resources with different conversion factors
222 : // Explicitly assume it's not a water meter nor an electric meter nor a gas meter (was already done in constructor though)
223 288 : tariff(iInObj).kindWaterMtr = kindMeterNotWater;
224 288 : tariff(iInObj).kindElectricMtr = kindMeterNotElectric;
225 288 : tariff(iInObj).kindGasMtr = kindMeterNotGas;
226 :
227 : // Determine whether this meter is related to electricity, or water, or gas
228 288 : if (tariff(iInObj).reportMeterIndx != 0) {
229 :
230 : std::string const &SELECT_CASE_var(
231 576 : UtilityRoutines::MakeUPPERCase(state.dataOutputProcessor->EnergyMeters(tariff(iInObj).reportMeterIndx).ResourceType));
232 :
233 : // Various types of electricity meters
234 288 : if (SELECT_CASE_var == "ELECTRICITY") {
235 187 : tariff(iInObj).kindElectricMtr = kindMeterElecSimple;
236 101 : } else if (SELECT_CASE_var == "ELECTRICITYPRODUCED") {
237 0 : tariff(iInObj).kindElectricMtr = kindMeterElecProduced;
238 101 : } else if (SELECT_CASE_var == "ELECTRICITYPURCHASED") {
239 11 : tariff(iInObj).kindElectricMtr = kindMeterElecPurchased;
240 90 : } else if (SELECT_CASE_var == "ELECTRICITYSURPLUSSOLD") {
241 1 : tariff(iInObj).kindElectricMtr = kindMeterElecSurplusSold;
242 89 : } else if (SELECT_CASE_var == "ELECTRICITYNET") {
243 5 : tariff(iInObj).kindElectricMtr = kindMeterElecNet;
244 :
245 : // Handle the case where its a water meter
246 334 : } else if (SELECT_CASE_var == "WATER" || SELECT_CASE_var == "H2O" || SELECT_CASE_var == "ONSITEWATER" ||
247 249 : SELECT_CASE_var == "WATERPRODUCED" || SELECT_CASE_var == "ONSITE WATER" || SELECT_CASE_var == "MAINSWATER" ||
248 249 : SELECT_CASE_var == "WATERSUPPLY" || SELECT_CASE_var == "RAINWATER" || SELECT_CASE_var == "PRECIPITATION" ||
249 250 : SELECT_CASE_var == "WELLWATER" || SELECT_CASE_var == "GROUNDWATER" || SELECT_CASE_var == "CONDENSATE") {
250 1 : tariff(iInObj).kindWaterMtr = kindMeterWater;
251 : // Or a Natural Gas meter
252 83 : } else if (SELECT_CASE_var == "GAS" || SELECT_CASE_var == "NATURALGAS") {
253 83 : tariff(iInObj).kindGasMtr = kindMeterGas;
254 : }
255 : }
256 :
257 : // Assign the right conversion factors based on the resource type
258 :
259 : // If it's a water meter
260 : // We set demandConv to something analogous to m3/h
261 288 : if (tariff(iInObj).kindWaterMtr == kindMeterWater) {
262 : // conversion factor
263 1 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "USERDEFINED")) {
264 1 : tariff(iInObj).convChoice = EconConv::USERDEF;
265 1 : tariff(iInObj).energyConv = state.dataIPShortCut->rNumericArgs(1); // energy conversion factor
266 1 : tariff(iInObj).demandConv = state.dataIPShortCut->rNumericArgs(2); // demand conversion factor
267 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "M3")) {
268 0 : tariff(iInObj).convChoice = EconConv::M3;
269 0 : tariff(iInObj).energyConv = 1.0;
270 0 : tariff(iInObj).demandConv = 3600.0;
271 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "CCF")) {
272 0 : tariff(iInObj).convChoice = EconConv::CCF;
273 0 : tariff(iInObj).energyConv = 0.35314666721488586;
274 0 : tariff(iInObj).demandConv = 0.35314666721488586 * 3600;
275 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "GAL")) {
276 0 : tariff(iInObj).convChoice = EconConv::GAL;
277 0 : tariff(iInObj).energyConv = 264.1720523602524;
278 0 : tariff(iInObj).demandConv = 264.1720523602524 * 3600;
279 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KGAL")) {
280 0 : tariff(iInObj).convChoice = EconConv::KGAL;
281 0 : tariff(iInObj).energyConv = 0.2641720523602524;
282 0 : tariff(iInObj).demandConv = 0.2641720523602524 * 3600;
283 : } else {
284 : // ERROR: not a valid conversion, default to M3
285 0 : tariff(iInObj).convChoice = EconConv::M3;
286 0 : tariff(iInObj).energyConv = 1.0;
287 0 : tariff(iInObj).demandConv = 3600.0;
288 0 : ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
289 0 : ShowContinueError(state,
290 0 : format("{}=\"{}\", Defaulting to m^3 (Water resource detected).",
291 0 : state.dataIPShortCut->cAlphaFieldNames(3),
292 0 : state.dataIPShortCut->cAlphaArgs(3)));
293 : }
294 :
295 : // If it's an electric meter
296 : // Volumetric units such as MCF or CCF doesn't make sense IMHO (JM)
297 : // THERM is strange for an electric meter but currently I accept but issue a warning
298 287 : } else if (tariff(iInObj).kindElectricMtr != kindMeterNotElectric) {
299 204 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "USERDEFINED")) {
300 0 : tariff(iInObj).convChoice = EconConv::USERDEF;
301 0 : tariff(iInObj).energyConv = state.dataIPShortCut->rNumericArgs(1); // energy conversion factor
302 0 : tariff(iInObj).demandConv = state.dataIPShortCut->rNumericArgs(2); // demand conversion factor
303 204 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KWH")) {
304 204 : tariff(iInObj).convChoice = EconConv::KWH;
305 204 : tariff(iInObj).energyConv = 0.0000002778;
306 204 : tariff(iInObj).demandConv = 0.001;
307 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MJ")) {
308 0 : tariff(iInObj).convChoice = EconConv::MJ;
309 0 : tariff(iInObj).energyConv = 0.000001;
310 0 : tariff(iInObj).demandConv = 0.0036;
311 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MMBTU")) {
312 0 : tariff(iInObj).convChoice = EconConv::MMBTU;
313 0 : tariff(iInObj).energyConv = 9.4781712e-10;
314 0 : tariff(iInObj).demandConv = 0.000003412;
315 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KBTU")) {
316 0 : tariff(iInObj).convChoice = EconConv::KBTU;
317 0 : tariff(iInObj).energyConv = 9.4781712e-7;
318 0 : tariff(iInObj).demandConv = 0.003412;
319 :
320 : // We accept the following choices, but issue a warning
321 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "THERM")) {
322 0 : tariff(iInObj).convChoice = EconConv::THERM;
323 0 : tariff(iInObj).energyConv = 9.4781712e-9;
324 0 : tariff(iInObj).demandConv = 0.00003412;
325 0 : ShowWarningError(
326 0 : state, format("{}{}=\"{}\" potentially invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
327 0 : ShowContinueError(state,
328 0 : format("{}=\"{}\", Therm is an unusual choice for an electric resource.",
329 0 : state.dataIPShortCut->cAlphaFieldNames(3),
330 0 : state.dataIPShortCut->cAlphaArgs(3)));
331 :
332 : // Otherwise, default to kWh
333 : } else {
334 0 : tariff(iInObj).convChoice = EconConv::KWH;
335 0 : tariff(iInObj).energyConv = 0.0000002778;
336 0 : tariff(iInObj).demandConv = 0.001;
337 0 : ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
338 0 : ShowContinueError(state,
339 0 : format("{}=\"{}\", Defaulting to kWh (Electric resource detected)",
340 0 : state.dataIPShortCut->cAlphaFieldNames(3),
341 0 : state.dataIPShortCut->cAlphaArgs(3)));
342 : }
343 :
344 : // If it's a gas meter
345 83 : } else if (tariff(iInObj).kindGasMtr == kindMeterGas) {
346 83 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "USERDEFINED")) {
347 0 : tariff(iInObj).convChoice = EconConv::USERDEF;
348 0 : tariff(iInObj).energyConv = state.dataIPShortCut->rNumericArgs(1); // energy conversion factor
349 0 : tariff(iInObj).demandConv = state.dataIPShortCut->rNumericArgs(2); // demand conversion factor
350 83 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KWH")) {
351 0 : tariff(iInObj).convChoice = EconConv::KWH;
352 0 : tariff(iInObj).energyConv = 0.0000002778;
353 0 : tariff(iInObj).demandConv = 0.001;
354 83 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "THERM")) {
355 1 : tariff(iInObj).convChoice = EconConv::THERM;
356 1 : tariff(iInObj).energyConv = 9.4781712e-9;
357 1 : tariff(iInObj).demandConv = 0.00003412;
358 82 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MMBTU")) {
359 0 : tariff(iInObj).convChoice = EconConv::MMBTU;
360 0 : tariff(iInObj).energyConv = 9.4781712e-10;
361 0 : tariff(iInObj).demandConv = 0.000003412;
362 82 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MJ")) {
363 0 : tariff(iInObj).convChoice = EconConv::MJ;
364 0 : tariff(iInObj).energyConv = 0.000001;
365 0 : tariff(iInObj).demandConv = 0.0036;
366 82 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KBTU")) {
367 0 : tariff(iInObj).convChoice = EconConv::KBTU;
368 0 : tariff(iInObj).energyConv = 9.4781712e-7;
369 0 : tariff(iInObj).demandConv = 0.003412;
370 :
371 : // Volumetric units for natural gas
372 : // Actually assuming 1 therm = 1 CCF (= 100 ft^3)
373 82 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MCF")) {
374 82 : tariff(iInObj).convChoice = EconConv::MCF;
375 82 : tariff(iInObj).energyConv = 9.4781712e-10;
376 82 : tariff(iInObj).demandConv = 0.000003412;
377 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "CCF")) {
378 0 : tariff(iInObj).convChoice = EconConv::CCF;
379 0 : tariff(iInObj).energyConv = 9.4781712e-9;
380 0 : tariff(iInObj).demandConv = 0.00003412;
381 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "M3")) {
382 : // Obtained from converting CCF above to m^3 so the same heat content of natural gas is used (1 therm = 1 CCF)
383 0 : tariff(iInObj).convChoice = EconConv::M3;
384 0 : tariff(iInObj).energyConv = 2.6839192e-10;
385 0 : tariff(iInObj).demandConv = 9.6617081E-05;
386 :
387 : // Otherwise, default to kWh
388 : } else {
389 0 : tariff(iInObj).convChoice = EconConv::KWH;
390 0 : tariff(iInObj).energyConv = 0.0000002778;
391 0 : tariff(iInObj).demandConv = 0.001;
392 0 : ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
393 0 : ShowContinueError(
394 0 : state, format("{}=\"{}\", Defaulting to kWh.", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
395 : }
396 :
397 : // It it's neither an electric, water or gas meter, we cannot accept volumetric units
398 : // because we cannot infer the heat content
399 : } else {
400 0 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "USERDEFINED")) {
401 0 : tariff(iInObj).convChoice = EconConv::USERDEF;
402 0 : tariff(iInObj).energyConv = state.dataIPShortCut->rNumericArgs(1); // energy conversion factor
403 0 : tariff(iInObj).demandConv = state.dataIPShortCut->rNumericArgs(2); // demand conversion factor
404 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KWH")) {
405 0 : tariff(iInObj).convChoice = EconConv::KWH;
406 0 : tariff(iInObj).energyConv = 0.0000002778;
407 0 : tariff(iInObj).demandConv = 0.001;
408 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "THERM")) {
409 0 : tariff(iInObj).convChoice = EconConv::THERM;
410 0 : tariff(iInObj).energyConv = 9.4781712e-9;
411 0 : tariff(iInObj).demandConv = 0.00003412;
412 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MMBTU")) {
413 0 : tariff(iInObj).convChoice = EconConv::MMBTU;
414 0 : tariff(iInObj).energyConv = 9.4781712e-10;
415 0 : tariff(iInObj).demandConv = 0.000003412;
416 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "MJ")) {
417 0 : tariff(iInObj).convChoice = EconConv::MJ;
418 0 : tariff(iInObj).energyConv = 0.000001;
419 0 : tariff(iInObj).demandConv = 0.0036;
420 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "KBTU")) {
421 0 : tariff(iInObj).convChoice = EconConv::KBTU;
422 0 : tariff(iInObj).energyConv = 9.4781712e-7;
423 0 : tariff(iInObj).demandConv = 0.003412;
424 :
425 : // Otherwise, default to kWh
426 : } else {
427 0 : tariff(iInObj).convChoice = EconConv::KWH;
428 0 : tariff(iInObj).energyConv = 0.0000002778;
429 0 : tariff(iInObj).demandConv = 0.001;
430 0 : ShowWarningError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
431 0 : ShowContinueError(
432 0 : state, format("{}=\"{}\", Defaulting to kWh.", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
433 : }
434 : } // Default conversion factors have been applied from here on
435 :
436 : // schedules
437 : // period schedule
438 288 : if (len(state.dataIPShortCut->cAlphaArgs(4)) > 0) {
439 15 : tariff(iInObj).periodSchedule = state.dataIPShortCut->cAlphaArgs(4); // name of the period schedule (time of day)
440 15 : tariff(iInObj).periodSchIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(4)); // index to the period schedule
441 15 : if (tariff(iInObj).periodSchIndex == 0) {
442 0 : ShowSevereError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
443 0 : ShowContinueError(state,
444 0 : format(" not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(4), state.dataIPShortCut->cAlphaArgs(4)));
445 0 : ErrorsFound = true;
446 : }
447 : } else {
448 273 : tariff(iInObj).periodSchIndex = 0; // flag value for no schedule used
449 : }
450 : // season schedule
451 288 : if (len(state.dataIPShortCut->cAlphaArgs(5)) > 0) {
452 29 : tariff(iInObj).seasonSchedule = state.dataIPShortCut->cAlphaArgs(5); // name of the season schedule (winter/summer)
453 29 : tariff(iInObj).seasonSchIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(5)); // index to the season schedule
454 29 : if (tariff(iInObj).seasonSchIndex == 0) {
455 0 : ShowSevereError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
456 0 : ShowContinueError(state,
457 0 : format(" not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(5), state.dataIPShortCut->cAlphaArgs(5)));
458 0 : ErrorsFound = true;
459 : }
460 : } else {
461 259 : tariff(iInObj).seasonSchIndex = 0; // flag value for no schedule used
462 : }
463 : // month schedule
464 288 : if (len(state.dataIPShortCut->cAlphaArgs(6)) > 0) {
465 0 : tariff(iInObj).monthSchedule = state.dataIPShortCut->cAlphaArgs(6); // name of month schedule (when months end)
466 0 : tariff(iInObj).monthSchIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(6)); // index to the month schedule
467 0 : if (tariff(iInObj).monthSchIndex == 0) {
468 0 : ShowSevereError(state, format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
469 0 : ShowContinueError(state,
470 0 : format(" not found {}=\"{}\".", state.dataIPShortCut->cAlphaFieldNames(6), state.dataIPShortCut->cAlphaArgs(6)));
471 0 : ErrorsFound = true;
472 : }
473 : } else {
474 288 : tariff(iInObj).monthSchIndex = 0; // flag value for no schedule used
475 : }
476 : // type of demand window
477 288 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "QuarterHour")) {
478 : // check to make sure that the demand window and the TIMESTEP IN HOUR are consistant.
479 : {
480 1 : auto const SELECT_CASE_var(state.dataGlobal->NumOfTimeStepInHour);
481 1 : if ((SELECT_CASE_var == 1) || (SELECT_CASE_var == 3) || (SELECT_CASE_var == 5) || (SELECT_CASE_var == 15)) {
482 0 : tariff(iInObj).demandWindow = DemandWindow::Hour;
483 0 : tariff(iInObj).demWinTime = 1.00;
484 0 : ShowWarningError(state,
485 0 : format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
486 0 : ShowContinueError(state,
487 0 : format("Demand window of QuarterHour is not consistent with number of timesteps per hour [{}].",
488 0 : state.dataGlobal->NumOfTimeStepInHour));
489 0 : ShowContinueError(state, "Demand window will be set to FullHour, and the simulation continues.");
490 1 : } else if ((SELECT_CASE_var == 2) || (SELECT_CASE_var == 6) || (SELECT_CASE_var == 10) || (SELECT_CASE_var == 30)) {
491 0 : tariff(iInObj).demandWindow = DemandWindow::Half;
492 0 : tariff(iInObj).demWinTime = 0.50;
493 0 : ShowWarningError(state,
494 0 : format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
495 0 : ShowContinueError(state,
496 0 : format("Demand window of QuarterHour is not consistent with number of timesteps per hour [{}].",
497 0 : state.dataGlobal->NumOfTimeStepInHour));
498 0 : ShowContinueError(state, "Demand window will be set to HalfHour, and the simulation continues.");
499 1 : } else if ((SELECT_CASE_var == 4) || (SELECT_CASE_var == 12) || (SELECT_CASE_var == 20) || (SELECT_CASE_var == 60)) {
500 1 : tariff(iInObj).demandWindow = DemandWindow::Quarter;
501 1 : tariff(iInObj).demWinTime = 0.25;
502 : }
503 : }
504 287 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "HalfHour")) {
505 : {
506 104 : auto const SELECT_CASE_var(state.dataGlobal->NumOfTimeStepInHour);
507 104 : if ((SELECT_CASE_var == 1) || (SELECT_CASE_var == 3) || (SELECT_CASE_var == 5) || (SELECT_CASE_var == 15)) {
508 0 : tariff(iInObj).demandWindow = DemandWindow::Hour;
509 0 : tariff(iInObj).demWinTime = 1.00;
510 0 : ShowWarningError(state,
511 0 : format("{}{}=\"{}\" invalid data", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
512 0 : ShowContinueError(state,
513 0 : format("Demand window of HalfHour is not consistent with number of timesteps per hour [{}].",
514 0 : state.dataGlobal->NumOfTimeStepInHour));
515 0 : ShowContinueError(state, "Demand window will be set to FullHour, and the simulation continues.");
516 104 : } else if ((SELECT_CASE_var == 2) || (SELECT_CASE_var == 4) || (SELECT_CASE_var == 6) || (SELECT_CASE_var == 10) ||
517 0 : (SELECT_CASE_var == 12) || (SELECT_CASE_var == 20) || (SELECT_CASE_var == 30) || (SELECT_CASE_var == 60)) {
518 104 : tariff(iInObj).demandWindow = DemandWindow::Half;
519 104 : tariff(iInObj).demWinTime = 0.50;
520 : }
521 : }
522 183 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "FullHour")) {
523 0 : tariff(iInObj).demandWindow = DemandWindow::Hour;
524 0 : tariff(iInObj).demWinTime = 1.00;
525 183 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "Day")) {
526 0 : tariff(iInObj).demandWindow = DemandWindow::Day;
527 0 : tariff(iInObj).demWinTime = 24.00;
528 183 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "Week")) {
529 0 : tariff(iInObj).demandWindow = DemandWindow::Week;
530 0 : tariff(iInObj).demWinTime = 24.0 * 7.0;
531 : } else {
532 : // if not entered default to the same logic as quarter of an hour
533 : {
534 183 : auto const SELECT_CASE_var(state.dataGlobal->NumOfTimeStepInHour);
535 183 : if ((SELECT_CASE_var == 1) || (SELECT_CASE_var == 3) || (SELECT_CASE_var == 5) || (SELECT_CASE_var == 15)) {
536 0 : tariff(iInObj).demandWindow = DemandWindow::Hour;
537 0 : tariff(iInObj).demWinTime = 1.00;
538 183 : } else if ((SELECT_CASE_var == 2) || (SELECT_CASE_var == 6) || (SELECT_CASE_var == 10) || (SELECT_CASE_var == 30)) {
539 116 : tariff(iInObj).demandWindow = DemandWindow::Half;
540 116 : tariff(iInObj).demWinTime = 0.50;
541 67 : } else if ((SELECT_CASE_var == 4) || (SELECT_CASE_var == 12) || (SELECT_CASE_var == 20) || (SELECT_CASE_var == 60)) {
542 67 : tariff(iInObj).demandWindow = DemandWindow::Quarter;
543 67 : tariff(iInObj).demWinTime = 0.25;
544 : }
545 : }
546 : }
547 : // monthly charge
548 288 : tariff(iInObj).monthChgVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(8), isNotNumeric);
549 288 : tariff(iInObj).monthChgPt =
550 288 : AssignVariablePt(state, state.dataIPShortCut->cAlphaArgs(8), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
551 : // minimum monthly charge
552 288 : if (len(state.dataIPShortCut->cAlphaArgs(9)) > 0) {
553 2 : tariff(iInObj).minMonthChgVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(9), isNotNumeric);
554 : } else {
555 286 : tariff(iInObj).minMonthChgVal = -HUGE_(-1.0); // set to a very negative value
556 : }
557 288 : tariff(iInObj).minMonthChgPt =
558 288 : AssignVariablePt(state, state.dataIPShortCut->cAlphaArgs(9), isNotNumeric, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, iInObj);
559 : // real time pricing
560 288 : tariff(iInObj).chargeSchedule = state.dataIPShortCut->cAlphaArgs(10);
561 288 : tariff(iInObj).chargeSchIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(10));
562 288 : tariff(iInObj).baseUseSchedule = state.dataIPShortCut->cAlphaArgs(11);
563 288 : tariff(iInObj).baseUseSchIndex = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(11));
564 : // group name for separate distribution and transmission rates
565 288 : tariff(iInObj).groupName = state.dataIPShortCut->cAlphaArgs(12);
566 : // buy or sell option
567 288 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(13), "BuyFromUtility")) {
568 1 : tariff(iInObj).buyOrSell = buyFromUtility;
569 287 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(13), "SellToUtility")) {
570 1 : tariff(iInObj).buyOrSell = sellToUtility;
571 286 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(13), "NetMetering")) {
572 1 : tariff(iInObj).buyOrSell = netMetering;
573 : } else {
574 285 : tariff(iInObj).buyOrSell = buyFromUtility;
575 : }
576 : // check if meter is consistent with buy or sell option
577 577 : if ((tariff(iInObj).buyOrSell == sellToUtility) &&
578 289 : (!UtilityRoutines::SameString(tariff(iInObj).reportMeter, "ELECTRICITYSURPLUSSOLD:FACILITY"))) {
579 0 : ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
580 0 : ShowContinueError(state,
581 0 : format("The meter chosen \"{}\" is not typically used with the sellToUtility option.", tariff(iInObj).reportMeter));
582 0 : ShowContinueError(state, "Usually the ElectricitySurplusSold:Facility meter is selected when the sellToUtility option is used.");
583 : }
584 288 : if ((tariff(iInObj).buyOrSell == netMetering) && (!UtilityRoutines::SameString(tariff(iInObj).reportMeter, "ELECTRICITYNET:FACILITY"))) {
585 0 : ShowWarningError(state, format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
586 0 : ShowContinueError(state,
587 0 : format("The meter chosen \"{}\" is not typically used with the netMetering option.", tariff(iInObj).reportMeter));
588 0 : ShowContinueError(state, "Usually the ElectricityNet:Facility meter is selected when the netMetering option is used.");
589 : }
590 : // also test the buy option for electricity
591 288 : if (tariff(iInObj).buyOrSell == buyFromUtility) {
592 286 : if (hasi(tariff(iInObj).reportMeter, "Elec")) { // test if electric meter
593 419 : if (!(UtilityRoutines::SameString(tariff(iInObj).reportMeter, "Electricity:Facility") ||
594 217 : UtilityRoutines::SameString(tariff(iInObj).reportMeter, "ElectricityPurchased:Facility"))) {
595 12 : ShowWarningError(state,
596 8 : format("{}{}=\"{}\" atypical meter", RoutineName, CurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
597 12 : ShowContinueError(
598 8 : state, format("The meter chosen \"{}\" is not typically used with the buyFromUtility option.", tariff(iInObj).reportMeter));
599 4 : ShowContinueError(state,
600 : "Usually the Electricity:Facility meter or the ElectricityPurchased:Facility is selected when the "
601 : "buyFromUtility option is used.");
602 : }
603 : }
604 : }
605 : // initialize gathering arrays
606 288 : tariff(iInObj).seasonForMonth = 0;
607 288 : tariff(iInObj).gatherEnergy = 0.0;
608 288 : tariff(iInObj).gatherDemand = 0.0;
609 : // assume that the tariff is qualified
610 288 : tariff(iInObj).isQualified = true;
611 288 : tariff(iInObj).ptDisqualifier = 0;
612 : // assume that the tariff is not selected
613 288 : tariff(iInObj).isSelected = false;
614 288 : tariff(iInObj).totalAnnualCost = 0.0;
615 : // now create the Table Of Contents entries for an HTML file
616 288 : if (state.dataOutRptTab->displayTariffReport) {
617 85 : OutputReportTabular::AddTOCEntry(state, "Tariff Report", tariff(iInObj).tariffName);
618 : }
619 : // associate the resource number with each tariff
620 288 : if (tariff(iInObj).reportMeterIndx >= 1) {
621 288 : tariff(iInObj).resourceNum =
622 288 : DataGlobalConstants::AssignResourceTypeNum(state.dataOutputProcessor->EnergyMeters(tariff(iInObj).reportMeterIndx).ResourceType);
623 : }
624 : }
625 769 : }
626 :
627 95 : void GetInputEconomicsQualify(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
628 : {
629 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
630 : // DATE WRITTEN May 2004
631 :
632 : // Read the input file for "Economics:Qualify" objects.
633 :
634 : static constexpr std::string_view RoutineName("GetInputEconomicsQualify: ");
635 : int iInObj; // loop index variable for reading in objects
636 : int NumAlphas; // Number of elements in the alpha array
637 : int NumNums; // Number of elements in the numeric array
638 : int IOStat; // IO Status when calling get input subroutine
639 : bool isNotNumeric;
640 : int jFld;
641 190 : std::string CurrentModuleObject; // for ease in renaming.
642 :
643 95 : auto &qualify(state.dataEconTariff->qualify);
644 :
645 95 : CurrentModuleObject = "UtilityCost:Qualify";
646 95 : state.dataEconTariff->numQualify = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
647 95 : qualify.allocate(state.dataEconTariff->numQualify);
648 304 : for (iInObj = 1; iInObj <= state.dataEconTariff->numQualify; ++iInObj) {
649 1463 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
650 : CurrentModuleObject,
651 : iInObj,
652 209 : state.dataIPShortCut->cAlphaArgs,
653 : NumAlphas,
654 209 : state.dataIPShortCut->rNumericArgs,
655 : NumNums,
656 : IOStat,
657 209 : state.dataIPShortCut->lNumericFieldBlanks,
658 209 : state.dataIPShortCut->lAlphaFieldBlanks,
659 209 : state.dataIPShortCut->cAlphaFieldNames,
660 209 : state.dataIPShortCut->cNumericFieldNames);
661 : // check to make sure none of the values are another economic object
662 1672 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
663 1463 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
664 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
665 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
666 : }
667 : }
668 : // index of the tariff name in the tariff array
669 209 : qualify(iInObj).tariffIndx =
670 209 : FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
671 209 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), qualify(iInObj).tariffIndx, ErrorsFound, CurrentModuleObject);
672 418 : qualify(iInObj).namePt = AssignVariablePt(
673 418 : state, state.dataIPShortCut->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::Qualify, iInObj, qualify(iInObj).tariffIndx);
674 : // index of the variable in the variable array
675 418 : qualify(iInObj).sourcePt = AssignVariablePt(
676 418 : state, state.dataIPShortCut->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, qualify(iInObj).tariffIndx);
677 : // indicator if maximum test otherwise minimum
678 209 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "Minimum")) {
679 105 : qualify(iInObj).isMaximum = false;
680 104 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(4), "Maximum")) {
681 104 : qualify(iInObj).isMaximum = true;
682 : } else {
683 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data");
684 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
685 0 : ErrorsFound = true;
686 0 : qualify(iInObj).isMaximum = true;
687 : }
688 : // value of the threshold
689 209 : qualify(iInObj).thresholdVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(5), isNotNumeric);
690 418 : qualify(iInObj).thresholdPt = AssignVariablePt(state,
691 209 : state.dataIPShortCut->cAlphaArgs(5),
692 : isNotNumeric,
693 : varIsArgument,
694 : varNotYetDefined,
695 : ObjType::Invalid,
696 : 0,
697 209 : qualify(iInObj).tariffIndx);
698 : // enumerated list of the kind of season
699 209 : qualify(iInObj).season = LookUpSeason(state, state.dataIPShortCut->cAlphaArgs(6), state.dataIPShortCut->cAlphaArgs(1));
700 : // indicator if consecutive months otherwise count
701 209 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "Count")) {
702 209 : qualify(iInObj).isConsecutive = false;
703 0 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(7), "Consecutive")) {
704 0 : qualify(iInObj).isConsecutive = true;
705 : } else {
706 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data");
707 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(5) + "=\"" + state.dataIPShortCut->cAlphaArgs(5) + "\".");
708 0 : ErrorsFound = true;
709 0 : qualify(iInObj).isConsecutive = true;
710 : }
711 : // number of months the test must be good for
712 209 : qualify(iInObj).numberOfMonths = state.dataIPShortCut->rNumericArgs(1);
713 : }
714 95 : }
715 :
716 95 : void GetInputEconomicsChargeSimple(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
717 : {
718 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
719 : // DATE WRITTEN May 2004
720 :
721 : // Read the input file for "Economics:Charge:Simple" objects.
722 :
723 : static constexpr std::string_view RoutineName("GetInputEconomicsChargeSimple: ");
724 : int iInObj; // loop index variable for reading in objects
725 : int NumAlphas; // Number of elements in the alpha array
726 : int NumNums; // Number of elements in the numeric array
727 : int IOStat; // IO Status when calling get input subroutine
728 : bool isNotNumeric;
729 : int jFld;
730 190 : std::string CurrentModuleObject; // for ease in renaming.
731 :
732 95 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
733 95 : auto &tariff(state.dataEconTariff->tariff);
734 :
735 95 : CurrentModuleObject = "UtilityCost:Charge:Simple";
736 95 : state.dataEconTariff->numChargeSimple = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
737 95 : chargeSimple.allocate(state.dataEconTariff->numChargeSimple);
738 1648 : for (iInObj = 1; iInObj <= state.dataEconTariff->numChargeSimple; ++iInObj) {
739 10871 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
740 : CurrentModuleObject,
741 : iInObj,
742 1553 : state.dataIPShortCut->cAlphaArgs,
743 : NumAlphas,
744 1553 : state.dataIPShortCut->rNumericArgs,
745 : NumNums,
746 : IOStat,
747 1553 : state.dataIPShortCut->lNumericFieldBlanks,
748 1553 : state.dataIPShortCut->lAlphaFieldBlanks,
749 1553 : state.dataIPShortCut->cAlphaFieldNames,
750 1553 : state.dataIPShortCut->cNumericFieldNames);
751 : // check to make sure none of the values are another economic object
752 10871 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
753 9318 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
754 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
755 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
756 : }
757 : }
758 : // index of the tariff name in the tariff array
759 1553 : chargeSimple(iInObj).tariffIndx =
760 1553 : FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
761 1553 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), chargeSimple(iInObj).tariffIndx, ErrorsFound, CurrentModuleObject);
762 3106 : chargeSimple(iInObj).namePt = AssignVariablePt(state,
763 1553 : state.dataIPShortCut->cAlphaArgs(1),
764 : true,
765 : varIsAssigned,
766 : varNotYetDefined,
767 : ObjType::ChargeSimple,
768 : iInObj,
769 1553 : chargeSimple(iInObj).tariffIndx);
770 : // index of the variable in the variable array
771 3106 : chargeSimple(iInObj).sourcePt = AssignVariablePt(
772 3106 : state, state.dataIPShortCut->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeSimple(iInObj).tariffIndx);
773 : // enumerated list of the kind of season
774 1553 : chargeSimple(iInObj).season = LookUpSeason(state, state.dataIPShortCut->cAlphaArgs(4), state.dataIPShortCut->cAlphaArgs(1));
775 : // check to make sure a seasonal schedule is specified if the season is not annual
776 1553 : if (chargeSimple(iInObj).season != seasonAnnual) {
777 143 : if (chargeSimple(iInObj).tariffIndx != 0) {
778 143 : if (tariff(chargeSimple(iInObj).tariffIndx).seasonSchIndex == 0) {
779 0 : ShowWarningError(
780 0 : state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data");
781 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
782 0 : ShowContinueError(state,
783 : " a Season other than Annual is used but no Season Schedule Name is specified in the UtilityCost:Tariff.");
784 : }
785 : }
786 : }
787 : // index of the category in the variable array
788 3106 : chargeSimple(iInObj).categoryPt = AssignVariablePt(state,
789 1553 : state.dataIPShortCut->cAlphaArgs(5),
790 : true,
791 : varIsAssigned,
792 : varNotYetDefined,
793 : ObjType::Category,
794 : iInObj,
795 1553 : chargeSimple(iInObj).tariffIndx);
796 : // cost per unit value or variable
797 1553 : chargeSimple(iInObj).costPerVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(6), isNotNumeric);
798 3106 : chargeSimple(iInObj).costPerPt = AssignVariablePt(state,
799 1553 : state.dataIPShortCut->cAlphaArgs(6),
800 : isNotNumeric,
801 : varIsArgument,
802 : varNotYetDefined,
803 : ObjType::Invalid,
804 : 0,
805 1553 : chargeSimple(iInObj).tariffIndx);
806 : }
807 95 : }
808 :
809 95 : void GetInputEconomicsChargeBlock(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
810 : {
811 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
812 : // DATE WRITTEN May 2004
813 :
814 : // Read the input file for "Economics:Charge:Block" objects.
815 :
816 : static constexpr std::string_view RoutineName("GetInputEconomicsChargeBlock: ");
817 : int iInObj; // loop index variable for reading in objects
818 : int NumAlphas; // Number of elements in the alpha array
819 : int NumNums; // Number of elements in the numeric array
820 : int IOStat; // IO Status when calling get input subroutine
821 : bool isNotNumeric;
822 : int jBlk; // loop index for blocks
823 : int alphaOffset; // offset used in blocks for alpha array
824 95 : Real64 hugeNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
825 : int jFld;
826 190 : std::string CurrentModuleObject; // for ease in renaming.
827 :
828 95 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
829 95 : auto &tariff(state.dataEconTariff->tariff);
830 :
831 95 : CurrentModuleObject = "UtilityCost:Charge:Block";
832 95 : hugeNumber = HUGE_(hugeNumber);
833 95 : state.dataEconTariff->numChargeBlock = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
834 95 : chargeBlock.allocate(state.dataEconTariff->numChargeBlock);
835 365 : for (iInObj = 1; iInObj <= state.dataEconTariff->numChargeBlock; ++iInObj) {
836 1890 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
837 : CurrentModuleObject,
838 : iInObj,
839 270 : state.dataIPShortCut->cAlphaArgs,
840 : NumAlphas,
841 270 : state.dataIPShortCut->rNumericArgs,
842 : NumNums,
843 : IOStat,
844 270 : state.dataIPShortCut->lNumericFieldBlanks,
845 270 : state.dataIPShortCut->lAlphaFieldBlanks,
846 270 : state.dataIPShortCut->cAlphaFieldNames,
847 270 : state.dataIPShortCut->cNumericFieldNames);
848 : // check to make sure none of the values are another economic object
849 3964 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
850 3694 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
851 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
852 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
853 : }
854 : }
855 : // index of the tariff name in the tariff array
856 270 : chargeBlock(iInObj).tariffIndx =
857 270 : FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
858 270 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), chargeBlock(iInObj).tariffIndx, ErrorsFound, CurrentModuleObject);
859 540 : chargeBlock(iInObj).namePt = AssignVariablePt(state,
860 270 : state.dataIPShortCut->cAlphaArgs(1),
861 : true,
862 : varIsAssigned,
863 : varNotYetDefined,
864 : ObjType::ChargeBlock,
865 : iInObj,
866 270 : chargeBlock(iInObj).tariffIndx);
867 : // index of the variable in the variable array
868 540 : chargeBlock(iInObj).sourcePt = AssignVariablePt(
869 540 : state, state.dataIPShortCut->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, chargeBlock(iInObj).tariffIndx);
870 : // enumerated list of the kind of season
871 270 : chargeBlock(iInObj).season = LookUpSeason(state, state.dataIPShortCut->cAlphaArgs(4), state.dataIPShortCut->cAlphaArgs(1));
872 : // check to make sure a seasonal schedule is specified if the season is not annual
873 270 : if (chargeBlock(iInObj).season != seasonAnnual) {
874 24 : if (chargeBlock(iInObj).tariffIndx != 0) {
875 24 : if (tariff(chargeBlock(iInObj).tariffIndx).seasonSchIndex == 0) {
876 0 : ShowWarningError(
877 0 : state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data");
878 0 : ShowContinueError(state, state.dataIPShortCut->cAlphaFieldNames(4) + "=\"" + state.dataIPShortCut->cAlphaArgs(4) + "\".");
879 0 : ShowContinueError(state,
880 : " a Season other than Annual is used but no Season Schedule Name is specified in the UtilityCost:Tariff.");
881 : }
882 : }
883 : }
884 : // index of the category in the variable array
885 540 : chargeBlock(iInObj).categoryPt = AssignVariablePt(state,
886 270 : state.dataIPShortCut->cAlphaArgs(5),
887 : true,
888 : varIsAssigned,
889 : varNotYetDefined,
890 : ObjType::Category,
891 : iInObj,
892 270 : chargeBlock(iInObj).tariffIndx);
893 : // index of the remaining into variable in the variable array
894 540 : chargeBlock(iInObj).remainingPt = AssignVariablePt(state,
895 270 : state.dataIPShortCut->cAlphaArgs(6),
896 : true,
897 : varIsAssigned,
898 : varNotYetDefined,
899 : ObjType::Category,
900 : iInObj,
901 270 : chargeBlock(iInObj).tariffIndx);
902 : // block size multiplier
903 270 : if (len(state.dataIPShortCut->cAlphaArgs(7)) == 0) { // if blank
904 182 : chargeBlock(iInObj).blkSzMultVal = 1.0; // default is 1 if left blank
905 182 : chargeBlock(iInObj).blkSzMultPt = 0;
906 : } else {
907 88 : chargeBlock(iInObj).blkSzMultVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(7), isNotNumeric);
908 176 : chargeBlock(iInObj).blkSzMultPt = AssignVariablePt(state,
909 88 : state.dataIPShortCut->cAlphaArgs(7),
910 : isNotNumeric,
911 : varIsArgument,
912 : varNotYetDefined,
913 : ObjType::Invalid,
914 : 0,
915 88 : chargeBlock(iInObj).tariffIndx);
916 : }
917 : // number of blocks used
918 270 : chargeBlock(iInObj).numBlk = (NumAlphas - 7) / 2;
919 1172 : for (jBlk = 1; jBlk <= chargeBlock(iInObj).numBlk; ++jBlk) {
920 902 : alphaOffset = 7 + (jBlk - 1) * 2;
921 : // catch the "remaining" code word for the block size
922 902 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(alphaOffset + 1), "REMAINING")) {
923 269 : chargeBlock(iInObj).blkSzVal(jBlk) = hugeNumber / 1000000; // using small portion of largest possible value to prevent overflow
924 269 : chargeBlock(iInObj).blkSzPt(jBlk) = 0;
925 : } else {
926 : // array of block size
927 633 : chargeBlock(iInObj).blkSzVal(jBlk) = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(alphaOffset + 1), isNotNumeric);
928 :
929 1266 : chargeBlock(iInObj).blkSzPt(jBlk) = AssignVariablePt(state,
930 633 : state.dataIPShortCut->cAlphaArgs(alphaOffset + 1),
931 : isNotNumeric,
932 : varIsArgument,
933 : varNotYetDefined,
934 : ObjType::Invalid,
935 : 0,
936 633 : chargeBlock(iInObj).tariffIndx);
937 : }
938 : // array of block cost
939 902 : chargeBlock(iInObj).blkCostVal(jBlk) = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(alphaOffset + 2), isNotNumeric);
940 1804 : chargeBlock(iInObj).blkCostPt(jBlk) = AssignVariablePt(state,
941 902 : state.dataIPShortCut->cAlphaArgs(alphaOffset + 2),
942 : isNotNumeric,
943 : varIsArgument,
944 : varNotYetDefined,
945 : ObjType::Invalid,
946 : 0,
947 902 : chargeBlock(iInObj).tariffIndx);
948 : }
949 : }
950 95 : }
951 :
952 95 : void GetInputEconomicsRatchet(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
953 : {
954 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
955 : // DATE WRITTEN May 2004
956 :
957 : // Read the input file for "Economics:Ratchet" objects.
958 :
959 : static constexpr std::string_view RoutineName("GetInputEconomicsRatchet: ");
960 : int iInObj; // loop index variable for reading in objects
961 : int NumAlphas; // Number of elements in the alpha array
962 : int NumNums; // Number of elements in the numeric array
963 : int IOStat; // IO Status when calling get input subroutine
964 : bool isNotNumeric;
965 : int jFld;
966 190 : std::string CurrentModuleObject; // for ease in renaming.
967 :
968 95 : auto &ratchet(state.dataEconTariff->ratchet);
969 :
970 95 : CurrentModuleObject = "UtilityCost:Ratchet";
971 95 : state.dataEconTariff->numRatchet = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
972 95 : ratchet.allocate(state.dataEconTariff->numRatchet);
973 96 : for (iInObj = 1; iInObj <= state.dataEconTariff->numRatchet; ++iInObj) {
974 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
975 : CurrentModuleObject,
976 : iInObj,
977 1 : state.dataIPShortCut->cAlphaArgs,
978 : NumAlphas,
979 1 : state.dataIPShortCut->rNumericArgs,
980 : NumNums,
981 : IOStat,
982 1 : state.dataIPShortCut->lNumericFieldBlanks,
983 1 : state.dataIPShortCut->lAlphaFieldBlanks,
984 1 : state.dataIPShortCut->cAlphaFieldNames,
985 1 : state.dataIPShortCut->cNumericFieldNames);
986 : // check to make sure none of the values are another economic object
987 9 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
988 8 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
989 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
990 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
991 : }
992 : }
993 : // index of the tariff name in the tariff array
994 1 : ratchet(iInObj).tariffIndx =
995 1 : FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
996 1 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), ratchet(iInObj).tariffIndx, ErrorsFound, CurrentModuleObject);
997 2 : ratchet(iInObj).namePt = AssignVariablePt(
998 2 : state, state.dataIPShortCut->cAlphaArgs(1), true, varIsAssigned, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet(iInObj).tariffIndx);
999 : // index of the variable in the variable array
1000 2 : ratchet(iInObj).baselinePt = AssignVariablePt(
1001 2 : state, state.dataIPShortCut->cAlphaArgs(3), true, varIsArgument, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet(iInObj).tariffIndx);
1002 : // index of the variable in the variable array
1003 2 : ratchet(iInObj).adjustmentPt = AssignVariablePt(
1004 2 : state, state.dataIPShortCut->cAlphaArgs(4), true, varIsArgument, varNotYetDefined, ObjType::Ratchet, iInObj, ratchet(iInObj).tariffIndx);
1005 : // seasons to and from
1006 1 : ratchet(iInObj).seasonFrom = LookUpSeason(state, state.dataIPShortCut->cAlphaArgs(5), state.dataIPShortCut->cAlphaArgs(1));
1007 1 : ratchet(iInObj).seasonTo = LookUpSeason(state, state.dataIPShortCut->cAlphaArgs(6), state.dataIPShortCut->cAlphaArgs(1));
1008 : // ratchet multiplier
1009 1 : ratchet(iInObj).multiplierVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(7), isNotNumeric);
1010 2 : ratchet(iInObj).multiplierPt = AssignVariablePt(state,
1011 1 : state.dataIPShortCut->cAlphaArgs(7),
1012 : isNotNumeric,
1013 : varIsArgument,
1014 : varNotYetDefined,
1015 : ObjType::Invalid,
1016 : 0,
1017 1 : ratchet(iInObj).tariffIndx);
1018 : // ratchet offset
1019 1 : ratchet(iInObj).offsetVal = UtilityRoutines::ProcessNumber(state.dataIPShortCut->cAlphaArgs(8), isNotNumeric);
1020 2 : ratchet(iInObj).offsetPt = AssignVariablePt(state,
1021 1 : state.dataIPShortCut->cAlphaArgs(8),
1022 : isNotNumeric,
1023 : varIsArgument,
1024 : varNotYetDefined,
1025 : ObjType::Invalid,
1026 : 0,
1027 1 : ratchet(iInObj).tariffIndx);
1028 : }
1029 95 : }
1030 :
1031 95 : void GetInputEconomicsVariable(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
1032 : {
1033 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1034 : // DATE WRITTEN May 2004
1035 :
1036 : // Read the input file for "Economics:Variable" objects.
1037 :
1038 : static constexpr std::string_view RoutineName("GetInputEconomicsVariable: ");
1039 :
1040 : int numEconVarObj;
1041 : int tariffPt;
1042 : int iInObj; // loop index variable for reading in objects
1043 : int NumAlphas; // Number of elements in the alpha array
1044 : int NumNums; // Number of elements in the numeric array
1045 : int IOStat; // IO Status when calling get input subroutine
1046 : int jVal;
1047 : int variablePt;
1048 : int jFld;
1049 190 : std::string CurrentModuleObject; // for ease in renaming.
1050 :
1051 95 : auto &econVar(state.dataEconTariff->econVar);
1052 :
1053 95 : CurrentModuleObject = "UtilityCost:Variable";
1054 95 : numEconVarObj = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
1055 178 : for (iInObj = 1; iInObj <= numEconVarObj; ++iInObj) {
1056 581 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1057 : CurrentModuleObject,
1058 : iInObj,
1059 83 : state.dataIPShortCut->cAlphaArgs,
1060 : NumAlphas,
1061 83 : state.dataIPShortCut->rNumericArgs,
1062 : NumNums,
1063 : IOStat,
1064 83 : state.dataIPShortCut->lNumericFieldBlanks,
1065 83 : state.dataIPShortCut->lAlphaFieldBlanks,
1066 83 : state.dataIPShortCut->cAlphaFieldNames,
1067 83 : state.dataIPShortCut->cNumericFieldNames);
1068 : // check to make sure none of the values are another economic object
1069 332 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
1070 249 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
1071 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
1072 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
1073 : }
1074 : }
1075 83 : tariffPt = FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
1076 83 : variablePt =
1077 83 : AssignVariablePt(state, state.dataIPShortCut->cAlphaArgs(1), true, varIsArgument, varUserDefined, ObjType::Variable, iInObj, tariffPt);
1078 83 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), tariffPt, ErrorsFound, CurrentModuleObject);
1079 : // validate the kind of variable - not used internally except for validation
1080 83 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "ENERGY")) {
1081 0 : econVar(variablePt).varUnitType = varUnitTypeEnergy;
1082 83 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "DEMAND")) {
1083 0 : econVar(variablePt).varUnitType = varUnitTypeDemand;
1084 83 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "DIMENSIONLESS")) {
1085 0 : econVar(variablePt).varUnitType = varUnitTypeDimensionless;
1086 83 : } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(3), "CURRENCY")) {
1087 83 : econVar(variablePt).varUnitType = varUnitTypeCurrency;
1088 : } else {
1089 0 : econVar(variablePt).varUnitType = varUnitTypeDimensionless;
1090 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data");
1091 0 : ShowContinueError(state, "invalid " + state.dataIPShortCut->cAlphaFieldNames(3) + "=\"" + state.dataIPShortCut->cAlphaArgs(3) + "\".");
1092 0 : ErrorsFound = true;
1093 : }
1094 : // move number inputs into econVar
1095 1079 : for (jVal = 1; jVal <= NumNums; ++jVal) {
1096 996 : econVar(variablePt).values(jVal) = state.dataIPShortCut->rNumericArgs(jVal);
1097 : }
1098 : // fill the rest of the array with the last value entered
1099 83 : if (NumNums < MaxNumMonths) {
1100 0 : for (jVal = NumNums + 1; jVal <= MaxNumMonths; ++jVal) {
1101 0 : econVar(variablePt).values(jVal) = state.dataIPShortCut->rNumericArgs(NumNums);
1102 : }
1103 : }
1104 : }
1105 95 : }
1106 :
1107 95 : void GetInputEconomicsComputation(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
1108 : {
1109 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1110 : // DATE WRITTEN May 2004
1111 :
1112 : // Read the input file for "Economics:Computation" objects.
1113 : // This object is only used for very complex rates.
1114 :
1115 : static constexpr std::string_view RoutineName("GetInputEconomicsComputation: ");
1116 :
1117 : int tariffPt;
1118 : int iInObj; // loop index variable for reading in objects
1119 : int NumAlphas; // Number of elements in the alpha array
1120 : int NumNums; // Number of elements in the numeric array
1121 : int IOStat; // IO Status when calling get input subroutine
1122 : int jLine;
1123 : int jFld;
1124 190 : std::string CurrentModuleObject; // for ease in renaming.
1125 :
1126 95 : auto &computation(state.dataEconTariff->computation);
1127 :
1128 95 : CurrentModuleObject = "UtilityCost:Computation";
1129 95 : state.dataEconTariff->numComputation = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
1130 95 : computation.allocate(state.dataEconTariff->numTariff); // not the number of Computations but the number of tariffs
1131 : // set default values for computation
1132 383 : for (auto &e : computation) {
1133 288 : e.computeName.clear();
1134 288 : e.firstStep = 0;
1135 288 : e.lastStep = -1;
1136 288 : e.isUserDef = false;
1137 : }
1138 96 : for (iInObj = 1; iInObj <= state.dataEconTariff->numComputation; ++iInObj) {
1139 7 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1140 : CurrentModuleObject,
1141 : iInObj,
1142 1 : state.dataIPShortCut->cAlphaArgs,
1143 : NumAlphas,
1144 1 : state.dataIPShortCut->rNumericArgs,
1145 : NumNums,
1146 : IOStat,
1147 1 : state.dataIPShortCut->lNumericFieldBlanks,
1148 1 : state.dataIPShortCut->lAlphaFieldBlanks,
1149 1 : state.dataIPShortCut->cAlphaFieldNames,
1150 1 : state.dataIPShortCut->cNumericFieldNames);
1151 : // check to make sure none of the values are another economic object
1152 9 : for (jFld = 1; jFld <= NumAlphas; ++jFld) {
1153 8 : if (hasi(state.dataIPShortCut->cAlphaArgs(jFld), "UtilityCost:")) {
1154 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\".");
1155 0 : ShowContinueError(state, "... a field was found containing UtilityCost: which may indicate a missing comma.");
1156 : }
1157 : }
1158 1 : tariffPt = FindTariffIndex(state, state.dataIPShortCut->cAlphaArgs(2), state.dataIPShortCut->cAlphaArgs(1), ErrorsFound, CurrentModuleObject);
1159 1 : warnIfNativeVarname(state, state.dataIPShortCut->cAlphaArgs(1), tariffPt, ErrorsFound, CurrentModuleObject);
1160 : // tariff and computation share the same index, the tariff index
1161 : // so all references are to the tariffPt
1162 1 : if (isWithinRange(state, tariffPt, 1, state.dataEconTariff->numTariff)) {
1163 1 : computation(tariffPt).computeName = state.dataIPShortCut->cAlphaArgs(1);
1164 1 : computation(tariffPt).firstStep = state.dataEconTariff->numSteps + 1;
1165 7 : for (jLine = 3; jLine <= NumAlphas; ++jLine) {
1166 6 : parseComputeLine(state, state.dataIPShortCut->cAlphaArgs(jLine), tariffPt);
1167 : }
1168 1 : computation(tariffPt).lastStep = state.dataEconTariff->numSteps;
1169 : // check to make sure that some steps were defined
1170 1 : if (computation(tariffPt).firstStep >= computation(tariffPt).lastStep) {
1171 0 : computation(tariffPt).firstStep = 0;
1172 0 : computation(tariffPt).lastStep = -1;
1173 0 : computation(tariffPt).isUserDef = false;
1174 0 : ShowSevereError(state,
1175 0 : std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data.");
1176 0 : ShowContinueError(state, "... No lines in the computation can be interpreted ");
1177 0 : ErrorsFound = true;
1178 : } else {
1179 1 : computation(tariffPt).isUserDef = true;
1180 : }
1181 : } else {
1182 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data.");
1183 0 : ShowContinueError(state,
1184 0 : "... not found " + state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\".");
1185 0 : ErrorsFound = true;
1186 : }
1187 : }
1188 95 : }
1189 :
1190 769 : void GetInputEconomicsCurrencyType(EnergyPlusData &state, bool &ErrorsFound) // true if errors found during getting input objects.
1191 : {
1192 : // AUTHOR Jason Glazer
1193 : // DATE WRITTEN August 2008
1194 :
1195 : // Sets the type of currency (U.S. Dollar, Euro, Yen, etc.. )
1196 : // This is a "unique" object.
1197 :
1198 1538 : std::string const CurrentModuleObject("CurrencyType");
1199 : static constexpr std::string_view RoutineName("GetInputEconomicsCurrencyType: ");
1200 :
1201 : int NumCurrencyType;
1202 : int NumAlphas; // Number of elements in the alpha array
1203 : int NumNums; // Number of elements in the numeric array
1204 : int IOStat; // IO Status when calling get input subroutine
1205 : int i;
1206 :
1207 769 : initializeMonetaryUnit(state);
1208 769 : NumCurrencyType = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
1209 769 : state.dataCostEstimateManager->selectedMonetaryUnit = 0; // invalid
1210 769 : if (NumCurrencyType == 0) {
1211 767 : state.dataCostEstimateManager->selectedMonetaryUnit = 1; // USD - U.S. Dollar
1212 2 : } else if (NumCurrencyType == 1) {
1213 14 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
1214 : CurrentModuleObject,
1215 : 1,
1216 2 : state.dataIPShortCut->cAlphaArgs,
1217 : NumAlphas,
1218 2 : state.dataIPShortCut->rNumericArgs,
1219 : NumNums,
1220 : IOStat,
1221 2 : state.dataIPShortCut->lNumericFieldBlanks,
1222 2 : state.dataIPShortCut->lAlphaFieldBlanks,
1223 2 : state.dataIPShortCut->cAlphaFieldNames,
1224 2 : state.dataIPShortCut->cNumericFieldNames);
1225 : // Monetary Unit
1226 2 : for (i = 1; i <= (int)state.dataCostEstimateManager->monetaryUnit.size(); ++i) {
1227 2 : if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(1), state.dataCostEstimateManager->monetaryUnit(i).code)) {
1228 2 : state.dataCostEstimateManager->selectedMonetaryUnit = i;
1229 2 : break;
1230 : }
1231 : }
1232 2 : if (state.dataCostEstimateManager->selectedMonetaryUnit == 0) {
1233 0 : ShowSevereError(state, std::string{RoutineName} + CurrentModuleObject + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\" invalid data.");
1234 0 : ShowContinueError(state, "... invalid " + state.dataIPShortCut->cAlphaFieldNames(1) + '.');
1235 0 : ErrorsFound = true;
1236 : }
1237 0 : } else if (NumCurrencyType > 1) {
1238 0 : ShowWarningError(state, std::string{RoutineName} + CurrentModuleObject + " Only one instance of this object is allowed. USD will be used.");
1239 0 : state.dataCostEstimateManager->selectedMonetaryUnit = 1; // USD - U.S. Dollar
1240 : }
1241 769 : }
1242 :
1243 6 : void parseComputeLine(EnergyPlusData &state, std::string const &lineOfCompute, int const fromTariff)
1244 : {
1245 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1246 : // DATE WRITTEN June 2004
1247 :
1248 : // Converts a single line in the ECONOMICS:COMPUTE
1249 : // command into tokens for computation
1250 :
1251 : // Scan the line from the end of the line to the front of the
1252 : // line and search for operators and variables. All items
1253 : // are put into the step array.
1254 :
1255 12 : std::string word;
1256 : std::string::size_type endOfWord;
1257 : int token;
1258 :
1259 6 : endOfWord = len(lineOfCompute) - 1;
1260 58 : while (endOfWord != std::string::npos) {
1261 : // get a single word (text string delimited by spaces)
1262 26 : GetLastWord(lineOfCompute, endOfWord, word);
1263 : // first see if word is an operator
1264 26 : token = lookupOperator(word);
1265 : // if not an operator then look for
1266 26 : if (token == 0) {
1267 : // see if argument or assignment (assignment will be first string on line)
1268 20 : if (endOfWord != std::string::npos) {
1269 14 : token = AssignVariablePt(state, word, true, varIsArgument, varNotYetDefined, ObjType::Invalid, 0, fromTariff);
1270 : } else {
1271 6 : token = AssignVariablePt(state, word, true, varIsAssigned, varNotYetDefined, ObjType::AssignCompute, 0, fromTariff);
1272 : }
1273 : }
1274 : // if a token is found then put it into step array
1275 26 : if (token == 0) {
1276 0 : ShowWarningError(state, "In UtilityCost:Computation line: " + lineOfCompute);
1277 0 : ShowContinueError(state, " Do not recognize: " + word + " Will skip.");
1278 : } else {
1279 26 : incrementSteps(state);
1280 26 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = token;
1281 : }
1282 : }
1283 6 : incrementSteps(state);
1284 6 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = 0; // at the end of the line show a zero to clear the stack
1285 6 : }
1286 :
1287 26 : void GetLastWord(std::string const &lineOfText, std::string::size_type &endOfScan, std::string &aWord)
1288 : {
1289 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1290 : // DATE WRITTEN June 2004
1291 :
1292 : // Returns the last substring of the line of text to the
1293 : // left of the endOfSubStrg pointer. A substring is
1294 : // delimitted by spaces. Quotes are not significant
1295 : // (they are treated just like any other non-space character)
1296 :
1297 : // Scan the string from the end.
1298 :
1299 : bool isInWord;
1300 : bool isSpace;
1301 : std::string::size_type iString;
1302 : std::string::size_type curEndOfScan;
1303 : std::string::size_type beginOfWord;
1304 : std::string::size_type endOfWord;
1305 :
1306 26 : curEndOfScan = endOfScan;
1307 26 : if (curEndOfScan != std::string::npos) {
1308 26 : if (curEndOfScan >= len(lineOfText)) {
1309 0 : curEndOfScan = len(lineOfText) - 1;
1310 : }
1311 : // check if currently on a space or not
1312 26 : if (lineOfText[curEndOfScan] == ' ') {
1313 20 : isInWord = false;
1314 20 : beginOfWord = 0;
1315 20 : endOfWord = 0;
1316 : } else {
1317 6 : isInWord = true;
1318 6 : beginOfWord = curEndOfScan;
1319 6 : endOfWord = curEndOfScan;
1320 : }
1321 : // scan backwards from
1322 274 : for (iString = curEndOfScan; iString <= curEndOfScan; --iString) { // Unsigned will wrap to npos after 0
1323 268 : if (lineOfText[iString] == ' ') {
1324 40 : isSpace = true;
1325 : } else {
1326 228 : isSpace = false;
1327 : }
1328 : // all logical conditions of isSpace and isInWord
1329 268 : if (isSpace) {
1330 40 : if (isInWord) {
1331 : // found the space in front of the word
1332 20 : break;
1333 : } else {
1334 : // still have not found the back of the word
1335 : // do nothing
1336 : }
1337 : } else {
1338 228 : if (isInWord) {
1339 : // still have not found the space in front of the word
1340 208 : beginOfWord = iString;
1341 : } else {
1342 : // found the last character of the word
1343 20 : endOfWord = iString;
1344 20 : beginOfWord = iString;
1345 20 : isInWord = true;
1346 : }
1347 : }
1348 : }
1349 26 : aWord = lineOfText.substr(beginOfWord, endOfWord - beginOfWord + 1);
1350 26 : endOfScan = beginOfWord - 1;
1351 26 : if (endOfScan == std::string::npos) {
1352 6 : endOfScan = std::string::npos;
1353 : }
1354 : } else {
1355 0 : endOfScan = std::string::npos;
1356 0 : aWord = "";
1357 : }
1358 26 : }
1359 :
1360 769 : void initializeMonetaryUnit(EnergyPlusData &state)
1361 : {
1362 : // AUTHOR Jason Glazer
1363 : // DATE WRITTEN August 2008
1364 :
1365 : // Sets the type of monetary unit array.
1366 :
1367 : // Uses get input structure similar to other objects
1368 : // The monetaryUnitSymbols.xls spreadsheet helps create the code for this routine
1369 :
1370 : // www.xe.com/symbols.php
1371 :
1372 769 : int numMonetaryUnit = 111;
1373 769 : state.dataCostEstimateManager->monetaryUnit.allocate(numMonetaryUnit);
1374 769 : state.dataCostEstimateManager->monetaryUnit(1).code = "USD";
1375 769 : state.dataCostEstimateManager->monetaryUnit(2).code = "AFN";
1376 769 : state.dataCostEstimateManager->monetaryUnit(3).code = "ALL";
1377 769 : state.dataCostEstimateManager->monetaryUnit(4).code = "ANG";
1378 769 : state.dataCostEstimateManager->monetaryUnit(5).code = "ARS";
1379 769 : state.dataCostEstimateManager->monetaryUnit(6).code = "AUD";
1380 769 : state.dataCostEstimateManager->monetaryUnit(7).code = "AWG";
1381 769 : state.dataCostEstimateManager->monetaryUnit(8).code = "AZN";
1382 769 : state.dataCostEstimateManager->monetaryUnit(9).code = "BAM";
1383 769 : state.dataCostEstimateManager->monetaryUnit(10).code = "BBD";
1384 769 : state.dataCostEstimateManager->monetaryUnit(11).code = "BGN";
1385 769 : state.dataCostEstimateManager->monetaryUnit(12).code = "BMD";
1386 769 : state.dataCostEstimateManager->monetaryUnit(13).code = "BND";
1387 769 : state.dataCostEstimateManager->monetaryUnit(14).code = "BOB";
1388 769 : state.dataCostEstimateManager->monetaryUnit(15).code = "BRL";
1389 769 : state.dataCostEstimateManager->monetaryUnit(16).code = "BSD";
1390 769 : state.dataCostEstimateManager->monetaryUnit(17).code = "BWP";
1391 769 : state.dataCostEstimateManager->monetaryUnit(18).code = "BYR";
1392 769 : state.dataCostEstimateManager->monetaryUnit(19).code = "BZD";
1393 769 : state.dataCostEstimateManager->monetaryUnit(20).code = "CAD";
1394 769 : state.dataCostEstimateManager->monetaryUnit(21).code = "CHF";
1395 769 : state.dataCostEstimateManager->monetaryUnit(22).code = "CLP";
1396 769 : state.dataCostEstimateManager->monetaryUnit(23).code = "CNY";
1397 769 : state.dataCostEstimateManager->monetaryUnit(24).code = "COP";
1398 769 : state.dataCostEstimateManager->monetaryUnit(25).code = "CRC";
1399 769 : state.dataCostEstimateManager->monetaryUnit(26).code = "CUP";
1400 769 : state.dataCostEstimateManager->monetaryUnit(27).code = "CZK";
1401 769 : state.dataCostEstimateManager->monetaryUnit(28).code = "DKK";
1402 769 : state.dataCostEstimateManager->monetaryUnit(29).code = "DOP";
1403 769 : state.dataCostEstimateManager->monetaryUnit(30).code = "EEK";
1404 769 : state.dataCostEstimateManager->monetaryUnit(31).code = "EGP";
1405 769 : state.dataCostEstimateManager->monetaryUnit(32).code = "EUR";
1406 769 : state.dataCostEstimateManager->monetaryUnit(33).code = "FJD";
1407 769 : state.dataCostEstimateManager->monetaryUnit(34).code = "GBP";
1408 769 : state.dataCostEstimateManager->monetaryUnit(35).code = "GHC";
1409 769 : state.dataCostEstimateManager->monetaryUnit(36).code = "GIP";
1410 769 : state.dataCostEstimateManager->monetaryUnit(37).code = "GTQ";
1411 769 : state.dataCostEstimateManager->monetaryUnit(38).code = "GYD";
1412 769 : state.dataCostEstimateManager->monetaryUnit(39).code = "HKD";
1413 769 : state.dataCostEstimateManager->monetaryUnit(40).code = "HNL";
1414 769 : state.dataCostEstimateManager->monetaryUnit(41).code = "HRK";
1415 769 : state.dataCostEstimateManager->monetaryUnit(42).code = "HUF";
1416 769 : state.dataCostEstimateManager->monetaryUnit(43).code = "IDR";
1417 769 : state.dataCostEstimateManager->monetaryUnit(44).code = "ILS";
1418 769 : state.dataCostEstimateManager->monetaryUnit(45).code = "IMP";
1419 769 : state.dataCostEstimateManager->monetaryUnit(46).code = "INR";
1420 769 : state.dataCostEstimateManager->monetaryUnit(47).code = "IRR";
1421 769 : state.dataCostEstimateManager->monetaryUnit(48).code = "ISK";
1422 769 : state.dataCostEstimateManager->monetaryUnit(49).code = "JEP";
1423 769 : state.dataCostEstimateManager->monetaryUnit(50).code = "JMD";
1424 769 : state.dataCostEstimateManager->monetaryUnit(51).code = "JPY";
1425 769 : state.dataCostEstimateManager->monetaryUnit(52).code = "KGS";
1426 769 : state.dataCostEstimateManager->monetaryUnit(53).code = "KHR";
1427 769 : state.dataCostEstimateManager->monetaryUnit(54).code = "KPW";
1428 769 : state.dataCostEstimateManager->monetaryUnit(55).code = "KRW";
1429 769 : state.dataCostEstimateManager->monetaryUnit(56).code = "KYD";
1430 769 : state.dataCostEstimateManager->monetaryUnit(57).code = "KZT";
1431 769 : state.dataCostEstimateManager->monetaryUnit(58).code = "LAK";
1432 769 : state.dataCostEstimateManager->monetaryUnit(59).code = "LBP";
1433 769 : state.dataCostEstimateManager->monetaryUnit(60).code = "LKR";
1434 769 : state.dataCostEstimateManager->monetaryUnit(61).code = "LRD";
1435 769 : state.dataCostEstimateManager->monetaryUnit(62).code = "LTL";
1436 769 : state.dataCostEstimateManager->monetaryUnit(63).code = "LVL";
1437 769 : state.dataCostEstimateManager->monetaryUnit(64).code = "MKD";
1438 769 : state.dataCostEstimateManager->monetaryUnit(65).code = "MNT";
1439 769 : state.dataCostEstimateManager->monetaryUnit(66).code = "MUR";
1440 769 : state.dataCostEstimateManager->monetaryUnit(67).code = "MXN";
1441 769 : state.dataCostEstimateManager->monetaryUnit(68).code = "MYR";
1442 769 : state.dataCostEstimateManager->monetaryUnit(69).code = "MZN";
1443 769 : state.dataCostEstimateManager->monetaryUnit(70).code = "NAD";
1444 769 : state.dataCostEstimateManager->monetaryUnit(71).code = "NGN";
1445 769 : state.dataCostEstimateManager->monetaryUnit(72).code = "NIO";
1446 769 : state.dataCostEstimateManager->monetaryUnit(73).code = "NOK";
1447 769 : state.dataCostEstimateManager->monetaryUnit(74).code = "NPR";
1448 769 : state.dataCostEstimateManager->monetaryUnit(75).code = "NZD";
1449 769 : state.dataCostEstimateManager->monetaryUnit(76).code = "OMR";
1450 769 : state.dataCostEstimateManager->monetaryUnit(77).code = "PAB";
1451 769 : state.dataCostEstimateManager->monetaryUnit(78).code = "PEN";
1452 769 : state.dataCostEstimateManager->monetaryUnit(79).code = "PHP";
1453 769 : state.dataCostEstimateManager->monetaryUnit(80).code = "PKR";
1454 769 : state.dataCostEstimateManager->monetaryUnit(81).code = "PLN";
1455 769 : state.dataCostEstimateManager->monetaryUnit(82).code = "PYG";
1456 769 : state.dataCostEstimateManager->monetaryUnit(83).code = "QAR";
1457 769 : state.dataCostEstimateManager->monetaryUnit(84).code = "RON";
1458 769 : state.dataCostEstimateManager->monetaryUnit(85).code = "RSD";
1459 769 : state.dataCostEstimateManager->monetaryUnit(86).code = "RUB";
1460 769 : state.dataCostEstimateManager->monetaryUnit(87).code = "SAR";
1461 769 : state.dataCostEstimateManager->monetaryUnit(88).code = "SBD";
1462 769 : state.dataCostEstimateManager->monetaryUnit(89).code = "SCR";
1463 769 : state.dataCostEstimateManager->monetaryUnit(90).code = "SEK";
1464 769 : state.dataCostEstimateManager->monetaryUnit(91).code = "SGD";
1465 769 : state.dataCostEstimateManager->monetaryUnit(92).code = "SHP";
1466 769 : state.dataCostEstimateManager->monetaryUnit(93).code = "SOS";
1467 769 : state.dataCostEstimateManager->monetaryUnit(94).code = "SRD";
1468 769 : state.dataCostEstimateManager->monetaryUnit(95).code = "SVC";
1469 769 : state.dataCostEstimateManager->monetaryUnit(96).code = "SYP";
1470 769 : state.dataCostEstimateManager->monetaryUnit(97).code = "THB";
1471 769 : state.dataCostEstimateManager->monetaryUnit(98).code = "TRL";
1472 769 : state.dataCostEstimateManager->monetaryUnit(99).code = "TRY";
1473 769 : state.dataCostEstimateManager->monetaryUnit(100).code = "TTD";
1474 769 : state.dataCostEstimateManager->monetaryUnit(101).code = "TVD";
1475 769 : state.dataCostEstimateManager->monetaryUnit(102).code = "TWD";
1476 769 : state.dataCostEstimateManager->monetaryUnit(103).code = "UAH";
1477 769 : state.dataCostEstimateManager->monetaryUnit(104).code = "UYU";
1478 769 : state.dataCostEstimateManager->monetaryUnit(105).code = "UZS";
1479 769 : state.dataCostEstimateManager->monetaryUnit(106).code = "VEF";
1480 769 : state.dataCostEstimateManager->monetaryUnit(107).code = "VND";
1481 769 : state.dataCostEstimateManager->monetaryUnit(108).code = "XCD";
1482 769 : state.dataCostEstimateManager->monetaryUnit(109).code = "YER";
1483 769 : state.dataCostEstimateManager->monetaryUnit(110).code = "ZAR";
1484 769 : state.dataCostEstimateManager->monetaryUnit(111).code = "ZWD";
1485 :
1486 769 : state.dataCostEstimateManager->monetaryUnit(1).txt = "$";
1487 769 : state.dataCostEstimateManager->monetaryUnit(2).txt = "AFN";
1488 769 : state.dataCostEstimateManager->monetaryUnit(3).txt = "Lek";
1489 769 : state.dataCostEstimateManager->monetaryUnit(4).txt = "ANG";
1490 769 : state.dataCostEstimateManager->monetaryUnit(5).txt = "$";
1491 769 : state.dataCostEstimateManager->monetaryUnit(6).txt = "$";
1492 769 : state.dataCostEstimateManager->monetaryUnit(7).txt = "AWG";
1493 769 : state.dataCostEstimateManager->monetaryUnit(8).txt = "AZN";
1494 769 : state.dataCostEstimateManager->monetaryUnit(9).txt = "KM";
1495 769 : state.dataCostEstimateManager->monetaryUnit(10).txt = "$";
1496 769 : state.dataCostEstimateManager->monetaryUnit(11).txt = "BGN";
1497 769 : state.dataCostEstimateManager->monetaryUnit(12).txt = "$";
1498 769 : state.dataCostEstimateManager->monetaryUnit(13).txt = "$";
1499 769 : state.dataCostEstimateManager->monetaryUnit(14).txt = "$b";
1500 769 : state.dataCostEstimateManager->monetaryUnit(15).txt = "R$";
1501 769 : state.dataCostEstimateManager->monetaryUnit(16).txt = "$";
1502 769 : state.dataCostEstimateManager->monetaryUnit(17).txt = "P";
1503 769 : state.dataCostEstimateManager->monetaryUnit(18).txt = "p.";
1504 769 : state.dataCostEstimateManager->monetaryUnit(19).txt = "BZ$";
1505 769 : state.dataCostEstimateManager->monetaryUnit(20).txt = "$";
1506 769 : state.dataCostEstimateManager->monetaryUnit(21).txt = "CHF";
1507 769 : state.dataCostEstimateManager->monetaryUnit(22).txt = "$";
1508 769 : state.dataCostEstimateManager->monetaryUnit(23).txt = "CNY";
1509 769 : state.dataCostEstimateManager->monetaryUnit(24).txt = "$";
1510 769 : state.dataCostEstimateManager->monetaryUnit(25).txt = "CRC";
1511 769 : state.dataCostEstimateManager->monetaryUnit(26).txt = "CUP";
1512 769 : state.dataCostEstimateManager->monetaryUnit(27).txt = "CZK";
1513 769 : state.dataCostEstimateManager->monetaryUnit(28).txt = "kr";
1514 769 : state.dataCostEstimateManager->monetaryUnit(29).txt = "RD$";
1515 769 : state.dataCostEstimateManager->monetaryUnit(30).txt = "kr";
1516 769 : state.dataCostEstimateManager->monetaryUnit(31).txt = "£";
1517 769 : state.dataCostEstimateManager->monetaryUnit(32).txt = "EUR";
1518 769 : state.dataCostEstimateManager->monetaryUnit(33).txt = "$";
1519 769 : state.dataCostEstimateManager->monetaryUnit(34).txt = "£";
1520 769 : state.dataCostEstimateManager->monetaryUnit(35).txt = "¢";
1521 769 : state.dataCostEstimateManager->monetaryUnit(36).txt = "£";
1522 769 : state.dataCostEstimateManager->monetaryUnit(37).txt = "Q";
1523 769 : state.dataCostEstimateManager->monetaryUnit(38).txt = "$";
1524 769 : state.dataCostEstimateManager->monetaryUnit(39).txt = "HK$";
1525 769 : state.dataCostEstimateManager->monetaryUnit(40).txt = "L";
1526 769 : state.dataCostEstimateManager->monetaryUnit(41).txt = "kn";
1527 769 : state.dataCostEstimateManager->monetaryUnit(42).txt = "Ft";
1528 769 : state.dataCostEstimateManager->monetaryUnit(43).txt = "Rp";
1529 769 : state.dataCostEstimateManager->monetaryUnit(44).txt = "ILS";
1530 769 : state.dataCostEstimateManager->monetaryUnit(45).txt = "£";
1531 769 : state.dataCostEstimateManager->monetaryUnit(46).txt = "INR";
1532 769 : state.dataCostEstimateManager->monetaryUnit(47).txt = "IRR";
1533 769 : state.dataCostEstimateManager->monetaryUnit(48).txt = "kr";
1534 769 : state.dataCostEstimateManager->monetaryUnit(49).txt = "£";
1535 769 : state.dataCostEstimateManager->monetaryUnit(50).txt = "J$";
1536 769 : state.dataCostEstimateManager->monetaryUnit(51).txt = "Â¥";
1537 769 : state.dataCostEstimateManager->monetaryUnit(52).txt = "KGS";
1538 769 : state.dataCostEstimateManager->monetaryUnit(53).txt = "KHR";
1539 769 : state.dataCostEstimateManager->monetaryUnit(54).txt = "KPW";
1540 769 : state.dataCostEstimateManager->monetaryUnit(55).txt = "KRW";
1541 769 : state.dataCostEstimateManager->monetaryUnit(56).txt = "$";
1542 769 : state.dataCostEstimateManager->monetaryUnit(57).txt = "KZT";
1543 769 : state.dataCostEstimateManager->monetaryUnit(58).txt = "LAK";
1544 769 : state.dataCostEstimateManager->monetaryUnit(59).txt = "£";
1545 769 : state.dataCostEstimateManager->monetaryUnit(60).txt = "LKR";
1546 769 : state.dataCostEstimateManager->monetaryUnit(61).txt = "$";
1547 769 : state.dataCostEstimateManager->monetaryUnit(62).txt = "Lt";
1548 769 : state.dataCostEstimateManager->monetaryUnit(63).txt = "Ls";
1549 769 : state.dataCostEstimateManager->monetaryUnit(64).txt = "MKD";
1550 769 : state.dataCostEstimateManager->monetaryUnit(65).txt = "MNT";
1551 769 : state.dataCostEstimateManager->monetaryUnit(66).txt = "MUR";
1552 769 : state.dataCostEstimateManager->monetaryUnit(67).txt = "$";
1553 769 : state.dataCostEstimateManager->monetaryUnit(68).txt = "RM";
1554 769 : state.dataCostEstimateManager->monetaryUnit(69).txt = "MT";
1555 769 : state.dataCostEstimateManager->monetaryUnit(70).txt = "$";
1556 769 : state.dataCostEstimateManager->monetaryUnit(71).txt = "NGN";
1557 769 : state.dataCostEstimateManager->monetaryUnit(72).txt = "C$";
1558 769 : state.dataCostEstimateManager->monetaryUnit(73).txt = "kr";
1559 769 : state.dataCostEstimateManager->monetaryUnit(74).txt = "NPR";
1560 769 : state.dataCostEstimateManager->monetaryUnit(75).txt = "$";
1561 769 : state.dataCostEstimateManager->monetaryUnit(76).txt = "OMR";
1562 769 : state.dataCostEstimateManager->monetaryUnit(77).txt = "B/.";
1563 769 : state.dataCostEstimateManager->monetaryUnit(78).txt = "S/.";
1564 769 : state.dataCostEstimateManager->monetaryUnit(79).txt = "Php";
1565 769 : state.dataCostEstimateManager->monetaryUnit(80).txt = "PKR";
1566 769 : state.dataCostEstimateManager->monetaryUnit(81).txt = "PLN";
1567 769 : state.dataCostEstimateManager->monetaryUnit(82).txt = "Gs";
1568 769 : state.dataCostEstimateManager->monetaryUnit(83).txt = "QAR";
1569 769 : state.dataCostEstimateManager->monetaryUnit(84).txt = "lei";
1570 769 : state.dataCostEstimateManager->monetaryUnit(85).txt = "RSD";
1571 769 : state.dataCostEstimateManager->monetaryUnit(86).txt = "RUB";
1572 769 : state.dataCostEstimateManager->monetaryUnit(87).txt = "SAR";
1573 769 : state.dataCostEstimateManager->monetaryUnit(88).txt = "$";
1574 769 : state.dataCostEstimateManager->monetaryUnit(89).txt = "SCR";
1575 769 : state.dataCostEstimateManager->monetaryUnit(90).txt = "kr";
1576 769 : state.dataCostEstimateManager->monetaryUnit(91).txt = "$";
1577 769 : state.dataCostEstimateManager->monetaryUnit(92).txt = "£";
1578 769 : state.dataCostEstimateManager->monetaryUnit(93).txt = "S";
1579 769 : state.dataCostEstimateManager->monetaryUnit(94).txt = "$";
1580 769 : state.dataCostEstimateManager->monetaryUnit(95).txt = "$";
1581 769 : state.dataCostEstimateManager->monetaryUnit(96).txt = "£";
1582 769 : state.dataCostEstimateManager->monetaryUnit(97).txt = "THB";
1583 769 : state.dataCostEstimateManager->monetaryUnit(98).txt = "TRL";
1584 769 : state.dataCostEstimateManager->monetaryUnit(99).txt = "YTL";
1585 769 : state.dataCostEstimateManager->monetaryUnit(100).txt = "TT$";
1586 769 : state.dataCostEstimateManager->monetaryUnit(101).txt = "$";
1587 769 : state.dataCostEstimateManager->monetaryUnit(102).txt = "NT$";
1588 769 : state.dataCostEstimateManager->monetaryUnit(103).txt = "UAH";
1589 769 : state.dataCostEstimateManager->monetaryUnit(104).txt = "$U";
1590 769 : state.dataCostEstimateManager->monetaryUnit(105).txt = "UZS";
1591 769 : state.dataCostEstimateManager->monetaryUnit(106).txt = "Bs";
1592 769 : state.dataCostEstimateManager->monetaryUnit(107).txt = "VND";
1593 769 : state.dataCostEstimateManager->monetaryUnit(108).txt = "$";
1594 769 : state.dataCostEstimateManager->monetaryUnit(109).txt = "YER";
1595 769 : state.dataCostEstimateManager->monetaryUnit(110).txt = "R";
1596 769 : state.dataCostEstimateManager->monetaryUnit(111).txt = "Z$";
1597 :
1598 769 : state.dataCostEstimateManager->monetaryUnit(1).html = "$";
1599 769 : state.dataCostEstimateManager->monetaryUnit(2).html = "؋";
1600 769 : state.dataCostEstimateManager->monetaryUnit(3).html = "Lek";
1601 769 : state.dataCostEstimateManager->monetaryUnit(4).html = "ƒ";
1602 769 : state.dataCostEstimateManager->monetaryUnit(5).html = "$";
1603 769 : state.dataCostEstimateManager->monetaryUnit(6).html = "$";
1604 769 : state.dataCostEstimateManager->monetaryUnit(7).html = "ƒ";
1605 769 : state.dataCostEstimateManager->monetaryUnit(8).html = "ман";
1606 769 : state.dataCostEstimateManager->monetaryUnit(9).html = "KM";
1607 769 : state.dataCostEstimateManager->monetaryUnit(10).html = "$";
1608 769 : state.dataCostEstimateManager->monetaryUnit(11).html = "лв";
1609 769 : state.dataCostEstimateManager->monetaryUnit(12).html = "$";
1610 769 : state.dataCostEstimateManager->monetaryUnit(13).html = "$";
1611 769 : state.dataCostEstimateManager->monetaryUnit(14).html = "$b";
1612 769 : state.dataCostEstimateManager->monetaryUnit(15).html = "R$";
1613 769 : state.dataCostEstimateManager->monetaryUnit(16).html = "$";
1614 769 : state.dataCostEstimateManager->monetaryUnit(17).html = "P";
1615 769 : state.dataCostEstimateManager->monetaryUnit(18).html = "p.";
1616 769 : state.dataCostEstimateManager->monetaryUnit(19).html = "BZ$";
1617 769 : state.dataCostEstimateManager->monetaryUnit(20).html = "$";
1618 769 : state.dataCostEstimateManager->monetaryUnit(21).html = "CHF";
1619 769 : state.dataCostEstimateManager->monetaryUnit(22).html = "$";
1620 769 : state.dataCostEstimateManager->monetaryUnit(23).html = "元";
1621 769 : state.dataCostEstimateManager->monetaryUnit(24).html = "$";
1622 769 : state.dataCostEstimateManager->monetaryUnit(25).html = "₡";
1623 769 : state.dataCostEstimateManager->monetaryUnit(26).html = "₱";
1624 769 : state.dataCostEstimateManager->monetaryUnit(27).html = "Kč";
1625 769 : state.dataCostEstimateManager->monetaryUnit(28).html = "kr";
1626 769 : state.dataCostEstimateManager->monetaryUnit(29).html = "RD$";
1627 769 : state.dataCostEstimateManager->monetaryUnit(30).html = "kr";
1628 769 : state.dataCostEstimateManager->monetaryUnit(31).html = "£";
1629 769 : state.dataCostEstimateManager->monetaryUnit(32).html = "€";
1630 769 : state.dataCostEstimateManager->monetaryUnit(33).html = "$";
1631 769 : state.dataCostEstimateManager->monetaryUnit(34).html = "£";
1632 769 : state.dataCostEstimateManager->monetaryUnit(35).html = "¢";
1633 769 : state.dataCostEstimateManager->monetaryUnit(36).html = "£";
1634 769 : state.dataCostEstimateManager->monetaryUnit(37).html = "Q";
1635 769 : state.dataCostEstimateManager->monetaryUnit(38).html = "$";
1636 769 : state.dataCostEstimateManager->monetaryUnit(39).html = "HK$";
1637 769 : state.dataCostEstimateManager->monetaryUnit(40).html = "L";
1638 769 : state.dataCostEstimateManager->monetaryUnit(41).html = "kn";
1639 769 : state.dataCostEstimateManager->monetaryUnit(42).html = "Ft";
1640 769 : state.dataCostEstimateManager->monetaryUnit(43).html = "Rp";
1641 769 : state.dataCostEstimateManager->monetaryUnit(44).html = "₪";
1642 769 : state.dataCostEstimateManager->monetaryUnit(45).html = "£";
1643 769 : state.dataCostEstimateManager->monetaryUnit(46).html = "₨";
1644 769 : state.dataCostEstimateManager->monetaryUnit(47).html = "﷼";
1645 769 : state.dataCostEstimateManager->monetaryUnit(48).html = "kr";
1646 769 : state.dataCostEstimateManager->monetaryUnit(49).html = "£";
1647 769 : state.dataCostEstimateManager->monetaryUnit(50).html = "J$";
1648 769 : state.dataCostEstimateManager->monetaryUnit(51).html = "Â¥";
1649 769 : state.dataCostEstimateManager->monetaryUnit(52).html = "лв";
1650 769 : state.dataCostEstimateManager->monetaryUnit(53).html = "៛";
1651 769 : state.dataCostEstimateManager->monetaryUnit(54).html = "₩";
1652 769 : state.dataCostEstimateManager->monetaryUnit(55).html = "₩";
1653 769 : state.dataCostEstimateManager->monetaryUnit(56).html = "$";
1654 769 : state.dataCostEstimateManager->monetaryUnit(57).html = "лв";
1655 769 : state.dataCostEstimateManager->monetaryUnit(58).html = "₭";
1656 769 : state.dataCostEstimateManager->monetaryUnit(59).html = "£";
1657 769 : state.dataCostEstimateManager->monetaryUnit(60).html = "₨";
1658 769 : state.dataCostEstimateManager->monetaryUnit(61).html = "$";
1659 769 : state.dataCostEstimateManager->monetaryUnit(62).html = "Lt";
1660 769 : state.dataCostEstimateManager->monetaryUnit(63).html = "Ls";
1661 769 : state.dataCostEstimateManager->monetaryUnit(64).html = "ден";
1662 769 : state.dataCostEstimateManager->monetaryUnit(65).html = "₮";
1663 769 : state.dataCostEstimateManager->monetaryUnit(66).html = "₨";
1664 769 : state.dataCostEstimateManager->monetaryUnit(67).html = "$";
1665 769 : state.dataCostEstimateManager->monetaryUnit(68).html = "RM";
1666 769 : state.dataCostEstimateManager->monetaryUnit(69).html = "MT";
1667 769 : state.dataCostEstimateManager->monetaryUnit(70).html = "$";
1668 769 : state.dataCostEstimateManager->monetaryUnit(71).html = "₦";
1669 769 : state.dataCostEstimateManager->monetaryUnit(72).html = "C$";
1670 769 : state.dataCostEstimateManager->monetaryUnit(73).html = "kr";
1671 769 : state.dataCostEstimateManager->monetaryUnit(74).html = "₨";
1672 769 : state.dataCostEstimateManager->monetaryUnit(75).html = "$";
1673 769 : state.dataCostEstimateManager->monetaryUnit(76).html = "﷼";
1674 769 : state.dataCostEstimateManager->monetaryUnit(77).html = "B/.";
1675 769 : state.dataCostEstimateManager->monetaryUnit(78).html = "S/.";
1676 769 : state.dataCostEstimateManager->monetaryUnit(79).html = "Php";
1677 769 : state.dataCostEstimateManager->monetaryUnit(80).html = "₨";
1678 769 : state.dataCostEstimateManager->monetaryUnit(81).html = "zł";
1679 769 : state.dataCostEstimateManager->monetaryUnit(82).html = "Gs";
1680 769 : state.dataCostEstimateManager->monetaryUnit(83).html = "﷼";
1681 769 : state.dataCostEstimateManager->monetaryUnit(84).html = "lei";
1682 769 : state.dataCostEstimateManager->monetaryUnit(85).html = "Дин.";
1683 769 : state.dataCostEstimateManager->monetaryUnit(86).html = "руб";
1684 769 : state.dataCostEstimateManager->monetaryUnit(87).html = "﷼";
1685 769 : state.dataCostEstimateManager->monetaryUnit(88).html = "$";
1686 769 : state.dataCostEstimateManager->monetaryUnit(89).html = "₨";
1687 769 : state.dataCostEstimateManager->monetaryUnit(90).html = "kr";
1688 769 : state.dataCostEstimateManager->monetaryUnit(91).html = "$";
1689 769 : state.dataCostEstimateManager->monetaryUnit(92).html = "£";
1690 769 : state.dataCostEstimateManager->monetaryUnit(93).html = "S";
1691 769 : state.dataCostEstimateManager->monetaryUnit(94).html = "$";
1692 769 : state.dataCostEstimateManager->monetaryUnit(95).html = "$";
1693 769 : state.dataCostEstimateManager->monetaryUnit(96).html = "£";
1694 769 : state.dataCostEstimateManager->monetaryUnit(97).html = "฿";
1695 769 : state.dataCostEstimateManager->monetaryUnit(98).html = "₤";
1696 769 : state.dataCostEstimateManager->monetaryUnit(99).html = "YTL";
1697 769 : state.dataCostEstimateManager->monetaryUnit(100).html = "TT$";
1698 769 : state.dataCostEstimateManager->monetaryUnit(101).html = "$";
1699 769 : state.dataCostEstimateManager->monetaryUnit(102).html = "NT$";
1700 769 : state.dataCostEstimateManager->monetaryUnit(103).html = "₴";
1701 769 : state.dataCostEstimateManager->monetaryUnit(104).html = "$U";
1702 769 : state.dataCostEstimateManager->monetaryUnit(105).html = "лв";
1703 769 : state.dataCostEstimateManager->monetaryUnit(106).html = "Bs";
1704 769 : state.dataCostEstimateManager->monetaryUnit(107).html = "₫";
1705 769 : state.dataCostEstimateManager->monetaryUnit(108).html = "$";
1706 769 : state.dataCostEstimateManager->monetaryUnit(109).html = "﷼";
1707 769 : state.dataCostEstimateManager->monetaryUnit(110).html = "R";
1708 769 : state.dataCostEstimateManager->monetaryUnit(111).html = "Z$";
1709 769 : }
1710 :
1711 2034 : int LookUpSeason(EnergyPlusData &state, std::string const &nameOfSeason, std::string const &nameOfReferingObj)
1712 : {
1713 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1714 : // DATE WRITTEN May 2004
1715 :
1716 : // Find the index for the season string provided or else
1717 : // raise a warning.
1718 :
1719 : int LookUpSeason;
1720 :
1721 2034 : if (UtilityRoutines::SameString(nameOfSeason, "Summer")) {
1722 107 : LookUpSeason = seasonSummer;
1723 1927 : } else if (UtilityRoutines::SameString(nameOfSeason, "Winter")) {
1724 61 : LookUpSeason = seasonWinter;
1725 1866 : } else if (UtilityRoutines::SameString(nameOfSeason, "Spring")) {
1726 0 : LookUpSeason = seasonSpring;
1727 1866 : } else if (UtilityRoutines::SameString(nameOfSeason, "Fall")) {
1728 0 : LookUpSeason = seasonFall;
1729 1866 : } else if (UtilityRoutines::SameString(nameOfSeason, "Annual")) {
1730 1866 : LookUpSeason = seasonAnnual;
1731 : } else {
1732 0 : ShowWarningError(state, "UtilityCost: Invalid season name " + nameOfSeason + " in: " + nameOfReferingObj);
1733 0 : ShowContinueError(state, " Defaulting to Annual");
1734 0 : LookUpSeason = seasonAnnual;
1735 : }
1736 2034 : return LookUpSeason;
1737 : }
1738 :
1739 2117 : int FindTariffIndex(
1740 : EnergyPlusData &state, std::string const &nameOfTariff, std::string const &nameOfReferingObj, bool &ErrorsFound, std::string const &nameOfCurObj)
1741 : {
1742 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1743 : // DATE WRITTEN May 2004
1744 :
1745 : // Find the index for the tariff string provided or else
1746 : // raise a warning.
1747 :
1748 : int FindTariffIndex;
1749 : int iTariff;
1750 : int found;
1751 :
1752 2117 : found = 0;
1753 3912 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
1754 3912 : if (UtilityRoutines::SameString(nameOfTariff, state.dataEconTariff->tariff(iTariff).tariffName)) {
1755 2117 : found = iTariff;
1756 2117 : break;
1757 : }
1758 : }
1759 2117 : if (found > 0) {
1760 2117 : FindTariffIndex = found;
1761 : } else {
1762 0 : ShowSevereError(state, nameOfCurObj + "=\"" + nameOfReferingObj + "\" invalid tariff referenced");
1763 0 : ShowContinueError(state, "not found UtilityCost:Tariff=\"" + nameOfTariff + "\".");
1764 0 : ErrorsFound = true;
1765 0 : FindTariffIndex = 0;
1766 : }
1767 2117 : return FindTariffIndex;
1768 : }
1769 :
1770 2117 : void warnIfNativeVarname(
1771 : EnergyPlusData &state, std::string const &objName, int const curTariffIndex, bool &ErrorsFound, std::string const &curobjName)
1772 : {
1773 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1774 : // DATE WRITTEN March 2007
1775 :
1776 : // Issue a warning if the variable name (usually the object name) is
1777 : // one of the names of native variables
1778 :
1779 : bool throwError;
1780 :
1781 2117 : throwError = false;
1782 2117 : if (UtilityRoutines::SameString(objName, "TotalEnergy")) throwError = true;
1783 2117 : if (UtilityRoutines::SameString(objName, "TotalDemand")) throwError = true;
1784 2117 : if (UtilityRoutines::SameString(objName, "PeakEnergy")) throwError = true;
1785 2117 : if (UtilityRoutines::SameString(objName, "PeakDemand")) throwError = true;
1786 2117 : if (UtilityRoutines::SameString(objName, "ShoulderEnergy")) throwError = true;
1787 2117 : if (UtilityRoutines::SameString(objName, "ShoulderDemand")) throwError = true;
1788 2117 : if (UtilityRoutines::SameString(objName, "OffPeakEnergy")) throwError = true;
1789 2117 : if (UtilityRoutines::SameString(objName, "OffPeakDemand")) throwError = true;
1790 2117 : if (UtilityRoutines::SameString(objName, "MidPeakEnergy")) throwError = true;
1791 2117 : if (UtilityRoutines::SameString(objName, "MidPeakDemand")) throwError = true;
1792 2117 : if (UtilityRoutines::SameString(objName, "PeakExceedsOffPeak")) throwError = true;
1793 2117 : if (UtilityRoutines::SameString(objName, "OffPeakExceedsPeak")) throwError = true;
1794 2117 : if (UtilityRoutines::SameString(objName, "PeakExceedsMidPeak")) throwError = true;
1795 2117 : if (UtilityRoutines::SameString(objName, "MidPeakExceedsPeak")) throwError = true;
1796 2117 : if (UtilityRoutines::SameString(objName, "PeakExceedsShoulder")) throwError = true;
1797 2117 : if (UtilityRoutines::SameString(objName, "ShoulderExceedsPeak")) throwError = true;
1798 2117 : if (UtilityRoutines::SameString(objName, "IsWinter")) throwError = true;
1799 2117 : if (UtilityRoutines::SameString(objName, "IsNotWinter")) throwError = true;
1800 2117 : if (UtilityRoutines::SameString(objName, "IsSpring")) throwError = true;
1801 2117 : if (UtilityRoutines::SameString(objName, "IsNotSpring")) throwError = true;
1802 2117 : if (UtilityRoutines::SameString(objName, "IsSummer")) throwError = true;
1803 2117 : if (UtilityRoutines::SameString(objName, "IsNotSummer")) throwError = true;
1804 2117 : if (UtilityRoutines::SameString(objName, "IsAutumn")) throwError = true;
1805 2117 : if (UtilityRoutines::SameString(objName, "IsNotAutumn")) throwError = true;
1806 2117 : if (UtilityRoutines::SameString(objName, "PeakAndShoulderEnergy")) throwError = true;
1807 2117 : if (UtilityRoutines::SameString(objName, "PeakAndShoulderDemand")) throwError = true;
1808 2117 : if (UtilityRoutines::SameString(objName, "PeakAndMidPeakEnergy")) throwError = true;
1809 2117 : if (UtilityRoutines::SameString(objName, "PeakAndMidPeakDemand")) throwError = true;
1810 2117 : if (UtilityRoutines::SameString(objName, "ShoulderAndOffPeakEnergy")) throwError = true;
1811 2117 : if (UtilityRoutines::SameString(objName, "ShoulderAndOffPeakDemand")) throwError = true;
1812 2117 : if (UtilityRoutines::SameString(objName, "PeakAndOffPeakEnergy")) throwError = true;
1813 2117 : if (UtilityRoutines::SameString(objName, "PeakAndOffPeakDemand")) throwError = true;
1814 2117 : if (UtilityRoutines::SameString(objName, "RealTimePriceCosts")) throwError = true;
1815 2117 : if (UtilityRoutines::SameString(objName, "AboveCustomerBaseCosts")) throwError = true;
1816 2117 : if (UtilityRoutines::SameString(objName, "BelowCustomerBaseCosts")) throwError = true;
1817 2117 : if (UtilityRoutines::SameString(objName, "AboveCustomerBaseEnergy")) throwError = true;
1818 2117 : if (UtilityRoutines::SameString(objName, "BelowCustomerBaseEnergy")) throwError = true;
1819 2117 : if (UtilityRoutines::SameString(objName, "EnergyCharges")) throwError = true;
1820 2117 : if (UtilityRoutines::SameString(objName, "DemandCharges")) throwError = true;
1821 2117 : if (UtilityRoutines::SameString(objName, "ServiceCharges")) throwError = true;
1822 2117 : if (UtilityRoutines::SameString(objName, "Basis")) throwError = true;
1823 2117 : if (UtilityRoutines::SameString(objName, "Surcharges")) throwError = true;
1824 2117 : if (UtilityRoutines::SameString(objName, "Adjustments")) throwError = true;
1825 2117 : if (UtilityRoutines::SameString(objName, "Subtotal")) throwError = true;
1826 2117 : if (UtilityRoutines::SameString(objName, "Taxes")) throwError = true;
1827 2117 : if (UtilityRoutines::SameString(objName, "Total")) throwError = true;
1828 2117 : if (throwError) {
1829 0 : ErrorsFound = true;
1830 0 : if (curTariffIndex >= 1 && curTariffIndex <= state.dataEconTariff->numTariff) {
1831 0 : ShowSevereError(state, "UtilityCost:Tariff=\"" + state.dataEconTariff->tariff(curTariffIndex).tariffName + "\" invalid referenced name");
1832 0 : ShowContinueError(state, curobjName + "=\"" + objName + "\" You cannot name an object using the same name as a native variable.");
1833 : } else {
1834 0 : ShowSevereError(state, curobjName + "=\"" + objName + "\" You cannot name an object using the same name as a native variable.");
1835 : }
1836 : }
1837 2117 : }
1838 :
1839 23762 : int AssignVariablePt(EnergyPlusData &state,
1840 : std::string const &stringIn,
1841 : bool const flagIfNotNumeric,
1842 : int const useOfVar,
1843 : int const varSpecific,
1844 : ObjType const econObjKind,
1845 : int const objIndex,
1846 : int const tariffPt)
1847 : {
1848 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1849 : // DATE WRITTEN May 2004
1850 :
1851 : // If the string is not numeric, check if it is a valid string to use as
1852 : // a variable name. Check if name has been used before and if not create
1853 : // the variable using the string as its name.
1854 : // Return the index of the variable.
1855 :
1856 : int AssignVariablePt;
1857 :
1858 47524 : std::string inNoSpaces;
1859 : int found;
1860 : int iVar;
1861 :
1862 23762 : auto &econVar(state.dataEconTariff->econVar);
1863 :
1864 23762 : if (flagIfNotNumeric && (len(stringIn) >= 1)) {
1865 19701 : inNoSpaces = RemoveSpaces(state, stringIn);
1866 19701 : found = 0;
1867 19701 : if (allocated(econVar)) {
1868 1750315 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
1869 1734769 : if (econVar(iVar).tariffIndx == tariffPt) {
1870 450979 : if (UtilityRoutines::SameString(econVar(iVar).name, inNoSpaces)) {
1871 4060 : found = iVar;
1872 4060 : break;
1873 : }
1874 : }
1875 : }
1876 : }
1877 19701 : if (found > 0) {
1878 4060 : AssignVariablePt = found;
1879 4060 : if (econVar(found).kindOfObj == ObjType::Invalid) {
1880 85 : econVar(found).kindOfObj = econObjKind;
1881 85 : if (econVar(found).index == 0) econVar(found).index = objIndex;
1882 : }
1883 : } else {
1884 15641 : incrementEconVar(state);
1885 15641 : econVar(state.dataEconTariff->numEconVar).name = inNoSpaces;
1886 15641 : econVar(state.dataEconTariff->numEconVar).kindOfObj = econObjKind;
1887 15641 : econVar(state.dataEconTariff->numEconVar).index = objIndex;
1888 15641 : AssignVariablePt = state.dataEconTariff->numEconVar;
1889 : }
1890 : // now set the flag for the type of usage the variable has
1891 19701 : if (useOfVar == varIsArgument) {
1892 12958 : econVar(AssignVariablePt).isArgument = true;
1893 6743 : } else if (useOfVar == varIsAssigned) {
1894 6743 : econVar(AssignVariablePt).isAssigned = true;
1895 : }
1896 19701 : econVar(AssignVariablePt).tariffIndx = tariffPt;
1897 : // if the user defines the UtilityCost:Computation then this is called when reading the
1898 : // UtilityCost:Tariff with varNotYetDefined but they are already defined because
1899 : // the subroutine CreateCategoryNativeVariables has already been called.
1900 19701 : if (!((varSpecific == varNotYetDefined) && (econVar(AssignVariablePt).specific >= catEnergyCharges))) {
1901 15748 : econVar(AssignVariablePt).specific = varSpecific;
1902 : }
1903 : } else { // if the string was numeric return a zero
1904 4061 : AssignVariablePt = 0;
1905 : }
1906 47524 : return AssignVariablePt;
1907 : }
1908 :
1909 15641 : void incrementEconVar(EnergyPlusData &state)
1910 : {
1911 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1912 : // DATE WRITTEN May 2004
1913 :
1914 : // Increment the Increase the size of the
1915 :
1916 15641 : int constexpr sizeIncrement(100);
1917 :
1918 15641 : auto &econVar(state.dataEconTariff->econVar);
1919 :
1920 15641 : if (!allocated(econVar)) {
1921 95 : econVar.allocate(sizeIncrement);
1922 95 : state.dataEconTariff->sizeEconVar = sizeIncrement;
1923 95 : state.dataEconTariff->numEconVar = 1;
1924 : } else {
1925 15546 : ++state.dataEconTariff->numEconVar;
1926 : // if larger than current size grow the array
1927 15546 : if (state.dataEconTariff->numEconVar > state.dataEconTariff->sizeEconVar) {
1928 101 : econVar.redimension(state.dataEconTariff->sizeEconVar += sizeIncrement);
1929 : }
1930 : }
1931 : // initialize new record) //Autodesk Most of these match default initialization so not needed
1932 15641 : econVar(state.dataEconTariff->numEconVar).name = "";
1933 15641 : econVar(state.dataEconTariff->numEconVar).tariffIndx = 0;
1934 15641 : econVar(state.dataEconTariff->numEconVar).kindOfObj = ObjType::Invalid;
1935 15641 : econVar(state.dataEconTariff->numEconVar).index = 0;
1936 15641 : econVar(state.dataEconTariff->numEconVar).values = 0.0;
1937 15641 : econVar(state.dataEconTariff->numEconVar).isArgument = false;
1938 15641 : econVar(state.dataEconTariff->numEconVar).isAssigned = false;
1939 15641 : econVar(state.dataEconTariff->numEconVar).specific = varNotYetDefined;
1940 : // econVar( numEconVar ).values = 0.0; //Autodesk Already initialized above
1941 : // Autodesk Don't initialize cntMeDependOn
1942 15641 : econVar(state.dataEconTariff->numEconVar).Operator = 0;
1943 15641 : econVar(state.dataEconTariff->numEconVar).firstOperand = 1; // Autodesk Default initialization sets this to 0
1944 15641 : econVar(state.dataEconTariff->numEconVar).lastOperand = 0;
1945 15641 : econVar(state.dataEconTariff->numEconVar).activeNow = false;
1946 15641 : econVar(state.dataEconTariff->numEconVar).isEvaluated = false;
1947 : // Autodesk Don't initialize isReported
1948 : // Autodesk Don't initialize varUnitType
1949 15641 : }
1950 :
1951 16769 : void incrementSteps(EnergyPlusData &state)
1952 : {
1953 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1954 : // DATE WRITTEN June 2004
1955 :
1956 : // Increment the step array counter and if
1957 : // necessary increase the size of the array.
1958 :
1959 16769 : int constexpr sizeIncrement(100);
1960 :
1961 16769 : if (!allocated(state.dataEconTariff->steps)) {
1962 95 : state.dataEconTariff->steps.allocate(sizeIncrement);
1963 95 : state.dataEconTariff->sizeSteps = sizeIncrement;
1964 95 : state.dataEconTariff->numSteps = 1;
1965 : } else {
1966 16674 : ++state.dataEconTariff->numSteps;
1967 : // if larger than current size grow the array
1968 16674 : if (state.dataEconTariff->numSteps > state.dataEconTariff->sizeSteps) {
1969 98 : state.dataEconTariff->steps.redimension(state.dataEconTariff->sizeSteps += sizeIncrement);
1970 : }
1971 : }
1972 : // initialize new record
1973 16769 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = 0;
1974 16769 : }
1975 :
1976 19701 : std::string RemoveSpaces(EnergyPlusData &state, std::string const &StringIn)
1977 : {
1978 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
1979 : // DATE WRITTEN May 2004
1980 :
1981 : // Return the string with all spaces removed.
1982 :
1983 19701 : std::string StringOut;
1984 19701 : bool foundSpaces = false;
1985 310892 : for (std::string::size_type iString = 0; iString < len(StringIn); ++iString) {
1986 291191 : if (StringIn[iString] != ' ') {
1987 291191 : StringOut += StringIn[iString];
1988 : } else {
1989 0 : foundSpaces = true;
1990 : }
1991 : }
1992 19701 : if (foundSpaces) {
1993 0 : ShowWarningError(state, "UtilityCost: Spaces were removed from the variable=\"" + StringIn + "\".");
1994 0 : ShowContinueError(state, "...Resultant variable=\"" + StringOut + "\".");
1995 : }
1996 19701 : return StringOut;
1997 : }
1998 :
1999 95 : void CreateCategoryNativeVariables(EnergyPlusData &state)
2000 : {
2001 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2002 : // DATE WRITTEN May 2004
2003 :
2004 : // For each tariff create variables that are used for the
2005 : // categories (i.e., EnergyCharges).
2006 :
2007 : int iTariff;
2008 :
2009 95 : auto &tariff(state.dataEconTariff->tariff);
2010 :
2011 383 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
2012 : // category variables first
2013 288 : tariff(iTariff).ptEnergyCharges =
2014 576 : AssignVariablePt(state, "EnergyCharges", true, varIsAssigned, catEnergyCharges, ObjType::Category, 0, iTariff);
2015 288 : tariff(iTariff).firstCategory = state.dataEconTariff->numEconVar;
2016 288 : tariff(iTariff).ptDemandCharges =
2017 576 : AssignVariablePt(state, "DemandCharges", true, varIsAssigned, catDemandCharges, ObjType::Category, 0, iTariff);
2018 288 : tariff(iTariff).ptServiceCharges =
2019 576 : AssignVariablePt(state, "ServiceCharges", true, varIsAssigned, catServiceCharges, ObjType::Category, 0, iTariff);
2020 288 : tariff(iTariff).ptBasis = AssignVariablePt(state, "Basis", true, varIsAssigned, catBasis, ObjType::Category, 0, iTariff);
2021 288 : tariff(iTariff).ptAdjustment = AssignVariablePt(state, "Adjustment", true, varIsAssigned, catAdjustment, ObjType::Category, 0, iTariff);
2022 288 : tariff(iTariff).ptSurcharge = AssignVariablePt(state, "Surcharge", true, varIsAssigned, catSurcharge, ObjType::Category, 0, iTariff);
2023 288 : tariff(iTariff).ptSubtotal = AssignVariablePt(state, "Subtotal", true, varIsAssigned, catSubtotal, ObjType::Category, 0, iTariff);
2024 288 : tariff(iTariff).ptTaxes = AssignVariablePt(state, "Taxes", true, varIsAssigned, catTaxes, ObjType::Category, 0, iTariff);
2025 288 : tariff(iTariff).ptTotal = AssignVariablePt(state, "Total", true, varIsAssigned, catTotal, ObjType::Category, 0, iTariff);
2026 288 : tariff(iTariff).ptNotIncluded = AssignVariablePt(state, "NotIncluded", true, varIsAssigned, catNotIncluded, ObjType::Category, 0, iTariff);
2027 288 : tariff(iTariff).lastCategory = state.dataEconTariff->numEconVar;
2028 : // category variables first
2029 288 : tariff(iTariff).nativeTotalEnergy =
2030 576 : AssignVariablePt(state, "TotalEnergy", true, varIsArgument, nativeTotalEnergy, ObjType::Native, 0, iTariff);
2031 288 : tariff(iTariff).firstNative = state.dataEconTariff->numEconVar;
2032 288 : tariff(iTariff).nativeTotalDemand =
2033 576 : AssignVariablePt(state, "TotalDemand", true, varIsArgument, nativeTotalDemand, ObjType::Native, 0, iTariff);
2034 288 : tariff(iTariff).nativePeakEnergy = AssignVariablePt(state, "PeakEnergy", true, varIsArgument, nativePeakEnergy, ObjType::Native, 0, iTariff);
2035 288 : tariff(iTariff).nativePeakDemand = AssignVariablePt(state, "PeakDemand", true, varIsArgument, nativePeakDemand, ObjType::Native, 0, iTariff);
2036 288 : tariff(iTariff).nativeShoulderEnergy =
2037 576 : AssignVariablePt(state, "ShoulderEnergy", true, varIsArgument, nativeShoulderEnergy, ObjType::Native, 0, iTariff);
2038 288 : tariff(iTariff).nativeShoulderDemand =
2039 576 : AssignVariablePt(state, "ShoulderDemand", true, varIsArgument, nativeShoulderDemand, ObjType::Native, 0, iTariff);
2040 288 : tariff(iTariff).nativeOffPeakEnergy =
2041 576 : AssignVariablePt(state, "OffPeakEnergy", true, varIsArgument, nativeOffPeakEnergy, ObjType::Native, 0, iTariff);
2042 288 : tariff(iTariff).nativeOffPeakDemand =
2043 576 : AssignVariablePt(state, "OffPeakDemand", true, varIsArgument, nativeOffPeakDemand, ObjType::Native, 0, iTariff);
2044 288 : tariff(iTariff).nativeMidPeakEnergy =
2045 576 : AssignVariablePt(state, "MidPeakEnergy", true, varIsArgument, nativeMidPeakEnergy, ObjType::Native, 0, iTariff);
2046 288 : tariff(iTariff).nativeMidPeakDemand =
2047 576 : AssignVariablePt(state, "MidPeakDemand", true, varIsArgument, nativeMidPeakDemand, ObjType::Native, 0, iTariff);
2048 288 : tariff(iTariff).nativePeakExceedsOffPeak =
2049 576 : AssignVariablePt(state, "PeakExceedsOffPeak", true, varIsArgument, nativePeakExceedsOffPeak, ObjType::Native, 0, iTariff);
2050 288 : tariff(iTariff).nativeOffPeakExceedsPeak =
2051 576 : AssignVariablePt(state, "OffPeakExceedsPeak", true, varIsArgument, nativeOffPeakExceedsPeak, ObjType::Native, 0, iTariff);
2052 288 : tariff(iTariff).nativePeakExceedsMidPeak =
2053 576 : AssignVariablePt(state, "PeakExceedsMidPeak", true, varIsArgument, nativePeakExceedsMidPeak, ObjType::Native, 0, iTariff);
2054 288 : tariff(iTariff).nativeMidPeakExceedsPeak =
2055 576 : AssignVariablePt(state, "MidPeakExceedsPeak", true, varIsArgument, nativeMidPeakExceedsPeak, ObjType::Native, 0, iTariff);
2056 288 : tariff(iTariff).nativePeakExceedsShoulder =
2057 576 : AssignVariablePt(state, "PeakExceedsShoulder", true, varIsArgument, nativePeakExceedsShoulder, ObjType::Native, 0, iTariff);
2058 288 : tariff(iTariff).nativeShoulderExceedsPeak =
2059 576 : AssignVariablePt(state, "ShoulderExceedsPeak", true, varIsArgument, nativeShoulderExceedsPeak, ObjType::Native, 0, iTariff);
2060 288 : tariff(iTariff).nativeIsWinter = AssignVariablePt(state, "IsWinter", true, varIsArgument, nativeIsWinter, ObjType::Native, 0, iTariff);
2061 288 : tariff(iTariff).nativeIsNotWinter =
2062 576 : AssignVariablePt(state, "IsNotWinter", true, varIsArgument, nativeIsNotWinter, ObjType::Native, 0, iTariff);
2063 288 : tariff(iTariff).nativeIsSpring = AssignVariablePt(state, "IsSpring", true, varIsArgument, nativeIsSpring, ObjType::Native, 0, iTariff);
2064 288 : tariff(iTariff).nativeIsNotSpring =
2065 576 : AssignVariablePt(state, "IsNotSpring", true, varIsArgument, nativeIsNotSpring, ObjType::Native, 0, iTariff);
2066 288 : tariff(iTariff).nativeIsSummer = AssignVariablePt(state, "IsSummer", true, varIsArgument, nativeIsSummer, ObjType::Native, 0, iTariff);
2067 288 : tariff(iTariff).nativeIsNotSummer =
2068 576 : AssignVariablePt(state, "IsNotSummer", true, varIsArgument, nativeIsNotSummer, ObjType::Native, 0, iTariff);
2069 288 : tariff(iTariff).nativeIsAutumn = AssignVariablePt(state, "IsAutumn", true, varIsArgument, nativeIsAutumn, ObjType::Native, 0, iTariff);
2070 288 : tariff(iTariff).nativeIsNotAutumn =
2071 576 : AssignVariablePt(state, "IsNotAutumn", true, varIsArgument, nativeIsNotAutumn, ObjType::Native, 0, iTariff);
2072 :
2073 288 : tariff(iTariff).nativePeakAndShoulderEnergy =
2074 576 : AssignVariablePt(state, "PeakAndShoulderEnergy", true, varIsArgument, nativePeakAndShoulderEnergy, ObjType::Native, 0, iTariff);
2075 288 : tariff(iTariff).nativePeakAndShoulderDemand =
2076 576 : AssignVariablePt(state, "PeakAndShoulderDemand", true, varIsArgument, nativePeakAndShoulderDemand, ObjType::Native, 0, iTariff);
2077 288 : tariff(iTariff).nativePeakAndMidPeakEnergy =
2078 576 : AssignVariablePt(state, "PeakAndMidPeakEnergy", true, varIsArgument, nativePeakAndMidPeakEnergy, ObjType::Native, 0, iTariff);
2079 288 : tariff(iTariff).nativePeakAndMidPeakDemand =
2080 576 : AssignVariablePt(state, "PeakAndMidPeakDemand", true, varIsArgument, nativePeakAndMidPeakDemand, ObjType::Native, 0, iTariff);
2081 288 : tariff(iTariff).nativeShoulderAndOffPeakEnergy =
2082 576 : AssignVariablePt(state, "ShoulderAndOffPeakEnergy", true, varIsArgument, nativeShoulderAndOffPeakEnergy, ObjType::Native, 0, iTariff);
2083 288 : tariff(iTariff).nativeShoulderAndOffPeakDemand =
2084 576 : AssignVariablePt(state, "ShoulderAndOffPeakDemand", true, varIsArgument, nativeShoulderAndOffPeakDemand, ObjType::Native, 0, iTariff);
2085 288 : tariff(iTariff).nativePeakAndOffPeakEnergy =
2086 576 : AssignVariablePt(state, "PeakAndOffPeakEnergy", true, varIsArgument, nativePeakAndOffPeakEnergy, ObjType::Native, 0, iTariff);
2087 288 : tariff(iTariff).nativePeakAndOffPeakDemand =
2088 576 : AssignVariablePt(state, "PeakAndOffPeakDemand", true, varIsArgument, nativePeakAndOffPeakDemand, ObjType::Native, 0, iTariff);
2089 288 : tariff(iTariff).nativeRealTimePriceCosts =
2090 576 : AssignVariablePt(state, "RealTimePriceCosts", true, varIsArgument, nativeRealTimePriceCosts, ObjType::Native, 0, iTariff);
2091 288 : tariff(iTariff).nativeAboveCustomerBaseCosts =
2092 576 : AssignVariablePt(state, "AboveCustomerBaseCosts", true, varIsArgument, nativeAboveCustomerBaseCosts, ObjType::Native, 0, iTariff);
2093 288 : tariff(iTariff).nativeBelowCustomerBaseCosts =
2094 576 : AssignVariablePt(state, "BelowCustomerBaseCosts", true, varIsArgument, nativeBelowCustomerBaseCosts, ObjType::Native, 0, iTariff);
2095 288 : tariff(iTariff).nativeAboveCustomerBaseEnergy =
2096 576 : AssignVariablePt(state, "AboveCustomerBaseEnergy", true, varIsArgument, nativeAboveCustomerBaseEnergy, ObjType::Native, 0, iTariff);
2097 288 : tariff(iTariff).nativeBelowCustomerBaseEnergy =
2098 576 : AssignVariablePt(state, "BelowCustomerBaseEnergy", true, varIsArgument, nativeBelowCustomerBaseEnergy, ObjType::Native, 0, iTariff);
2099 288 : tariff(iTariff).lastNative = state.dataEconTariff->numEconVar;
2100 : }
2101 95 : }
2102 :
2103 26 : int lookupOperator(std::string const &opString)
2104 : {
2105 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2106 : // DATE WRITTEN May 2004
2107 :
2108 : int lookupOperator;
2109 :
2110 26 : if (UtilityRoutines::SameString(opString, "Sum")) {
2111 6 : lookupOperator = opSUM;
2112 20 : } else if (UtilityRoutines::SameString(opString, "MULTIPLY")) {
2113 0 : lookupOperator = opMULTIPLY;
2114 20 : } else if (UtilityRoutines::SameString(opString, "MULT")) {
2115 0 : lookupOperator = opMULTIPLY;
2116 20 : } else if (UtilityRoutines::SameString(opString, "SUBTRACT")) {
2117 0 : lookupOperator = opSUBTRACT;
2118 20 : } else if (UtilityRoutines::SameString(opString, "SUBT")) {
2119 0 : lookupOperator = opSUBTRACT;
2120 20 : } else if (UtilityRoutines::SameString(opString, "DIVIDE")) {
2121 0 : lookupOperator = opDIVIDE;
2122 20 : } else if (UtilityRoutines::SameString(opString, "DIV")) {
2123 0 : lookupOperator = opDIVIDE;
2124 20 : } else if (UtilityRoutines::SameString(opString, "ABSOLUTE")) {
2125 0 : lookupOperator = opABSOLUTE;
2126 20 : } else if (UtilityRoutines::SameString(opString, "ABS")) {
2127 0 : lookupOperator = opABSOLUTE;
2128 20 : } else if (UtilityRoutines::SameString(opString, "INTEGER")) {
2129 0 : lookupOperator = opINTEGER;
2130 20 : } else if (UtilityRoutines::SameString(opString, "INT")) {
2131 0 : lookupOperator = opINTEGER;
2132 20 : } else if (UtilityRoutines::SameString(opString, "SIGN")) {
2133 0 : lookupOperator = opSIGN;
2134 20 : } else if (UtilityRoutines::SameString(opString, "ROUND")) {
2135 0 : lookupOperator = opROUND;
2136 20 : } else if (UtilityRoutines::SameString(opString, "Maximum")) {
2137 0 : lookupOperator = opMAXIMUM;
2138 20 : } else if (UtilityRoutines::SameString(opString, "MAX")) {
2139 0 : lookupOperator = opMAXIMUM;
2140 20 : } else if (UtilityRoutines::SameString(opString, "MINIMUM")) {
2141 0 : lookupOperator = opMINIMUM;
2142 20 : } else if (UtilityRoutines::SameString(opString, "MIN")) {
2143 0 : lookupOperator = opMINIMUM;
2144 20 : } else if (UtilityRoutines::SameString(opString, "EXCEEDS")) {
2145 0 : lookupOperator = opEXCEEDS;
2146 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALMINIMUM")) {
2147 0 : lookupOperator = opANNUALMINIMUM;
2148 20 : } else if (UtilityRoutines::SameString(opString, "ANMIN")) {
2149 0 : lookupOperator = opANNUALMINIMUM;
2150 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALMAXIMUM")) {
2151 0 : lookupOperator = opANNUALMAXIMUM;
2152 20 : } else if (UtilityRoutines::SameString(opString, "ANMAX")) {
2153 0 : lookupOperator = opANNUALMAXIMUM;
2154 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALSUM")) {
2155 0 : lookupOperator = opANNUALSUM;
2156 20 : } else if (UtilityRoutines::SameString(opString, "ANSUM")) {
2157 0 : lookupOperator = opANNUALSUM;
2158 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALAVERAGE")) {
2159 0 : lookupOperator = opANNUALAVERAGE;
2160 20 : } else if (UtilityRoutines::SameString(opString, "ANAVG")) {
2161 0 : lookupOperator = opANNUALAVERAGE;
2162 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALOR")) {
2163 0 : lookupOperator = opANNUALOR;
2164 20 : } else if (UtilityRoutines::SameString(opString, "ANOR")) {
2165 0 : lookupOperator = opANNUALOR;
2166 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALAND")) {
2167 0 : lookupOperator = opANNUALAND;
2168 20 : } else if (UtilityRoutines::SameString(opString, "ANAND")) {
2169 0 : lookupOperator = opANNUALAND;
2170 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALMAXIMUMZERO")) {
2171 0 : lookupOperator = opANNUALMAXIMUMZERO;
2172 20 : } else if (UtilityRoutines::SameString(opString, "ANMAXZ")) {
2173 0 : lookupOperator = opANNUALMAXIMUMZERO;
2174 20 : } else if (UtilityRoutines::SameString(opString, "ANNUALMINIMUMZERO")) {
2175 0 : lookupOperator = opANNUALMINIMUMZERO;
2176 20 : } else if (UtilityRoutines::SameString(opString, "ANMINZ")) {
2177 0 : lookupOperator = opANNUALMINIMUMZERO;
2178 20 : } else if (UtilityRoutines::SameString(opString, "IF")) {
2179 0 : lookupOperator = opIF;
2180 20 : } else if (UtilityRoutines::SameString(opString, "GREATERTHAN")) {
2181 0 : lookupOperator = opGREATERTHAN;
2182 20 : } else if (UtilityRoutines::SameString(opString, "GT")) {
2183 0 : lookupOperator = opGREATERTHAN;
2184 20 : } else if (UtilityRoutines::SameString(opString, "GREATEREQUAL")) {
2185 0 : lookupOperator = opGREATEREQUAL;
2186 20 : } else if (UtilityRoutines::SameString(opString, "GE")) {
2187 0 : lookupOperator = opGREATEREQUAL;
2188 20 : } else if (UtilityRoutines::SameString(opString, "LESSTHAN")) {
2189 0 : lookupOperator = opLESSTHAN;
2190 20 : } else if (UtilityRoutines::SameString(opString, "LT")) {
2191 0 : lookupOperator = opLESSTHAN;
2192 20 : } else if (UtilityRoutines::SameString(opString, "LESSEQUAL")) {
2193 0 : lookupOperator = opLESSEQUAL;
2194 20 : } else if (UtilityRoutines::SameString(opString, "LE")) {
2195 0 : lookupOperator = opLESSEQUAL;
2196 20 : } else if (UtilityRoutines::SameString(opString, "EQUAL")) {
2197 0 : lookupOperator = opEQUAL;
2198 20 : } else if (UtilityRoutines::SameString(opString, "EQ")) {
2199 0 : lookupOperator = opEQUAL;
2200 20 : } else if (UtilityRoutines::SameString(opString, "NOTEQUAL")) {
2201 0 : lookupOperator = opNOTEQUAL;
2202 20 : } else if (UtilityRoutines::SameString(opString, "NE")) {
2203 0 : lookupOperator = opNOTEQUAL;
2204 20 : } else if (UtilityRoutines::SameString(opString, "AND")) {
2205 0 : lookupOperator = opAND;
2206 20 : } else if (UtilityRoutines::SameString(opString, "OR")) {
2207 0 : lookupOperator = opOR;
2208 20 : } else if (UtilityRoutines::SameString(opString, "NOT")) {
2209 0 : lookupOperator = opNOT;
2210 20 : } else if (UtilityRoutines::SameString(opString, "FROM")) {
2211 0 : lookupOperator = opNOOP;
2212 20 : } else if (UtilityRoutines::SameString(opString, "ADD")) {
2213 0 : lookupOperator = opADD;
2214 : } else {
2215 20 : lookupOperator = 0;
2216 : }
2217 26 : return lookupOperator;
2218 : }
2219 :
2220 : //======================================================================================================================
2221 : //======================================================================================================================
2222 :
2223 : // DEFAULT COMPUTATION RELATED ROUTINES
2224 :
2225 : //======================================================================================================================
2226 : //======================================================================================================================
2227 :
2228 95 : void CreateDefaultComputation(EnergyPlusData &state)
2229 : {
2230 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2231 : // DATE WRITTEN June 2004
2232 :
2233 : // PURPOSE OF THIS SUBROUTINE:
2234 : // For most tariffs defined in EnergyPlus no specific
2235 : // ECONOMICS:COMPUTATION will be entered. In that case,
2236 : // a default sequence of computation steps needs to be
2237 : // created. This routine creates the default
2238 : // computation steps.
2239 : // Object Fields Depend On Fields
2240 : // Qualify namePt sourcePt
2241 : // thresholdPt
2242 : // Charge:Simple namePt sourcePt
2243 : // categoryPt costPerPt
2244 : // Charge:Block namePt sourcePt
2245 : // categoryPt blkSzMultPt
2246 : // remainingPt blkSzPt
2247 : // blkCostPt
2248 : // Ratchet namePt baselinePt
2249 : // adjustmentPt
2250 : // multiplierPt
2251 : // offsetPt
2252 : // These will be formed into expressions that look like
2253 : // namePt NOOP sourcePt thresholdPt
2254 : // The different Charges are combined using the SUM operation
2255 : // into categories.
2256 : // category SUM chg1Name chg2Name chg3Name
2257 : // Since the dependency array has one target and multiple
2258 : // parameters, remainingPt is shown as a seperate equation that
2259 : // depends on namePt for Charge:Block. The equation will not be
2260 : // displayed or processed except in the sort.
2261 : // remainingPt NOOP namePt
2262 : // Many lines of the computation will include just the name of
2263 : // a single variable which triggers the calculation for that
2264 : // charge, ratchet or qualify.
2265 : // chg1Name
2266 : // It is also possible that two variables referenced within one
2267 : // object could include a dependancy relationship also. For
2268 : // example, the blkSzPt could be calculated using the same sourePt
2269 : // in Charge:Block.
2270 :
2271 : // METHODOLOGY EMPLOYED:
2272 : // Since some ECONOMCIS:* objects depend on other variables
2273 : // first must create the order of when to perform the
2274 : // computations. First a dependancy table is created that
2275 : // indicates what variables are dependant on other variables.
2276 : // A directed acyclic graph (DAG) describes the general
2277 : // problem which is usually solved using a topological
2278 : // sorting algorithm.
2279 : // Each line/step is generated and put into the depend
2280 : // array. Also in the array are counts of how many items it
2281 : // depends on and a list of entries that are dependant on that
2282 : // line.
2283 :
2284 : int iTariff;
2285 : int iVar;
2286 : int jVar;
2287 : int kObj;
2288 : int mBlock;
2289 : int kOperand;
2290 : int curBasis;
2291 : int curSubtotal;
2292 : int curTotal;
2293 : int curObject;
2294 : int numNoDepend;
2295 : int referVar;
2296 : int loopCount;
2297 : bool remainingVarFlag;
2298 : int remainPt;
2299 :
2300 95 : auto &tariff(state.dataEconTariff->tariff);
2301 95 : auto &econVar(state.dataEconTariff->econVar);
2302 95 : auto &computation(state.dataEconTariff->computation);
2303 95 : auto &qualify(state.dataEconTariff->qualify);
2304 95 : auto &ratchet(state.dataEconTariff->ratchet);
2305 95 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
2306 95 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
2307 :
2308 : // for each tariff that does not have a UtilityCost:Computation object go through the variables
2309 383 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
2310 288 : if (!computation(iTariff).isUserDef) {
2311 : // clear all variables so that they are not active
2312 57061 : for (jVar = 1; jVar <= state.dataEconTariff->numEconVar; ++jVar) {
2313 56774 : econVar(jVar).activeNow = false;
2314 : }
2315 : // make all native variables active
2316 10906 : for (jVar = tariff(iTariff).firstNative; jVar <= tariff(iTariff).lastNative; ++jVar) {
2317 10619 : econVar(jVar).activeNow = true;
2318 : }
2319 : //"clear" the dependOn array
2320 287 : state.dataEconTariff->numOperand = 0;
2321 : // Define the preset equations (category sumation)
2322 287 : curTotal = tariff(iTariff).ptTotal;
2323 287 : curSubtotal = tariff(iTariff).ptSubtotal;
2324 287 : curBasis = tariff(iTariff).ptBasis;
2325 : // total SUM subtotal taxes
2326 287 : econVar(curTotal).Operator = opSUM;
2327 287 : econVar(curTotal).activeNow = true;
2328 287 : addOperand(state, curTotal, curSubtotal);
2329 287 : addOperand(state, curTotal, tariff(iTariff).ptTaxes);
2330 : // subtotal SUM basis adjustments surcharges
2331 287 : econVar(curSubtotal).Operator = opSUM;
2332 287 : econVar(curSubtotal).activeNow = true;
2333 287 : addOperand(state, curSubtotal, curBasis);
2334 287 : addOperand(state, curSubtotal, tariff(iTariff).ptAdjustment);
2335 287 : addOperand(state, curSubtotal, tariff(iTariff).ptSurcharge);
2336 : // basis SUM EnergyCharges DemandCharges ServiceCharges
2337 287 : econVar(curBasis).Operator = opSUM;
2338 287 : econVar(curBasis).activeNow = true;
2339 287 : addOperand(state, curBasis, tariff(iTariff).ptEnergyCharges);
2340 287 : addOperand(state, curBasis, tariff(iTariff).ptDemandCharges);
2341 287 : addOperand(state, curBasis, tariff(iTariff).ptServiceCharges);
2342 : // set up the equations for other objects
2343 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptEnergyCharges);
2344 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptDemandCharges);
2345 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptServiceCharges);
2346 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptAdjustment);
2347 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptSurcharge);
2348 287 : addChargesToOperand(state, iTariff, tariff(iTariff).ptTaxes);
2349 : // add the real time pricing to the energy charges
2350 287 : if (tariff(iTariff).chargeSchIndex != 0) {
2351 1 : addOperand(state, tariff(iTariff).ptEnergyCharges, tariff(iTariff).nativeRealTimePriceCosts);
2352 : }
2353 : // now add equations with NOOP to represent each object with its
2354 : // dependancies
2355 : // Qualify
2356 1012 : for (kObj = 1; kObj <= state.dataEconTariff->numQualify; ++kObj) {
2357 725 : if (qualify(kObj).tariffIndx == iTariff) {
2358 208 : curObject = qualify(kObj).namePt;
2359 208 : econVar(curObject).Operator = opNOOP;
2360 208 : econVar(curObject).activeNow = true;
2361 208 : addOperand(state, curObject, qualify(kObj).sourcePt);
2362 208 : addOperand(state, curObject, qualify(kObj).thresholdPt);
2363 : }
2364 : }
2365 : // Ratchet
2366 301 : for (kObj = 1; kObj <= state.dataEconTariff->numRatchet; ++kObj) {
2367 14 : if (ratchet(kObj).tariffIndx == iTariff) {
2368 1 : curObject = ratchet(kObj).namePt;
2369 1 : econVar(curObject).Operator = opNOOP;
2370 1 : econVar(curObject).activeNow = true;
2371 1 : addOperand(state, curObject, ratchet(kObj).baselinePt);
2372 1 : addOperand(state, curObject, ratchet(kObj).adjustmentPt);
2373 1 : addOperand(state, curObject, ratchet(kObj).multiplierPt);
2374 1 : addOperand(state, curObject, ratchet(kObj).offsetPt);
2375 : }
2376 : }
2377 : // ChargeSimple
2378 5327 : for (kObj = 1; kObj <= state.dataEconTariff->numChargeSimple; ++kObj) {
2379 5040 : if (chargeSimple(kObj).tariffIndx == iTariff) {
2380 1549 : curObject = chargeSimple(kObj).namePt;
2381 1549 : econVar(curObject).Operator = opNOOP;
2382 1549 : econVar(curObject).activeNow = true;
2383 1549 : addOperand(state, curObject, chargeSimple(kObj).sourcePt);
2384 1549 : addOperand(state, curObject, chargeSimple(kObj).costPerPt);
2385 : }
2386 : }
2387 : // ChargeBlock
2388 1232 : for (kObj = 1; kObj <= state.dataEconTariff->numChargeBlock; ++kObj) {
2389 945 : if (chargeBlock(kObj).tariffIndx == iTariff) {
2390 270 : curObject = chargeBlock(kObj).namePt;
2391 270 : econVar(curObject).Operator = opNOOP;
2392 270 : econVar(curObject).activeNow = true;
2393 270 : addOperand(state, curObject, chargeBlock(kObj).sourcePt);
2394 270 : addOperand(state, curObject, chargeBlock(kObj).blkSzMultPt);
2395 1172 : for (mBlock = 1; mBlock <= chargeBlock(kObj).numBlk; ++mBlock) {
2396 902 : addOperand(state, curObject, chargeBlock(kObj).blkSzPt(mBlock));
2397 902 : addOperand(state, curObject, chargeBlock(kObj).blkCostPt(mBlock));
2398 : }
2399 : // now add a new "equation" for dependency of remainingPt on namePt
2400 270 : remainPt = chargeBlock(kObj).remainingPt;
2401 270 : if (remainPt > 0) {
2402 1 : econVar(remainPt).Operator = opNOOP;
2403 1 : econVar(remainPt).activeNow = true;
2404 1 : addOperand(state, remainPt, curObject);
2405 : }
2406 : }
2407 : }
2408 : // Economic:Variable
2409 : // make all of the user defined variables as active
2410 57061 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
2411 56774 : if (econVar(iVar).tariffIndx == iTariff) {
2412 15587 : if (econVar(iVar).kindOfObj == ObjType::Variable) {
2413 83 : econVar(iVar).activeNow = true;
2414 : }
2415 : }
2416 : }
2417 : // make sure no compuation is already user defined
2418 287 : if (computation(iTariff).firstStep != 0) {
2419 0 : ShowWarningError(state, "In UtilityCost:Tariff: Overwriting user defined tariff " + tariff(iTariff).tariffName);
2420 : }
2421 : // initialize the computation
2422 287 : computation(iTariff).computeName = "Autogenerated - " + tariff(iTariff).tariffName;
2423 287 : computation(iTariff).firstStep = state.dataEconTariff->numSteps + 1;
2424 287 : computation(iTariff).lastStep = -1; // this will be incremented by addStep
2425 287 : computation(iTariff).isUserDef = false;
2426 : // now all "equations" are defined, treat the variables with the list
2427 : // of dependancies as a directed acyclic graph and use "count down" algorithm
2428 : // to do a topological sort of the variables into the order for computation
2429 : // First, clear the counters
2430 57061 : for (jVar = 1; jVar <= state.dataEconTariff->numEconVar; ++jVar) {
2431 56774 : econVar(jVar).cntMeDependOn = 0;
2432 : }
2433 : // Second, add up the number of dependancies on each variable
2434 57061 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
2435 56774 : if (econVar(iVar).activeNow) {
2436 15300 : if (econVar(iVar).lastOperand >= econVar(iVar).firstOperand) {
2437 3474 : econVar(iVar).cntMeDependOn = 1 + econVar(iVar).lastOperand - econVar(iVar).firstOperand;
2438 : }
2439 : }
2440 : }
2441 : // Third, start removing items with zero connections and decrease each
2442 : // counter.
2443 287 : numNoDepend = -1;
2444 287 : loopCount = 0;
2445 2709 : while ((numNoDepend != 0) || (loopCount > 100000)) {
2446 1211 : numNoDepend = 0;
2447 232531 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
2448 231320 : if (econVar(iVar).activeNow) {
2449 : // find a variable that has no more dangling dependancies
2450 18139 : if (econVar(iVar).cntMeDependOn == 0) {
2451 : // If the variable is a native variable then
2452 : // IF (econVar(iVar)%kindOfObj .NE. iEconVarObjType::Native) THEN
2453 15300 : if ((econVar(iVar).kindOfObj != ObjType::Native) && (econVar(iVar).kindOfObj != ObjType::Variable)) {
2454 4598 : if (econVar(iVar).lastOperand >= econVar(iVar).firstOperand) {
2455 : // transfer variables and operator to the computation and list of steps
2456 : // go through the operands backwards (end of line is evaluated first)
2457 9789 : for (kOperand = econVar(iVar).lastOperand; kOperand >= econVar(iVar).firstOperand; --kOperand) {
2458 6315 : incrementSteps(state);
2459 6315 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = state.dataEconTariff->operand(kOperand);
2460 : }
2461 : // append the operator (either SUM or NOOP)
2462 3474 : incrementSteps(state);
2463 3474 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = econVar(iVar).Operator;
2464 : // append the variable itself
2465 3474 : incrementSteps(state);
2466 3474 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = iVar;
2467 : // at the end of the line show a zero to clear the stack
2468 3474 : incrementSteps(state);
2469 3474 : state.dataEconTariff->steps(state.dataEconTariff->numSteps) = 0;
2470 : }
2471 : }
2472 : // go through each other variable looking for places where this variable is used
2473 : // and decrement their counters.
2474 3004731 : for (jVar = 1; jVar <= state.dataEconTariff->numEconVar; ++jVar) {
2475 2989431 : if (econVar(jVar).activeNow) {
2476 729077 : for (kOperand = econVar(jVar).firstOperand; kOperand <= econVar(jVar).lastOperand; ++kOperand) {
2477 311614 : referVar = state.dataEconTariff->operand(kOperand);
2478 311614 : if (iVar == referVar) {
2479 6315 : --econVar(jVar).cntMeDependOn;
2480 : // for each variable that has been decremented to zero increment the counter
2481 6315 : if (econVar(jVar).cntMeDependOn <= 0) {
2482 3474 : ++numNoDepend;
2483 : }
2484 : }
2485 : }
2486 : }
2487 : }
2488 : // make the variable inactive
2489 15300 : econVar(iVar).activeNow = false;
2490 : }
2491 : }
2492 : }
2493 1211 : ++loopCount;
2494 : }
2495 287 : if (loopCount > 100000) {
2496 0 : ShowWarningError(state,
2497 0 : "UtilityCost:Tariff: Loop count exceeded when counting dependancies in tariff: " + tariff(iTariff).tariffName);
2498 : }
2499 : // make sure that all variables associated with the tariff are included
2500 287 : remainingVarFlag = false;
2501 57061 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
2502 56774 : if (econVar(iVar).activeNow) {
2503 0 : remainingVarFlag = true;
2504 : }
2505 : }
2506 287 : if (remainingVarFlag) {
2507 0 : ShowWarningError(state,
2508 0 : "CreateDefaultComputation: In UtilityCost:Computation: Circular or invalid dependencies found in tariff: " +
2509 0 : tariff(iTariff).tariffName);
2510 0 : ShowContinueError(state, " UtilityCost variables that may have invalid dependencies and the variables they are dependant on.");
2511 0 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
2512 0 : if (econVar(iVar).tariffIndx == iTariff) {
2513 0 : if (econVar(iVar).activeNow) {
2514 0 : ShowContinueError(state, " " + econVar(iVar).name);
2515 0 : for (kOperand = econVar(iVar).firstOperand; kOperand <= econVar(iVar).lastOperand; ++kOperand) {
2516 0 : ShowContinueError(state, " -> " + econVar(state.dataEconTariff->operand(kOperand)).name);
2517 : }
2518 : }
2519 : }
2520 : }
2521 : }
2522 : // set the end of the computations
2523 287 : computation(iTariff).lastStep = state.dataEconTariff->numSteps;
2524 287 : if (computation(iTariff).firstStep >= computation(iTariff).lastStep) {
2525 0 : computation(iTariff).firstStep = 0;
2526 0 : computation(iTariff).lastStep = -1;
2527 0 : ShowWarningError(state,
2528 : "CreateDefaultComputation: In UtilityCost:Computation: No lines in the auto generated computation can be "
2529 0 : "interpreted in tariff: " +
2530 0 : tariff(iTariff).tariffName);
2531 : }
2532 : }
2533 : }
2534 95 : }
2535 :
2536 9978 : void addOperand(EnergyPlusData &state, int const varMe, int const varOperand)
2537 : {
2538 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2539 : // DATE WRITTEN July 2004
2540 :
2541 : // Used by CreateDefaultComputation to create the dependancy
2542 : // relationship in the EconVar array
2543 :
2544 9978 : int constexpr sizeIncrement(100);
2545 :
2546 9978 : auto &econVar(state.dataEconTariff->econVar);
2547 :
2548 9978 : if (varOperand != 0) {
2549 : // increment the numOperand and allocate/reallocate the array
2550 : // if necessary
2551 6315 : if (!allocated(state.dataEconTariff->operand)) {
2552 95 : state.dataEconTariff->operand.allocate(sizeIncrement);
2553 95 : state.dataEconTariff->sizeOperand = sizeIncrement;
2554 95 : state.dataEconTariff->numOperand = 1;
2555 : } else {
2556 6220 : ++state.dataEconTariff->numOperand;
2557 : // if larger than current size grow the array
2558 6220 : if (state.dataEconTariff->numOperand > state.dataEconTariff->sizeOperand) {
2559 0 : state.dataEconTariff->operand.redimension(state.dataEconTariff->sizeOperand += sizeIncrement);
2560 : }
2561 : }
2562 : // now add the dependency relationship
2563 6315 : state.dataEconTariff->operand(state.dataEconTariff->numOperand) = varOperand;
2564 6315 : econVar(varMe).lastOperand = state.dataEconTariff->numOperand;
2565 : // if it is the first time addOperand was called with the varMe value
2566 : // then set the first pointer as well
2567 6315 : if (varMe != state.dataEconTariff->addOperand_prevVarMe) {
2568 3474 : econVar(varMe).firstOperand = state.dataEconTariff->numOperand;
2569 3474 : state.dataEconTariff->addOperand_prevVarMe = varMe;
2570 : }
2571 : }
2572 9978 : }
2573 :
2574 1722 : void addChargesToOperand(EnergyPlusData &state, int const curTariff, int const curPointer)
2575 : {
2576 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2577 : // DATE WRITTEN July 2004
2578 :
2579 : // Used by CreateDefaultComputation to create the "equation"
2580 : // for the categories that are summations of ECONOMICS:CHARGES:BLOCK
2581 : // and ECONOMICS:CHARGES:SIMPLE
2582 :
2583 : int kObj;
2584 :
2585 1722 : auto &econVar(state.dataEconTariff->econVar);
2586 1722 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
2587 1722 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
2588 :
2589 1722 : econVar(curPointer).Operator = opSUM;
2590 1722 : econVar(curPointer).activeNow = true;
2591 31962 : for (kObj = 1; kObj <= state.dataEconTariff->numChargeSimple; ++kObj) {
2592 30240 : if (chargeSimple(kObj).tariffIndx == curTariff) {
2593 9294 : if (chargeSimple(kObj).categoryPt == curPointer) {
2594 1549 : addOperand(state, curPointer, chargeSimple(kObj).namePt);
2595 : }
2596 : }
2597 : }
2598 7392 : for (kObj = 1; kObj <= state.dataEconTariff->numChargeBlock; ++kObj) {
2599 5670 : if (chargeBlock(kObj).tariffIndx == curTariff) {
2600 1620 : if (chargeBlock(kObj).categoryPt == curPointer) {
2601 269 : addOperand(state, curPointer, chargeBlock(kObj).namePt);
2602 : }
2603 : }
2604 : }
2605 1722 : }
2606 :
2607 : //======================================================================================================================
2608 : //======================================================================================================================
2609 :
2610 : // GATHER TIMESTEP VALUES ROUTINE
2611 :
2612 : //======================================================================================================================
2613 : //======================================================================================================================
2614 :
2615 70176 : void GatherForEconomics(EnergyPlusData &state)
2616 : {
2617 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2618 : // DATE WRITTEN June 2004
2619 :
2620 : // Gathers the data each timestep and updates the arrays
2621 : // holding the data that will be used by the tariff
2622 : // calculation.
2623 :
2624 : using ScheduleManager::GetCurrentScheduleValue;
2625 :
2626 : int iTariff;
2627 : Real64 curInstantValue;
2628 : Real64 curDemand;
2629 : Real64 curEnergy;
2630 : bool isGood;
2631 : int curSeason;
2632 : int curMonth;
2633 : int curPeriod;
2634 : Real64 curRTPprice; // real time price
2635 : Real64 curRTPbaseline; // real time price customer baseline load
2636 : Real64 curRTPenergy; // energy applied to real time price
2637 : Real64 curRTPcost; // cost for energy for current time
2638 :
2639 70176 : auto &tariff(state.dataEconTariff->tariff);
2640 :
2641 70176 : if (state.dataEconTariff->numTariff >= 1) {
2642 0 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
2643 0 : isGood = false;
2644 : // if the meter is defined get the value
2645 0 : if (tariff(iTariff).reportMeterIndx != 0) {
2646 0 : curInstantValue = GetCurrentMeterValue(state, tariff(iTariff).reportMeterIndx);
2647 : } else {
2648 0 : curInstantValue = 0.0;
2649 : }
2650 : // remember the demand is still energy over a period of time divided by the
2651 : // length of time. This gathers the energy also.
2652 0 : tariff(iTariff).collectEnergy += curInstantValue;
2653 0 : tariff(iTariff).collectTime += state.dataGlobal->TimeStepZoneSec;
2654 : // added *SecInHour when adding RTP support August 2008
2655 0 : if (tariff(iTariff).collectTime >= tariff(iTariff).demWinTime * DataGlobalConstants::SecInHour) {
2656 : // get current value that has been converted into desired units
2657 0 : curDemand = tariff(iTariff).demandConv * tariff(iTariff).collectEnergy / tariff(iTariff).collectTime;
2658 0 : curEnergy = tariff(iTariff).energyConv * tariff(iTariff).collectEnergy;
2659 : // get the schedule values
2660 : // remember no confirmation of schedule values occurs prior to now
2661 0 : if (tariff(iTariff).seasonSchIndex != 0) {
2662 0 : curSeason = GetCurrentScheduleValue(state, tariff(iTariff).seasonSchIndex);
2663 : } else {
2664 0 : curSeason = 1;
2665 : }
2666 0 : if (tariff(iTariff).periodSchIndex != 0) {
2667 0 : curPeriod = GetCurrentScheduleValue(state, tariff(iTariff).periodSchIndex);
2668 : } else {
2669 0 : curPeriod = 1;
2670 : }
2671 0 : if (tariff(iTariff).monthSchIndex != 0) {
2672 0 : curMonth = GetCurrentScheduleValue(state, tariff(iTariff).monthSchIndex);
2673 : } else {
2674 : // #7814 - Have to be careful with DST. tariff::seasonForMonth is overwritten at each timestep, and only the last value is
2675 : // retained, so make sure to capture the right one
2676 0 : if ((state.dataGlobal->HourOfDay + state.dataEnvrn->DSTIndicator) <= 24) {
2677 0 : curMonth = state.dataEnvrn->Month;
2678 : } else {
2679 0 : curMonth = state.dataEnvrn->MonthTomorrow;
2680 : }
2681 : }
2682 0 : if (isWithinRange(state, curSeason, 1, 5)) {
2683 0 : if (isWithinRange(state, curPeriod, 1, 4)) {
2684 0 : if (isWithinRange(state, curMonth, 1, 12)) {
2685 0 : isGood = true;
2686 : }
2687 : }
2688 : }
2689 0 : if (isGood) {
2690 0 : tariff(iTariff).seasonForMonth(curMonth) = curSeason;
2691 0 : tariff(iTariff).gatherEnergy(curMonth, curPeriod) += curEnergy;
2692 0 : if (tariff(iTariff).gatherDemand(curMonth, curPeriod) < curDemand) {
2693 0 : tariff(iTariff).gatherDemand(curMonth, curPeriod) = curDemand;
2694 : }
2695 : } else {
2696 0 : ShowWarningError(state, "UtilityCost:Tariff: While gathering for: " + tariff(iTariff).tariffName);
2697 0 : ShowContinueError(state, "Invalid schedule values - outside of range");
2698 : }
2699 : // Real Time Pricing
2700 0 : if (tariff(iTariff).chargeSchIndex != 0) {
2701 0 : curRTPprice = GetCurrentScheduleValue(state, tariff(iTariff).chargeSchIndex);
2702 : // if customer baseline load schedule is used, subtract that off of the
2703 : // current energy
2704 0 : if (tariff(iTariff).baseUseSchIndex != 0) {
2705 0 : curRTPbaseline = GetCurrentScheduleValue(state, tariff(iTariff).baseUseSchIndex);
2706 0 : curRTPenergy = curEnergy - curRTPbaseline;
2707 : } else {
2708 0 : curRTPenergy = curEnergy;
2709 : }
2710 : // calculate the real time cost for current times energy
2711 0 : curRTPcost = curRTPenergy * curRTPprice;
2712 0 : tariff(iTariff).RTPcost(curMonth) += curRTPcost;
2713 0 : if (curRTPcost > 0) {
2714 0 : tariff(iTariff).RTPaboveBaseCost(curMonth) += curRTPcost;
2715 : } else {
2716 0 : tariff(iTariff).RTPbelowBaseCost(curMonth) += curRTPcost;
2717 : }
2718 0 : if (curRTPenergy > 0) {
2719 0 : tariff(iTariff).RTPaboveBaseEnergy(curMonth) += curRTPenergy;
2720 : } else {
2721 0 : tariff(iTariff).RTPbelowBaseEnergy(curMonth) += curRTPenergy;
2722 : }
2723 : }
2724 : // reset the counters
2725 0 : tariff(iTariff).collectEnergy = 0.0;
2726 0 : tariff(iTariff).collectTime = 0.0;
2727 : }
2728 : }
2729 : }
2730 70176 : }
2731 :
2732 1451 : bool isWithinRange(EnergyPlusData &state, int const testVal, int const minThreshold, int const maxThreshold)
2733 : {
2734 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2735 : // DATE WRITTEN July 2004
2736 :
2737 : // Simple function to check if an integer is equal to or between
2738 : // two other values.
2739 :
2740 : bool isWithinRange;
2741 :
2742 1451 : if (maxThreshold < minThreshold) {
2743 0 : ShowWarningError(state, "UtilityCost: Invalid thresholds in IsWithinRange routine.");
2744 : }
2745 1451 : if ((testVal <= maxThreshold) && (testVal >= minThreshold)) {
2746 1451 : isWithinRange = true;
2747 : } else {
2748 0 : isWithinRange = false;
2749 : }
2750 1451 : return isWithinRange;
2751 : }
2752 :
2753 : //======================================================================================================================
2754 : //======================================================================================================================
2755 :
2756 : // COMPUTE THE UTILITY BILLS AND CREATE REPORTS
2757 :
2758 : //======================================================================================================================
2759 : //======================================================================================================================
2760 :
2761 769 : void ComputeTariff(EnergyPlusData &state)
2762 : {
2763 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
2764 : // DATE WRITTEN July 2004
2765 :
2766 : // Perform the calculation steps to compute the monthly
2767 : // utility bills for the user entered tariffs.
2768 : // The list of steps for the tariff computation are in order
2769 : // for stack based computation (reverse polish notation)
2770 :
2771 : // values used in specific operations
2772 1537 : Array1D<Real64> a(MaxNumMonths);
2773 : int aPt;
2774 1537 : Array1D<Real64> b(MaxNumMonths);
2775 : int bPt;
2776 1537 : Array1D<Real64> c(MaxNumMonths);
2777 : int cPt;
2778 1537 : Array1D<Real64> d(MaxNumMonths);
2779 :
2780 : int iTariff;
2781 : int jStep;
2782 : int lMonth;
2783 : int nVar;
2784 : int curStep;
2785 769 : int constexpr noVar(0);
2786 :
2787 : Real64 hugeValue;
2788 : Real64 annualAggregate;
2789 : int annualCnt;
2790 :
2791 769 : auto &econVar(state.dataEconTariff->econVar);
2792 769 : auto &computation(state.dataEconTariff->computation);
2793 :
2794 769 : if (!(state.files.outputControl.tabular || state.files.outputControl.sqlite)) {
2795 1 : state.dataOutRptTab->WriteTabularFiles = false;
2796 1 : return;
2797 : }
2798 :
2799 768 : hugeValue = HUGE_(Real64());
2800 : // Clear the isEvaluated flags for all economics variables.
2801 16244 : for (nVar = 1; nVar <= state.dataEconTariff->numEconVar; ++nVar) {
2802 15476 : econVar(nVar).isEvaluated = false;
2803 : }
2804 768 : if (state.dataEconTariff->numTariff >= 1) {
2805 94 : state.dataOutRptTab->WriteTabularFiles = true;
2806 94 : setNativeVariables(state);
2807 379 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
2808 16870 : for (jStep = computation(iTariff).firstStep; jStep <= computation(iTariff).lastStep; ++jStep) {
2809 16585 : curStep = state.dataEconTariff->steps(jStep);
2810 : {
2811 16585 : auto const SELECT_CASE_var(curStep);
2812 16585 : if (SELECT_CASE_var == 0) { // end of line - assign variable and clear stack
2813 : // if the stack still has two items on it then assign the values to the
2814 : // pointer otherwise if it follows a NOOP line it will only have one item
2815 : // that has already been assigned and no further action is required.
2816 3442 : if (state.dataEconTariff->topOfStack >= 2) {
2817 1450 : popStack(state, b, bPt); // pop the variable pointer
2818 1450 : popStack(state, a, aPt); // pop the values
2819 1450 : if (isWithinRange(state, bPt, 1, state.dataEconTariff->numEconVar)) {
2820 1450 : econVar(bPt).values = a;
2821 : }
2822 : }
2823 3442 : state.dataEconTariff->topOfStack = 0;
2824 13143 : } else if ((SELECT_CASE_var >= 1)) { // all positive values are a reference to an econVar
2825 9701 : pushStack(state, econVar(curStep).values, curStep);
2826 3442 : } else if (SELECT_CASE_var == opSUM) {
2827 1450 : a = 0.0;
2828 5534 : for (int kStack = 1, kStack_end = state.dataEconTariff->topOfStack; kStack <= kStack_end;
2829 : ++kStack) { // popStack modifies topOfStack
2830 4084 : popStack(state, b, bPt);
2831 4084 : a += b;
2832 : }
2833 1450 : pushStack(state, a, noVar);
2834 1992 : } else if (SELECT_CASE_var == opMULTIPLY) {
2835 0 : popStack(state, b, bPt);
2836 0 : popStack(state, a, aPt);
2837 0 : pushStack(state, a * b, noVar);
2838 1992 : } else if (SELECT_CASE_var == opSUBTRACT) {
2839 0 : popStack(state, b, bPt);
2840 0 : popStack(state, a, aPt);
2841 0 : pushStack(state, b - a, noVar);
2842 1992 : } else if (SELECT_CASE_var == opDIVIDE) {
2843 0 : popStack(state, a, aPt);
2844 0 : popStack(state, b, bPt);
2845 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2846 0 : if (b(lMonth) != 0) {
2847 0 : c(lMonth) = a(lMonth) / b(lMonth);
2848 : } else {
2849 0 : c(lMonth) = 0.0;
2850 : }
2851 : }
2852 0 : pushStack(state, c, noVar);
2853 1992 : } else if (SELECT_CASE_var == opABSOLUTE) {
2854 0 : popStack(state, a, aPt);
2855 0 : pushStack(state, ObjexxFCL::abs(a), noVar);
2856 1992 : } else if (SELECT_CASE_var == opINTEGER) {
2857 0 : popStack(state, a, aPt);
2858 0 : pushStack(state, Array1D_double(Array1D_int(a)), noVar);
2859 1992 : } else if (SELECT_CASE_var == opSIGN) {
2860 0 : popStack(state, a, aPt);
2861 0 : pushStack(state, sign(1.0, a), noVar);
2862 : // CASE (opROUND)
2863 : // CALL popStack(b,bPt)
2864 : // CALL popStack(a,aPt)
2865 : // DO lMonth = 1,MaxNumMonths
2866 : // IF ((b(lMonth) .LE. 5) .AND. (b(lMonth) .GE. -5)) THEN
2867 : // c(lMonth) = FLOAT(INT(a(lMonth) / (10 ** b(lMonth))) * (10 ** b(lMonth)))
2868 : // END IF
2869 : // END DO
2870 : // CALL pushStack(c,noVar)
2871 1992 : } else if (SELECT_CASE_var == opMAXIMUM) {
2872 0 : a = -hugeValue;
2873 0 : for (int kStack = 1, kStack_end = state.dataEconTariff->topOfStack; kStack <= kStack_end;
2874 : ++kStack) { // popStack modifies topOfStack
2875 0 : popStack(state, b, bPt);
2876 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2877 0 : if (b(lMonth) > a(lMonth)) {
2878 0 : a(lMonth) = b(lMonth);
2879 : }
2880 : }
2881 : }
2882 0 : pushStack(state, a, noVar);
2883 1992 : } else if (SELECT_CASE_var == opMINIMUM) {
2884 0 : a = hugeValue;
2885 0 : for (int kStack = 1, kStack_end = state.dataEconTariff->topOfStack; kStack <= kStack_end;
2886 : ++kStack) { // popStack modifies topOfStack
2887 0 : popStack(state, b, bPt);
2888 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2889 0 : if (b(lMonth) < a(lMonth)) {
2890 0 : a(lMonth) = b(lMonth);
2891 : }
2892 : }
2893 : }
2894 0 : pushStack(state, a, noVar);
2895 1992 : } else if (SELECT_CASE_var == opEXCEEDS) {
2896 0 : popStack(state, b, bPt);
2897 0 : popStack(state, a, aPt);
2898 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2899 0 : if (a(lMonth) > b(lMonth)) {
2900 0 : c(lMonth) = a(lMonth) - b(lMonth);
2901 : } else {
2902 0 : c(lMonth) = 0.0;
2903 : }
2904 : }
2905 0 : pushStack(state, c, noVar);
2906 1992 : } else if (SELECT_CASE_var == opANNUALMINIMUM) {
2907 : // takes the minimum but ignores zeros
2908 0 : annualAggregate = hugeValue;
2909 0 : popStack(state, a, aPt);
2910 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2911 0 : if (a(lMonth) != 0) {
2912 0 : if (a(lMonth) < annualAggregate) {
2913 0 : annualAggregate = a(lMonth);
2914 : }
2915 : }
2916 : }
2917 : // if all months are zero then hugeValue still in annual but should be zero
2918 0 : if (annualAggregate == hugeValue) {
2919 0 : annualAggregate = 0.0;
2920 : }
2921 0 : c = annualAggregate;
2922 0 : pushStack(state, c, noVar);
2923 1992 : } else if (SELECT_CASE_var == opANNUALMAXIMUM) {
2924 : // takes the maximum but ignores zeros
2925 0 : annualAggregate = -hugeValue;
2926 0 : popStack(state, a, aPt);
2927 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2928 0 : if (a(lMonth) != 0) {
2929 0 : if (a(lMonth) > annualAggregate) {
2930 0 : annualAggregate = a(lMonth);
2931 : }
2932 : }
2933 : }
2934 : // if all months are zero then hugeValue still in annual but should be zero
2935 0 : if (annualAggregate == -hugeValue) {
2936 0 : annualAggregate = 0.0;
2937 : }
2938 0 : c = annualAggregate;
2939 0 : pushStack(state, c, noVar);
2940 1992 : } else if (SELECT_CASE_var == opANNUALSUM) {
2941 : // takes the maximum but ignores zeros
2942 0 : annualAggregate = 0.0;
2943 0 : popStack(state, a, aPt);
2944 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2945 0 : annualAggregate += a(lMonth);
2946 : }
2947 0 : c = annualAggregate;
2948 0 : pushStack(state, c, noVar);
2949 1992 : } else if (SELECT_CASE_var == opANNUALAVERAGE) {
2950 : // takes the annual sum but ignores zeros
2951 0 : annualAggregate = 0.0;
2952 0 : annualCnt = 0;
2953 0 : popStack(state, a, aPt);
2954 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2955 0 : if (a(lMonth) != 0) {
2956 0 : annualAggregate += a(lMonth);
2957 0 : ++annualCnt;
2958 : }
2959 : }
2960 : // if all months are zero then return zero
2961 0 : if (annualCnt != 0) {
2962 0 : c = annualAggregate / annualCnt;
2963 : } else {
2964 0 : c = 0.0;
2965 : }
2966 0 : pushStack(state, c, noVar);
2967 1992 : } else if (SELECT_CASE_var == opANNUALOR) {
2968 0 : annualCnt = 0;
2969 0 : popStack(state, a, aPt);
2970 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2971 0 : if (a(lMonth) != 0) {
2972 0 : ++annualCnt;
2973 : }
2974 : }
2975 : // if any months is not zero then "true"
2976 0 : if (annualCnt >= 1) {
2977 0 : c = 1.0;
2978 : } else {
2979 0 : c = 0.0;
2980 : }
2981 0 : pushStack(state, c, noVar);
2982 1992 : } else if (SELECT_CASE_var == opANNUALAND) {
2983 0 : annualCnt = 0;
2984 0 : popStack(state, a, aPt);
2985 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
2986 0 : if (a(lMonth) != 0) {
2987 0 : ++annualCnt;
2988 : }
2989 : }
2990 : // if all months are not zero then "true"
2991 0 : if (annualCnt == MaxNumMonths) {
2992 0 : c = 1.0;
2993 : } else {
2994 0 : c = 0.0;
2995 : }
2996 0 : pushStack(state, c, noVar);
2997 1992 : } else if (SELECT_CASE_var == opANNUALMAXIMUMZERO) {
2998 : // takes the maximum including zeros
2999 0 : annualAggregate = -hugeValue;
3000 0 : popStack(state, a, aPt);
3001 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3002 0 : if (a(lMonth) > annualAggregate) {
3003 0 : annualAggregate = a(lMonth);
3004 : }
3005 : }
3006 0 : c = annualAggregate;
3007 0 : pushStack(state, c, noVar);
3008 1992 : } else if (SELECT_CASE_var == opANNUALMINIMUMZERO) {
3009 : // takes the maximum including zeros
3010 0 : annualAggregate = hugeValue;
3011 0 : popStack(state, a, aPt);
3012 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3013 0 : if (a(lMonth) < annualAggregate) {
3014 0 : annualAggregate = a(lMonth);
3015 : }
3016 : }
3017 0 : c = annualAggregate;
3018 0 : pushStack(state, c, noVar);
3019 1992 : } else if (SELECT_CASE_var == opIF) {
3020 0 : popStack(state, c, cPt);
3021 0 : popStack(state, b, bPt);
3022 0 : popStack(state, a, aPt);
3023 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3024 0 : if (a(lMonth) != 0) {
3025 0 : d(lMonth) = b(lMonth);
3026 : } else {
3027 0 : d(lMonth) = c(lMonth);
3028 : }
3029 : }
3030 0 : pushStack(state, d, noVar);
3031 1992 : } else if (SELECT_CASE_var == opGREATERTHAN) {
3032 0 : popStack(state, b, bPt);
3033 0 : popStack(state, a, aPt);
3034 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3035 0 : if (a(lMonth) > b(lMonth)) {
3036 0 : c(lMonth) = 1.0;
3037 : } else {
3038 0 : c(lMonth) = 0.0;
3039 : }
3040 : }
3041 0 : pushStack(state, c, noVar);
3042 1992 : } else if (SELECT_CASE_var == opGREATEREQUAL) {
3043 0 : popStack(state, b, bPt);
3044 0 : popStack(state, a, aPt);
3045 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3046 0 : if (a(lMonth) >= b(lMonth)) {
3047 0 : c(lMonth) = 1.0;
3048 : } else {
3049 0 : c(lMonth) = 0.0;
3050 : }
3051 : }
3052 0 : pushStack(state, c, noVar);
3053 1992 : } else if (SELECT_CASE_var == opLESSTHAN) {
3054 0 : popStack(state, b, bPt);
3055 0 : popStack(state, a, aPt);
3056 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3057 0 : if (a(lMonth) < b(lMonth)) {
3058 0 : c(lMonth) = 1.0;
3059 : } else {
3060 0 : c(lMonth) = 0.0;
3061 : }
3062 : }
3063 0 : pushStack(state, c, noVar);
3064 1992 : } else if (SELECT_CASE_var == opLESSEQUAL) {
3065 0 : popStack(state, b, bPt);
3066 0 : popStack(state, a, aPt);
3067 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3068 0 : if (a(lMonth) <= b(lMonth)) {
3069 0 : c(lMonth) = 1.0;
3070 : } else {
3071 0 : c(lMonth) = 0.0;
3072 : }
3073 : }
3074 0 : pushStack(state, c, noVar);
3075 1992 : } else if (SELECT_CASE_var == opEQUAL) {
3076 0 : popStack(state, b, bPt);
3077 0 : popStack(state, a, aPt);
3078 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3079 0 : if (a(lMonth) == b(lMonth)) {
3080 0 : c(lMonth) = 1.0;
3081 : } else {
3082 0 : c(lMonth) = 0.0;
3083 : }
3084 : }
3085 0 : pushStack(state, c, noVar);
3086 1992 : } else if (SELECT_CASE_var == opNOTEQUAL) {
3087 0 : popStack(state, b, bPt);
3088 0 : popStack(state, a, aPt);
3089 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3090 0 : if (a(lMonth) != b(lMonth)) {
3091 0 : c(lMonth) = 1.0;
3092 : } else {
3093 0 : c(lMonth) = 0.0;
3094 : }
3095 : }
3096 0 : pushStack(state, c, noVar);
3097 1992 : } else if (SELECT_CASE_var == opAND) {
3098 0 : popStack(state, b, bPt);
3099 0 : popStack(state, a, aPt);
3100 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3101 0 : if ((a(lMonth) != 0) && (b(lMonth) != 0)) {
3102 0 : c(lMonth) = 1.0;
3103 : } else {
3104 0 : c(lMonth) = 0.0;
3105 : }
3106 : }
3107 0 : pushStack(state, c, noVar);
3108 1992 : } else if (SELECT_CASE_var == opOR) {
3109 0 : popStack(state, b, bPt);
3110 0 : popStack(state, a, aPt);
3111 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3112 0 : if ((a(lMonth) != 0) || (b(lMonth) != 0)) {
3113 0 : c(lMonth) = 1.0;
3114 : } else {
3115 0 : c(lMonth) = 0.0;
3116 : }
3117 : }
3118 0 : pushStack(state, c, noVar);
3119 1992 : } else if (SELECT_CASE_var == opNOT) {
3120 0 : popStack(state, a, aPt);
3121 0 : for (lMonth = 1; lMonth <= MaxNumMonths; ++lMonth) {
3122 0 : if (a(lMonth) == 0) {
3123 0 : c(lMonth) = 1.0;
3124 : } else {
3125 0 : c(lMonth) = 0.0;
3126 : }
3127 : }
3128 0 : pushStack(state, c, noVar);
3129 1992 : } else if (SELECT_CASE_var == opADD) {
3130 0 : popStack(state, b, bPt);
3131 0 : popStack(state, a, aPt);
3132 0 : pushStack(state, a + b, noVar);
3133 1992 : } else if (SELECT_CASE_var == opNOOP) {
3134 : // do nothing but clear the stack
3135 1992 : state.dataEconTariff->topOfStack = 0;
3136 : // No longer pushing a zero to fix bug
3137 : // and push zero
3138 : // a = 0
3139 : }
3140 : }
3141 : }
3142 285 : checkMinimumMonthlyCharge(state, iTariff);
3143 : }
3144 94 : selectTariff(state);
3145 94 : LEEDtariffReporting(state);
3146 : }
3147 : }
3148 :
3149 11151 : void pushStack(EnergyPlusData &state, Array1A<Real64> const monthlyArray, int const variablePointer)
3150 : {
3151 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3152 : // DATE WRITTEN July 2004
3153 :
3154 : // A stack is used in the evaluation of the tariff since
3155 : // the variables and operators are in a reverse polish
3156 : // notation order. The stack operates on a last-in
3157 : // first out basis. The stack consists of both a pointer
3158 : // to the variable and the twelve monthly values.
3159 : // This routine puts an item on the top of the stack.
3160 :
3161 11151 : monthlyArray.dim(MaxNumMonths);
3162 :
3163 22302 : Array1D<Real64> curMonthlyArray(MaxNumMonths);
3164 11151 : int constexpr sizeIncrement(50);
3165 :
3166 11151 : auto &stack(state.dataEconTariff->stack);
3167 11151 : auto &econVar(state.dataEconTariff->econVar);
3168 11151 : auto &tariff(state.dataEconTariff->tariff);
3169 :
3170 11151 : curMonthlyArray = monthlyArray;
3171 11151 : if (!allocated(stack)) {
3172 94 : stack.allocate(sizeIncrement);
3173 94 : state.dataEconTariff->sizeStack = sizeIncrement;
3174 94 : state.dataEconTariff->topOfStack = 1;
3175 : } else {
3176 11057 : ++state.dataEconTariff->topOfStack;
3177 : // if larger than current size grow the array
3178 11057 : if (state.dataEconTariff->topOfStack > state.dataEconTariff->sizeStack) {
3179 0 : stack.redimension(state.dataEconTariff->sizeStack += sizeIncrement);
3180 : }
3181 : }
3182 : // now push the values on to the stack
3183 11151 : stack(state.dataEconTariff->topOfStack).varPt = variablePointer;
3184 : // check if variable has been evaluated if it is CHARGE:SIMPLE, CHARGE:BLOCK, RATCHET, or QUALIFY
3185 : // if it has not overwrite the values for monthlyArray with the evaluated values
3186 11151 : if (variablePointer != 0) {
3187 9701 : if (!econVar(variablePointer).isEvaluated) {
3188 :
3189 7900 : switch (econVar(variablePointer).kindOfObj) {
3190 1525 : case ObjType::ChargeSimple:
3191 1525 : evaluateChargeSimple(state, variablePointer);
3192 1525 : break;
3193 263 : case ObjType::ChargeBlock:
3194 263 : evaluateChargeBlock(state, variablePointer);
3195 263 : break;
3196 1 : case ObjType::Ratchet:
3197 1 : evaluateRatchet(state, variablePointer);
3198 1 : break;
3199 206 : case ObjType::Qualify:
3200 206 : evaluateQualify(state, variablePointer);
3201 206 : break;
3202 0 : case ObjType::Invalid:
3203 0 : ShowWarningError(state, "UtilityCost variable not defined: " + econVar(variablePointer).name);
3204 0 : ShowContinueError(state, " In tariff: " + tariff(econVar(variablePointer).tariffIndx).tariffName);
3205 0 : ShowContinueError(state, " This may be the result of a misspelled variable name in the UtilityCost:Computation object.");
3206 0 : ShowContinueError(state, " All zero values will be assumed for this variable.");
3207 0 : break;
3208 5905 : case ObjType::Variable:
3209 : case ObjType::Category:
3210 : case ObjType::Native:
3211 : case ObjType::AssignCompute:
3212 : case ObjType::Tariff:
3213 : case ObjType::Computation:
3214 : // do nothing
3215 5905 : break;
3216 0 : default:
3217 0 : ShowWarningError(state,
3218 0 : format("UtilityCost Debugging issue. Invalid kind of variable used (pushStack). {} in tariff: {}",
3219 0 : econVar(variablePointer).kindOfObj,
3220 0 : tariff(econVar(variablePointer).tariffIndx).tariffName));
3221 : }
3222 : // if the serviceCharges are being evaluated add in the monthly charges
3223 7900 : if (econVar(variablePointer).specific == catServiceCharges) addMonthlyCharge(state, variablePointer);
3224 : // get the results of performing the evaulation - should have been
3225 : // put into the econVar values
3226 7900 : curMonthlyArray = econVar(variablePointer).values;
3227 : }
3228 : }
3229 : // now assign
3230 11151 : stack(state.dataEconTariff->topOfStack).values = curMonthlyArray;
3231 11151 : }
3232 :
3233 6984 : void popStack(EnergyPlusData &state, Array1A<Real64> monthlyArray, int &variablePointer)
3234 : {
3235 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3236 : // DATE WRITTEN July 2004
3237 :
3238 : // A stack is used in the evaluation of the tariff since
3239 : // the variables and operators are in a reverse polish
3240 : // notation order. The stack operates on a last-in
3241 : // first out basis. The stack consists of both a pointer
3242 : // to the variable and the twelve monthly values.
3243 : // This routine returns the item on the top of the stack
3244 : // and removes it from the stack.
3245 :
3246 6984 : monthlyArray.dim(MaxNumMonths);
3247 :
3248 6984 : auto &stack(state.dataEconTariff->stack);
3249 :
3250 6984 : if (state.dataEconTariff->topOfStack >= 1) {
3251 6984 : variablePointer = stack(state.dataEconTariff->topOfStack).varPt;
3252 6984 : monthlyArray = stack(state.dataEconTariff->topOfStack).values;
3253 : } else {
3254 0 : ShowWarningError(state,
3255 0 : "UtilityCost:Tariff: stack underflow in calculation of utility bills. On variable: " +
3256 0 : state.dataEconTariff->econVar(variablePointer).name);
3257 0 : variablePointer = 0;
3258 0 : monthlyArray = 0.0;
3259 0 : state.dataEconTariff->topOfStack = 0;
3260 : }
3261 6984 : --state.dataEconTariff->topOfStack;
3262 6984 : }
3263 :
3264 1525 : void evaluateChargeSimple(EnergyPlusData &state, int const usingVariable)
3265 : {
3266 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3267 : // DATE WRITTEN July 2004
3268 :
3269 : int curTariff;
3270 : int indexInChg;
3271 3050 : Array1D<Real64> sourceVals(MaxNumMonths);
3272 3050 : Array1D<Real64> costPer(MaxNumMonths);
3273 3050 : Array1D<Real64> resultChg(MaxNumMonths);
3274 3050 : Array1D<Real64> seasonMask(MaxNumMonths);
3275 :
3276 1525 : auto &econVar(state.dataEconTariff->econVar);
3277 1525 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
3278 1525 : auto &tariff(state.dataEconTariff->tariff);
3279 :
3280 1525 : curTariff = econVar(usingVariable).tariffIndx;
3281 1525 : indexInChg = econVar(usingVariable).index;
3282 :
3283 : // check the tariff - make sure they match
3284 1525 : if (chargeSimple(indexInChg).namePt != usingVariable) {
3285 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. ChargeSimple index does not match variable pointer.");
3286 0 : ShowContinueError(state, " Between: " + econVar(usingVariable).name);
3287 0 : ShowContinueError(state, " And: " + econVar(chargeSimple(indexInChg).namePt).name);
3288 : }
3289 1525 : if (chargeSimple(indexInChg).tariffIndx != curTariff) {
3290 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. ChargeSimple index does not match tariff index.");
3291 0 : ShowContinueError(state, " Between: " + tariff(curTariff).tariffName);
3292 0 : ShowContinueError(state, " And: " + tariff(chargeSimple(indexInChg).tariffIndx).tariffName);
3293 : }
3294 : // data from the Charge:Simple
3295 1525 : sourceVals = econVar(chargeSimple(indexInChg).sourcePt).values;
3296 : // determine if costPer should be based on variable or value
3297 1525 : if (chargeSimple(indexInChg).costPerPt != 0) {
3298 81 : costPer = econVar(chargeSimple(indexInChg).costPerPt).values;
3299 : } else {
3300 1444 : costPer = chargeSimple(indexInChg).costPerVal;
3301 : }
3302 : // find proper season mask
3303 : {
3304 1525 : auto const SELECT_CASE_var(chargeSimple(indexInChg).season);
3305 1525 : if (SELECT_CASE_var == seasonSummer) {
3306 85 : seasonMask = econVar(tariff(curTariff).nativeIsSummer).values;
3307 1440 : } else if (SELECT_CASE_var == seasonWinter) {
3308 55 : seasonMask = econVar(tariff(curTariff).nativeIsWinter).values;
3309 1385 : } else if (SELECT_CASE_var == seasonSpring) {
3310 0 : seasonMask = econVar(tariff(curTariff).nativeIsSpring).values;
3311 1385 : } else if (SELECT_CASE_var == seasonFall) {
3312 0 : seasonMask = econVar(tariff(curTariff).nativeIsAutumn).values;
3313 1385 : } else if (SELECT_CASE_var == seasonAnnual) {
3314 1385 : seasonMask = 1.0; // all months are 1
3315 : }
3316 : }
3317 : // finally perform calculations
3318 1525 : resultChg = sourceVals * costPer * seasonMask;
3319 : // store the cost in the name of the variable
3320 1525 : econVar(usingVariable).values = resultChg;
3321 : // set the flag that it has been evaluated so it won't be evaluated multiple times
3322 1525 : econVar(usingVariable).isEvaluated = true;
3323 1525 : }
3324 :
3325 263 : void evaluateChargeBlock(EnergyPlusData &state, int const usingVariable)
3326 : {
3327 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3328 : // DATE WRITTEN July 2004
3329 :
3330 : int curTariff;
3331 : int indexInChg;
3332 : int iBlk;
3333 : int jMonth;
3334 526 : Array1D<Real64> sourceVals(MaxNumMonths);
3335 526 : Array1D<Real64> blkSzMult(MaxNumMonths);
3336 526 : Array1D<Real64> remainVals(MaxNumMonths);
3337 526 : Array1D<Real64> resultChg(MaxNumMonths);
3338 526 : Array1D<Real64> amountForBlk(MaxNumMonths);
3339 526 : Array1D<Real64> curBlkSz(MaxNumMonths);
3340 526 : Array1D<Real64> curBlkCost(MaxNumMonths);
3341 526 : Array1D<Real64> seasonMask(MaxNumMonths);
3342 : bool flagAllZero;
3343 :
3344 263 : auto &econVar(state.dataEconTariff->econVar);
3345 263 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
3346 263 : auto &tariff(state.dataEconTariff->tariff);
3347 :
3348 263 : curTariff = econVar(usingVariable).tariffIndx;
3349 263 : indexInChg = econVar(usingVariable).index;
3350 :
3351 : // check the tariff - make sure they match
3352 263 : if (chargeBlock(indexInChg).namePt != usingVariable) {
3353 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. chargeBlock index does not match variable pointer.");
3354 0 : ShowContinueError(state, " Between: " + econVar(usingVariable).name);
3355 0 : ShowContinueError(state, " And: " + econVar(chargeBlock(indexInChg).namePt).name);
3356 : }
3357 263 : if (chargeBlock(indexInChg).tariffIndx != curTariff) {
3358 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. chargeBlock index does not match tariff index.");
3359 0 : ShowContinueError(state, " Between: " + tariff(curTariff).tariffName);
3360 0 : ShowContinueError(state, " And: " + tariff(chargeBlock(indexInChg).tariffIndx).tariffName);
3361 : }
3362 : // data from the chargeBlock
3363 263 : sourceVals = econVar(chargeBlock(indexInChg).sourcePt).values;
3364 : // find proper season mask
3365 : {
3366 263 : auto const SELECT_CASE_var(chargeBlock(indexInChg).season);
3367 263 : if (SELECT_CASE_var == seasonSummer) {
3368 14 : seasonMask = econVar(tariff(curTariff).nativeIsSummer).values;
3369 249 : } else if (SELECT_CASE_var == seasonWinter) {
3370 6 : seasonMask = econVar(tariff(curTariff).nativeIsWinter).values;
3371 243 : } else if (SELECT_CASE_var == seasonSpring) {
3372 0 : seasonMask = econVar(tariff(curTariff).nativeIsSpring).values;
3373 243 : } else if (SELECT_CASE_var == seasonFall) {
3374 0 : seasonMask = econVar(tariff(curTariff).nativeIsAutumn).values;
3375 243 : } else if (SELECT_CASE_var == seasonAnnual) {
3376 243 : seasonMask = 1.0; // all months are 1
3377 : }
3378 : }
3379 : // get block size multiplier
3380 263 : if (chargeBlock(indexInChg).blkSzMultPt != 0) {
3381 83 : blkSzMult = econVar(chargeBlock(indexInChg).blkSzMultPt).values;
3382 : } else {
3383 180 : blkSzMult = chargeBlock(indexInChg).blkSzMultVal;
3384 : }
3385 : // initially set the remaing energy or demand to the source
3386 263 : remainVals = sourceVals;
3387 : // initially set the result (cost) to zero
3388 263 : resultChg = 0.0;
3389 : // loop through the blocks performing calculations
3390 1142 : for (iBlk = 1; iBlk <= chargeBlock(indexInChg).numBlk; ++iBlk) {
3391 879 : if (chargeBlock(indexInChg).blkSzPt(iBlk) != 0) {
3392 0 : curBlkSz = econVar(chargeBlock(indexInChg).blkSzPt(iBlk)).values;
3393 : } else {
3394 879 : curBlkSz = chargeBlock(indexInChg).blkSzVal(iBlk);
3395 : }
3396 879 : if (chargeBlock(indexInChg).blkCostPt(iBlk) != 0) {
3397 0 : curBlkCost = econVar(chargeBlock(indexInChg).blkCostPt(iBlk)).values;
3398 : } else {
3399 879 : curBlkCost = chargeBlock(indexInChg).blkCostVal(iBlk);
3400 : }
3401 : // loop through the months
3402 11427 : for (jMonth = 1; jMonth <= MaxNumMonths; ++jMonth) {
3403 10548 : if (seasonMask(jMonth) == 1) {
3404 : // IF ((curBlkSz(jMonth) * blkSzMult(jMonth)) .GT. remainVals(jMonth)) THEN - CR 6547
3405 9924 : if (blkSzMult(jMonth) != 0) {
3406 7380 : if (curBlkSz(jMonth) > (remainVals(jMonth) / blkSzMult(jMonth))) {
3407 7380 : amountForBlk(jMonth) = remainVals(jMonth);
3408 : } else {
3409 0 : amountForBlk(jMonth) = curBlkSz(jMonth) * blkSzMult(jMonth);
3410 : }
3411 : } else {
3412 2544 : amountForBlk(jMonth) = 0.0;
3413 : }
3414 9924 : resultChg(jMonth) += amountForBlk(jMonth) * curBlkCost(jMonth);
3415 9924 : remainVals(jMonth) -= amountForBlk(jMonth);
3416 : }
3417 : }
3418 : }
3419 : // store the amount remaining if a variable is specified
3420 263 : if (chargeBlock(indexInChg).remainingPt != 0) {
3421 1 : econVar(chargeBlock(indexInChg).remainingPt).values = remainVals;
3422 : } else {
3423 262 : flagAllZero = true;
3424 3406 : for (jMonth = 1; jMonth <= MaxNumMonths; ++jMonth) {
3425 3144 : if (seasonMask(jMonth) == 1) {
3426 2904 : if (remainVals(jMonth) != 0) {
3427 0 : flagAllZero = false;
3428 : }
3429 : }
3430 : }
3431 262 : if (!flagAllZero) {
3432 0 : ShowWarningError(state, "UtilityCost:Tariff Not all energy or demand was assigned in the block charge: " + econVar(usingVariable).name);
3433 : }
3434 : }
3435 : // store the cost in the name of the variable
3436 263 : econVar(usingVariable).values = resultChg;
3437 : // set the flag that it has been evaluated so it won't be evaluated multiple times
3438 263 : econVar(usingVariable).isEvaluated = true;
3439 263 : }
3440 :
3441 1 : void evaluateRatchet(EnergyPlusData &state, int const usingVariable)
3442 : {
3443 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3444 : // DATE WRITTEN July 2004
3445 :
3446 : int curTariff;
3447 : int indexInChg;
3448 2 : Array1D<Real64> baselineVals(MaxNumMonths);
3449 2 : Array1D<Real64> adjustmentVals(MaxNumMonths);
3450 2 : Array1D<Real64> multiplierVals(MaxNumMonths);
3451 2 : Array1D<Real64> offsetVals(MaxNumMonths);
3452 2 : Array1D<Real64> seasonFromMask(MaxNumMonths);
3453 2 : Array1D<Real64> seasonToMask(MaxNumMonths);
3454 1 : bool isMonthly(false);
3455 2 : Array1D<Real64> adjSeasonal(MaxNumMonths);
3456 2 : Array1D<Real64> adjPeak(MaxNumMonths);
3457 2 : Array1D<Real64> maxAdjBase(MaxNumMonths);
3458 : Real64 maximumVal;
3459 : int iMonth;
3460 2 : Array1D<Real64> finalResult(MaxNumMonths);
3461 :
3462 1 : auto &econVar(state.dataEconTariff->econVar);
3463 1 : auto &tariff(state.dataEconTariff->tariff);
3464 1 : auto &ratchet(state.dataEconTariff->ratchet);
3465 :
3466 1 : curTariff = econVar(usingVariable).tariffIndx;
3467 1 : indexInChg = econVar(usingVariable).index;
3468 :
3469 : // check the tariff - make sure they match
3470 1 : if (ratchet(indexInChg).namePt != usingVariable) {
3471 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Ratchet index does not match variable pointer.");
3472 0 : ShowContinueError(state, " Between: " + econVar(usingVariable).name);
3473 0 : ShowContinueError(state, " And: " + econVar(ratchet(indexInChg).namePt).name);
3474 : }
3475 1 : if (ratchet(indexInChg).tariffIndx != curTariff) {
3476 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Ratchet index does not match tariff index.");
3477 0 : ShowContinueError(state, " Between: " + tariff(curTariff).tariffName);
3478 0 : ShowContinueError(state, " And: " + tariff(ratchet(indexInChg).tariffIndx).tariffName);
3479 : }
3480 : // data from the Ratchet
3481 1 : baselineVals = econVar(ratchet(indexInChg).baselinePt).values;
3482 1 : adjustmentVals = econVar(ratchet(indexInChg).adjustmentPt).values;
3483 : // determine if multiplier should be based on variable or value
3484 1 : if (ratchet(indexInChg).multiplierPt != 0) {
3485 0 : multiplierVals = econVar(ratchet(indexInChg).multiplierPt).values;
3486 : } else {
3487 1 : multiplierVals = ratchet(indexInChg).multiplierVal;
3488 : }
3489 : // determine if offset should be based on variable or value
3490 1 : if (ratchet(indexInChg).offsetPt != 0) {
3491 0 : offsetVals = econVar(ratchet(indexInChg).offsetPt).values;
3492 : } else {
3493 1 : offsetVals = ratchet(indexInChg).offsetVal;
3494 : }
3495 : // find proper season from mask
3496 : {
3497 1 : auto const SELECT_CASE_var(ratchet(indexInChg).seasonFrom);
3498 1 : if (SELECT_CASE_var == seasonSummer) {
3499 1 : seasonFromMask = econVar(tariff(curTariff).nativeIsSummer).values;
3500 1 : isMonthly = false;
3501 0 : } else if (SELECT_CASE_var == seasonWinter) {
3502 0 : seasonFromMask = econVar(tariff(curTariff).nativeIsWinter).values;
3503 0 : isMonthly = false;
3504 0 : } else if (SELECT_CASE_var == seasonSpring) {
3505 0 : seasonFromMask = econVar(tariff(curTariff).nativeIsSpring).values;
3506 0 : isMonthly = false;
3507 0 : } else if (SELECT_CASE_var == seasonFall) {
3508 0 : seasonFromMask = econVar(tariff(curTariff).nativeIsAutumn).values;
3509 0 : isMonthly = false;
3510 0 : } else if (SELECT_CASE_var == seasonAnnual) {
3511 0 : seasonFromMask = 1.0; // all months are 1
3512 0 : isMonthly = false;
3513 0 : } else if (SELECT_CASE_var == seasonMonthly) {
3514 0 : seasonFromMask = 1.0; // all months are 1
3515 0 : isMonthly = true;
3516 : } else {
3517 0 : assert(false);
3518 : }
3519 : }
3520 : // find proper season to mask
3521 : {
3522 1 : auto const SELECT_CASE_var(ratchet(indexInChg).seasonTo);
3523 1 : if (SELECT_CASE_var == seasonSummer) {
3524 0 : seasonToMask = econVar(tariff(curTariff).nativeIsSummer).values;
3525 1 : } else if (SELECT_CASE_var == seasonWinter) {
3526 0 : seasonToMask = econVar(tariff(curTariff).nativeIsWinter).values;
3527 1 : } else if (SELECT_CASE_var == seasonSpring) {
3528 0 : seasonToMask = econVar(tariff(curTariff).nativeIsSpring).values;
3529 1 : } else if (SELECT_CASE_var == seasonFall) {
3530 0 : seasonToMask = econVar(tariff(curTariff).nativeIsAutumn).values;
3531 1 : } else if (SELECT_CASE_var == seasonAnnual) {
3532 1 : seasonToMask = 1.0; // all months are 1
3533 : }
3534 : }
3535 : // finally perform calculations
3536 1 : if (isMonthly) {
3537 0 : adjSeasonal = adjustmentVals;
3538 : } else {
3539 1 : maximumVal = -HUGE_(Real64());
3540 13 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3541 12 : if (seasonFromMask(iMonth) == 1) {
3542 0 : if (adjustmentVals(iMonth) > maximumVal) {
3543 0 : maximumVal = adjustmentVals(iMonth);
3544 : }
3545 : }
3546 : }
3547 1 : adjSeasonal = maximumVal;
3548 : }
3549 13 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3550 : // calculate adjusted peak value after offset and multiplier
3551 12 : adjPeak(iMonth) = (adjSeasonal(iMonth) + offsetVals(iMonth)) * multiplierVals(iMonth);
3552 : // the maximum of the adjustment and the baseline
3553 12 : if (adjPeak(iMonth) > baselineVals(iMonth)) {
3554 0 : maxAdjBase(iMonth) = adjPeak(iMonth);
3555 : } else {
3556 12 : maxAdjBase(iMonth) = baselineVals(iMonth);
3557 : }
3558 : }
3559 13 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3560 12 : if (seasonToMask(iMonth) == 1) {
3561 12 : finalResult(iMonth) = maxAdjBase(iMonth);
3562 : } else {
3563 0 : finalResult(iMonth) = baselineVals(iMonth);
3564 : }
3565 : }
3566 : // store the cost in the name of the variable
3567 1 : econVar(usingVariable).values = finalResult;
3568 : // set the flag that it has been evaluated so it won't be evaluated multiple times
3569 1 : econVar(usingVariable).isEvaluated = true;
3570 1 : }
3571 :
3572 206 : void evaluateQualify(EnergyPlusData &state, int const usingVariable)
3573 : {
3574 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3575 : // DATE WRITTEN July 2004
3576 :
3577 : int curTariff;
3578 : int indexInQual;
3579 412 : Array1D<Real64> sourceVals(MaxNumMonths);
3580 412 : Array1D<Real64> thresholdVals(MaxNumMonths);
3581 412 : Array1D_int monthsQualify(MaxNumMonths);
3582 412 : Array1D<Real64> seasonMask(MaxNumMonths);
3583 : bool curIsMaximum;
3584 : bool curIsConsecutive;
3585 : int curNumberOfMonths;
3586 : int adjNumberOfMonths;
3587 : int iMonth;
3588 : bool isQualified;
3589 : int monthsInSeason;
3590 : int cntAllQualMonths;
3591 : int cntConsecQualMonths;
3592 : int maxConsecQualMonths;
3593 :
3594 206 : auto &econVar(state.dataEconTariff->econVar);
3595 206 : auto &qualify(state.dataEconTariff->qualify);
3596 206 : auto &tariff(state.dataEconTariff->tariff);
3597 :
3598 206 : curTariff = econVar(usingVariable).tariffIndx;
3599 206 : indexInQual = econVar(usingVariable).index;
3600 : // check the tariff - make sure they match
3601 206 : if (qualify(indexInQual).namePt != usingVariable) {
3602 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Qualify index does not match variable pointer.");
3603 0 : ShowContinueError(state, " Between: " + econVar(usingVariable).name);
3604 0 : ShowContinueError(state, " And: " + econVar(qualify(indexInQual).namePt).name);
3605 : }
3606 206 : if (qualify(indexInQual).tariffIndx != curTariff) {
3607 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Qualify index does not match tariff index.");
3608 0 : ShowContinueError(state, " Between: " + tariff(curTariff).tariffName);
3609 0 : ShowContinueError(state, " And: " + tariff(qualify(indexInQual).tariffIndx).tariffName);
3610 : }
3611 : // data from the Qualify
3612 206 : sourceVals = econVar(qualify(indexInQual).sourcePt).values;
3613 206 : curIsMaximum = qualify(indexInQual).isMaximum;
3614 206 : curIsConsecutive = qualify(indexInQual).isConsecutive;
3615 206 : curNumberOfMonths = qualify(indexInQual).numberOfMonths;
3616 : // determine if threshold should be based on variable or value
3617 206 : if (qualify(indexInQual).thresholdPt != 0) {
3618 0 : thresholdVals = econVar(qualify(indexInQual).thresholdPt).values;
3619 : } else {
3620 206 : thresholdVals = qualify(indexInQual).thresholdVal;
3621 : }
3622 : // find proper season mask
3623 : {
3624 206 : auto const SELECT_CASE_var(qualify(indexInQual).season);
3625 206 : if (SELECT_CASE_var == seasonSummer) {
3626 0 : seasonMask = econVar(tariff(curTariff).nativeIsSummer).values;
3627 206 : } else if (SELECT_CASE_var == seasonWinter) {
3628 0 : seasonMask = econVar(tariff(curTariff).nativeIsWinter).values;
3629 206 : } else if (SELECT_CASE_var == seasonSpring) {
3630 0 : seasonMask = econVar(tariff(curTariff).nativeIsSpring).values;
3631 206 : } else if (SELECT_CASE_var == seasonFall) {
3632 0 : seasonMask = econVar(tariff(curTariff).nativeIsAutumn).values;
3633 206 : } else if (SELECT_CASE_var == seasonAnnual) {
3634 206 : seasonMask = 1.0; // all months are 1
3635 : }
3636 : }
3637 : // any months with no energy use are excluded from the qualification process
3638 2678 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3639 2472 : if (econVar(tariff(curTariff).nativeTotalEnergy).values(iMonth) == 0) {
3640 2472 : seasonMask(iMonth) = 0.0;
3641 : }
3642 : }
3643 : // finally perform calculations
3644 : // loop through the months
3645 206 : monthsInSeason = 0;
3646 2678 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3647 2472 : if (seasonMask(iMonth) == 1) {
3648 0 : ++monthsInSeason;
3649 : // use threshold as maximum or minimum
3650 0 : if (curIsMaximum) {
3651 0 : if (sourceVals(iMonth) > thresholdVals(iMonth)) {
3652 0 : monthsQualify(iMonth) = 0; // greater than maximum threshold so it is not qualified
3653 : } else {
3654 0 : monthsQualify(iMonth) = 1; // less than maximum threshold so it is qualified
3655 : }
3656 : } else {
3657 0 : if (sourceVals(iMonth) < thresholdVals(iMonth)) {
3658 0 : monthsQualify(iMonth) = 0; // less than minimum threshold so it is not qualified
3659 : } else {
3660 0 : monthsQualify(iMonth) = 1; // greater than minimum threshold so it is qualified
3661 : }
3662 : }
3663 : } else {
3664 2472 : monthsQualify(iMonth) = -1; // flag that indicates not part of the season
3665 : }
3666 : }
3667 : // see if the number of months is longer then the number of months and adjust
3668 206 : if (curNumberOfMonths > monthsInSeason) {
3669 206 : adjNumberOfMonths = monthsInSeason;
3670 : } else {
3671 0 : adjNumberOfMonths = curNumberOfMonths;
3672 : }
3673 : // now that each month is qualified or not, depending on the type of test see if the entire qualify passe or not
3674 206 : cntAllQualMonths = 0;
3675 206 : cntConsecQualMonths = 0;
3676 206 : maxConsecQualMonths = 0;
3677 2678 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3678 : {
3679 2472 : auto const SELECT_CASE_var(monthsQualify(iMonth));
3680 2472 : if (SELECT_CASE_var == 1) { // qualified
3681 0 : ++cntAllQualMonths;
3682 0 : ++cntConsecQualMonths;
3683 : // see if the count is greater then the previous count and if it is make it the new count
3684 0 : if (cntConsecQualMonths > maxConsecQualMonths) {
3685 0 : maxConsecQualMonths = cntConsecQualMonths;
3686 : }
3687 2472 : } else if (SELECT_CASE_var == 0) { // not qualified
3688 : // reset the counter on consecutive months
3689 0 : cntConsecQualMonths = 0;
3690 : }
3691 : }
3692 : }
3693 : // if test is for consecutive months
3694 206 : if (curIsConsecutive) {
3695 0 : if (maxConsecQualMonths >= adjNumberOfMonths) {
3696 0 : isQualified = true;
3697 : } else {
3698 0 : isQualified = false;
3699 : }
3700 : } else { // count not consecutive
3701 206 : if (cntAllQualMonths >= adjNumberOfMonths) {
3702 206 : isQualified = true;
3703 : } else {
3704 0 : isQualified = false;
3705 : }
3706 : }
3707 : // now update the tariff level qualifier - only update if the tariff is still qualified
3708 : // and the current qualifer fails.
3709 206 : if (tariff(curTariff).isQualified) {
3710 206 : if (!isQualified) {
3711 0 : tariff(curTariff).isQualified = false;
3712 0 : tariff(curTariff).ptDisqualifier = usingVariable;
3713 : }
3714 : }
3715 : // store the cost in the name of the variable
3716 206 : econVar(usingVariable).values = monthsQualify;
3717 : // set the flag that it has been evaluated so it won't be evaluated multiple times
3718 206 : econVar(usingVariable).isEvaluated = true;
3719 206 : }
3720 :
3721 285 : void addMonthlyCharge(EnergyPlusData &state, int const usingVariable)
3722 : {
3723 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3724 : // DATE WRITTEN July 2004
3725 :
3726 : // Include the monthly charges in the calculations
3727 :
3728 : int curTariff;
3729 :
3730 285 : auto &econVar(state.dataEconTariff->econVar);
3731 285 : auto &tariff(state.dataEconTariff->tariff);
3732 :
3733 285 : curTariff = econVar(usingVariable).tariffIndx;
3734 : // check the tariff - make sure they match
3735 285 : if (tariff(curTariff).ptServiceCharges != usingVariable) {
3736 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging issue. Tariff index for service charge does not match variable pointer.");
3737 0 : ShowContinueError(state, " Between: " + tariff(curTariff).tariffName);
3738 0 : ShowContinueError(state, " And: " + tariff(tariff(curTariff).ptServiceCharges).tariffName);
3739 : }
3740 285 : if (tariff(curTariff).monthChgPt != 0) {
3741 1 : econVar(usingVariable).values += econVar(tariff(curTariff).monthChgPt).values;
3742 : } else {
3743 284 : econVar(usingVariable).values += tariff(curTariff).monthChgVal;
3744 : }
3745 : // zero out months with no energy consumption
3746 : // curTotalEnergy = tariff(curTariff)%nativeTotalEnergy
3747 : // DO iMonth = 1, MaxNumMonths
3748 : // IF (econVar(curTotalEnergy)%values(iMonth) .EQ. 0) THEN
3749 : // econVar(usingVariable)%values(iMonth) = 0
3750 : // END IF
3751 : // END DO
3752 285 : }
3753 :
3754 285 : void checkMinimumMonthlyCharge(EnergyPlusData &state, int const curTariff)
3755 : {
3756 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3757 : // DATE WRITTEN August 2008
3758 :
3759 : // Check if the total is as big as the minimum monthly charge
3760 :
3761 : int iMonth;
3762 : int totalVar;
3763 : int minMonVar;
3764 :
3765 285 : auto &tariff(state.dataEconTariff->tariff);
3766 285 : auto &econVar(state.dataEconTariff->econVar);
3767 :
3768 285 : totalVar = tariff(curTariff).ptTotal;
3769 285 : minMonVar = tariff(curTariff).minMonthChgPt;
3770 : // if a variable is defined use that
3771 285 : if (minMonVar != 0) {
3772 0 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3773 0 : if (econVar(totalVar).values(iMonth) < econVar(minMonVar).values(iMonth)) {
3774 0 : econVar(totalVar).values(iMonth) = econVar(minMonVar).values(iMonth);
3775 : }
3776 : }
3777 : } else { // use the constant value
3778 3705 : for (iMonth = 1; iMonth <= MaxNumMonths; ++iMonth) {
3779 3420 : if (econVar(totalVar).values(iMonth) < tariff(curTariff).minMonthChgVal) {
3780 24 : econVar(totalVar).values(iMonth) = tariff(curTariff).minMonthChgVal;
3781 : }
3782 : }
3783 : }
3784 285 : }
3785 :
3786 94 : void setNativeVariables(EnergyPlusData &state)
3787 : {
3788 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3789 : // DATE WRITTEN July 2004
3790 :
3791 : // Set up the "built in" i.e. native variables that hold
3792 : // the energy and demand from the simulation.
3793 :
3794 : int iTariff;
3795 : int jPeriod;
3796 : int kMonth;
3797 188 : Array1D<Real64> monthVal(MaxNumMonths);
3798 94 : Real64 bigNumber(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
3799 :
3800 94 : auto &tariff(state.dataEconTariff->tariff);
3801 94 : auto &econVar(state.dataEconTariff->econVar);
3802 :
3803 94 : bigNumber = HUGE_(bigNumber);
3804 379 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
3805 : // nativeTotalEnergy
3806 285 : monthVal = 0.0;
3807 1425 : for (jPeriod = 1; jPeriod <= countPeriod; ++jPeriod) {
3808 14820 : for (kMonth = 1; kMonth <= MaxNumMonths; ++kMonth) {
3809 13680 : monthVal(kMonth) += tariff(iTariff).gatherEnergy(kMonth, jPeriod);
3810 : }
3811 : }
3812 285 : econVar(tariff(iTariff).nativeTotalEnergy).values = monthVal;
3813 : // nativeTotalDemand
3814 285 : monthVal = -bigNumber;
3815 1425 : for (jPeriod = 1; jPeriod <= countPeriod; ++jPeriod) {
3816 14820 : for (kMonth = 1; kMonth <= MaxNumMonths; ++kMonth) {
3817 13680 : if (tariff(iTariff).gatherDemand(kMonth, jPeriod) > monthVal(kMonth)) {
3818 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, jPeriod);
3819 : }
3820 : }
3821 : }
3822 : // if no maximum was set just set to zero
3823 3705 : for (kMonth = 1; kMonth <= MaxNumMonths; ++kMonth) {
3824 3420 : if (monthVal(kMonth) == -bigNumber) {
3825 0 : monthVal(kMonth) = 0.0;
3826 : }
3827 : }
3828 285 : econVar(tariff(iTariff).nativeTotalDemand).values = monthVal;
3829 3705 : for (kMonth = 1; kMonth <= MaxNumMonths; ++kMonth) {
3830 : // nativePeakEnergy
3831 3420 : econVar(tariff(iTariff).nativePeakEnergy).values(kMonth) = tariff(iTariff).gatherEnergy(kMonth, periodPeak);
3832 : // nativePeakDemand
3833 3420 : econVar(tariff(iTariff).nativePeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak);
3834 : // nativeShoulderEnergy
3835 3420 : econVar(tariff(iTariff).nativeShoulderEnergy).values(kMonth) = tariff(iTariff).gatherEnergy(kMonth, periodShoulder);
3836 : // nativeShoulderDemand
3837 3420 : econVar(tariff(iTariff).nativeShoulderDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodShoulder);
3838 : // nativeOffPeakEnergy
3839 3420 : econVar(tariff(iTariff).nativeOffPeakEnergy).values(kMonth) = tariff(iTariff).gatherEnergy(kMonth, periodOffPeak);
3840 : // nativeOffPeakDemand
3841 3420 : econVar(tariff(iTariff).nativeOffPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodOffPeak);
3842 : // nativeMidPeakEnergy
3843 3420 : econVar(tariff(iTariff).nativeMidPeakEnergy).values(kMonth) = tariff(iTariff).gatherEnergy(kMonth, periodMidPeak);
3844 : // nativeMidPeakDemand
3845 3420 : econVar(tariff(iTariff).nativeMidPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodMidPeak);
3846 : // nativePeakExceedsOffPeak
3847 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak) - tariff(iTariff).gatherDemand(kMonth, periodOffPeak);
3848 3420 : if (monthVal(kMonth) > 0) {
3849 0 : econVar(tariff(iTariff).nativePeakExceedsOffPeak).values(kMonth) = monthVal(kMonth);
3850 : } else {
3851 3420 : econVar(tariff(iTariff).nativePeakExceedsOffPeak).values(kMonth) = 0.0;
3852 : }
3853 : // nativeOffPeakExceedsPeak
3854 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodOffPeak) - tariff(iTariff).gatherDemand(kMonth, periodPeak);
3855 3420 : if (monthVal(kMonth) > 0) {
3856 0 : econVar(tariff(iTariff).nativeOffPeakExceedsPeak).values(kMonth) = monthVal(kMonth);
3857 : } else {
3858 3420 : econVar(tariff(iTariff).nativeOffPeakExceedsPeak).values(kMonth) = 0.0;
3859 : }
3860 : // nativePeakExceedsMidPeak
3861 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak) - tariff(iTariff).gatherDemand(kMonth, periodMidPeak);
3862 3420 : if (monthVal(kMonth) > 0) {
3863 0 : econVar(tariff(iTariff).nativePeakExceedsMidPeak).values(kMonth) = monthVal(kMonth);
3864 : } else {
3865 3420 : econVar(tariff(iTariff).nativePeakExceedsOffPeak).values(kMonth) = 0.0;
3866 : }
3867 : // nativeMidPeakExceedsPeak
3868 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodMidPeak) - tariff(iTariff).gatherDemand(kMonth, periodPeak);
3869 3420 : if (monthVal(kMonth) > 0) {
3870 0 : econVar(tariff(iTariff).nativeMidPeakExceedsPeak).values(kMonth) = monthVal(kMonth);
3871 : } else {
3872 3420 : econVar(tariff(iTariff).nativeMidPeakExceedsPeak).values(kMonth) = 0.0;
3873 : }
3874 : // nativePeakExceedsShoulder
3875 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak) - tariff(iTariff).gatherDemand(kMonth, periodShoulder);
3876 3420 : if (monthVal(kMonth) > 0) {
3877 0 : econVar(tariff(iTariff).nativePeakExceedsShoulder).values(kMonth) = monthVal(kMonth);
3878 : } else {
3879 3420 : econVar(tariff(iTariff).nativePeakExceedsShoulder).values(kMonth) = 0.0;
3880 : }
3881 : // nativeShoulderExceedsPeak
3882 3420 : monthVal(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodShoulder) - tariff(iTariff).gatherDemand(kMonth, periodPeak);
3883 3420 : if (monthVal(kMonth) > 0) {
3884 0 : econVar(tariff(iTariff).nativeShoulderExceedsPeak).values(kMonth) = monthVal(kMonth);
3885 : } else {
3886 3420 : econVar(tariff(iTariff).nativeShoulderExceedsPeak).values(kMonth) = 0.0;
3887 : }
3888 : // nativeIsWinter
3889 : // nativeIsNotWinter
3890 3420 : if (tariff(iTariff).seasonForMonth(kMonth) == seasonWinter) {
3891 0 : econVar(tariff(iTariff).nativeIsWinter).values(kMonth) = 1.0;
3892 0 : econVar(tariff(iTariff).nativeIsNotWinter).values(kMonth) = 0.0;
3893 : } else {
3894 3420 : econVar(tariff(iTariff).nativeIsWinter).values(kMonth) = 0.0;
3895 3420 : econVar(tariff(iTariff).nativeIsNotWinter).values(kMonth) = 1.0;
3896 : }
3897 : // nativeIsSpring
3898 : // nativeIsNotSpring
3899 3420 : if (tariff(iTariff).seasonForMonth(kMonth) == seasonSpring) {
3900 0 : econVar(tariff(iTariff).nativeIsSpring).values(kMonth) = 1.0;
3901 0 : econVar(tariff(iTariff).nativeIsNotSpring).values(kMonth) = 0.0;
3902 : } else {
3903 3420 : econVar(tariff(iTariff).nativeIsSpring).values(kMonth) = 0.0;
3904 3420 : econVar(tariff(iTariff).nativeIsNotSpring).values(kMonth) = 1.0;
3905 : }
3906 : // nativeIsSummer
3907 : // nativeIsNotSummer
3908 3420 : if (tariff(iTariff).seasonForMonth(kMonth) == seasonSummer) {
3909 0 : econVar(tariff(iTariff).nativeIsSummer).values(kMonth) = 1.0;
3910 0 : econVar(tariff(iTariff).nativeIsNotSummer).values(kMonth) = 0.0;
3911 : } else {
3912 3420 : econVar(tariff(iTariff).nativeIsSummer).values(kMonth) = 0.0;
3913 3420 : econVar(tariff(iTariff).nativeIsNotSummer).values(kMonth) = 1.0;
3914 : }
3915 : // nativeIsAutumn
3916 : // nativeIsNotAutumn
3917 3420 : if (tariff(iTariff).seasonForMonth(kMonth) == seasonFall) {
3918 0 : econVar(tariff(iTariff).nativeIsAutumn).values(kMonth) = 1.0;
3919 0 : econVar(tariff(iTariff).nativeIsNotAutumn).values(kMonth) = 0.0;
3920 : } else {
3921 3420 : econVar(tariff(iTariff).nativeIsAutumn).values(kMonth) = 0.0;
3922 3420 : econVar(tariff(iTariff).nativeIsNotAutumn).values(kMonth) = 1.0;
3923 : }
3924 : // nativePeakAndShoulderEnergy
3925 3420 : econVar(tariff(iTariff).nativePeakAndShoulderEnergy).values(kMonth) =
3926 3420 : tariff(iTariff).gatherEnergy(kMonth, periodPeak) + tariff(iTariff).gatherEnergy(kMonth, periodShoulder);
3927 : // nativePeakAndShoulderDemand
3928 3420 : if (tariff(iTariff).gatherDemand(kMonth, periodPeak) > tariff(iTariff).gatherDemand(kMonth, periodShoulder)) {
3929 0 : econVar(tariff(iTariff).nativePeakAndShoulderDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak);
3930 : } else {
3931 3420 : econVar(tariff(iTariff).nativePeakAndShoulderDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodShoulder);
3932 : }
3933 : // nativePeakAndMidPeakEnergy
3934 3420 : econVar(tariff(iTariff).nativePeakAndMidPeakEnergy).values(kMonth) =
3935 3420 : tariff(iTariff).gatherEnergy(kMonth, periodPeak) + tariff(iTariff).gatherEnergy(kMonth, periodMidPeak);
3936 : // nativePeakAndMidPeakDemand
3937 3420 : if (tariff(iTariff).gatherDemand(kMonth, periodPeak) > tariff(iTariff).gatherDemand(kMonth, periodMidPeak)) {
3938 0 : econVar(tariff(iTariff).nativePeakAndMidPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak);
3939 : } else {
3940 3420 : econVar(tariff(iTariff).nativePeakAndMidPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodMidPeak);
3941 : }
3942 : // nativeShoulderAndOffPeakEnergy
3943 3420 : econVar(tariff(iTariff).nativeShoulderAndOffPeakEnergy).values(kMonth) =
3944 3420 : tariff(iTariff).gatherEnergy(kMonth, periodShoulder) + tariff(iTariff).gatherEnergy(kMonth, periodOffPeak);
3945 : // nativeShoulderAndOffPeakDemand
3946 3420 : if (tariff(iTariff).gatherDemand(kMonth, periodShoulder) > tariff(iTariff).gatherDemand(kMonth, periodOffPeak)) {
3947 0 : econVar(tariff(iTariff).nativeShoulderAndOffPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodShoulder);
3948 : } else {
3949 3420 : econVar(tariff(iTariff).nativeShoulderAndOffPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodOffPeak);
3950 : }
3951 : // nativePeakAndOffPeakEnergy
3952 3420 : econVar(tariff(iTariff).nativePeakAndOffPeakEnergy).values(kMonth) =
3953 3420 : tariff(iTariff).gatherEnergy(kMonth, periodPeak) + tariff(iTariff).gatherEnergy(kMonth, periodOffPeak);
3954 : // nativePeakAndOffPeakDemand
3955 3420 : if (tariff(iTariff).gatherDemand(kMonth, periodPeak) > tariff(iTariff).gatherDemand(kMonth, periodOffPeak)) {
3956 0 : econVar(tariff(iTariff).nativePeakAndOffPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodPeak);
3957 : } else {
3958 3420 : econVar(tariff(iTariff).nativePeakAndOffPeakDemand).values(kMonth) = tariff(iTariff).gatherDemand(kMonth, periodOffPeak);
3959 : }
3960 : // nativeRealTimePriceCosts
3961 3420 : econVar(tariff(iTariff).nativeRealTimePriceCosts).values(kMonth) = tariff(iTariff).RTPcost(kMonth);
3962 : // nativeAboveCustomerBaseCosts
3963 3420 : econVar(tariff(iTariff).nativeAboveCustomerBaseCosts).values(kMonth) = tariff(iTariff).RTPaboveBaseCost(kMonth);
3964 : // nativeBelowCustomerBaseCosts
3965 3420 : econVar(tariff(iTariff).nativeBelowCustomerBaseCosts).values(kMonth) = tariff(iTariff).RTPbelowBaseCost(kMonth);
3966 : // nativeAboveCustomerBaseEnergy
3967 3420 : econVar(tariff(iTariff).nativeAboveCustomerBaseEnergy).values(kMonth) = tariff(iTariff).RTPaboveBaseEnergy(kMonth);
3968 : // nativeBelowCustomerBaseEnergy
3969 3420 : econVar(tariff(iTariff).nativeBelowCustomerBaseEnergy).values(kMonth) = tariff(iTariff).RTPbelowBaseEnergy(kMonth);
3970 : }
3971 : }
3972 94 : }
3973 :
3974 94 : void LEEDtariffReporting(EnergyPlusData &state)
3975 : {
3976 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
3977 : // DATE WRITTEN October 2012
3978 :
3979 : // Write the economic results for LEED reporting
3980 :
3981 : using namespace OutputReportPredefined;
3982 :
3983 : int distCoolFacilMeter;
3984 : int distHeatFacilMeter;
3985 : Real64 elecTotalEne;
3986 : Real64 gasTotalEne;
3987 : Real64 distCoolTotalEne;
3988 : Real64 distHeatTotalEne;
3989 : Real64 otherTotalEne;
3990 : Real64 elecTotalCost;
3991 : Real64 gasTotalCost;
3992 : Real64 otherTotalCost;
3993 : Real64 distCoolTotalCost;
3994 : Real64 distHeatTotalCost;
3995 : Real64 allTotalCost;
3996 188 : std::string elecTariffNames;
3997 188 : std::string gasTariffNames;
3998 188 : std::string distCoolTariffNames;
3999 188 : std::string distHeatTariffNames;
4000 188 : std::string othrTariffNames;
4001 : EconConv elecUnits;
4002 : EconConv gasUnits;
4003 : EconConv distCoolUnits;
4004 : EconConv distHeatUnits;
4005 : EconConv othrUnits;
4006 : DemandWindow gasDemWindowUnits;
4007 : DemandWindow distCoolDemWindowUnits;
4008 : DemandWindow distHeatDemWindowUnits;
4009 : DemandWindow othrDemWindowUnits;
4010 : int iTariff;
4011 :
4012 94 : auto &tariff(state.dataEconTariff->tariff);
4013 :
4014 94 : if (state.dataEconTariff->numTariff > 0) {
4015 94 : distCoolFacilMeter = GetMeterIndex(state, "DISTRICTCOOLING:FACILITY");
4016 94 : distHeatFacilMeter = GetMeterIndex(state, "DISTRICTHEATING:FACILITY");
4017 94 : elecTotalEne = 0.0;
4018 94 : gasTotalEne = 0.0;
4019 94 : distCoolTotalEne = 0.0;
4020 94 : distHeatTotalEne = 0.0;
4021 94 : otherTotalEne = 0.0;
4022 94 : elecTotalCost = 0.0;
4023 94 : gasTotalCost = 0.0;
4024 94 : distCoolTotalCost = 0.0;
4025 94 : distHeatTotalCost = 0.0;
4026 94 : otherTotalCost = 0.0;
4027 94 : allTotalCost = 0.0;
4028 94 : elecUnits = EconConv::USERDEF;
4029 94 : gasUnits = EconConv::USERDEF;
4030 94 : distCoolUnits = EconConv::USERDEF;
4031 94 : distHeatUnits = EconConv::USERDEF;
4032 94 : othrUnits = EconConv::USERDEF;
4033 94 : gasDemWindowUnits = DemandWindow::Invalid;
4034 94 : othrDemWindowUnits = DemandWindow::Invalid;
4035 94 : elecTariffNames = "";
4036 94 : gasTariffNames = "";
4037 94 : distCoolTariffNames = "";
4038 94 : distHeatTariffNames = "";
4039 94 : othrTariffNames = "";
4040 379 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4041 285 : if (tariff(iTariff).isSelected) {
4042 178 : allTotalCost += tariff(iTariff).totalAnnualCost;
4043 178 : if (tariff(iTariff).kindElectricMtr >= kindMeterElecSimple) {
4044 95 : if (tariff(iTariff).totalAnnualEnergy > elecTotalEne) elecTotalEne = tariff(iTariff).totalAnnualEnergy;
4045 95 : elecTotalCost += tariff(iTariff).totalAnnualCost;
4046 95 : elecTariffNames += ' ' + tariff(iTariff).tariffName;
4047 95 : elecUnits = tariff(iTariff).convChoice;
4048 83 : } else if (tariff(iTariff).kindGasMtr == kindMeterGas) {
4049 82 : if (tariff(iTariff).totalAnnualEnergy > gasTotalEne) gasTotalEne = tariff(iTariff).totalAnnualEnergy;
4050 82 : gasTotalCost += tariff(iTariff).totalAnnualCost;
4051 82 : gasTariffNames += ' ' + tariff(iTariff).tariffName;
4052 82 : gasUnits = tariff(iTariff).convChoice;
4053 82 : gasDemWindowUnits = tariff(iTariff).demandWindow;
4054 1 : } else if (tariff(iTariff).reportMeterIndx == distCoolFacilMeter) {
4055 0 : if (tariff(iTariff).totalAnnualEnergy > distCoolTotalEne) distCoolTotalEne = tariff(iTariff).totalAnnualEnergy;
4056 0 : distCoolTotalCost += tariff(iTariff).totalAnnualCost;
4057 0 : distCoolTariffNames += ' ' + tariff(iTariff).tariffName;
4058 0 : distCoolUnits = tariff(iTariff).convChoice;
4059 0 : distCoolDemWindowUnits = tariff(iTariff).demandWindow;
4060 1 : } else if (tariff(iTariff).reportMeterIndx == distHeatFacilMeter) {
4061 0 : if (tariff(iTariff).totalAnnualEnergy > distHeatTotalEne) distHeatTotalEne = tariff(iTariff).totalAnnualEnergy;
4062 0 : distHeatTotalCost += tariff(iTariff).totalAnnualCost;
4063 0 : distHeatTariffNames += ' ' + tariff(iTariff).tariffName;
4064 0 : distHeatUnits = tariff(iTariff).convChoice;
4065 0 : distHeatDemWindowUnits = tariff(iTariff).demandWindow;
4066 1 : } else if (tariff(iTariff).kindWaterMtr == kindMeterNotWater) {
4067 0 : if (tariff(iTariff).totalAnnualEnergy > otherTotalEne) otherTotalEne = tariff(iTariff).totalAnnualEnergy;
4068 0 : otherTotalCost += tariff(iTariff).totalAnnualCost;
4069 0 : othrTariffNames += ' ' + tariff(iTariff).tariffName;
4070 0 : othrUnits = tariff(iTariff).convChoice;
4071 0 : othrDemWindowUnits = tariff(iTariff).demandWindow;
4072 : } else {
4073 : }
4074 : }
4075 : }
4076 : // names of the rates
4077 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsRtNm, "Electricity", elecTariffNames);
4078 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsRtNm, "Natural Gas", gasTariffNames);
4079 94 : if (distCoolTotalEne != 0) PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsRtNm, "District Cooling", distCoolTariffNames);
4080 94 : if (distHeatTotalEne != 0) PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsRtNm, "District Heating", distHeatTariffNames);
4081 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsRtNm, "Other", othrTariffNames);
4082 : // virtual rate
4083 94 : if (elecTotalEne != 0) PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsVirt, "Electricity", elecTotalCost / elecTotalEne, 3);
4084 94 : if (gasTotalEne != 0) PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsVirt, "Natural Gas", gasTotalCost / gasTotalEne, 3);
4085 94 : if (otherTotalEne != 0) PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsVirt, "Other", otherTotalCost / otherTotalEne, 3);
4086 : // units
4087 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsEneUnt, "Electricity", format("{}", convEneStrings(elecUnits)));
4088 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsEneUnt, "Natural Gas", format("{}", convEneStrings(gasUnits)));
4089 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsEneUnt, "Other", format("{}", convEneStrings(othrUnits)));
4090 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsDemUnt, "Electricity", format("{}", convDemStrings(elecUnits)));
4091 188 : PreDefTableEntry(state,
4092 94 : state.dataOutRptPredefined->pdchLeedEtsDemUnt,
4093 : "Natural Gas",
4094 282 : format("{}{}", convDemStrings(gasUnits), demWindowStrings(gasDemWindowUnits)));
4095 188 : PreDefTableEntry(state,
4096 94 : state.dataOutRptPredefined->pdchLeedEtsDemUnt,
4097 : "Other",
4098 282 : format("{}{}", convDemStrings(othrUnits), demWindowStrings(othrDemWindowUnits)));
4099 : // total cost
4100 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEcsTotal, "Electricity", elecTotalCost, 2);
4101 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEcsTotal, "Natural Gas", gasTotalCost, 2);
4102 94 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEcsTotal, "Other", otherTotalCost, 2);
4103 : // show district energy if used
4104 94 : if (distCoolTotalEne != 0) {
4105 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsVirt, "District Cooling", distCoolTotalCost / distCoolTotalEne, 3);
4106 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsEneUnt, "District Cooling", format("{}", convEneStrings(distCoolUnits)));
4107 0 : PreDefTableEntry(state,
4108 0 : state.dataOutRptPredefined->pdchLeedEtsDemUnt,
4109 : "District Cooling",
4110 0 : format("{}{}", convDemStrings(distCoolUnits), demWindowStrings(distCoolDemWindowUnits)));
4111 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEcsTotal, "District Cooling", distCoolTotalCost, 2);
4112 : }
4113 94 : if (distHeatTotalEne != 0) {
4114 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsVirt, "District Heating", distHeatTotalCost / distHeatTotalEne, 3);
4115 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEtsEneUnt, "District Heating", format("{}", convEneStrings(distHeatUnits)));
4116 0 : PreDefTableEntry(state,
4117 0 : state.dataOutRptPredefined->pdchLeedEtsDemUnt,
4118 : "District Heating",
4119 0 : format("{}{}", convDemStrings(distHeatUnits), demWindowStrings(distHeatDemWindowUnits)));
4120 0 : PreDefTableEntry(state, state.dataOutRptPredefined->pdchLeedEcsTotal, "District Heating", distHeatTotalCost, 2);
4121 : }
4122 : // save the total costs for later to compute process fraction
4123 94 : state.dataOutRptPredefined->LEEDelecCostTotal = elecTotalCost;
4124 94 : state.dataOutRptPredefined->LEEDgasCostTotal = gasTotalCost;
4125 94 : state.dataOutRptPredefined->LEEDothrCostTotal = distCoolTotalCost + distHeatTotalCost + otherTotalCost;
4126 282 : PreDefTableEntry(state,
4127 94 : state.dataOutRptPredefined->pdchLeedEcsTotal,
4128 : "Total",
4129 94 : elecTotalCost + gasTotalCost + distCoolTotalCost + distHeatTotalCost + otherTotalCost,
4130 94 : 2);
4131 : }
4132 94 : }
4133 :
4134 769 : void WriteTabularTariffReports(EnergyPlusData &state)
4135 : {
4136 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
4137 : // DATE WRITTEN July 2004
4138 : // MODIFIED January 2010, Kyle Benne
4139 : // Added SQLite output
4140 :
4141 : using OutputReportTabular::ConvertIP;
4142 : using OutputReportTabular::DetermineBuildingFloorArea;
4143 : using OutputReportTabular::LookupSItoIP;
4144 : using OutputReportTabular::RealToStr;
4145 : using OutputReportTabular::WriteReportHeaders;
4146 : using OutputReportTabular::WriteSubtitle;
4147 : using OutputReportTabular::WriteTable;
4148 : using OutputReportTabular::WriteTextLine;
4149 :
4150 : // all arrays are in the format: (row, column)
4151 1538 : Array1D_string columnHead;
4152 1538 : Array1D_int columnWidth;
4153 1538 : Array1D_string rowHead;
4154 1538 : Array2D_string tableBody;
4155 : // other local variables
4156 : Real64 elecTotalCost;
4157 : Real64 gasTotalCost;
4158 : Real64 otherTotalCost;
4159 : Real64 allTotalCost;
4160 1538 : std::string outString; // an arbitarilty long string
4161 : int curStep;
4162 : int indexInChg;
4163 : int iTariff;
4164 : int kVar;
4165 : int lStep;
4166 1538 : std::string SIunit;
4167 769 : int unitConvIndex(0);
4168 769 : Real64 perAreaUnitConv(0.0);
4169 1538 : std::string perAreaUnitName;
4170 :
4171 769 : auto &tariff(state.dataEconTariff->tariff);
4172 769 : auto &econVar(state.dataEconTariff->econVar);
4173 769 : auto &computation(state.dataEconTariff->computation);
4174 769 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
4175 769 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
4176 :
4177 : // Here to it is ready to assign ort->unitStyle_SQLite (not in SQLiteProcedures.cc)
4178 : // when ort->unitsStyle inputs should have been concretely processed and assigned.
4179 : // Included this here to make sure the units specifications are correctly updated.
4180 769 : if (state.dataOutRptTab->unitsStyle_SQLite == OutputReportTabular::UnitsStyle::NotFound) {
4181 0 : state.dataOutRptTab->unitsStyle_SQLite = state.dataOutRptTab->unitsStyle; // This is the default UseOutputControlTableStyles
4182 : }
4183 :
4184 : // compute floor area if no ABUPS
4185 769 : if (state.dataOutRptTab->buildingConditionedFloorArea == 0.0) {
4186 117 : DetermineBuildingFloorArea(state);
4187 : }
4188 :
4189 769 : if (state.dataEconTariff->numTariff > 0) {
4190 95 : if (state.dataOutRptTab->displayEconomicResultSummary) {
4191 28 : DisplayString(state, "Writing Tariff Reports");
4192 6028 : for (auto &e : econVar)
4193 6000 : e.isReported = false;
4194 28 : showWarningsBasedOnTotal(state);
4195 : //---------------------------------
4196 : // Economics Results Summary Report
4197 : //---------------------------------
4198 28 : WriteReportHeaders(state, "Economics Results Summary Report", "Entire Facility", OutputProcessor::StoreType::Averaged);
4199 :
4200 56 : for (int iUnitSystem = 0; iUnitSystem <= 1; iUnitSystem++) {
4201 56 : OutputReportTabular::UnitsStyle unitsStyle_cur = state.dataOutRptTab->unitsStyle;
4202 56 : bool produceTabular = true;
4203 56 : bool produceSQLite = false;
4204 112 : if (produceDualUnitsFlags(iUnitSystem,
4205 56 : state.dataOutRptTab->unitsStyle,
4206 56 : state.dataOutRptTab->unitsStyle_SQLite,
4207 : unitsStyle_cur,
4208 : produceTabular,
4209 : produceSQLite))
4210 28 : break;
4211 :
4212 : // do unit conversions if necessary
4213 28 : if (unitsStyle_cur == OutputReportTabular::UnitsStyle::InchPound) {
4214 0 : SIunit = "[~~$~~/m2]";
4215 0 : LookupSItoIP(state, SIunit, unitConvIndex, perAreaUnitName);
4216 0 : perAreaUnitConv = ConvertIP(state, unitConvIndex, 1.0);
4217 : } else {
4218 28 : perAreaUnitName = "[~~$~~/m2]";
4219 28 : perAreaUnitConv = 1.0;
4220 : }
4221 :
4222 : //---- Annual Summary
4223 28 : rowHead.allocate(3);
4224 28 : columnHead.allocate(4);
4225 28 : columnWidth.allocate(4);
4226 28 : tableBody.allocate(4, 3);
4227 28 : tableBody = "";
4228 28 : columnHead(1) = "Electricity";
4229 28 : columnHead(2) = "Natural Gas";
4230 28 : columnHead(3) = "Other";
4231 28 : columnHead(4) = "Total";
4232 28 : rowHead(1) = "Cost [~~$~~]";
4233 28 : rowHead(2) = "Cost per Total Building Area " + perAreaUnitName;
4234 28 : rowHead(3) = "Cost per Net Conditioned Building Area " + perAreaUnitName;
4235 28 : elecTotalCost = 0.0;
4236 28 : gasTotalCost = 0.0;
4237 28 : otherTotalCost = 0.0;
4238 28 : allTotalCost = 0.0;
4239 113 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4240 85 : if (tariff(iTariff).isSelected) {
4241 46 : allTotalCost += tariff(iTariff).totalAnnualCost;
4242 46 : if (tariff(iTariff).kindElectricMtr >= kindMeterElecSimple) {
4243 29 : elecTotalCost += tariff(iTariff).totalAnnualCost;
4244 17 : } else if (tariff(iTariff).kindGasMtr == kindMeterGas) {
4245 16 : gasTotalCost += tariff(iTariff).totalAnnualCost;
4246 1 : } else if (tariff(iTariff).kindWaterMtr == kindMeterNotWater) {
4247 0 : otherTotalCost += tariff(iTariff).totalAnnualCost;
4248 : // removed because this was confusing columnHead(3) = tariff(iTariff)%reportMeter
4249 : } else {
4250 : }
4251 : }
4252 : }
4253 28 : tableBody(1, 1) = RealToStr(elecTotalCost, 2);
4254 28 : tableBody(2, 1) = RealToStr(gasTotalCost, 2);
4255 28 : tableBody(3, 1) = RealToStr(otherTotalCost, 2);
4256 28 : tableBody(4, 1) = RealToStr(allTotalCost, 2);
4257 28 : if (state.dataOutRptTab->buildingGrossFloorArea > 0.0) {
4258 28 : tableBody(1, 2) = RealToStr((elecTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
4259 28 : tableBody(2, 2) = RealToStr((gasTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
4260 28 : tableBody(3, 2) = RealToStr((otherTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
4261 28 : tableBody(4, 2) = RealToStr((allTotalCost / state.dataOutRptTab->buildingGrossFloorArea) * perAreaUnitConv, 2);
4262 : }
4263 28 : if (state.dataOutRptTab->buildingConditionedFloorArea > 0.0) {
4264 28 : tableBody(1, 3) = RealToStr((elecTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
4265 28 : tableBody(2, 3) = RealToStr((gasTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
4266 28 : tableBody(3, 3) = RealToStr((otherTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
4267 28 : tableBody(4, 3) = RealToStr((allTotalCost / state.dataOutRptTab->buildingConditionedFloorArea) * perAreaUnitConv, 2);
4268 : }
4269 28 : columnWidth = 14; // array assignment - same for all columns
4270 28 : if (produceTabular) {
4271 28 : WriteSubtitle(state, "Annual Cost");
4272 28 : WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
4273 : }
4274 28 : if (produceSQLite) {
4275 28 : if (state.dataSQLiteProcedures->sqlite) {
4276 9 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
4277 : tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Annual Cost");
4278 : }
4279 : }
4280 28 : if (produceTabular) {
4281 28 : if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
4282 0 : state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
4283 : tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Annual Cost");
4284 : }
4285 : }
4286 28 : columnHead.deallocate();
4287 28 : rowHead.deallocate();
4288 28 : columnWidth.deallocate();
4289 28 : tableBody.deallocate();
4290 : }
4291 : //---- Tariff Summary
4292 28 : rowHead.allocate(state.dataEconTariff->numTariff);
4293 28 : columnHead.allocate(6);
4294 28 : columnWidth.allocate(6);
4295 28 : tableBody.allocate(6, state.dataEconTariff->numTariff);
4296 28 : tableBody = "";
4297 28 : columnHead(1) = "Selected";
4298 28 : columnHead(2) = "Qualified";
4299 28 : columnHead(3) = "Meter";
4300 28 : columnHead(4) = "Buy or Sell";
4301 28 : columnHead(5) = "Group";
4302 28 : columnHead(6) = "Annual Cost (~~$~~)";
4303 113 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4304 85 : rowHead(iTariff) = tariff(iTariff).tariffName;
4305 85 : if (tariff(iTariff).isSelected) {
4306 46 : tableBody(1, iTariff) = "Yes";
4307 : } else {
4308 39 : tableBody(1, iTariff) = "No";
4309 : }
4310 85 : if (tariff(iTariff).isQualified) {
4311 85 : tableBody(2, iTariff) = "Yes";
4312 : } else {
4313 0 : tableBody(2, iTariff) = "No";
4314 : }
4315 85 : tableBody(3, iTariff) = tariff(iTariff).reportMeter;
4316 : {
4317 85 : auto const SELECT_CASE_var(tariff(iTariff).buyOrSell);
4318 85 : if (SELECT_CASE_var == buyFromUtility) {
4319 83 : tableBody(4, iTariff) = "Buy";
4320 2 : } else if (SELECT_CASE_var == sellToUtility) {
4321 1 : tableBody(4, iTariff) = "Sell";
4322 1 : } else if (SELECT_CASE_var == netMetering) {
4323 1 : tableBody(4, iTariff) = "Net";
4324 : }
4325 : }
4326 85 : if (tariff(iTariff).groupName == "") {
4327 21 : tableBody(5, iTariff) = "(none)";
4328 : } else {
4329 64 : tableBody(5, iTariff) = tariff(iTariff).groupName;
4330 : }
4331 85 : tableBody(6, iTariff) = RealToStr(tariff(iTariff).totalAnnualCost, 2);
4332 : }
4333 28 : columnWidth = 14; // array assignment - same for all columns
4334 28 : WriteSubtitle(state, "Tariff Summary");
4335 28 : WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
4336 28 : if (state.dataSQLiteProcedures->sqlite) {
4337 9 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
4338 : tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Tariff Summary");
4339 : }
4340 28 : if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
4341 0 : state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
4342 : tableBody, rowHead, columnHead, "Economics Results Summary Report", "Entire Facility", "Tariff Summary");
4343 : }
4344 28 : columnHead.deallocate();
4345 28 : rowHead.deallocate();
4346 28 : columnWidth.deallocate();
4347 28 : tableBody.deallocate();
4348 : }
4349 : //---------------------------------
4350 : // Tariff Report
4351 : //---------------------------------
4352 95 : if (state.dataOutRptTab->displayTariffReport) {
4353 113 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4354 85 : WriteReportHeaders(state, "Tariff Report", tariff(iTariff).tariffName, OutputProcessor::StoreType::Averaged);
4355 85 : rowHead.allocate(7);
4356 85 : columnHead.allocate(1);
4357 85 : columnWidth.allocate(1);
4358 85 : tableBody.allocate(1, 7);
4359 85 : tableBody = "";
4360 85 : columnHead(1) = "Parameter";
4361 85 : rowHead(1) = "Meter";
4362 85 : rowHead(2) = "Selected";
4363 85 : rowHead(3) = "Group";
4364 85 : rowHead(4) = "Qualified";
4365 85 : rowHead(5) = "Disqualifier";
4366 85 : rowHead(6) = "Computation";
4367 85 : rowHead(7) = "Units";
4368 85 : tableBody(1, 1) = tariff(iTariff).reportMeter;
4369 85 : if (tariff(iTariff).isSelected) {
4370 46 : tableBody(1, 2) = "Yes";
4371 : } else {
4372 39 : tableBody(1, 2) = "No";
4373 : }
4374 85 : if (tariff(iTariff).groupName == "") {
4375 21 : tableBody(1, 3) = "(none)";
4376 : } else {
4377 64 : tableBody(1, 3) = tariff(iTariff).groupName;
4378 : }
4379 85 : if (tariff(iTariff).isQualified) {
4380 85 : tableBody(1, 4) = "Yes";
4381 : } else {
4382 0 : tableBody(1, 4) = "No";
4383 : }
4384 85 : if (tariff(iTariff).isQualified) {
4385 85 : tableBody(1, 5) = "n/a";
4386 : } else {
4387 0 : tableBody(1, 5) = econVar(tariff(iTariff).ptDisqualifier).name;
4388 : }
4389 85 : if (computation(iTariff).isUserDef) {
4390 1 : tableBody(1, 6) = computation(iTariff).computeName;
4391 : } else {
4392 84 : tableBody(1, 6) = "automatic";
4393 : }
4394 85 : switch (tariff(iTariff).convChoice) {
4395 1 : case EconConv::USERDEF: {
4396 1 : tableBody(1, 7) = "User Defined";
4397 1 : } break;
4398 68 : case EconConv::KWH: {
4399 68 : tableBody(1, 7) = "kWh";
4400 68 : } break;
4401 1 : case EconConv::THERM: {
4402 1 : tableBody(1, 7) = "Therm";
4403 1 : } break;
4404 0 : case EconConv::MMBTU: {
4405 0 : tableBody(1, 7) = "MMBtu";
4406 0 : } break;
4407 0 : case EconConv::MJ: {
4408 0 : tableBody(1, 7) = "MJ";
4409 0 : } break;
4410 0 : case EconConv::KBTU: {
4411 0 : tableBody(1, 7) = "kBtu";
4412 0 : } break;
4413 15 : case EconConv::MCF: {
4414 15 : tableBody(1, 7) = "MCF";
4415 15 : } break;
4416 0 : case EconConv::CCF: {
4417 0 : tableBody(1, 7) = "CCF";
4418 0 : } break;
4419 0 : default:
4420 0 : break;
4421 : }
4422 85 : columnWidth = 14; // array assignment - same for all columns
4423 85 : WriteSubtitle(state, "General");
4424 85 : WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
4425 85 : if (state.dataSQLiteProcedures->sqlite) {
4426 52 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(
4427 26 : tableBody, rowHead, columnHead, "Tariff Report", tariff(iTariff).tariffName, "General");
4428 : }
4429 85 : if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
4430 0 : state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
4431 0 : tableBody, rowHead, columnHead, "Tariff Report", tariff(iTariff).tariffName, "General");
4432 : }
4433 85 : columnHead.deallocate();
4434 85 : rowHead.deallocate();
4435 85 : columnWidth.deallocate();
4436 85 : tableBody.deallocate();
4437 : //---- Categories
4438 28285 : for (auto &e : econVar)
4439 28200 : e.activeNow = false;
4440 85 : econVar(tariff(iTariff).ptEnergyCharges).activeNow = true;
4441 85 : econVar(tariff(iTariff).ptDemandCharges).activeNow = true;
4442 85 : econVar(tariff(iTariff).ptServiceCharges).activeNow = true;
4443 85 : econVar(tariff(iTariff).ptBasis).activeNow = true;
4444 85 : econVar(tariff(iTariff).ptAdjustment).activeNow = true;
4445 85 : econVar(tariff(iTariff).ptSurcharge).activeNow = true;
4446 85 : econVar(tariff(iTariff).ptSubtotal).activeNow = true;
4447 85 : econVar(tariff(iTariff).ptTaxes).activeNow = true;
4448 85 : econVar(tariff(iTariff).ptTotal).activeNow = true;
4449 85 : ReportEconomicVariable(state, "Categories", false, true, tariff(iTariff).tariffName);
4450 : //---- Charges
4451 28285 : for (auto &e : econVar)
4452 28200 : e.activeNow = false;
4453 23649 : for (kVar = 1; kVar <= state.dataEconTariff->numEconVar; ++kVar) {
4454 23564 : if (econVar(kVar).tariffIndx == iTariff) {
4455 4476 : if ((econVar(kVar).kindOfObj == ObjType::ChargeSimple) || (econVar(kVar).kindOfObj == ObjType::ChargeBlock)) {
4456 390 : econVar(kVar).activeNow = true;
4457 : }
4458 : }
4459 : }
4460 85 : ReportEconomicVariable(state, "Charges", true, true, tariff(iTariff).tariffName);
4461 : //---- Sources for Charges
4462 28285 : for (auto &e : econVar)
4463 28200 : e.activeNow = false;
4464 23649 : for (kVar = 1; kVar <= state.dataEconTariff->numEconVar; ++kVar) {
4465 23564 : if (econVar(kVar).tariffIndx == iTariff) {
4466 4476 : indexInChg = econVar(kVar).index;
4467 4476 : if (econVar(kVar).kindOfObj == ObjType::ChargeSimple) {
4468 318 : if (chargeSimple(indexInChg).sourcePt > 0) {
4469 318 : econVar(chargeSimple(indexInChg).sourcePt).activeNow = true;
4470 : }
4471 4158 : } else if (econVar(kVar).kindOfObj == ObjType::ChargeBlock) {
4472 72 : if (chargeBlock(indexInChg).sourcePt > 0) {
4473 72 : econVar(chargeBlock(indexInChg).sourcePt).activeNow = true;
4474 : }
4475 : }
4476 : }
4477 : }
4478 85 : ReportEconomicVariable(state, "Corresponding Sources for Charges", false, false, tariff(iTariff).tariffName);
4479 : //---- Rachets
4480 28285 : for (auto &e : econVar)
4481 28200 : e.activeNow = false;
4482 23649 : for (kVar = 1; kVar <= state.dataEconTariff->numEconVar; ++kVar) {
4483 23564 : if (econVar(kVar).tariffIndx == iTariff) {
4484 4476 : if (econVar(kVar).kindOfObj == ObjType::Ratchet) {
4485 1 : econVar(kVar).activeNow = true;
4486 : }
4487 : }
4488 : }
4489 85 : ReportEconomicVariable(state, "Ratchets", false, false, tariff(iTariff).tariffName);
4490 : //---- Qualifies
4491 28285 : for (auto &e : econVar)
4492 28200 : e.activeNow = false;
4493 23649 : for (kVar = 1; kVar <= state.dataEconTariff->numEconVar; ++kVar) {
4494 23564 : if (econVar(kVar).tariffIndx == iTariff) {
4495 4476 : if (econVar(kVar).kindOfObj == ObjType::Qualify) {
4496 71 : econVar(kVar).activeNow = true;
4497 : }
4498 : }
4499 : }
4500 85 : ReportEconomicVariable(state, "Qualifies", false, false, tariff(iTariff).tariffName);
4501 : //---- Native Variables
4502 28285 : for (auto &e : econVar)
4503 28200 : e.activeNow = false;
4504 3230 : for (kVar = tariff(iTariff).firstNative; kVar <= tariff(iTariff).lastNative; ++kVar) {
4505 3145 : econVar(kVar).activeNow = true;
4506 : }
4507 85 : ReportEconomicVariable(state, "Native Variables", false, false, tariff(iTariff).tariffName);
4508 : //---- Other Variables
4509 28285 : for (auto &e : econVar)
4510 28200 : e.activeNow = false;
4511 23649 : for (kVar = 1; kVar <= state.dataEconTariff->numEconVar; ++kVar) {
4512 23564 : if (econVar(kVar).tariffIndx == iTariff) {
4513 4476 : if (!econVar(kVar).isReported) {
4514 103 : econVar(kVar).activeNow = true;
4515 : }
4516 : }
4517 : }
4518 85 : ReportEconomicVariable(state, "Other Variables", false, false, tariff(iTariff).tariffName);
4519 : //---- Computation
4520 85 : if (computation(iTariff).isUserDef) {
4521 1 : WriteTextLine(state, "Computation - User Defined", true);
4522 : } else {
4523 84 : WriteTextLine(state, "Computation - Automatic", true);
4524 : }
4525 85 : outString = "";
4526 4386 : for (lStep = computation(iTariff).firstStep; lStep <= computation(iTariff).lastStep; ++lStep) {
4527 4301 : curStep = state.dataEconTariff->steps(lStep);
4528 : {
4529 4301 : auto const SELECT_CASE_var(curStep);
4530 4301 : if (SELECT_CASE_var == 0) { // end of line
4531 901 : WriteTextLine(state, rstrip(outString));
4532 901 : outString = "";
4533 3400 : } else if ((SELECT_CASE_var >= 1)) { // all positive values are a reference to an econVar
4534 2499 : outString = econVar(curStep).name + ' ' + outString;
4535 901 : } else if (SELECT_CASE_var == opSUM) {
4536 443 : outString = "SUM " + outString;
4537 458 : } else if (SELECT_CASE_var == opMULTIPLY) {
4538 0 : outString = "MULTIPLY " + outString;
4539 458 : } else if (SELECT_CASE_var == opSUBTRACT) {
4540 0 : outString = "SUBTRACT " + outString;
4541 458 : } else if (SELECT_CASE_var == opDIVIDE) {
4542 0 : outString = "DIVIDE " + outString;
4543 458 : } else if (SELECT_CASE_var == opABSOLUTE) {
4544 0 : outString = "ABSOLUTE " + outString;
4545 458 : } else if (SELECT_CASE_var == opINTEGER) {
4546 0 : outString = "INTEGER " + outString;
4547 458 : } else if (SELECT_CASE_var == opSIGN) {
4548 0 : outString = "SIGN " + outString;
4549 458 : } else if (SELECT_CASE_var == opROUND) {
4550 0 : outString = "ROUND " + outString;
4551 458 : } else if (SELECT_CASE_var == opMAXIMUM) {
4552 0 : outString = "MAXIMUM " + outString;
4553 458 : } else if (SELECT_CASE_var == opMINIMUM) {
4554 0 : outString = "MINIMUM " + outString;
4555 458 : } else if (SELECT_CASE_var == opEXCEEDS) {
4556 0 : outString = "EXCEEDS " + outString;
4557 458 : } else if (SELECT_CASE_var == opANNUALMINIMUM) {
4558 0 : outString = "ANNUALMINIMUM " + outString;
4559 458 : } else if (SELECT_CASE_var == opANNUALMAXIMUM) {
4560 0 : outString = "ANNUALMAXIMUM " + outString;
4561 458 : } else if (SELECT_CASE_var == opANNUALSUM) {
4562 0 : outString = "ANNUALSUM " + outString;
4563 458 : } else if (SELECT_CASE_var == opANNUALAVERAGE) {
4564 0 : outString = "ANNUALAVERAGE " + outString;
4565 458 : } else if (SELECT_CASE_var == opANNUALOR) {
4566 0 : outString = "ANNUALOR " + outString;
4567 458 : } else if (SELECT_CASE_var == opANNUALAND) {
4568 0 : outString = "ANNUALAND " + outString;
4569 458 : } else if (SELECT_CASE_var == opANNUALMAXIMUMZERO) {
4570 0 : outString = "ANNUALMAXIMUMZERO " + outString;
4571 458 : } else if (SELECT_CASE_var == opANNUALMINIMUMZERO) {
4572 0 : outString = "ANNUALMINIMUMZERO " + outString;
4573 458 : } else if (SELECT_CASE_var == opIF) {
4574 0 : outString = "IF " + outString;
4575 458 : } else if (SELECT_CASE_var == opGREATERTHAN) {
4576 0 : outString = "GREATERTHAN " + outString;
4577 458 : } else if (SELECT_CASE_var == opGREATEREQUAL) {
4578 0 : outString = "GREATEREQUAL " + outString;
4579 458 : } else if (SELECT_CASE_var == opLESSTHAN) {
4580 0 : outString = "LESSTHAN " + outString;
4581 458 : } else if (SELECT_CASE_var == opLESSEQUAL) {
4582 0 : outString = "LESSEQUAL " + outString;
4583 458 : } else if (SELECT_CASE_var == opEQUAL) {
4584 0 : outString = "EQUAL " + outString;
4585 458 : } else if (SELECT_CASE_var == opNOTEQUAL) {
4586 0 : outString = "NOTEQUAL " + outString;
4587 458 : } else if (SELECT_CASE_var == opAND) {
4588 0 : outString = "AND " + outString;
4589 458 : } else if (SELECT_CASE_var == opOR) {
4590 0 : outString = "OR " + outString;
4591 458 : } else if (SELECT_CASE_var == opNOT) {
4592 0 : outString = "NOT " + outString;
4593 458 : } else if (SELECT_CASE_var == opADD) {
4594 0 : outString = "ADD " + outString;
4595 458 : } else if (SELECT_CASE_var == opNOOP) { // should clear the outString when done debugging
4596 : // outString = ''
4597 458 : outString = "FROM " + outString;
4598 : }
4599 : }
4600 : }
4601 : }
4602 : }
4603 : }
4604 769 : }
4605 :
4606 28 : void showWarningsBasedOnTotal(EnergyPlusData &state)
4607 : {
4608 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
4609 : // DATE WRITTEN July 2004
4610 :
4611 : // Get the annual maximum and sum for the econVariable.
4612 :
4613 : int iTariff;
4614 28 : auto &tariff(state.dataEconTariff->tariff);
4615 :
4616 28 : if (state.dataEconTariff->numTariff > 0) {
4617 113 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4618 : {
4619 85 : auto const SELECT_CASE_var(tariff(iTariff).buyOrSell);
4620 85 : if (SELECT_CASE_var == buyFromUtility) {
4621 83 : if (tariff(iTariff).totalAnnualCost < 0) {
4622 0 : ShowWarningError(state,
4623 : "UtilityCost:Tariff: A negative annual total cost when buying electricity from a utility is unusual. ");
4624 0 : ShowContinueError(state, " In UtilityCost:Tariff named " + tariff(iTariff).tariffName);
4625 : }
4626 2 : } else if (SELECT_CASE_var == sellToUtility) {
4627 1 : if (tariff(iTariff).totalAnnualCost > 0) {
4628 0 : ShowWarningError(state,
4629 : "UtilityCost:Tariff: A positive annual total cost when selling electricity to a utility is unusual. ");
4630 0 : ShowContinueError(state, " In UtilityCost:Tariff named " + tariff(iTariff).tariffName);
4631 : }
4632 : }
4633 : }
4634 : }
4635 : }
4636 28 : }
4637 :
4638 4703 : void getMaxAndSum(EnergyPlusData &state, int const varPointer, Real64 &sumResult, Real64 &maxResult)
4639 : {
4640 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
4641 : // DATE WRITTEN July 2004
4642 :
4643 : // Get the annual maximum and sum for the econVariable.
4644 :
4645 : Real64 sumVal;
4646 4703 : Real64 maximumVal(0.0); // Autodesk Value not used but suppresses warning about HUGE_() call
4647 : Real64 curVal;
4648 : int jMonth;
4649 :
4650 4703 : auto &econVar(state.dataEconTariff->econVar);
4651 :
4652 4703 : sumVal = 0.0;
4653 4703 : maximumVal = -HUGE_(maximumVal);
4654 61139 : for (jMonth = 1; jMonth <= 12; ++jMonth) { // note not all months get printed out if more than 12 are used.- need to fix this later
4655 56436 : curVal = econVar(varPointer).values(jMonth);
4656 56436 : sumVal += curVal;
4657 56436 : if (curVal > maximumVal) {
4658 4819 : maximumVal = curVal;
4659 : }
4660 : }
4661 4703 : sumResult = sumVal;
4662 4703 : maxResult = maximumVal;
4663 4703 : }
4664 :
4665 595 : void ReportEconomicVariable(
4666 : EnergyPlusData &state, std::string const &titleString, bool const includeCategory, bool const showCurrencySymbol, std::string const &forString)
4667 : {
4668 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
4669 : // DATE WRITTEN July 2004
4670 : // MODIFIED January 2010, Kyle Benne
4671 : // Added sqlite output
4672 :
4673 : // Report all econVar that show as activeNow
4674 :
4675 : using OutputReportTabular::RealToStr;
4676 : using OutputReportTabular::WriteReportHeaders;
4677 : using OutputReportTabular::WriteSubtitle;
4678 : using OutputReportTabular::WriteTable;
4679 :
4680 : // all arrays are in the format: (row, column)
4681 1190 : Array1D_string columnHead;
4682 1190 : Array1D_int columnWidth;
4683 1190 : Array1D_string rowHead;
4684 1190 : Array2D_string tableBody;
4685 : Real64 sumVal;
4686 : Real64 maximumVal;
4687 : Real64 curVal;
4688 : int curIndex;
4689 : int curCatPt;
4690 : int curCategory;
4691 :
4692 : int iVar;
4693 : int jMonth;
4694 : int cntOfVar;
4695 : int nCntOfVar;
4696 :
4697 595 : auto &econVar(state.dataEconTariff->econVar);
4698 595 : auto &chargeBlock(state.dataEconTariff->chargeBlock);
4699 595 : auto &chargeSimple(state.dataEconTariff->chargeSimple);
4700 :
4701 595 : cntOfVar = 0;
4702 165543 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
4703 164948 : if (econVar(iVar).activeNow) {
4704 4703 : ++cntOfVar;
4705 : }
4706 : }
4707 595 : if (includeCategory) {
4708 85 : rowHead.allocate(cntOfVar);
4709 85 : columnHead.allocate(15);
4710 85 : columnWidth.allocate(15);
4711 85 : tableBody.allocate(15, cntOfVar);
4712 : } else {
4713 510 : rowHead.allocate(cntOfVar);
4714 510 : columnHead.allocate(14);
4715 510 : columnWidth.allocate(14);
4716 510 : tableBody.allocate(14, cntOfVar);
4717 : }
4718 : // column names
4719 595 : columnHead(1) = "Jan";
4720 595 : columnHead(2) = "Feb";
4721 595 : columnHead(3) = "Mar";
4722 595 : columnHead(4) = "Apr";
4723 595 : columnHead(5) = "May";
4724 595 : columnHead(6) = "Jun";
4725 595 : columnHead(7) = "Jul";
4726 595 : columnHead(8) = "Aug";
4727 595 : columnHead(9) = "Sep";
4728 595 : columnHead(10) = "Oct";
4729 595 : columnHead(11) = "Nov";
4730 595 : columnHead(12) = "Dec";
4731 595 : columnHead(13) = "Sum";
4732 595 : columnHead(14) = "Max";
4733 595 : if (includeCategory) {
4734 85 : columnHead(15) = "Category";
4735 : }
4736 595 : nCntOfVar = 0;
4737 : // row names
4738 165543 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
4739 164948 : if (econVar(iVar).activeNow) {
4740 4703 : ++nCntOfVar;
4741 4703 : if (showCurrencySymbol) {
4742 1155 : rowHead(nCntOfVar) = econVar(iVar).name + " (~~$~~)";
4743 : } else {
4744 3548 : rowHead(nCntOfVar) = econVar(iVar).name;
4745 : }
4746 : }
4747 : }
4748 : // fill the body
4749 595 : nCntOfVar = 0;
4750 165543 : for (iVar = 1; iVar <= state.dataEconTariff->numEconVar; ++iVar) {
4751 164948 : if (econVar(iVar).activeNow) {
4752 4703 : ++nCntOfVar;
4753 61139 : for (jMonth = 1; jMonth <= 12; ++jMonth) { // note not all months get printed out if more than 12 are used.- need to fix this later
4754 56436 : curVal = econVar(iVar).values(jMonth);
4755 56436 : if ((curVal > 0) && (curVal < 1)) {
4756 408 : tableBody(jMonth, nCntOfVar) = RealToStr(curVal, 4);
4757 : } else {
4758 56028 : tableBody(jMonth, nCntOfVar) = RealToStr(curVal, 2);
4759 : }
4760 : }
4761 4703 : getMaxAndSum(state, iVar, sumVal, maximumVal);
4762 4703 : tableBody(13, nCntOfVar) = RealToStr(sumVal, 2);
4763 4703 : tableBody(14, nCntOfVar) = RealToStr(maximumVal, 2);
4764 4703 : if (includeCategory) {
4765 : // first find category
4766 390 : curCategory = 0;
4767 390 : curIndex = econVar(iVar).index;
4768 :
4769 390 : switch (econVar(iVar).kindOfObj) {
4770 318 : case ObjType::ChargeSimple:
4771 318 : if ((curIndex >= 1) && (curIndex <= state.dataEconTariff->numChargeSimple)) {
4772 318 : curCatPt = chargeSimple(curIndex).categoryPt;
4773 : }
4774 318 : break;
4775 72 : case ObjType::ChargeBlock:
4776 72 : if ((curIndex >= 1) && (curIndex <= state.dataEconTariff->numChargeBlock)) {
4777 72 : curCatPt = chargeBlock(curIndex).categoryPt;
4778 : }
4779 72 : break;
4780 0 : default:
4781 0 : break;
4782 : }
4783 :
4784 390 : if ((curCatPt >= 1) && (curCatPt <= state.dataEconTariff->numEconVar)) {
4785 390 : curCategory = econVar(curCatPt).specific;
4786 : }
4787 : {
4788 390 : auto const SELECT_CASE_var(curCategory);
4789 390 : if (SELECT_CASE_var == catEnergyCharges) {
4790 245 : tableBody(15, nCntOfVar) = "EnergyCharges";
4791 145 : } else if (SELECT_CASE_var == catDemandCharges) {
4792 80 : tableBody(15, nCntOfVar) = "DemandCharges";
4793 65 : } else if (SELECT_CASE_var == catServiceCharges) {
4794 0 : tableBody(15, nCntOfVar) = "ServiceCharges";
4795 65 : } else if (SELECT_CASE_var == catBasis) {
4796 0 : tableBody(15, nCntOfVar) = "Basis";
4797 65 : } else if (SELECT_CASE_var == catAdjustment) {
4798 0 : tableBody(15, nCntOfVar) = "Adjustment";
4799 65 : } else if (SELECT_CASE_var == catSurcharge) {
4800 0 : tableBody(15, nCntOfVar) = "Surcharge";
4801 65 : } else if (SELECT_CASE_var == catSubtotal) {
4802 0 : tableBody(15, nCntOfVar) = "Subtotal";
4803 65 : } else if (SELECT_CASE_var == catTaxes) {
4804 64 : tableBody(15, nCntOfVar) = "Taxes";
4805 1 : } else if (SELECT_CASE_var == catTotal) {
4806 0 : tableBody(15, nCntOfVar) = "Total";
4807 : } else {
4808 1 : tableBody(15, nCntOfVar) = "none";
4809 : }
4810 : }
4811 : }
4812 4703 : econVar(iVar).isReported = true;
4813 : }
4814 : }
4815 595 : columnWidth = 14; // array assignment - same for all columns
4816 595 : WriteSubtitle(state, titleString);
4817 595 : WriteTable(state, tableBody, rowHead, columnHead, columnWidth);
4818 595 : if (state.dataSQLiteProcedures->sqlite) {
4819 182 : state.dataSQLiteProcedures->sqlite->createSQLiteTabularDataRecords(tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
4820 : }
4821 595 : if (state.dataResultsFramework->resultsFramework->timeSeriesAndTabularEnabled()) {
4822 0 : state.dataResultsFramework->resultsFramework->TabularReportsCollection.addReportTable(
4823 : tableBody, rowHead, columnHead, "Tariff Report", forString, titleString);
4824 : }
4825 595 : columnHead.deallocate();
4826 595 : rowHead.deallocate();
4827 595 : columnWidth.deallocate();
4828 595 : tableBody.deallocate();
4829 595 : }
4830 :
4831 94 : void selectTariff(EnergyPlusData &state)
4832 : {
4833 : // AUTHOR Jason Glazer of GARD Analytics, Inc.
4834 : // DATE WRITTEN July 2004
4835 :
4836 : // To select tariffs for each combination of meter and
4837 : // group. If multipler tariffs have the same meter and
4838 : // group, then select the one with the lowest cost.
4839 : // For electric tariffs, since they may have buy, sell, or
4840 : // netmetering, they need to be combined more carefully.
4841 : // Multiple meters are used but buy + sell might be more or
4842 : // less expensive than netmeter.
4843 :
4844 : int totalVarPt;
4845 : int totEneVarPt;
4846 : Real64 annualTotal;
4847 : Real64 annEneTotal;
4848 : int iTariff;
4849 : int jMonth;
4850 : int kTariff;
4851 : int lMin;
4852 : int mGroup;
4853 188 : Array1D_int groupIndex; // index number (in tariff) for the group name
4854 188 : Array1D_int MinTariffIndex; // tariff index for the Minimum value
4855 : int numMins;
4856 : int curMinTariffIndex;
4857 : bool isFound;
4858 : int groupCount;
4859 : int lowestSimpleTariff;
4860 : int lowestPurchaseTariff;
4861 : int lowestSurplusSoldTariff;
4862 : int lowestNetMeterTariff;
4863 :
4864 94 : auto &tariff(state.dataEconTariff->tariff);
4865 94 : auto &econVar(state.dataEconTariff->econVar);
4866 :
4867 94 : groupIndex.dimension(state.dataEconTariff->numTariff, 0);
4868 94 : groupCount = 0;
4869 94 : numMins = 0;
4870 94 : MinTariffIndex.dimension(state.dataEconTariff->numTariff, 0);
4871 379 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4872 : // compute the total annual cost of each tariff
4873 285 : totalVarPt = tariff(iTariff).ptTotal;
4874 285 : totEneVarPt = tariff(iTariff).nativeTotalEnergy;
4875 285 : annualTotal = 0.0;
4876 285 : annEneTotal = 0.0;
4877 3705 : for (jMonth = 1; jMonth <= MaxNumMonths; ++jMonth) {
4878 3420 : annualTotal += econVar(totalVarPt).values(jMonth);
4879 3420 : annEneTotal += econVar(totEneVarPt).values(jMonth);
4880 : }
4881 285 : tariff(iTariff).totalAnnualCost = annualTotal;
4882 285 : tariff(iTariff).totalAnnualEnergy = annEneTotal;
4883 : // Set the groupIndex
4884 285 : if (groupIndex(iTariff) == 0) {
4885 : // set the current item to the tariff index
4886 175 : ++groupCount;
4887 175 : groupIndex(iTariff) = groupCount;
4888 : // set all remaining matching items to the same index
4889 367 : for (kTariff = iTariff + 1; kTariff <= state.dataEconTariff->numTariff; ++kTariff) {
4890 192 : if (UtilityRoutines::SameString(tariff(kTariff).groupName, tariff(iTariff).groupName)) {
4891 110 : groupIndex(kTariff) = groupCount;
4892 : }
4893 : }
4894 : }
4895 : }
4896 : // First process the all tariff and identify the lowest cost for each type of meter and group.
4897 379 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4898 285 : if (tariff(iTariff).isQualified) {
4899 285 : isFound = false;
4900 503 : for (lMin = 1; lMin <= numMins; ++lMin) {
4901 218 : curMinTariffIndex = MinTariffIndex(lMin);
4902 : // find matching meter and group
4903 218 : if (tariff(iTariff).reportMeterIndx == tariff(curMinTariffIndex).reportMeterIndx) {
4904 106 : if (groupIndex(iTariff) == groupIndex(curMinTariffIndex)) {
4905 106 : isFound = true;
4906 : // found the matching mater and group now test if smaller Min is current tariff
4907 106 : if (tariff(iTariff).totalAnnualCost < tariff(curMinTariffIndex).totalAnnualCost) {
4908 94 : MinTariffIndex(lMin) = iTariff;
4909 : // select the new Minimum tariff and deselect the one that was just exceeded
4910 94 : tariff(curMinTariffIndex).isSelected = false;
4911 94 : tariff(iTariff).isSelected = true;
4912 : }
4913 : }
4914 : }
4915 : }
4916 285 : if (!isFound) {
4917 179 : ++numMins;
4918 179 : if (numMins > state.dataEconTariff->numTariff) {
4919 0 : ShowWarningError(state, "UtilityCost:Tariff Debugging error numMins greater than numTariff.");
4920 : }
4921 179 : MinTariffIndex(numMins) = iTariff;
4922 : // tariff(numMins)%isSelected = .TRUE. !original
4923 179 : tariff(iTariff).isSelected = true; // BTG changed 2/7/2005 CR6573
4924 : }
4925 : }
4926 : }
4927 : // Now select for the electric meters. If electric buying and selling and netmetering all are going
4928 : // on, need to determine which combination should be selected. Within each group select just one set
4929 : // of electric results. The electric results can be either the buy rate only, the buy rate plus the
4930 : // sell rate, or the netmetering rate, whichever of these three is the lowest combination.
4931 : // (The kindElectricMtr was assigned in GetInputEconomicsTariff)
4932 269 : for (mGroup = 1; mGroup <= groupCount; ++mGroup) {
4933 175 : lowestSimpleTariff = 0;
4934 175 : lowestPurchaseTariff = 0;
4935 175 : lowestSurplusSoldTariff = 0;
4936 175 : lowestNetMeterTariff = 0;
4937 715 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
4938 540 : if (tariff(iTariff).isQualified) {
4939 540 : if (tariff(iTariff).isSelected) {
4940 341 : if (groupIndex(iTariff) == mGroup) {
4941 : {
4942 179 : auto const SELECT_CASE_var(tariff(iTariff).kindElectricMtr);
4943 179 : if (SELECT_CASE_var == kindMeterElecSimple) {
4944 91 : lowestSimpleTariff = iTariff;
4945 88 : } else if (SELECT_CASE_var == kindMeterElecProduced) {
4946 : // don't show electric produced rates as ever selected since surplus sold is more relevant
4947 0 : tariff(iTariff).isSelected = false;
4948 88 : } else if (SELECT_CASE_var == kindMeterElecPurchased) {
4949 1 : lowestPurchaseTariff = iTariff;
4950 87 : } else if (SELECT_CASE_var == kindMeterElecSurplusSold) {
4951 1 : lowestSurplusSoldTariff = iTariff;
4952 86 : } else if (SELECT_CASE_var == kindMeterElecNet) {
4953 3 : lowestNetMeterTariff = iTariff;
4954 : }
4955 : }
4956 : }
4957 : }
4958 : }
4959 : }
4960 : // compare the simple and purchased metered tariffs
4961 175 : if ((lowestSimpleTariff > 0) && (lowestPurchaseTariff > 0)) {
4962 0 : if (tariff(lowestSimpleTariff).totalAnnualCost < tariff(lowestPurchaseTariff).totalAnnualCost) {
4963 0 : tariff(lowestPurchaseTariff).isSelected = false;
4964 0 : lowestPurchaseTariff = 0;
4965 : } else {
4966 0 : tariff(lowestSimpleTariff).isSelected = false;
4967 0 : lowestSimpleTariff = 0;
4968 : }
4969 : }
4970 : // if surplus sold is negative use it otherwise don't
4971 175 : if (lowestSurplusSoldTariff > 0) {
4972 1 : if (tariff(lowestSurplusSoldTariff).totalAnnualCost > 0) {
4973 0 : tariff(lowestSurplusSoldTariff).isSelected = false;
4974 0 : lowestSurplusSoldTariff = 0;
4975 : }
4976 : }
4977 : // if netmetering is used compare it to simple plus surplus
4978 175 : if (((lowestNetMeterTariff > 0) && (lowestSurplusSoldTariff > 0)) && (lowestSimpleTariff > 0)) {
4979 0 : if (tariff(lowestNetMeterTariff).totalAnnualCost <
4980 0 : (tariff(lowestSimpleTariff).totalAnnualCost + tariff(lowestSurplusSoldTariff).totalAnnualCost)) {
4981 0 : tariff(lowestSimpleTariff).isSelected = false;
4982 0 : lowestSimpleTariff = 0;
4983 0 : tariff(lowestSurplusSoldTariff).isSelected = false;
4984 0 : lowestSurplusSoldTariff = 0;
4985 : } else {
4986 0 : tariff(lowestNetMeterTariff).isSelected = false;
4987 0 : lowestNetMeterTariff = 0;
4988 : }
4989 : }
4990 : // if netmetering is used compare it to purchased plus surplus
4991 175 : if (((lowestNetMeterTariff > 0) && (lowestSurplusSoldTariff > 0)) && (lowestPurchaseTariff > 0)) {
4992 2 : if (tariff(lowestNetMeterTariff).totalAnnualCost <
4993 1 : (tariff(lowestPurchaseTariff).totalAnnualCost + tariff(lowestSurplusSoldTariff).totalAnnualCost)) {
4994 0 : tariff(lowestPurchaseTariff).isSelected = false;
4995 0 : lowestPurchaseTariff = 0;
4996 0 : tariff(lowestSurplusSoldTariff).isSelected = false;
4997 0 : lowestSurplusSoldTariff = 0;
4998 : } else {
4999 1 : tariff(lowestNetMeterTariff).isSelected = false;
5000 1 : lowestNetMeterTariff = 0;
5001 : }
5002 : }
5003 : // if netmetering is used compare it to simple only
5004 175 : if ((lowestNetMeterTariff > 0) && (lowestSimpleTariff > 0)) {
5005 0 : if (tariff(lowestNetMeterTariff).totalAnnualCost < tariff(lowestSimpleTariff).totalAnnualCost) {
5006 0 : tariff(lowestSimpleTariff).isSelected = false;
5007 0 : lowestSimpleTariff = 0;
5008 : } else {
5009 0 : tariff(lowestNetMeterTariff).isSelected = false;
5010 0 : lowestNetMeterTariff = 0;
5011 : }
5012 : }
5013 : // if netmetering is used compare it to purchased only
5014 175 : if ((lowestNetMeterTariff > 0) && (lowestPurchaseTariff > 0)) {
5015 0 : if (tariff(lowestNetMeterTariff).totalAnnualCost < tariff(lowestPurchaseTariff).totalAnnualCost) {
5016 0 : tariff(lowestPurchaseTariff).isSelected = false;
5017 0 : lowestPurchaseTariff = 0;
5018 : } else {
5019 0 : tariff(lowestNetMeterTariff).isSelected = false;
5020 0 : lowestNetMeterTariff = 0;
5021 : }
5022 : }
5023 : }
5024 94 : groupIndex.deallocate();
5025 94 : MinTariffIndex.deallocate();
5026 94 : }
5027 :
5028 47 : void GetMonthlyCostForResource(EnergyPlusData &state, DataGlobalConstants::ResourceType const inResourceNumber, Array1A<Real64> outMonthlyCosts)
5029 : {
5030 : // AUTHOR Jason Glazer
5031 : // DATE WRITTEN May 2010
5032 :
5033 : // Return the total annual cost for a given resource number.
5034 :
5035 : // Argument array dimensioning
5036 47 : outMonthlyCosts.dim(12);
5037 :
5038 : int iTariff;
5039 : int jMonth;
5040 : int totalVarPt;
5041 :
5042 47 : auto &tariff(state.dataEconTariff->tariff);
5043 47 : auto &econVar(state.dataEconTariff->econVar);
5044 :
5045 47 : outMonthlyCosts = 0.0;
5046 752 : for (iTariff = 1; iTariff <= state.dataEconTariff->numTariff; ++iTariff) {
5047 705 : if (tariff(iTariff).isSelected) {
5048 188 : if (tariff(iTariff).resourceNum == inResourceNumber) {
5049 4 : totalVarPt = tariff(iTariff).ptTotal;
5050 52 : for (jMonth = 1; jMonth <= 12; ++jMonth) { // use 12 because LCC assume 12 months
5051 48 : outMonthlyCosts(jMonth) += econVar(totalVarPt).values(jMonth);
5052 : }
5053 : }
5054 : }
5055 : }
5056 47 : }
5057 :
5058 2313 : } // namespace EnergyPlus::EconomicTariff
|