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 1616 : 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 1616 : if (state.dataCostEstimateManager->GetCostInput) {
123 800 : GetCostEstimateInput(state);
124 800 : state.dataCostEstimateManager->GetCostInput = false;
125 : }
126 :
127 : // Need to add check Costs before this will work properly
128 :
129 1616 : if (state.dataGlobal->KickOffSimulation) {
130 817 : return;
131 : }
132 :
133 799 : if (state.dataCostEstimateManager->DoCostEstimate) {
134 40 : CalcCostEstimate(state);
135 : }
136 : }
137 :
138 800 : void GetCostEstimateInput(EnergyPlusData &state)
139 : {
140 :
141 : // SUBROUTINE INFORMATION:
142 : // AUTHOR BGriffith
143 : // DATE WRITTEN April 2004
144 : // MODIFIED na
145 : // RE-ENGINEERED na
146 :
147 : // PURPOSE OF THIS SUBROUTINE:
148 : // Get Cost Estimation object input.
149 :
150 : // Using/Aliasing
151 :
152 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
153 : int Item; // Item to be "gotten"
154 : int NumCostAdjust;
155 : int NumRefAdjust;
156 : int NumAlphas; // Number of Alphas for each GetObjectItem call
157 : int NumNumbers; // Number of Numbers for each GetObjectItem call
158 : int IOStatus; // Used in GetObjectItem
159 800 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
160 :
161 800 : int NumLineItems = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ComponentCost:LineItem");
162 :
163 800 : if (NumLineItems == 0) {
164 759 : state.dataCostEstimateManager->DoCostEstimate = false;
165 759 : return;
166 : } else {
167 41 : state.dataCostEstimateManager->DoCostEstimate = true;
168 : // WriteTabularFiles = .TRUE.
169 : }
170 :
171 41 : if (!allocated(state.dataCostEstimateManager->CostLineItem)) {
172 41 : state.dataCostEstimateManager->CostLineItem.allocate(NumLineItems);
173 : }
174 41 : auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
175 41 : cCurrentModuleObject = "ComponentCost:LineItem";
176 :
177 2969 : for (Item = 1; Item <= NumLineItems; ++Item) {
178 5856 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
179 : cCurrentModuleObject,
180 : Item,
181 2928 : state.dataIPShortCut->cAlphaArgs,
182 : NumAlphas,
183 2928 : state.dataIPShortCut->rNumericArgs,
184 : NumNumbers,
185 : IOStatus);
186 2928 : state.dataCostEstimateManager->CostLineItem(Item).LineName = state.dataIPShortCut->cAlphaArgs(1);
187 2928 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjType =
188 2928 : static_cast<ParentObject>(getEnumValue(ParentObjectNamesUC, state.dataIPShortCut->cAlphaArgs(3)));
189 2928 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName = state.dataIPShortCut->cAlphaArgs(4);
190 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerEach = state.dataIPShortCut->rNumericArgs(1);
191 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter = state.dataIPShortCut->rNumericArgs(2);
192 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap = state.dataIPShortCut->rNumericArgs(3);
193 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP = state.dataIPShortCut->rNumericArgs(4);
194 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerCubicMeter = state.dataIPShortCut->rNumericArgs(5);
195 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerCubMeterPerSec = state.dataIPShortCut->rNumericArgs(6);
196 2928 : state.dataCostEstimateManager->CostLineItem(Item).PerUAinWattperDelK = state.dataIPShortCut->rNumericArgs(7);
197 2928 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataIPShortCut->rNumericArgs(8);
198 : }
199 :
200 : // most input error checking to be performed later within Case construct in Calc routine.
201 :
202 41 : cCurrentModuleObject = "ComponentCost:Adjustments";
203 41 : NumCostAdjust = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
204 41 : if (NumCostAdjust == 1) {
205 10 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
206 : cCurrentModuleObject,
207 : 1,
208 5 : state.dataIPShortCut->cAlphaArgs,
209 : NumAlphas,
210 5 : state.dataIPShortCut->rNumericArgs,
211 : NumNumbers,
212 : IOStatus);
213 5 : state.dataCostEstimateManager->CurntBldg.MiscCostperSqMeter = state.dataIPShortCut->rNumericArgs(1);
214 5 : state.dataCostEstimateManager->CurntBldg.DesignFeeFrac = state.dataIPShortCut->rNumericArgs(2);
215 5 : state.dataCostEstimateManager->CurntBldg.ContractorFeeFrac = state.dataIPShortCut->rNumericArgs(3);
216 5 : state.dataCostEstimateManager->CurntBldg.ContingencyFrac = state.dataIPShortCut->rNumericArgs(4);
217 5 : state.dataCostEstimateManager->CurntBldg.BondCostFrac = state.dataIPShortCut->rNumericArgs(5);
218 5 : state.dataCostEstimateManager->CurntBldg.CommissioningFrac = state.dataIPShortCut->rNumericArgs(6);
219 5 : state.dataCostEstimateManager->CurntBldg.RegionalModifier = state.dataIPShortCut->rNumericArgs(7);
220 :
221 36 : } else if (NumCostAdjust > 1) {
222 0 : ShowSevereError(state, format("{}: Only one instance of this object is allowed.", cCurrentModuleObject));
223 0 : ErrorsFound = true;
224 : }
225 :
226 41 : cCurrentModuleObject = "ComponentCost:Reference";
227 41 : NumRefAdjust = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCurrentModuleObject);
228 41 : if (NumRefAdjust == 1) {
229 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
230 : cCurrentModuleObject,
231 : 1,
232 1 : state.dataIPShortCut->cAlphaArgs,
233 : NumAlphas,
234 1 : state.dataIPShortCut->rNumericArgs,
235 : NumNumbers,
236 : IOStatus);
237 1 : state.dataCostEstimateManager->RefrncBldg.LineItemTot = state.dataIPShortCut->rNumericArgs(1);
238 1 : state.dataCostEstimateManager->RefrncBldg.MiscCostperSqMeter = state.dataIPShortCut->rNumericArgs(2);
239 1 : state.dataCostEstimateManager->RefrncBldg.DesignFeeFrac = state.dataIPShortCut->rNumericArgs(3);
240 1 : state.dataCostEstimateManager->RefrncBldg.ContractorFeeFrac = state.dataIPShortCut->rNumericArgs(4);
241 1 : state.dataCostEstimateManager->RefrncBldg.ContingencyFrac = state.dataIPShortCut->rNumericArgs(5);
242 1 : state.dataCostEstimateManager->RefrncBldg.BondCostFrac = state.dataIPShortCut->rNumericArgs(6);
243 1 : state.dataCostEstimateManager->RefrncBldg.CommissioningFrac = state.dataIPShortCut->rNumericArgs(7);
244 1 : state.dataCostEstimateManager->RefrncBldg.RegionalModifier = state.dataIPShortCut->rNumericArgs(8);
245 :
246 40 : } else if (NumRefAdjust > 1) {
247 0 : ShowSevereError(state, format("{} : Only one instance of this object is allowed.", cCurrentModuleObject));
248 0 : ErrorsFound = true;
249 : }
250 :
251 41 : if (ErrorsFound) {
252 0 : ShowFatalError(state, "Errors found in processing cost estimate input");
253 : }
254 :
255 41 : CheckCostEstimateInput(state, ErrorsFound);
256 :
257 41 : if (ErrorsFound) {
258 0 : ShowFatalError(state, "Errors found in processing cost estimate input");
259 : }
260 : }
261 :
262 41 : void CheckCostEstimateInput(EnergyPlusData &state, bool &ErrorsFound) // Set to true if errors in input, fatal at end of routine
263 : {
264 :
265 : // SUBROUTINE INFORMATION:
266 : // AUTHOR BGriffith
267 : // DATE WRITTEN April 2004
268 : // MODIFIED February 2005, M. J. Witte
269 : // Add subscript to DX coil variables due to new multimode DX coil
270 : // RE-ENGINEERED na
271 :
272 : // PURPOSE OF THIS SUBROUTINE:
273 : // Calculates the Cost Estimate based on inputs.
274 :
275 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
276 : int Item; // do-loop counter for line items
277 : int ThisConstructID; // hold result of FindItem searching for Construct name
278 : int ThisSurfID; // hold result from findItem
279 : int ThisZoneID; // hold result from findItem
280 :
281 41 : std::string ThisConstructStr;
282 41 : auto &Zone(state.dataHeatBal->Zone);
283 :
284 : int thisCoil; // index of named coil in its derived type
285 : int thisChil;
286 : int thisPV;
287 :
288 : // Setup working data structure for line items
289 2969 : for (Item = 1; Item <= (int)state.dataCostEstimateManager->CostLineItem.size(); ++Item) { // Loop thru cost line items
290 :
291 2928 : state.dataCostEstimateManager->CostLineItem(Item).LineNumber = Item;
292 :
293 2928 : switch (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType) {
294 1763 : case ParentObject::General: {
295 1763 : } break;
296 383 : case ParentObject::Construction: {
297 :
298 : // test input for problems
299 : // is PerSquareMeter non-zero? if it is are other cost per values set?
300 : // issue warning that 'Cost Estimate requested for Constructions with zero cost per unit area
301 383 : if (state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter == 0) {
302 0 : ShowSevereError(state,
303 0 : format("ComponentCost:LineItem: \"{}\" Construction object needs non-zero construction costs per square meter",
304 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
305 0 : ErrorsFound = true;
306 : }
307 :
308 383 : ThisConstructStr = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
309 383 : ThisConstructID = Util::FindItem(ThisConstructStr, state.dataConstruction->Construct);
310 383 : if (ThisConstructID == 0) { // do any surfaces have the specified construction? If not issue warning.
311 2 : ShowWarningError(state,
312 2 : format("ComponentCost:LineItem: \"{}\" Construction=\"{}\", no surfaces have the Construction specified",
313 1 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
314 1 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
315 2 : ShowContinueError(state, "No costs will be calculated for this Construction.");
316 : // ErrorsFound = .TRUE.
317 1 : continue;
318 : }
319 382 : } break;
320 3 : case ParentObject::CoilDX:
321 : case ParentObject::CoilCoolingDX:
322 : case ParentObject::CoilCoolingDXSingleSpeed: {
323 : // test if too many pricing methods are set in user input
324 4 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
325 1 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
326 0 : ShowSevereError(state,
327 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
328 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
329 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
330 0 : ErrorsFound = true;
331 : }
332 4 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
333 1 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
334 0 : ShowSevereError(state,
335 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
336 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
337 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
338 0 : ErrorsFound = true;
339 : }
340 4 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) &&
341 1 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
342 0 : ShowSevereError(state,
343 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
344 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
345 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
346 0 : ErrorsFound = true;
347 : }
348 : // check for wildcard * in object name..
349 3 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
350 :
351 0 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
352 0 : ShowSevereError(state,
353 0 : format("ComponentCost:LineItem: \"{}\", {}, too many pricing methods specified",
354 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
355 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
356 0 : ErrorsFound = true;
357 :
358 : } else { // assume name is probably useful
359 0 : bool coilFound = false;
360 0 : auto &parentObjName = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
361 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilDX) ||
362 0 : (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilCoolingDXSingleSpeed)) {
363 0 : if (Util::FindItem(parentObjName, state.dataDXCoils->DXCoil) > 0) {
364 0 : coilFound = true;
365 : }
366 0 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType == ParentObject::CoilCoolingDX) {
367 0 : if (CoilCoolingDX::factory(state, parentObjName) != -1) {
368 0 : coilFound = true;
369 : }
370 : }
371 0 : if (!coilFound) {
372 0 : ShowWarningError(
373 : state,
374 0 : format("ComponentCost:LineItem: \"{}\", {}, invalid coil specified",
375 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName,
376 0 : ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)]));
377 0 : ShowContinueError(state,
378 0 : format("Coil Specified=\"{}\", calculations will not be completed for this item.",
379 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
380 : }
381 : }
382 3 : } break;
383 0 : case ParentObject::CoilHeatingFuel: {
384 : // test if too many pricing methods are set in user input
385 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
386 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
387 0 : ShowSevereError(state,
388 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
389 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
390 0 : ErrorsFound = true;
391 : }
392 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
393 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
394 0 : ShowSevereError(state,
395 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
396 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
397 0 : ErrorsFound = true;
398 : }
399 0 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) &&
400 0 : (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
401 0 : ShowSevereError(state,
402 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, too many pricing methods specified",
403 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
404 0 : ErrorsFound = true;
405 : }
406 : // check for wildcard * in object name..
407 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
408 :
409 0 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
410 0 : ShowSevereError(state,
411 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, need to specify a Reference Object Name",
412 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
413 0 : ErrorsFound = true;
414 :
415 : } else { // assume name is probably useful
416 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataHeatingCoils->HeatingCoil);
417 0 : if (thisCoil == 0) {
418 0 : ShowWarningError(state,
419 0 : format("ComponentCost:LineItem: \"{}\", Coil:Heating:Fuel, invalid coil specified",
420 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
421 0 : ShowContinueError(state,
422 0 : format("Coil Specified=\"{}\", calculations will not be completed for this item.",
423 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
424 : }
425 : }
426 0 : } break;
427 5 : case ParentObject::ChillerElectric: {
428 5 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
429 0 : ShowSevereError(state,
430 0 : format("ComponentCost:LineItem: \"{}\", Chiller:Electric, need to specify a Reference Object Name",
431 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
432 0 : ErrorsFound = true;
433 : }
434 5 : thisChil = 0;
435 5 : int chillNum = 0;
436 10 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
437 5 : chillNum++;
438 5 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == ch.Name) {
439 5 : thisChil = chillNum;
440 : }
441 5 : }
442 5 : if (thisChil == 0) {
443 0 : ShowWarningError(state,
444 0 : format("ComponentCost:LineItem: \"{}\", Chiller:Electric, invalid chiller specified.",
445 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
446 0 : ShowContinueError(state,
447 0 : format("Chiller Specified=\"{}\", calculations will not be completed for this item.",
448 0 : state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
449 : }
450 5 : } break;
451 73 : case ParentObject::DaylightingControls: {
452 73 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
453 73 : } else if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
454 0 : ShowSevereError(state,
455 0 : format("ComponentCost:LineItem: \"{}\", Daylighting:Controls, need to specify a Reference Object Name",
456 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
457 0 : ErrorsFound = true;
458 : } else {
459 73 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
460 73 : if (ThisZoneID > 0) {
461 73 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDayltg->ZoneDaylight(ThisZoneID).totRefPts;
462 : } else {
463 0 : ShowSevereError(state,
464 0 : format("ComponentCost:LineItem: \"{}\", Daylighting:Controls, need to specify a valid zone name",
465 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
466 0 : ShowContinueError(state, format("Zone specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
467 0 : ErrorsFound = true;
468 : }
469 : }
470 73 : } break;
471 40 : case ParentObject::ShadingZoneDetailed: {
472 40 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
473 40 : ThisSurfID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataSurface->Surface);
474 40 : if (ThisSurfID > 0) {
475 40 : ThisZoneID = Util::FindItem(state.dataSurface->Surface(ThisSurfID).ZoneName, Zone);
476 40 : if (ThisZoneID == 0) {
477 0 : ShowSevereError(state,
478 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, need to specify a valid zone name",
479 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
480 0 : ShowContinueError(state, format("Zone specified=\"{}\".", state.dataSurface->Surface(ThisSurfID).ZoneName));
481 0 : ErrorsFound = true;
482 : }
483 : } else {
484 0 : ShowSevereError(state,
485 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, need to specify a valid surface name",
486 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
487 0 : ShowContinueError(state,
488 0 : format("Surface specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
489 0 : ErrorsFound = true;
490 : }
491 : } else {
492 0 : ShowSevereError(state,
493 0 : format("ComponentCost:LineItem: \"{}\", Shading:Zone:Detailed, specify a Reference Object Name",
494 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
495 0 : ErrorsFound = true;
496 : }
497 40 : } break;
498 646 : case ParentObject::Lights: {
499 1292 : if ((state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) &&
500 646 : (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
501 0 : ShowSevereError(state,
502 0 : format("ComponentCost:LineItem: \"{}\", Lights, too many pricing methods specified",
503 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
504 0 : ErrorsFound = true;
505 : }
506 646 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
507 646 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
508 646 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
509 646 : if (ThisZoneID == 0) {
510 0 : ShowSevereError(state,
511 0 : format("ComponentCost:LineItem: \"{}\", Lights, need to specify a valid zone name",
512 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
513 0 : ShowContinueError(state,
514 0 : format("Zone specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
515 0 : ErrorsFound = true;
516 : }
517 : } else {
518 0 : ShowSevereError(state,
519 0 : format("ComponentCost:LineItem: \"{}\", Lights, need to specify a Reference Object Name",
520 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
521 0 : ErrorsFound = true;
522 : }
523 : }
524 646 : } break;
525 15 : case ParentObject::GeneratorPhotovoltaic: {
526 15 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
527 15 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
528 15 : thisPV = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataPhotovoltaic->PVarray);
529 15 : if (thisPV > 0) {
530 15 : if (state.dataPhotovoltaic->PVarray(thisPV).PVModelType != DataPhotovoltaics::PVModel::Simple) {
531 0 : ShowSevereError(state,
532 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, only available for model type "
533 : "PhotovoltaicPerformance:Simple",
534 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
535 0 : ErrorsFound = true;
536 : }
537 : } else {
538 0 : ShowSevereError(state,
539 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a valid PV array",
540 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
541 0 : ShowContinueError(state,
542 0 : format("PV Array specified=\"{}\".", state.dataCostEstimateManager->CostLineItem(Item).ParentObjName));
543 0 : ErrorsFound = true;
544 : }
545 : } else {
546 0 : ShowSevereError(state,
547 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a Reference Object Name",
548 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
549 0 : ErrorsFound = true;
550 : }
551 : } else {
552 0 : ShowSevereError(state,
553 0 : format("ComponentCost:LineItem: \"{}\", Generator:Photovoltaic, need to specify a per-kilowatt cost ",
554 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
555 0 : ErrorsFound = true;
556 : }
557 15 : } break;
558 0 : default: {
559 0 : ShowWarningError(state,
560 0 : format("ComponentCost:LineItem: \"{}\", invalid cost item -- not included in cost estimate.",
561 0 : state.dataCostEstimateManager->CostLineItem(Item).LineName));
562 0 : ShowContinueError(
563 : state,
564 0 : format("... invalid object type={}",
565 0 : format(ParentObjectNamesUC[static_cast<int>(state.dataCostEstimateManager->CostLineItem(Item).ParentObjType)])));
566 0 : } break;
567 : }
568 : }
569 41 : }
570 :
571 40 : void CalcCostEstimate(EnergyPlusData &state)
572 : {
573 :
574 : // SUBROUTINE INFORMATION:
575 : // AUTHOR BGriffith
576 : // DATE WRITTEN April 2004
577 : // MODIFIED February 2005, M. J. Witte
578 : // Add subscript to DX coil variables due to new multimode DX coil
579 : // RE-ENGINEERED na
580 :
581 : // PURPOSE OF THIS SUBROUTINE:
582 : // Calculates the Cost Estimate based on inputs.
583 :
584 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
585 : int Item; // do-loop counter for line items
586 : int ThisConstructID; // hold result of FindItem searching for Construct name
587 : int ThisSurfID; // hold result from findItem
588 : int ThisZoneID; // hold result from findItem
589 :
590 40 : auto &Zone(state.dataHeatBal->Zone);
591 40 : std::string ThisConstructStr;
592 :
593 40 : Array1D_bool uniqueSurfMask;
594 40 : Array1D<Real64> SurfMultipleARR;
595 : int surf; // do-loop counter for checking for surfaces for uniqueness
596 : int thisCoil; // index of named coil in its derived type
597 : bool WildcardObjNames;
598 : int thisChil;
599 : int thisPV;
600 : Real64 Multipliers;
601 :
602 : // Setup working data structure for line items
603 2937 : for (Item = 1; Item <= (int)state.dataCostEstimateManager->CostLineItem.size(); ++Item) { // Loop thru cost line items
604 :
605 2897 : state.dataCostEstimateManager->CostLineItem(Item).LineNumber = Item;
606 :
607 2897 : switch (state.dataCostEstimateManager->CostLineItem(Item).ParentObjType) {
608 1748 : case ParentObject::General: {
609 1748 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
610 1748 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
611 1748 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
612 1748 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
613 1748 : } break;
614 372 : case ParentObject::Construction: {
615 372 : ThisConstructStr = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
616 372 : ThisConstructID = Util::FindItem(ThisConstructStr, state.dataConstruction->Construct);
617 : // need to determine unique surfaces... some surfaces are shared by zones and hence doubled
618 372 : uniqueSurfMask.dimension(state.dataSurface->TotSurfaces, true); // init to true and change duplicates to false
619 372 : SurfMultipleARR.dimension(state.dataSurface->TotSurfaces, 1.0);
620 62664 : for (surf = 1; surf <= state.dataSurface->TotSurfaces; ++surf) {
621 62292 : if (state.dataSurface->Surface(surf).ExtBoundCond >= 1) {
622 39212 : if (state.dataSurface->Surface(surf).ExtBoundCond < surf) { // already cycled through
623 6969 : uniqueSurfMask(surf) = false;
624 : }
625 : }
626 62292 : if (state.dataSurface->Surface(surf).Construction == 0) { // throw out others for now
627 986 : uniqueSurfMask(surf) = false;
628 : }
629 62292 : if (state.dataSurface->Surface(surf).Zone > 0) {
630 61306 : SurfMultipleARR(surf) =
631 61306 : Zone(state.dataSurface->Surface(surf).Zone).Multiplier * Zone(state.dataSurface->Surface(surf).Zone).ListMultiplier;
632 : }
633 : }
634 : // determine which surfaces have the construction type and if any are duplicates..
635 372 : Real64 Qty(0.0);
636 62664 : for (int i = 1; i <= state.dataSurface->TotSurfaces; ++i) {
637 62292 : auto const &s(state.dataSurface->Surface(i));
638 62292 : if (uniqueSurfMask(i) && (s.Construction == ThisConstructID)) {
639 5020 : Qty += s.Area * SurfMultipleARR(i);
640 : }
641 : }
642 372 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty;
643 372 : state.dataCostEstimateManager->CostLineItem(Item).Units = "m2";
644 372 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter;
645 372 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
646 372 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
647 :
648 372 : uniqueSurfMask.deallocate();
649 372 : SurfMultipleARR.deallocate();
650 372 : } break;
651 0 : case ParentObject::CoilDX:
652 : case ParentObject::CoilCoolingDXSingleSpeed: {
653 0 : WildcardObjNames = false;
654 0 : thisCoil = 0;
655 : // check for wildcard * in object name..
656 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
657 0 : WildcardObjNames = true;
658 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
659 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataDXCoils->DXCoil);
660 : }
661 :
662 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
663 0 : if (WildcardObjNames) {
664 0 : Real64 Qty(0.0);
665 0 : for (auto const &e : state.dataDXCoils->DXCoil) {
666 0 : Qty += e.RatedTotCap(1);
667 : }
668 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 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 0 : if (thisCoil > 0) {
675 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDXCoils->DXCoil(thisCoil).RatedTotCap(1) / 1000.0;
676 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
677 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
678 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
679 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
680 : }
681 : }
682 :
683 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
684 0 : if (WildcardObjNames) {
685 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = double(state.dataDXCoils->NumDXCoils);
686 : }
687 0 : if (thisCoil > 0) {
688 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
689 : }
690 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
691 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
692 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
693 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
694 : }
695 :
696 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
697 0 : if (WildcardObjNames) {
698 0 : Real64 Qty(0.0);
699 0 : for (auto const &e : state.dataDXCoils->DXCoil) {
700 0 : int maxSpeed = e.RatedCOP.size();
701 0 : Qty += e.RatedCOP(maxSpeed) * e.RatedTotCap(maxSpeed);
702 : }
703 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
704 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
705 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
706 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
707 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
708 : }
709 0 : if (thisCoil > 0) {
710 0 : int maxSpeed = state.dataDXCoils->DXCoil(thisCoil).RatedCOP.size();
711 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDXCoils->DXCoil(thisCoil).RatedCOP(maxSpeed) *
712 0 : state.dataDXCoils->DXCoil(thisCoil).RatedTotCap(maxSpeed) / 1000.0;
713 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
714 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
715 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
716 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
717 : }
718 : }
719 0 : } break;
720 3 : case ParentObject::CoilCoolingDX: {
721 3 : WildcardObjNames = false;
722 3 : auto &parentObjName = state.dataCostEstimateManager->CostLineItem(Item).ParentObjName;
723 3 : bool coilFound = false;
724 : // check for wildcard * in object name..
725 3 : if (parentObjName == "*") { // wildcard, apply to all such components
726 3 : WildcardObjNames = true;
727 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
728 : // Purposefully not calling the factory here
729 : // Input validation happens before we get to this point
730 : // The factory throws a severe error when the coil is not found
731 : // Finding the coil like this here to protects against another SevereError being thrown out of context
732 0 : auto &v = state.dataCoilCoolingDX->coilCoolingDXs;
733 0 : auto isInCoils = [&parentObjName](const CoilCoolingDX &coil) { return coil.name == parentObjName; };
734 0 : auto it = std::find_if(v.begin(), v.end(), isInCoils);
735 0 : if (it != v.end()) {
736 0 : thisCoil = std::distance(v.begin(), it);
737 0 : coilFound = true;
738 : }
739 0 : }
740 :
741 3 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
742 1 : if (WildcardObjNames) {
743 1 : Real64 Qty(0.0);
744 2 : for (auto const &e : state.dataCoilCoolingDX->coilCoolingDXs) {
745 1 : Qty += e.performance.normalMode.ratedGrossTotalCap;
746 1 : }
747 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
748 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
749 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
750 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
751 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
752 : }
753 1 : if (coilFound) {
754 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
755 0 : state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.ratedGrossTotalCap / 1000.0;
756 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
757 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
758 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
759 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
760 : }
761 : }
762 :
763 3 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
764 1 : if (WildcardObjNames) {
765 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = double(state.dataCoilCoolingDX->coilCoolingDXs.size());
766 : }
767 1 : if (coilFound) {
768 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
769 : }
770 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
771 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
772 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
773 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
774 : }
775 :
776 3 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
777 1 : if (WildcardObjNames) {
778 1 : Real64 Qty(0.0);
779 2 : for (auto const &e : state.dataCoilCoolingDX->coilCoolingDXs) {
780 1 : auto const &maxSpeed = e.performance.normalMode.speeds.back();
781 1 : Real64 COP = maxSpeed.original_input_specs.gross_rated_cooling_COP;
782 1 : Qty += COP * e.performance.normalMode.ratedGrossTotalCap;
783 1 : }
784 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
785 1 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
786 1 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
787 1 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
788 1 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
789 : }
790 1 : if (coilFound) {
791 0 : auto const &maxSpeed = state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.speeds.back();
792 0 : Real64 COP = maxSpeed.original_input_specs.gross_rated_cooling_COP;
793 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
794 0 : COP * state.dataCoilCoolingDX->coilCoolingDXs[thisCoil].performance.normalMode.ratedGrossTotalCap / 1000.0;
795 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
796 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
797 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
798 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
799 : }
800 : }
801 3 : } break;
802 0 : case ParentObject::CoilHeatingFuel: {
803 0 : WildcardObjNames = false;
804 0 : thisCoil = 0;
805 : // check for wildcard * in object name..
806 0 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
807 0 : WildcardObjNames = true;
808 0 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
809 0 : thisCoil = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataHeatingCoils->HeatingCoil);
810 : }
811 :
812 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0) {
813 0 : if (WildcardObjNames) {
814 0 : Real64 Qty(0.0);
815 0 : for (auto const &e : state.dataHeatingCoils->HeatingCoil) {
816 0 : if (e.HCoilType_Num == 1) {
817 0 : Qty += e.NominalCapacity;
818 : }
819 : }
820 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
821 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot heat cap.)";
822 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
823 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
824 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
825 : }
826 0 : if (thisCoil > 0) {
827 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
828 0 : state.dataHeatingCoils->HeatingCoil(thisCoil).NominalCapacity / 1000.0;
829 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot heat cap.)";
830 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
831 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
832 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
833 : }
834 : }
835 :
836 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0) {
837 0 : if (WildcardObjNames) {
838 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataHeatingCoils->NumHeatingCoils;
839 : }
840 0 : if (thisCoil > 0) {
841 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
842 : }
843 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
844 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
845 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
846 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
847 : }
848 :
849 0 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0) {
850 0 : if (WildcardObjNames) {
851 0 : Real64 Qty(0.0);
852 0 : for (auto const &e : state.dataHeatingCoils->HeatingCoil) {
853 0 : if (e.HCoilType_Num == 1) {
854 0 : Qty += e.Efficiency * e.NominalCapacity;
855 : }
856 : }
857 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = Qty / 1000.0;
858 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*Eff (total, rated) ";
859 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
860 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
861 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
862 : }
863 0 : if (thisCoil > 0) {
864 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataHeatingCoils->HeatingCoil(thisCoil).Efficiency *
865 0 : state.dataHeatingCoils->HeatingCoil(thisCoil).NominalCapacity /
866 : 1000.0;
867 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*Eff (total, rated) ";
868 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
869 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
870 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
871 : }
872 : }
873 0 : } break;
874 5 : case ParentObject::ChillerElectric: {
875 5 : thisChil = 0;
876 5 : int chillNum = 0;
877 10 : for (auto const &ch : state.dataPlantChillers->ElectricChiller) {
878 5 : chillNum++;
879 5 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == ch.Name) {
880 5 : thisChil = chillNum;
881 : }
882 5 : }
883 5 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap > 0.0)) {
884 5 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataPlantChillers->ElectricChiller(thisChil).NomCap / 1000.0;
885 5 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (tot cool cap.)";
886 5 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
887 5 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
888 5 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
889 : }
890 5 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP > 0.0)) {
891 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
892 0 : state.dataPlantChillers->ElectricChiller(thisChil).COP * state.dataPlantChillers->ElectricChiller(thisChil).NomCap / 1000.0;
893 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW*COP (total, rated) ";
894 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerKWCapPerCOP;
895 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
896 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
897 : }
898 5 : if ((thisChil > 0) && (state.dataCostEstimateManager->CostLineItem(Item).PerEach > 0.0)) {
899 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
900 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
901 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
902 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
903 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
904 : }
905 5 : } break;
906 73 : case ParentObject::DaylightingControls: {
907 73 : if (state.dataCostEstimateManager->CostLineItem(Item).ParentObjName == "*") { // wildcard, apply to all such components
908 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = sum(state.dataDayltg->ZoneDaylight, &Dayltg::ZoneDaylightCalc::totRefPts);
909 73 : } else if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
910 73 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
911 73 : if (ThisZoneID > 0) {
912 73 : state.dataCostEstimateManager->CostLineItem(Item).Qty = state.dataDayltg->ZoneDaylight(ThisZoneID).totRefPts;
913 : }
914 : }
915 :
916 73 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
917 73 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
918 73 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
919 73 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
920 73 : } break;
921 40 : case ParentObject::ShadingZoneDetailed: {
922 40 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
923 40 : ThisSurfID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataSurface->Surface);
924 40 : if (ThisSurfID > 0) {
925 40 : ThisZoneID = Util::FindItem(state.dataSurface->Surface(ThisSurfID).ZoneName, Zone);
926 40 : if (ThisZoneID > 0) {
927 40 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
928 40 : state.dataSurface->Surface(ThisSurfID).Area * Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier;
929 40 : state.dataCostEstimateManager->CostLineItem(Item).Units = "m2";
930 40 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
931 40 : state.dataCostEstimateManager->CostLineItem(Item).PerSquareMeter;
932 40 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
933 40 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
934 : }
935 : }
936 : }
937 40 : } break;
938 641 : case ParentObject::Lights: {
939 641 : if (state.dataCostEstimateManager->CostLineItem(Item).PerEach != 0.0) {
940 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty = 1.0;
941 0 : state.dataCostEstimateManager->CostLineItem(Item).Units = "Ea.";
942 0 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer = state.dataCostEstimateManager->CostLineItem(Item).PerEach;
943 0 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
944 0 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
945 : }
946 :
947 641 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
948 641 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
949 641 : ThisZoneID = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, Zone);
950 641 : if (ThisZoneID > 0) {
951 641 : Real64 Qty(0.0);
952 54096 : for (auto const &e : state.dataHeatBal->Lights) {
953 53455 : if (e.ZonePtr == ThisZoneID) {
954 641 : Qty += e.DesignLevel;
955 : }
956 641 : }
957 641 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
958 641 : (Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier / 1000.0) *
959 : Qty; // this handles more than one light object per zone.
960 641 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW";
961 641 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
962 641 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
963 641 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
964 641 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
965 : }
966 : }
967 : }
968 641 : } break;
969 15 : case ParentObject::GeneratorPhotovoltaic: {
970 15 : if (state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap != 0.0) {
971 15 : if (!state.dataCostEstimateManager->CostLineItem(Item).ParentObjName.empty()) {
972 15 : thisPV = Util::FindItem(state.dataCostEstimateManager->CostLineItem(Item).ParentObjName, state.dataPhotovoltaic->PVarray);
973 15 : if (thisPV > 0) {
974 : ThisZoneID =
975 15 : Util::FindItem(state.dataSurface->Surface(state.dataPhotovoltaic->PVarray(thisPV).SurfacePtr).ZoneName, Zone);
976 15 : if (ThisZoneID == 0) {
977 0 : Multipliers = 1.0;
978 : } else {
979 15 : Multipliers = Zone(ThisZoneID).Multiplier * Zone(ThisZoneID).ListMultiplier;
980 : }
981 15 : if (state.dataPhotovoltaic->PVarray(thisPV).PVModelType == DataPhotovoltaics::PVModel::Simple) {
982 15 : state.dataCostEstimateManager->CostLineItem(Item).Qty =
983 15 : 1000.0 * state.dataPhotovoltaic->PVarray(thisPV).SimplePVModule.AreaCol *
984 15 : state.dataPhotovoltaic->PVarray(thisPV).SimplePVModule.PVEfficiency * Multipliers / 1000.0;
985 : }
986 15 : state.dataCostEstimateManager->CostLineItem(Item).Units = "kW (rated)";
987 15 : state.dataCostEstimateManager->CostLineItem(Item).ValuePer =
988 15 : state.dataCostEstimateManager->CostLineItem(Item).PerKiloWattCap;
989 15 : state.dataCostEstimateManager->CostLineItem(Item).LineSubTotal =
990 15 : state.dataCostEstimateManager->CostLineItem(Item).Qty * state.dataCostEstimateManager->CostLineItem(Item).ValuePer;
991 : }
992 : }
993 : }
994 15 : } break;
995 0 : default:
996 0 : break;
997 : }
998 : }
999 :
1000 : // now sum up the line items, result for the current building
1001 :
1002 40 : state.dataCostEstimateManager->CurntBldg.LineItemTot = sum(state.dataCostEstimateManager->CostLineItem, &CostLineItemStruct::LineSubTotal);
1003 40 : }
1004 :
1005 : } // namespace CostEstimateManager
1006 :
1007 : } // namespace EnergyPlus
|