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