Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <algorithm>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Array1D.hh>
54 : #include <ObjexxFCL/member.functions.hh>
55 :
56 : // EnergyPlus Headers
57 : #include <EnergyPlus/Coils/CoilCoolingDX.hh>
58 : #include <EnergyPlus/Construction.hh>
59 : #include <EnergyPlus/CostEstimateManager.hh>
60 : #include <EnergyPlus/DXCoils.hh>
61 : #include <EnergyPlus/Data/EnergyPlusData.hh>
62 : // #include <EnergyPlus/DataDaylighting.hh>
63 : #include <EnergyPlus/DataHeatBalance.hh>
64 : #include <EnergyPlus/DataIPShortCuts.hh>
65 : #include <EnergyPlus/DataPhotovoltaics.hh>
66 : #include <EnergyPlus/DataSurfaces.hh>
67 : #include <EnergyPlus/DaylightingManager.hh>
68 : #include <EnergyPlus/HeatingCoils.hh>
69 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
70 : #include <EnergyPlus/PlantChillers.hh>
71 : #include <EnergyPlus/UtilityRoutines.hh>
72 :
73 : namespace EnergyPlus {
74 :
75 : namespace CostEstimateManager {
76 :
77 : // Module containing the routines dealing with the Cost Estimation capability of EnergyPlus
78 :
79 : // MODULE INFORMATION:
80 : // AUTHOR B. Griffith
81 : // DATE WRITTEN April-May 2004
82 : // MODIFIED na
83 : // RE-ENGINEERED na
84 :
85 : // PURPOSE OF THIS MODULE:
86 : // produce a construction cost estimate report based on
87 : // input and certain building calculations by EnergyPlus
88 :
89 : // METHODOLOGY EMPLOYED:
90 : // Routine gets called once, Just before tabular reports.
91 : // Cost Estimate objects are child objects that will inherit from
92 : // other input objects.
93 : // Uses a Line Item metaphor where each Cost Estimate object is a line
94 : // Create report using utility subroutines taken from OutputReportTabular (by J.Glazer)
95 :
96 : // Using/Aliasing
97 :
98 : constexpr std::array<std::string_view, static_cast<int>(ParentObject::Num)> ParentObjectNamesUC{"GENERAL",
99 : "CONSTRUCTION",
100 : "COIL:DX",
101 : "COIL:COOLING:DX",
102 : "COIL:COOLING:DX:SINGLESPEED",
103 : "COIL:HEATING:FUEL",
104 : "CHILLER:ELECTRIC",
105 : "DAYLIGHTING:CONTROLS",
106 : "SHADING:ZONE:DETAILED",
107 : "LIGHTS",
108 : "GENERATOR:PHOTOVOLTAIC"};
109 :
110 162 : void SimCostEstimate(EnergyPlusData &state)
111 : {
112 :
113 : // SUBROUTINE INFORMATION:
114 : // AUTHOR BGriffith
115 : // DATE WRITTEN April 2004
116 : // MODIFIED na
117 : // RE-ENGINEERED na
118 :
119 : // PURPOSE OF THIS SUBROUTINE:
120 : // Entry point; manage calls to other subroutines
121 :
122 162 : if (state.dataCostEstimateManager->GetCostInput) {
123 89 : GetCostEstimateInput(state);
124 89 : state.dataCostEstimateManager->GetCostInput = false;
125 : }
126 :
127 : // Need to add check Costs before this will work properly
128 :
129 162 : if (state.dataGlobal->KickOffSimulation) return;
130 :
131 77 : if (state.dataCostEstimateManager->DoCostEstimate) {
132 0 : CalcCostEstimate(state);
133 : }
134 : }
135 :
136 90 : void GetCostEstimateInput(EnergyPlusData &state)
137 : {
138 :
139 : // SUBROUTINE INFORMATION:
140 : // AUTHOR BGriffith
141 : // DATE WRITTEN April 2004
142 : // MODIFIED na
143 : // RE-ENGINEERED na
144 :
145 : // PURPOSE OF THIS SUBROUTINE:
146 : // Get Cost Estimation object input.
147 :
148 : // Using/Aliasing
149 :
150 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
151 : int Item; // Item to be "gotten"
152 : int NumCostAdjust;
153 : int NumRefAdjust;
154 : int NumAlphas; // Number of Alphas for each GetObjectItem call
155 : int NumNumbers; // Number of Numbers for each GetObjectItem call
156 : int IOStatus; // Used in GetObjectItem
157 90 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
158 :
159 90 : int NumLineItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ComponentCost:LineItem");
160 :
161 90 : if (NumLineItems == 0) {
162 89 : state.dataCostEstimateManager->DoCostEstimate = false;
163 89 : return;
164 : } else {
165 1 : state.dataCostEstimateManager->DoCostEstimate = true;
166 : // WriteTabularFiles = .TRUE.
167 : }
168 :
169 1 : if (!allocated(state.dataCostEstimateManager->CostLineItem)) {
170 1 : state.dataCostEstimateManager->CostLineItem.allocate(NumLineItems);
171 : }
172 1 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
173 1 : cCurrentModuleObject = "ComponentCost:LineItem";
174 :
175 7 : for (Item = 1; Item <= NumLineItems; ++Item) {
176 12 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
177 : cCurrentModuleObject,
178 : Item,
179 6 : state.dataIPShortCut->cAlphaArgs,
180 : NumAlphas,
181 6 : state.dataIPShortCut->rNumericArgs,
182 : NumNumbers,
183 : IOStatus);
184 6 : state.dataCostEstimateManager->CostLineItem(Item).LineName = state.dataIPShortCut->cAlphaArgs(1);
185 6 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjType =
186 6 : static_cast<ParentObject>(getEnumValue(ParentObjectNamesUC, state.dataIPShortCut->cAlphaArgs(3)));
187 6 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName = state.dataIPShortCut->cAlphaArgs(4);
188 6 : state.dataCostEstimateManager->CostLineItem(Item).PerEach = state.dataIPShortCut->rNumericArgs(1);
189 6 : state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter = state.dataIPShortCut->rNumericArgs(2);
190 6 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap = state.dataIPShortCut->rNumericArgs(3);
191 6 : state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP = state.dataIPShortCut->rNumericArgs(4);
192 6 : state.dataCostEstimateManager->CostLineItem(Item).PerCubicMeter = state.dataIPShortCut->rNumericArgs(5);
193 6 : state.dataCostEstimateManager->CostLineItem(Item).PerCubMeterPerSec = state.dataIPShortCut->rNumericArgs(6);
194 6 : state.dataCostEstimateManager->CostLineItem(Item).PerUAinWattperDelK = state.dataIPShortCut->rNumericArgs(7);
195 6 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataIPShortCut->rNumericArgs(8);
196 : }
197 :
198 : // most input error checking to be performed later within Case construct in Calc routine.
199 :
200 1 : cCurrentModuleObject = "ComponentCost:Adjustments";
201 1 : NumCostAdjust = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
202 1 : if (NumCostAdjust == 1) {
203 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
204 : cCurrentModuleObject,
205 : 1,
206 0 : state.dataIPShortCut->cAlphaArgs,
207 : NumAlphas,
208 0 : state.dataIPShortCut->rNumericArgs,
209 : NumNumbers,
210 : IOStatus);
211 0 : state.dataCostEstimateManager->CurntBldg.MiscCostperSqMeter = state.dataIPShortCut->rNumericArgs(1);
212 0 : state.dataCostEstimateManager->CurntBldg.DesignFeeFrac = state.dataIPShortCut->rNumericArgs(2);
213 0 : state.dataCostEstimateManager->CurntBldg.ContractorFeeFrac = state.dataIPShortCut->rNumericArgs(3);
214 0 : state.dataCostEstimateManager->CurntBldg.ContingencyFrac = state.dataIPShortCut->rNumericArgs(4);
215 0 : state.dataCostEstimateManager->CurntBldg.BondCostFrac = state.dataIPShortCut->rNumericArgs(5);
216 0 : state.dataCostEstimateManager->CurntBldg.CommissioningFrac = state.dataIPShortCut->rNumericArgs(6);
217 0 : state.dataCostEstimateManager->CurntBldg.RegionalModifier = state.dataIPShortCut->rNumericArgs(7);
218 :
219 1 : } else if (NumCostAdjust > 1) {
220 0 : ShowSevereError(state, format("{}: Only one instance of this object is allowed.", cCurrentModuleObject));
221 0 : ErrorsFound = true;
222 : }
223 :
224 1 : cCurrentModuleObject = "ComponentCost:Reference";
225 1 : NumRefAdjust = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
226 1 : if (NumRefAdjust == 1) {
227 0 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
228 : cCurrentModuleObject,
229 : 1,
230 0 : state.dataIPShortCut->cAlphaArgs,
231 : NumAlphas,
232 0 : state.dataIPShortCut->rNumericArgs,
233 : NumNumbers,
234 : IOStatus);
235 0 : state.dataCostEstimateManager->RefrncBldg.LineItemTot = state.dataIPShortCut->rNumericArgs(1);
236 0 : state.dataCostEstimateManager->RefrncBldg.MiscCostperSqMeter = state.dataIPShortCut->rNumericArgs(2);
237 0 : state.dataCostEstimateManager->RefrncBldg.DesignFeeFrac = state.dataIPShortCut->rNumericArgs(3);
238 0 : state.dataCostEstimateManager->RefrncBldg.ContractorFeeFrac = state.dataIPShortCut->rNumericArgs(4);
239 0 : state.dataCostEstimateManager->RefrncBldg.ContingencyFrac = state.dataIPShortCut->rNumericArgs(5);
240 0 : state.dataCostEstimateManager->RefrncBldg.BondCostFrac = state.dataIPShortCut->rNumericArgs(6);
241 0 : state.dataCostEstimateManager->RefrncBldg.CommissioningFrac = state.dataIPShortCut->rNumericArgs(7);
242 0 : state.dataCostEstimateManager->RefrncBldg.RegionalModifier = state.dataIPShortCut->rNumericArgs(8);
243 :
244 1 : } else if (NumRefAdjust > 1) {
245 0 : ShowSevereError(state, format("{} : Only one instance of this object is allowed.", cCurrentModuleObject));
246 0 : ErrorsFound = true;
247 : }
248 :
249 1 : if (ErrorsFound) {
250 0 : ShowFatalError(state, "Errors found in processing cost estimate input");
251 : }
252 :
253 1 : CheckCostEstimateInput(state, ErrorsFound);
254 :
255 1 : if (ErrorsFound) {
256 0 : ShowFatalError(state, "Errors found in processing cost estimate input");
257 : }
258 : }
259 :
260 1 : void CheckCostEstimateInput(EnergyPlusData &state, bool &ErrorsFound) // Set to true if errors in input, fatal at end of routine
261 : {
262 :
263 : // SUBROUTINE INFORMATION:
264 : // AUTHOR BGriffith
265 : // DATE WRITTEN April 2004
266 : // MODIFIED February 2005, M. J. Witte
267 : // Add subscript to DX coil variables due to new multimode DX coil
268 : // RE-ENGINEERED na
269 :
270 : // PURPOSE OF THIS SUBROUTINE:
271 : // Calculates the Cost Estimate based on inputs.
272 :
273 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
274 : int Item; // do-loop counter for line items
275 : int ThisConstructID; // hold result of FindItem searching for Construct name
276 : int ThisSurfID; // hold result from findItem
277 : int ThisZoneID; // hold result from findItem
278 :
279 1 : std::string ThisConstructStr;
280 1 : auto &Zone(state.dataHeatBal->Zone);
281 :
282 : int thisCoil; // index of named coil in its derived type
283 : int thisChil;
284 : int thisPV;
285 :
286 : // Setup working data structure for line items
287 7 : for (Item = 1; Item <= (int)state.dataCostEstimateManager->CostLineItem.size(); ++Item) { // Loop thru cost line items
288 :
289 6 : state.dataCostEstimateManager->CostLineItem(Item).LineNumber = Item;
290 :
291 6 : switch (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType) {
292 0 : case ParentObject::General: {
293 0 : } break;
294 0 : case ParentObject::Construction: {
295 :
296 : // test input for problems
297 : // is PerSquareMeter non-zero? if it is are other cost per values set?
298 : // issue warning that 'Cost Estimate requested for Constructions with zero cost per unit area
299 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter == 0) {
300 0 : ShowSevereError(state,
301 0 : format("ComponentCost:LineItem: \"{}\" Construction object needs non-zero construction costs per square meter",
302 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
303 0 : ErrorsFound = true;
304 : }
305 :
306 0 : ThisConstructStr = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
307 0 : ThisConstructID = Util::FindItem(ThisConstructStr, state.dataConstruction->Construct);
308 0 : if (ThisConstructID == 0) { // do any surfaces have the specified construction? If not issue warning.
309 0 : ShowWarningError(state,
310 0 : format("ComponentCost:LineItem: \"{}\" Construction=\"{}\", no surfaces have the Construction specified",
311 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
312 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
313 0 : ShowContinueError(state, "No costs will be calculated for this Construction.");
314 : // ErrorsFound = .TRUE.
315 0 : continue;
316 : }
317 0 : } break;
318 6 : case ParentObject::CoilDX:
319 : case ParentObject::CoilCoolingDX:
320 : case ParentObject::CoilCoolingDXSingleSpeed: {
321 : // test if too many pricing methods are set in user input
322 8 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
323 2 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
324 0 : ShowSevereError(state,
325 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
326 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
327 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
328 0 : ErrorsFound = true;
329 : }
330 8 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
331 2 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
332 0 : ShowSevereError(state,
333 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
334 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
335 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
336 0 : ErrorsFound = true;
337 : }
338 8 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) &&
339 2 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
340 0 : ShowSevereError(state,
341 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
342 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
343 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
344 0 : ErrorsFound = true;
345 : }
346 : // check for wildcard * in object name..
347 6 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
348 :
349 3 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
350 0 : ShowSevereError(state,
351 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
352 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
353 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
354 0 : ErrorsFound = true;
355 :
356 : } else { // assume name is probably useful
357 3 : bool coilFound = false;
358 3 : auto &parentObjName = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
359 6 : if ((state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilDX) ||
360 3 : (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilCoolingDXSingleSpeed)) {
361 0 : if (Util::FindItem(parentObjName, state.dataDXCoils->DXCoil) > 0) coilFound = true;
362 3 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilCoolingDX) {
363 3 : if (CoilCoolingDX::factory(state, parentObjName) != -1) {
364 3 : coilFound = true;
365 : }
366 : }
367 3 : if (!coilFound) {
368 0 : ShowWarningError(
369 : state,
370 0 : format("ComponentCost:LineItem: \"{}\", {}, invalid coil specified",
371 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
372 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
373 0 : ShowContinueError(state,
374 0 : format("Coil Specified=\"{}\", calculations will not be completed for this item.",
375 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
376 : }
377 : }
378 6 : } break;
379 0 : case ParentObject::CoilHeatingFuel: {
380 : // test if too many pricing methods are set in user input
381 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
382 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
383 0 : ShowSevereError(state,
384 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
385 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
386 0 : ErrorsFound = true;
387 : }
388 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
389 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
390 0 : ShowSevereError(state,
391 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
392 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
393 0 : ErrorsFound = true;
394 : }
395 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) &&
396 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
397 0 : ShowSevereError(state,
398 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
399 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
400 0 : ErrorsFound = true;
401 : }
402 : // check for wildcard * in object name..
403 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
404 :
405 0 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
406 0 : ShowSevereError(state,
407 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, need to specify a Reference Object Name",
408 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
409 0 : ErrorsFound = true;
410 :
411 : } else { // assume name is probably useful
412 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataHeatingCoils->HeatingCoil);
413 0 : if (thisCoil == 0) {
414 0 : ShowWarningError(state,
415 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, invalid coil specified",
416 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
417 0 : ShowContinueError(state,
418 0 : format("Coil Specified=\"{}\", calculations will not be completed for this item.",
419 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
420 : }
421 : }
422 0 : } break;
423 0 : case ParentObject::ChillerElectric: {
424 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
425 0 : ShowSevereError(state,
426 0 : format("ComponentCost:LineItem: \"{}\", Chiller:Electric, need to specify a Reference Object Name",
427 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
428 0 : ErrorsFound = true;
429 : }
430 0 : thisChil = 0;
431 0 : int chillNum = 0;
432 0 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
433 0 : chillNum++;
434 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == ch.Name) {
435 0 : thisChil = chillNum;
436 : }
437 : }
438 0 : if (thisChil == 0) {
439 0 : ShowWarningError(state,
440 0 : format("ComponentCost:LineItem: \"{}\", Chiller:Electric, invalid chiller specified.",
441 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
442 0 : ShowContinueError(state,
443 0 : format("Chiller Specified=\"{}\", calculations will not be completed for this item.",
444 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
445 : }
446 0 : } break;
447 0 : case ParentObject::DaylightingControls: {
448 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
449 0 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
450 0 : ShowSevereError(state,
451 0 : format("ComponentCost:LineItem: \"{}\", Daylighting:Controls, need to specify a Reference Object Name",
452 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
453 0 : ErrorsFound = true;
454 : } else {
455 0 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
456 0 : if (ThisZoneID > 0) {
457 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDayltg->ZoneDaylight(ThisZoneID).totRefPts;
458 : } else {
459 0 : ShowSevereError(state,
460 0 : format("ComponentCost:LineItem: \"{}\", Daylighting:Controls, need to specify a valid zone name",
461 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
462 0 : ShowContinueError(state, format("Zone specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
463 0 : ErrorsFound = true;
464 : }
465 : }
466 0 : } break;
467 0 : case ParentObject::ShadingZoneDetailed: {
468 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
469 0 : ThisSurfID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataSurface->Surface);
470 0 : if (ThisSurfID > 0) {
471 0 : ThisZoneID = Util::FindItem(state.dataSurface->Surface(ThisSurfID).ZoneName, Zone);
472 0 : if (ThisZoneID == 0) {
473 0 : ShowSevereError(state,
474 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, need to specify a valid zone name",
475 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
476 0 : ShowContinueError(state, format("Zone specified=\"{}\".", state.dataSurface->Surface(ThisSurfID).ZoneName));
477 0 : ErrorsFound = true;
478 : }
479 : } else {
480 0 : ShowSevereError(state,
481 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, need to specify a valid surface name",
482 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
483 0 : ShowContinueError(state,
484 0 : format("Surface specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
485 0 : ErrorsFound = true;
486 : }
487 : } else {
488 0 : ShowSevereError(state,
489 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, specify a Reference Object Name",
490 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
491 0 : ErrorsFound = true;
492 : }
493 0 : } break;
494 0 : case ParentObject::Lights: {
495 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
496 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
497 0 : ShowSevereError(state,
498 0 : format("ComponentCost:LineItem: \"{}\", Lights, too many pricing methods specified",
499 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
500 0 : ErrorsFound = true;
501 : }
502 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
503 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
504 0 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
505 0 : if (ThisZoneID == 0) {
506 0 : ShowSevereError(state,
507 0 : format("ComponentCost:LineItem: \"{}\", Lights, need to specify a valid zone name",
508 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
509 0 : ShowContinueError(state,
510 0 : format("Zone specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
511 0 : ErrorsFound = true;
512 : }
513 : } else {
514 0 : ShowSevereError(state,
515 0 : format("ComponentCost:LineItem: \"{}\", Lights, need to specify a Reference Object Name",
516 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
517 0 : ErrorsFound = true;
518 : }
519 : }
520 0 : } break;
521 0 : case ParentObject::GeneratorPhotovoltaic: {
522 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
523 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
524 0 : thisPV = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataPhotovoltaic->PVarray);
525 0 : if (thisPV > 0) {
526 0 : if (state.dataPhotovoltaic->PVarray(thisPV).PVModelType != DataPhotovoltaics::PVModel::Simple) {
527 0 : ShowSevereError(state,
528 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, only available for model type "
529 : "PhotovoltaicPerformance:Simple",
530 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
531 0 : ErrorsFound = true;
532 : }
533 : } else {
534 0 : ShowSevereError(state,
535 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a valid PV array",
536 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
537 0 : ShowContinueError(state,
538 0 : format("PV Array specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
539 0 : ErrorsFound = true;
540 : }
541 : } else {
542 0 : ShowSevereError(state,
543 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a Reference Object Name",
544 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
545 0 : ErrorsFound = true;
546 : }
547 : } else {
548 0 : ShowSevereError(state,
549 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a per-kilowatt cost ",
550 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
551 0 : ErrorsFound = true;
552 : }
553 0 : } break;
554 0 : default: {
555 0 : ShowWarningError(state,
556 0 : format("ComponentCost:LineItem: \"{}\", invalid cost item -- not included in cost estimate.",
557 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
558 0 : ShowContinueError(
559 : state,
560 0 : format("... invalid object type={}",
561 0 : format(ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)])));
562 0 : } break;
563 : }
564 : }
565 1 : }
566 :
567 1 : void CalcCostEstimate(EnergyPlusData &state)
568 : {
569 :
570 : // SUBROUTINE INFORMATION:
571 : // AUTHOR BGriffith
572 : // DATE WRITTEN April 2004
573 : // MODIFIED February 2005, M. J. Witte
574 : // Add subscript to DX coil variables due to new multimode DX coil
575 : // RE-ENGINEERED na
576 :
577 : // PURPOSE OF THIS SUBROUTINE:
578 : // Calculates the Cost Estimate based on inputs.
579 :
580 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
581 : int Item; // do-loop counter for line items
582 : int ThisConstructID; // hold result of FindItem searching for Construct name
583 : int ThisSurfID; // hold result from findItem
584 : int ThisZoneID; // hold result from findItem
585 :
586 1 : auto &Zone(state.dataHeatBal->Zone);
587 1 : std::string ThisConstructStr;
588 :
589 1 : Array1D_bool uniqueSurfMask;
590 1 : Array1D<Real64> SurfMultipleARR;
591 : int surf; // do-loop counter for checking for surfaces for uniqueness
592 : int thisCoil; // index of named coil in its derived type
593 : bool WildcardObjNames;
594 : int thisChil;
595 : int thisPV;
596 : Real64 Multipliers;
597 :
598 : // Setup working data structure for line items
599 7 : for (Item = 1; Item <= (int)state.dataCostEstimateManager->CostLineItem.size(); ++Item) { // Loop thru cost line items
600 :
601 6 : state.dataCostEstimateManager->CostLineItem(Item).LineNumber = Item;
602 :
603 6 : switch (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType) {
604 0 : case ParentObject::General: {
605 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
606 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
607 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
608 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
609 0 : } break;
610 0 : case ParentObject::Construction: {
611 0 : ThisConstructStr = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
612 0 : ThisConstructID = Util::FindItem(ThisConstructStr, state.dataConstruction->Construct);
613 : // need to determine unique surfaces... some surfaces are shared by zones and hence doubled
614 0 : uniqueSurfMask.dimension(state.dataSurface->TotSurfaces, true); // init to true and change duplicates to false
615 0 : SurfMultipleARR.dimension(state.dataSurface->TotSurfaces, 1.0);
616 0 : for (surf = 1; surf <= state.dataSurface->TotSurfaces; ++surf) {
617 0 : if (state.dataSurface->Surface(surf).ExtBoundCond >= 1) {
618 0 : if (state.dataSurface->Surface(surf).ExtBoundCond < surf) { // already cycled through
619 0 : uniqueSurfMask(surf) = false;
620 : }
621 : }
622 0 : if (state.dataSurface->Surface(surf).Construction == 0) { // throw out others for now
623 0 : uniqueSurfMask(surf) = false;
624 : }
625 0 : if (state.dataSurface->Surface(surf).Zone > 0) {
626 0 : SurfMultipleARR(surf) =
627 0 : Zone(state.dataSurface->Surface(surf).Zone).Multiplier * Zone(state.dataSurface->Surface(surf).Zone).ListMultiplier;
628 : }
629 : }
630 : // determine which surfaces have the construction type and if any are duplicates..
631 0 : Real64 Qty(0.0);
632 0 : for (int i = 1; i <= state.dataSurface->TotSurfaces; ++i) {
633 0 : auto const &s(state.dataSurface->Surface(i));
634 0 : if (uniqueSurfMask(i) && (s.Construction == ThisConstructID)) Qty += s.Area * SurfMultipleARR(i);
635 : }
636 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty;
637 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "m2";
638 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter;
639 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
640 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
641 :
642 0 : uniqueSurfMask.deallocate();
643 0 : SurfMultipleARR.deallocate();
644 0 : } break;
645 0 : case ParentObject::CoilDX:
646 : case ParentObject::CoilCoolingDXSingleSpeed: {
647 0 : WildcardObjNames = false;
648 0 : thisCoil = 0;
649 : // check for wildcard * in object name..
650 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
651 0 : WildcardObjNames = true;
652 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
653 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataDXCoils->DXCoil);
654 : }
655 :
656 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
657 0 : if (WildcardObjNames) {
658 0 : Real64 Qty(0.0);
659 0 : for (auto const &e : state.dataDXCoils->DXCoil)
660 0 : Qty += e.RatedTotCap(1);
661 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
662 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
663 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
664 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
665 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
666 : }
667 0 : if (thisCoil > 0) {
668 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDXCoils->DXCoil(thisCoil).RatedTotCap(1) / 1000.0;
669 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
670 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
671 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
672 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
673 : }
674 : }
675 :
676 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
677 0 : if (WildcardObjNames) state.dataCostEstimateManager->CostLineItem(Item).Qty = double(state.dataDXCoils->NumDXCoils);
678 0 : if (thisCoil > 0) state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
679 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
680 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
681 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
682 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
683 : }
684 :
685 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
686 0 : if (WildcardObjNames) {
687 0 : Real64 Qty(0.0);
688 0 : for (auto const &e : state.dataDXCoils->DXCoil) {
689 0 : int maxSpeed = e.RatedCOP.size();
690 0 : Qty += e.RatedCOP(maxSpeed) * e.RatedTotCap(maxSpeed);
691 : }
692 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
693 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
694 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
695 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
696 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
697 : }
698 0 : if (thisCoil > 0) {
699 0 : int maxSpeed = state.dataDXCoils->DXCoil(thisCoil).RatedCOP.size();
700 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDXCoils->DXCoil(thisCoil).RatedCOP(maxSpeed) *
701 0 : state.dataDXCoils->DXCoil(thisCoil).RatedTotCap(maxSpeed) / 1000.0;
702 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
703 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
704 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
705 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
706 : }
707 : }
708 0 : } break;
709 6 : case ParentObject::CoilCoolingDX: {
710 6 : WildcardObjNames = false;
711 6 : auto &parentObjName = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
712 6 : bool coilFound = false;
713 : // check for wildcard * in object name..
714 6 : if (parentObjName == "*") { // wildcard, apply to all such components
715 3 : WildcardObjNames = true;
716 3 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
717 : // Purposefully not calling the factory here
718 : // Input validation happens before we get to this point
719 : // The factory throws a severe error when the coil is not found
720 : // Finding the coil like this here to protects against another SevereError being thrown out of context
721 3 : auto &v = state.dataCoilCoolingDX->coilCoolingDXs;
722 3 : auto isInCoils = [&parentObjName](const CoilCoolingDX &coil) { return coil.name == parentObjName; };
723 3 : auto it = std::find_if(v.begin(), v.end(), isInCoils);
724 3 : if (it != v.end()) {
725 3 : thisCoil = std::distance(v.begin(), it);
726 3 : coilFound = true;
727 : }
728 : }
729 :
730 6 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
731 2 : if (WildcardObjNames) {
732 1 : Real64 Qty(0.0);
733 2 : for (auto const &e : state.dataCoilCoolingDX->coilCoolingDXs)
734 1 : Qty += e.performance.normalMode.ratedGrossTotalCap;
735 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
736 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
737 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
738 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
739 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
740 : }
741 2 : if (coilFound) {
742 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
743 1 : state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.ratedGrossTotalCap / 1000.0;
744 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
745 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
746 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
747 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
748 : }
749 : }
750 :
751 6 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
752 2 : if (WildcardObjNames)
753 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = double(state.dataCoilCoolingDX->coilCoolingDXs.size());
754 2 : if (coilFound) state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
755 2 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
756 2 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
757 2 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
758 2 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
759 : }
760 :
761 6 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
762 2 : if (WildcardObjNames) {
763 1 : Real64 Qty(0.0);
764 2 : for (auto const &e : state.dataCoilCoolingDX->coilCoolingDXs) {
765 1 : auto const &maxSpeed = e.performance.normalMode.speeds.back();
766 1 : Real64 COP = maxSpeed.original_input_specs.gross_rated_cooling_COP;
767 1 : Qty += COP * e.performance.normalMode.ratedGrossTotalCap;
768 : }
769 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
770 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
771 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
772 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
773 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
774 : }
775 2 : if (coilFound) {
776 1 : auto const &maxSpeed = state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.speeds.back();
777 1 : Real64 COP = maxSpeed.original_input_specs.gross_rated_cooling_COP;
778 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
779 1 : COP * state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.ratedGrossTotalCap / 1000.0;
780 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
781 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
782 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
783 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
784 : }
785 : }
786 6 : } break;
787 0 : case ParentObject::CoilHeatingFuel: {
788 0 : WildcardObjNames = false;
789 0 : thisCoil = 0;
790 : // check for wildcard * in object name..
791 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
792 0 : WildcardObjNames = true;
793 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
794 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataHeatingCoils->HeatingCoil);
795 : }
796 :
797 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
798 0 : if (WildcardObjNames) {
799 0 : Real64 Qty(0.0);
800 0 : for (auto const &e : state.dataHeatingCoils->HeatingCoil)
801 0 : if (e.HCoilType_Num == 1) Qty += e.NominalCapacity;
802 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
803 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot heat cap.)";
804 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
805 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
806 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
807 : }
808 0 : if (thisCoil > 0) {
809 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
810 0 : state.dataHeatingCoils->HeatingCoil(thisCoil).NominalCapacity / 1000.0;
811 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot heat cap.)";
812 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
813 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
814 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
815 : }
816 : }
817 :
818 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
819 0 : if (WildcardObjNames) state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataHeatingCoils->NumHeatingCoils;
820 0 : if (thisCoil > 0) state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
821 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
822 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
823 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
824 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
825 : }
826 :
827 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
828 0 : if (WildcardObjNames) {
829 0 : Real64 Qty(0.0);
830 0 : for (auto const &e : state.dataHeatingCoils->HeatingCoil)
831 0 : if (e.HCoilType_Num == 1) Qty += e.Efficiency * e.NominalCapacity;
832 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
833 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*Eff (total, rated) ";
834 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
835 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
836 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
837 : }
838 0 : if (thisCoil > 0) {
839 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataHeatingCoils->HeatingCoil(thisCoil).Efficiency *
840 0 : state.dataHeatingCoils->HeatingCoil(thisCoil).NominalCapacity /
841 : 1000.0;
842 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*Eff (total, rated) ";
843 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
844 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
845 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
846 : }
847 : }
848 0 : } break;
849 0 : case ParentObject::ChillerElectric: {
850 0 : thisChil = 0;
851 0 : int chillNum = 0;
852 0 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
853 0 : chillNum++;
854 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == ch.Name) {
855 0 : thisChil = chillNum;
856 : }
857 : }
858 0 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0)) {
859 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataPlantChillers->ElectricChiller(thisChil).NomCap / 1000.0;
860 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
861 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
862 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
863 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
864 : }
865 0 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
866 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
867 0 : state.dataPlantChillers->ElectricChiller(thisChil).COP * state.dataPlantChillers->ElectricChiller(thisChil).NomCap / 1000.0;
868 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
869 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
870 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
871 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
872 : }
873 0 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
874 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
875 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
876 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
877 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
878 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
879 : }
880 0 : } break;
881 0 : case ParentObject::DaylightingControls: {
882 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
883 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = sum(state.dataDayltg->ZoneDaylight, &Dayltg::ZoneDaylightCalc::totRefPts);
884 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
885 0 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
886 0 : if (ThisZoneID > 0) {
887 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDayltg->ZoneDaylight(ThisZoneID).totRefPts;
888 : }
889 : }
890 :
891 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
892 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
893 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
894 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
895 0 : } break;
896 0 : case ParentObject::ShadingZoneDetailed: {
897 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
898 0 : ThisSurfID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataSurface->Surface);
899 0 : if (ThisSurfID > 0) {
900 0 : ThisZoneID = Util::FindItem(state.dataSurface->Surface(ThisSurfID).ZoneName, Zone);
901 0 : if (ThisZoneID > 0) {
902 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
903 0 : state.dataSurface->Surface(ThisSurfID).Area * Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier;
904 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "m2";
905 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
906 0 : state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter;
907 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
908 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
909 : }
910 : }
911 : }
912 0 : } break;
913 0 : case ParentObject::Lights: {
914 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach != 0.0) {
915 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
916 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
917 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
918 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
919 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
920 : }
921 :
922 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
923 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
924 0 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
925 0 : if (ThisZoneID > 0) {
926 0 : Real64 Qty(0.0);
927 0 : for (auto const &e : state.dataHeatBal->Lights)
928 0 : if (e.ZonePtr == ThisZoneID) Qty += e.DesignLevel;
929 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
930 0 : (Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier / 1000.0) *
931 : Qty; // this handles more than one light object per zone.
932 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW";
933 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
934 0 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
935 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
936 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
937 : }
938 : }
939 : }
940 0 : } break;
941 0 : case ParentObject::GeneratorPhotovoltaic: {
942 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
943 0 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
944 0 : thisPV = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataPhotovoltaic->PVarray);
945 0 : if (thisPV > 0) {
946 : ThisZoneID =
947 0 : Util::FindItem(state.dataSurface->Surface(state.dataPhotovoltaic->PVarray(thisPV).SurfacePtr).ZoneName, Zone);
948 0 : if (ThisZoneID == 0) {
949 0 : Multipliers = 1.0;
950 : } else {
951 0 : Multipliers = Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier;
952 : }
953 0 : if (state.dataPhotovoltaic->PVarray(thisPV).PVModelType == DataPhotovoltaics::PVModel::Simple) {
954 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
955 0 : 1000.0 * state.dataPhotovoltaic->PVarray(thisPV).SimplePVModule.AreaCol *
956 0 : state.dataPhotovoltaic->PVarray(thisPV).SimplePVModule.PVEfficiency * Multipliers / 1000.0;
957 : }
958 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (rated)";
959 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
960 0 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
961 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
962 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
963 : }
964 : }
965 : }
966 0 : } break;
967 0 : default:
968 0 : break;
969 : }
970 : }
971 :
972 : // now sum up the line items, result for the current building
973 :
974 1 : state.dataCostEstimateManager->CurntBldg.LineItemTot = sum(state.dataCostEstimateManager->CostLineItem, &CostLineItemStruct::LineSubTotal);
975 1 : }
976 :
977 : } // namespace CostEstimateManager
978 :
979 : } // namespace EnergyPlus
|