/
plant.h
2021 lines (1522 loc) · 102 KB
/
plant.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef PLANT_H
#define PLANT_H
#include <algorithm>
#include <cmath>
#include <numeric>
#include <vector>
#include <iostream>
#include <queue>
#include <stack>
#include <array>
#include "climate.h"
#include "util.h"
//beginning of contents added by Dapeng
#include "tinyxml.h"
class District;
class Building;
class DistrictEnergyCenter;
class Network;
//end of contents added by Dapeng
class NodePair;
class SubstationNodePair;
class ThermalStationNodePair;
class PipePair;
class Pipe;
class TemperatureSetpoint;
class PressureSetpoint;
class PIDController;
class PIDControllerValve;
class MassFlowSetpoint;
class MCR;
using namespace std;
// *** Plant class, CitySim *** //
// *** jerome.kaempf@epfl.ch *** //
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
class Polynomial {
private:
vector<double> a; // coefficients of the polynomial regression
public:
Polynomial(TiXmlHandle hdl);
size_t getSize() { return a.size(); }
double get_a(unsigned int i) { return a.at(i); }
};
class PhotoVoltaic {
protected:
double etampref, tref, tcnoct, muvoc, vmp;
double toutsoc = 20.;
double gtsoc = 800.;
Polynomial* iam_polynomial = nullptr;
string name = "No name";
#ifdef DEBUG
// IAM characteristics
vector<pair<float,double>> iam;
#endif // DEBUG
ostream logStream;
public:
PhotoVoltaic(double etampref, double tref, double tcnoct, double muvoc, double vmp):
etampref(etampref),tref(tref),tcnoct(tcnoct),muvoc(muvoc),vmp(vmp),logStream(std::cout.rdbuf()) {}
PhotoVoltaic(double pmp, double ac, double tref, double tcnoct, double muvoc, double vmp):
tref(tref),tcnoct(tcnoct),muvoc(muvoc),vmp(vmp),logStream(std::cout.rdbuf()) {etampref = pmp/(ac*1000.0);}
PhotoVoltaic(const PhotoVoltaic& pv):
etampref(pv.etampref),tref(pv.tref),tcnoct(pv.tcnoct),muvoc(pv.muvoc),vmp(pv.vmp),toutsoc(pv.toutsoc),gtsoc(pv.toutsoc),logStream(std::cout.rdbuf()) {}
PhotoVoltaic(TiXmlHandle hdl, ostream* pLogStr=nullptr);
virtual ~PhotoVoltaic();
void writeXML(ofstream& file, float ratio, string tab);
virtual double getMaxPowerEfficiency(double gt, double tout);
string getName(){ return name;}
double getIAM(float elevation); //!< Returns ths IAM with the elevation is given in radians
};
class SolarThermal {
private:
string name = "No name";
double eta0, a1, a2;
ostream logStream;
public:
SolarThermal(double eta0, double a1, double a2):eta0(eta0),a1(a1),a2(a2),logStream(std::cout.rdbuf()) {}
SolarThermal(TiXmlHandle hdl, ostream* pLogStr=NULL);
void writeXML(ofstream& file, float ratio, string tab);
double getEta0() { return eta0; }
double getA1() { return a1; }
double getA2() { return a2; }
string getName(){ return name;}
};
class SolarHybrid : public PhotoVoltaic {
private:
// fixed parameters of the model
const float FF=0.7595f, eta_exch=0.94f, eta0=0.554f, x_g=0.0032f, lambda_g=1.f, tau_g=0.88f, epsilon_g=0.85f, alpha_g=0.06f, x_air=0.005f, lambda_air=0.024f, x_eva=0.0005f, lambda_eva=0.007f, x_pv=3e-4, lambda_pv=150.f, alpha_pv=0.8f, tau_pv=0.95f, x_ab=5e-3, lambda_ab=25.f, epsilon_ab=0.6f, x_bs=5e-4, lambda_bs=0.007f, eff_ab=0.7289f, Cp_w=3800.f;
// user parameters
float Pth, massFlowRate=0.025f;
// internal results for the iterative calculations
float Tg=15.f+273.15f, Tpv=15.f+273.15f, Tab=15.f+273.15f, Tmw=25.f+273.15f;
public:
SolarHybrid(TiXmlHandle hdl, ostream* pLogStr=NULL);
float getThermalSurfacePowerDensity(float gt, float tout, float windspeed, float Tsky, float Tin);
double getMaxPowerEfficiency(double gt, double tout) {
return etampref*(1+(muvoc/vmp)*(Tpv-(tref+273.15f)));
}
//void writeXML(ofstream& file, float ratio, string tab);
};
class WindTurbine {
private:
unsigned int id;
float height, alpha, gamma;
double Pr, vi, vr, vm, c;
public:
WindTurbine(unsigned int id, float height, float alpha, float gamma):id(id),height(height),alpha(alpha),gamma(gamma) {}
WindTurbine(double Pr, double vi, double vr, double vm, double c):Pr(Pr),vi(vi),vr(vr),vm(vm),c(c) {}
unsigned int getId() {return id;}
double getPr() { return Pr; }
double getvi() { return vi; }
double getvr() { return vr; }
double getvm() { return vm; }
double getc() { return c; }
// note: the met station is assumed to be at 10 m above ground (from Awbi, 1991, p.64) and in a rural site
float getElectricPowerConversionEfficiency() { return alpha*pow( height/10.f, gamma)/0.85f; }
};
class MicroWindTurbine {
private:
float cutInSpeed, ratedSpeed,cutOutSpeed, c1, c2, c3, height, testAirDensity, alpha, gamma;
public:
MicroWindTurbine(float cutInSpeed, float ratedSpeed, float cutOutSpeed, float c1, float c2, float c3, float testAirDensity, float height, float alpha, float gamma)
:cutInSpeed(cutInSpeed),ratedSpeed(ratedSpeed),cutOutSpeed(cutOutSpeed),c1(c1),c2(c2),c3(c3),height(height),testAirDensity(testAirDensity),alpha(alpha),gamma(gamma) {}
float getWindElectricPower(float windSpeed, float metStationAltitude, float roofHeight) {
float windPower = 0.f;
// note: the met station is assumed to be at 10 m above ground (from Awbi, 1991, p.64) and in a rural site
windSpeed = windSpeed*alpha*pow((roofHeight+height)/10.f,gamma)/0.85f;
if (windSpeed <= cutInSpeed)
windPower = 0.f;
else if ((windSpeed > cutInSpeed) && (windSpeed < ratedSpeed))
windPower = c1*pow((windSpeed-cutInSpeed), 2) + c2*(windSpeed-cutInSpeed)+ c3;
else if (windSpeed >= ratedSpeed && windSpeed < cutOutSpeed)
windPower = c1*pow((ratedSpeed-cutInSpeed), 2) + c2*(ratedSpeed-cutInSpeed) + c3;
else if (windSpeed >= cutOutSpeed)
windPower= 0.f;
return windPower*Climate::getAirDensity(metStationAltitude+roofHeight+height)/testAirDensity; // standard at sea level with air density = 1.201385 kg/m3 , IEC 61400-12-1 more info: https://energypedia.info/wiki/Estimation_of_Wind_Energy_Production#Power_Curve_and_Air_Densit
}
};
class Tank {
private:
double volume, rho, Cp, phi, Tmin, Tmax, Tinlet=10., Tcritical=90.;
public:
Tank(double tankVolume, double tankHeight, double tankDiameter, double tankThickness, double tankRho, double tankCp, double tankTmin, double tankTmax) : volume(tankVolume), rho(tankRho), Cp(tankCp), Tmin(tankTmin), Tmax(tankTmax) {
const double Pi = 4.0*std::atan(1.0);
double D1_heat = 2.0*std::sqrt(volume/(Pi*tankHeight)); //diametre interieur
double D2_heat = D1_heat+2*tankThickness; //diametre exterieur
double lambdA = 0.029*1.1622; //coefficient de transmission de la chaleur de l'isolant (Hypothese: mousse rigide de polyurethane) en W/(m2.C)
double alpha1_heat = 156.0*std::pow((1/D1_heat),0.25); //coefficient de transmission superficielle dans l'eau du reservoir (Hypothese: la difference de temperature entre paroi et fluide est egale 1¡C, valider)
double alpha2_heat = 1.25; //coefficient de transmission superficielle dans l'air (Hypothese: la difference de temperature entre paroi et fluide est egale 1¡C, valider)
phi = Pi*tankHeight/(std::log(D2_heat/D1_heat)/(2.0*lambdA)+1.0/(D1_heat*alpha1_heat)+1.0/(D2_heat*alpha2_heat));
}
Tank(double tankVolume, double tankPhi, double tankRho, double tankCp, double tankTmin, double tankTmax) : volume(tankVolume), rho(tankRho), Cp(tankCp), phi(tankPhi), Tmin(tankTmin), Tmax(tankTmax) { }
Tank(TiXmlHandle hdl) {
volume = to<double>(hdl.ToElement()->Attribute("V"));
phi = to<double>(hdl.ToElement()->Attribute("phi"));
rho = to<double>(hdl.ToElement()->Attribute("rho"));
Cp = to<double>(hdl.ToElement()->Attribute("Cp"));
Tmin = to<double>(hdl.ToElement()->Attribute("Tmin"));
Tmax = to<double>(hdl.ToElement()->Attribute("Tmax"));
if (hdl.ToElement()->Attribute("Tinlet")) Tinlet = to<double>(hdl.ToElement()->Attribute("Tinlet"));
if (hdl.ToElement()->Attribute("Tcritical")) Tcritical = to<double>(hdl.ToElement()->Attribute("Tcritical")); // Cognet: By default, this is initialized to 90.
}
virtual ~Tank() {}
double getVolume() { return volume; }
double getRho() { return rho; }
double getCp() { return Cp; }
double getTmin() { return Tmin; }
double getTmax() { return Tmax; }
double getTinlet() { return Tinlet; }
double getTcritical() { return Tcritical; }
double getPhi() { return phi; }
void setTmin(double tankTmin) { Tmin = tankTmin; }
void setTmax(double tankTmax) { Tmax = tankTmax; }
// models
virtual double temperature(double t, double VdotUsed, double Pp2, double Pup2, double T0, double Tinlet, double Tamb);
virtual double power(double t, double Tf, double VdotUsed, double Pup2, double T0, double Tinlet, double Tamb);
virtual double time(double Tf, double VdotUsed,double Pp2, double Pup2, double T0, double Tinlet, double Tamb);
virtual double domesticHotWater(double t, double Tf, double VdotUsedUp, double Pp2, double Pup2, double T0, double Tinlet, double Tamb);
virtual double maxSolPowerToNotExceedTcrit(double t, double VdotUsed, double power, double solPower, double T0, double Tinlet, double Tamb); // Cognet: Added this.
void writeXML(ofstream& file, string tag, string tab=""){
file << tab << "<" << tag <<" V=\""<< volume << "\" phi=\"" << phi << "\" rho=\"" << rho << "\" Cp=\"" << Cp << "\" Tmin=\"" << Tmin << "\" Tmax=\"" << Tmax << "\"/>" << endl;
}
};
class TankPCM : public Tank {
private:
double mass, a, b, Tm, Cs;
public:
TankPCM(double tankVolume, double tankPhi, double tankRho, double tankCp, double tankTmin, double tankTmax, double massPCM, double aPCM, double bPCM, double TmPCM, double CsPCM) : Tank(tankVolume, tankPhi, tankRho, tankCp, tankTmin, tankTmax), mass(massPCM), a(aPCM), b(bPCM), Tm(TmPCM), Cs(CsPCM) { }
double Cp(double T) { if (b != 0.0) return Cs + a*std::exp(-(1./2.)*std::pow((T-Tm)/b, 2.0));
else return 0.0; }
double temperature(double t, double VdotUsed, double Pp2, double Pup2, double T0, double Tinlet, double Tamb);
double power(double t, double Tf, double VdotUsed, double Pup2, double T0, double Tinlet, double Tamb);
};
class Equations {
public:
// PV
static double photoVoltaicMaxPowerEfficiency(PhotoVoltaic *panel, double gt, double ta); // Duffie and Beckman
// Solar Heaters
static double solarHeaterEfficiency(SolarThermal *panel, double gt, double xsi);
// Wind Turbines
static double windTurbinePower(WindTurbine *turbine, double v);
// Wind Speed Model
static double windSpeedRatio(int type, double height, int typeRef, double heightRef);
};
class EnergyConversionSystem {
protected:
// run period of the system
unsigned int beginDay, endDay;
double boilerCO2EmissionCoefficient;
double electricCO2EmissionCoefficient;
double coGenCO2EmissionCoefficient;
double thermalPowerNeeded; // Cognet: Added this. Now first setThermalPowerNeeded(), then use getThermalPower() to see thermal power that can be provided.
double thermalPowerNeededHS; // Added by Max
double thermalPowerNeededDHW; // Added by Max
public:
ostream logStream;
EnergyConversionSystem(unsigned int beginDay=1, unsigned int endDay=365, ostream* pLogStr = &std::cout):beginDay(beginDay),endDay(endDay),logStream(std::cout.rdbuf()) {
// CO2 coefficients
logStream.rdbuf(pLogStr->rdbuf());
coGenCO2EmissionCoefficient = 0.238/3.6e6;
boilerCO2EmissionCoefficient = 0.238/3.6e6; //238g/kWh gas naturel = 0.238 kg/kWh = 0.238e-3 kg/Wh .. in kg/J!
electricCO2EmissionCoefficient = 0.129/3.6e6; // 129g/Kwh swiss electricity mix = 0.129 kg/Wh = 0.129e-3 kg/Wh .. in kg/J
}
virtual ~EnergyConversionSystem() { /*cerr << "Destructor of EnergyConversionSystem" << endl;*/ }
unsigned int getBeginDay(){ return beginDay;}
unsigned int getEndDay(){ return endDay;}
// check if the system is working
bool isWorking(unsigned int day) {
// check the given period
if (beginDay < endDay) { // standard order
if ( day >= beginDay && day <= endDay) return true;
}
else { // reversed order, for example given from september until april
if ( day >= beginDay || day <= endDay ) return true;
}
return false;
}
// version domestique
virtual void getMaxThermalPower(double thermalPower1Needed, double thermalPower2Needed, double &thermalPower1Available, double &thermalPower2Available, double sourceTemp=0.0) { return; }
virtual double getElectricProduction(double thermalPower1, double thermalPower2, double sourceTemp) { return 0.0; }
virtual double getCO2Production(double time, double thermalPower1, double thermalPower2, double sourceTemp) { return 0.0; }
virtual double getFuelConsumption(double time, double thermalPower1, double thermalPower2, double sourceTemp) { return 0.0; }
virtual double getElectricConsumption(double time, double thermalPower1, double thermalPower2, double sourceTemp) { return 0.0; }
virtual float getThermalPowerMax(double sourceTemp){return 0.f;} // Added by Max. Useful for the MCR
// version simplifi�e
virtual string getLabel() { return "EnergyConversionSystem"; } // Cognet: Corrected spelling.
// virtual double getThermalPower(double thermalPowerNeeded, double sourceTemperature) { return 0.0; } // Cognet: Deleted this.
virtual double getThermalPower(double sourceTemperature) { return 0.0; } // Cognet: Added this. Now first setThermalPowerNeeded(), then use getThermalPower() to see thermal power that can be provided.
virtual double getThermalPowerHS(double sourceTemperature) { return 0.0; } // Added by Max. Useful for the 2stages HP.
virtual double getThermalPowerDHW(double sourceTemperature) { return 0.0; } // Added by Max. Useful for the 2stages HP.
virtual double getFuelConsumption(double time, double thermalPower, double sourceTemp) { return 0.0; }
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp) { return 0.0; }
// version distribu�e par le r�seau
virtual void getMaxThermalPower(vector<double> thermalPowerNeeded, vector<double> &thermalPowerAvailable, double sourceTemp) { return; }
virtual double getElectricProduction(vector<double> thermalPower, double sourceTemp) { return 0.0; }
virtual double getCO2Production(double time, vector<double> thermalPower, double sourceTemp) { return 0.0; }
static double epsilonC(double sourceTemp, double outputTemp) { return ((273.15+outputTemp)/(outputTemp - sourceTemp)); }
// special aux heat pumps
virtual float getSourceTemperature(Climate* pClimate, unsigned int day, unsigned int hour) { return numeric_limits<float>::quiet_NaN(); }
virtual void setThermalPowerNeeded(double tPN) { thermalPowerNeeded=tPN; } // Cognet: Added this.
float getThermalPowerNeeded() const { return thermalPowerNeeded; }
virtual void setThermalPowerNeededHS(double tPN) { thermalPowerNeededHS=tPN; } // Added by Max.
virtual void setThermalPowerNeededDHW(double tPN) { thermalPowerNeededDHW=tPN; } // Added by Max.
virtual void writeXML(ofstream& file, string tab)=0;
virtual void writeGML(ofstream& file, string tab) {}
};
class Boiler : public EnergyConversionSystem {
private:
double boilerThermalPower, boilerThermalEfficiency;
string name="";
public:
Boiler(TiXmlHandle hdl, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
Boiler(double boilerThermalPower, double boilerThermalEfficiency,unsigned int beginDay=1,unsigned int endDay=365):EnergyConversionSystem(beginDay,endDay),boilerThermalPower(boilerThermalPower),boilerThermalEfficiency(boilerThermalEfficiency) {}
~Boiler() { /*cerr << "Destructor of Boiler..." << endl;*/ }
void writeXML(ofstream& file, string tab);
void writeGML(ofstream& file, string tab);
friend ostream& operator<< (ostream& s, Boiler& unit) {
s << "\n\nBoiler:\nThermal Power: " << unit.boilerThermalPower << " W(th)\nEfficiency: " << unit.boilerThermalEfficiency << endl;
return s;
}
string getLabel() { return "Boiler"; }
// double getThermalPower(double thermalPowerNeeded, double sourceTemp) { // Cognet: Deleted this.
double getThermalPower(double sourceTemp) override { // Cognet: Added this.
if ( thermalPowerNeeded<=0 ) return 0.; // Cognet: Added this.
if ( thermalPowerNeeded <= boilerThermalPower ) return thermalPowerNeeded;
else return boilerThermalPower;
}
double getFuelConsumption(double time, double thermalPower, double sourceTemp) {
if (thermalPower <= boilerThermalPower) return (time*(thermalPower)/boilerThermalEfficiency);
else return (time*boilerThermalPower/boilerThermalEfficiency);
}
float getThermalPowerMax(double sourceTemp)override{return boilerThermalPower;} //Added by Max
};
class CoGeneration: virtual public EnergyConversionSystem {
protected:
double coGenThermalPower, coGenElectricalEfficiency, coGenThermalEfficiency, coGenMinPartLoadCoefficient;
public:
CoGeneration(TiXmlHandle hdl, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
CoGeneration(double coGenThermalPower,double coGenElectricalEfficiency,double coGenThermalEfficiency,double coGenMinPartLoadCoefficient,unsigned int beginDay=1,unsigned int endDay=365);
~CoGeneration() { /*cerr << "Destructor of CoGeneration..." << endl;*/ }
void writeXML(ofstream& file, string tab);
friend ostream& operator<< (ostream& s, CoGeneration& unit){
s << "\nCoGeneration:\nThermal Power: \t" << unit.coGenThermalPower << " W(th)\nElectrical efficiency: " << unit.coGenElectricalEfficiency << "\nThermal efficiency: " << unit.coGenThermalEfficiency << "\nMin. part-load coefficient: " << unit.coGenMinPartLoadCoefficient << endl;
return s;
}
string getLabel() { return "CoGeneration"; }
virtual double getThermalPower(double sourceTemp) override; // Cognet: Added this.
virtual double getFuelConsumption(double time, double thermalPower, double sourceTemp);
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp);
virtual float getThermalPowerMax(double sourceTemp) override {return coGenThermalPower;}
};
class HeatPump : virtual public EnergyConversionSystem {
protected:
double heatPumpElectricPower;
double targetTemp;
double etaTech;
// for the ground heat pump
bool ground;
float z0,z1,alpha;
// for the fixed source temperature heat pump
float Tsource=numeric_limits<float>::quiet_NaN();
public:
HeatPump(TiXmlHandle hdl, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
HeatPump(double heatPumpElectricPower,double heatPumpCOP,double heatPumpSrcTemp,double heatPumpOutputTemp,unsigned int beginDay,unsigned int endDay);
HeatPump(double heatPumpElectricPower,double heatPumpEtaTech,double targetTemp,unsigned int beginDay,unsigned int endDay);
~HeatPump() { /*cerr << "Destructor of HeatPump..." << endl;*/ }
void writeXML(ofstream& file, string tab);
void writeGML(ofstream& file, string tab);
friend ostream& operator<< (ostream& s, HeatPump& unit){
s << "\nHeat Pump:\nElectrical Power: \t" << unit.heatPumpElectricPower << " W(el)\nEta tech: " << unit.etaTech << endl;
return s;
}
void setGround(float z0, float z1, float alpha) { this->z0=z0; this->z1=z1; this->alpha=alpha; ground = true; }
float getSourceTemperature(Climate* pClimate, unsigned int day, unsigned int hour) {
if (isnan(Tsource)) { // in this case, we compute the temperature based on the Climate
if (ground) return pClimate->getTgroundCelsius(day,hour,z0,alpha,z1); // ground temperature
else return pClimate->getToutCelsius(day,hour); // air temperature
}
else return Tsource;
}
string getLabel() { return "HeatPump"; }
double getHeatProduced(double work, double sourceTemp, double outputTemp);
double getWorkNeeded(double thermalPower, double sourceTemp, double outputTemp);
double getWorkNeededEvap(double PowerEvap, double sourceTemp, double outputTemp); // Added by Max. This function allows to compute the electricity power knowing the power at the evaporator.
double getTargetTemp(){return targetTemp;}; // Added by Max.
double getHeatPumpElectricPower(){return heatPumpElectricPower;}; // Added by Max.
double getEtaTech(){return etaTech;}; // Added by Max.
// virtual double getThermalPower(double thermalPowerNeeded, double sourceTemp); // Cognet: Deleted this.
virtual double getThermalPower(double sourceTemp) override; // Cognet: Added this.
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp);
virtual float getThermalPowerMax(double sourceTemp) override{return getHeatProduced(heatPumpElectricPower,sourceTemp,targetTemp);}
};
class CoGenerationHeatPump : public CoGeneration, public HeatPump {
public:
CoGenerationHeatPump(TiXmlHandle hdl, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
CoGenerationHeatPump(double coGenThermalPower, double coGenElectricalEfficiency, double coGenThermalEfficiency, double coGenMinPartLoadCoefficient,
double heatPumpCOP, double heatPumpSrcTemp, double heatPumpOutputTemp,unsigned int beginDay=1,unsigned int endDay=365);
CoGenerationHeatPump(double coGenThermalPower, double coGenElectricalEfficiency, double coGenThermalEfficiency, double coGenMinPartLoadCoefficient,
double heatPumpEtaTech, double targetTemp,unsigned int beginDay=1,unsigned int endDay=365);
~CoGenerationHeatPump() { /*cerr << "Destructor of CoGenerationHeatPump..." << endl;*/ }
void writeXML(ofstream& file, string tab);
friend ostream& operator<< (ostream& s, CoGenerationHeatPump& unit) {
s << "\nCoGeneration:\nThermal Power: \t" << unit.coGenThermalPower << " W(th)\nElectrical efficiency: " << unit.coGenElectricalEfficiency << "\nThermal efficiency: " << unit.coGenThermalEfficiency << "\nMin. part-load coefficient: " << unit.coGenMinPartLoadCoefficient;
s << "\nHeat pump:\nEtatech: " << unit.etaTech << "\nTarget Temperature: " << unit.targetTemp << endl;
return s;
}
string getLabel() { return "CoGenerationHeatPump"; }
// double getThermalPower(double thermalPowerNeeded, double sourceTemp); // Cognet: Deleted this.
double getThermalPower(double sourceTemp) override; // Cognet: Added this.
double getFuelConsumption(double time, double thermalPower, double sourceTemp);
double getElectricConsumption(double time, double thermalPower, double sourceTemp) { return 0.0; }
float getThermalPowerMax(double sourceTemp) override {return coGenThermalPower;}
};
// Added by Max
class EfficiencyPump{
public:
static EfficiencyPump* createNewEfficiencyPump(TiXmlHandle hdl);
EfficiencyPump() {}
virtual ~EfficiencyPump() {}
virtual float computeEfficiency(float const& massFlow) = 0;
};
class ConstantEfficiencyPump: public EfficiencyPump {
private:
float efficiencyPump; // must be in between 0 and 1.
public:
ConstantEfficiencyPump(TiXmlHandle hdl);
ConstantEfficiencyPump(float efficiencyPump):efficiencyPump(efficiencyPump) {}
virtual float computeEfficiency(float const& massFlow) override { return efficiencyPump; }
};
class AffineEfficiencyPump : public EfficiencyPump {
protected:
// The setpoint function of the pressure difference is a function of mass flow, affine by parts.
vector<float> massFlows; // [kg/s]
vector<float> efficiencyPumps; // [Pa]
public:
AffineEfficiencyPump(TiXmlHandle hdl);
virtual float computeEfficiency(float const& massFlow) override;
}; // end of Added by Max
class Pump {
private:
// Stays constant, define the Pump.
EfficiencyPump* efficiencyPump = nullptr;
float n0; // Nominal rotational speed [rotations/min].
float a0; // Coefficient of polynomial for flow/pressure curve [Pa] (eg. 1247180.f).
float a1; // Coefficient of polynomial for flow/pressure curve [Pa*s/kg] (eg. -1640.236f).
float a2; // Coefficient of polynomial for flow/pressure curve [Pa*(s/kg)^2] (eg. -0.00016031f).
// Evolves at each time step.
float n; // Current rotational speed [rotations/min].
float computeNMin() { return n0*0.001f; } // One one thousandth of max.
public:
Pump(TiXmlHandle hdl);
~Pump() { if (efficiencyPump) delete efficiencyPump; }
float getn() { return n; }
/**
* @brief computeElectricAndThermalPower
* @param pressureDiff Pressure loss through the pump (negative in normal conditions, since the pump increases pressure) [Pa].
* @param massFlow Mass flow through the pump (positive in normal conditions) [kg/s].
* @param rho Mass density of fluid going through pump [kg/m^3].
* @param electricPow Return variable for electric power (positive when pump consumes electricity) [W].
* @param thermalPow Return variable for thermal power (positive when fluid temperature increases in the direction of the flow) [W].
*/
void computeElectricAndThermalPower(float const& pressureDiff, float const& massFlow, float const& rho, float& electricPow, float& thermalPow);
float cpdT(float const& pressureDiff, float const& rho, float const& massFlow); //Added by Max
/**
* @brief computePressureDiff
* @param massFlow Mass flow through the pump (positive in normal conditions) [kg/s].
* @param deltaP Pressure loss through the pump (negative in normal conditions, since the pump increases pressure) [Pa].
* @param dDeltaP_dm Derivative of pressure loss through the pump [Pa/(kg/s)].
*/
void computePressureDiff(float const& massFlow, float& deltaP, float& dDeltaP_dm);
/**
* @brief computeIdealN Solves the rpm needed to get the pressureDiff, and the mass flow. If the mass flow is negative, there is no solution, simply try increasing to (n+n0)/2.
* @param massFlow Mass flow through the pump (positive in normal conditions) [kg/s].
* @param pressureDiff Pressure loss through the pump (negative in normal conditions, since the pump increases pressure) [Pa].
* @return The value of n needed to get the pressureDiff and massFlow [rotation/min].
*/
float computeIdealN(float const& massFlow, float const& pressureDiff);
void updateRpms(float& sumDeltaRpm, float& sumRpm, float const& learningRate, float const& targetMassFlow, float const& targetPressureDiff);
void setNToMax(float& sumDeltaRpm, float& sumRpm, float const& learningRate);
bool nIsMin() { return (n==computeNMin()); }
bool nIsAlmostMax() { return n>0.99*n0; }
};
class Valve {
private:
static float deltaP0_invRho0_36002; // deltaP0=1e5, invRho0=1/1e3, 3600^2=12960000, multiply them. Computed only once.
// Stays constant, define the Valve.
float kvMax; // Maximal valve flow coefficient (max opening of valve) [m^3/h].
// Evolves at each time step.
float kv; // Valve flow coefficient (opening of valve) [m^3/h].
float computeKvMin() { return kvMax*0.0001f; } // A fraction of the max. Modified by Max. The range of operation is reduced since for high mass flows it might give huge pressure differences from 1e-5 to 1e-4.
public:
Valve(float const& kvMax_) : kvMax(kvMax_), kv(kvMax_*0.5f) { }
virtual ~Valve() {}
void computePressureDiffAndDerivative(float const& m, float const& rho, float& deltaP, float& dDeltaP_dm);
float computeIdealKv(float const& rho, float const& massFlow, float const& pressureDiff);
void updateKv(float const& rho, float& sumDeltaKv, float& sumKv, float const& learningRate, float const& targetMassFlow, float const& targetPressureDiff, PIDControllerValve& pid, float& Targetkv, bool& ImposedValve);
/**
* @brief computeTemperatureIncrease
* @param pressureDiff Pressure loss through the valve (positive in normal conditions, since the valve decreases pressure) [Pa].
* @param cp Fluid heat capacity [J/(kg*K)].
* @param rho Fluid mass density [kg/(m^3)].
* @return Temperature increase (positive in normal conditions, since pressure loss due to friction increases temperature) [K]
*/
float computeTemperatureIncrease(float const& pressureDiff, float const& cp, float const& rho) { return pressureDiff/(cp*rho); }
void setKvToMax(float& sumDeltaKv, float& sumKv) { sumDeltaKv += abs(kv-kvMax); sumKv += kvMax; kv = kvMax; }
void setKvToMin(float& sumDeltaKv, float& sumKv, float const& learningRate);
void keepKvConst(float& sumDeltaKv, float& sumKv) { sumDeltaKv += 0.f; sumKv += kv; }
virtual int nbEdges() { return 1; } // It's only a valve.
float getkv(){return kv;}
bool kvIsMin() { return kv==computeKvMin(); }
bool kvIsAlmostMin() { return kv<1.5*computeKvMin(); }
};
class PIDController {
private:
float integralErr;
float prevErr;
protected:
float computeControlVariable(float const& desiredSetpoint, float const& processVariable, float const& kp, float const& ki, float const& kd);
public:
PIDController() : integralErr(0.f), prevErr(0.f) { }
virtual ~PIDController() { }
};
class PIDControllerValve : public PIDController {
public:
PIDControllerValve() : PIDController() { }
~PIDControllerValve() { }
float computeControlVariable(float const& desiredSetpoint, float const& processVariable) { return PIDController::computeControlVariable(desiredSetpoint, processVariable, 0.5f, 0.3f, 0.f); }
};
class PIDControllerPump : public PIDController {
public:
PIDControllerPump() : PIDController() { }
~PIDControllerPump() { }
float computeControlVariable(float const& desiredSetpoint, float const& processVariable) { return PIDController::computeControlVariable(desiredSetpoint, processVariable, 0.3f, 0.2f, 0.f); }
};
class MemoryManager {
private:
deque<float> q;
size_t r;
public:
MemoryManager(size_t r) : q(), r(r) { }
~MemoryManager() { }
size_t nbMemorized() { return q.size(); }
void addElement(float e) { q.push_front(e); if(q.size()>=r) { q.pop_back(); } }
float findMin() { float min = q.front(); for (auto const& el : q) { if (el<min) { min = el; } } return min; }
float findMedian() { vector<float> v (q.size()); for(size_t i=0; i<q.size(); i++) { v[i]=q[i]; } nth_element(v.begin(), v.begin()+v.size()/2, v.end()); return v[v.size()/2]; }
};
class Carla {
private:
vector<float> position_x;
vector<float> probaDensity_fx;
float actionChoice_r;
float xmin() { return position_x.front(); }
float xmax() { return position_x.back(); }
float integrate(vector<float> const& f, float const& xmin, float const& xmax);
float selectAction();
float solveQuadratic(float const& xi, float const& xip1, float const& fi, float const& fip1, float const& area);
public:
Carla(size_t const& n, float const& xmin, float const& xmax);
~Carla() { }
float step(float const& beta);
};
class PIDControllerCarla : public PIDController {
private:
Carla carlaKp;
Carla carlaKi;
// Carla carlaKd;
MemoryManager mm;
public:
PIDControllerCarla(size_t const& n, size_t const& r, float const& xmin, float const& xmax);
~PIDControllerCarla() { }
float evaluatePerformanceBeta(float const& costJ);
float computeControlVariable(float const& desiredSetpoint, float const& processVariable);
};
//beginning of contents added by Dapeng
class Substation : virtual public EnergyConversionSystem {
protected:
// Stays constant, define the substation.
float designThermalPower; // Must be positive. [W]
float designTempDifference; // Must be positive. [degree C]
float designEpsilon; // Must be positive and smaller or equal to one. []
DistrictEnergyCenter* pDEC; // The DEC that the substation is linked to.
SubstationNodePair* pNode; // The node where the substation links to in the DEC network.
Building* pBuilding; // The building that the substation is linked to.
// Evolve at each time step.
float desiredMassFlow; // on primary side [kg/s]
float secondarySideInputTemp;
float thermalPowerExchanged; // Heat exchanged at heat exchanger. Positive means primary side gives heat to secondary, if everything is ok, when the substation consumes, it should reach thermalPowerNeeded [W].
float primarySideOutputTemp; // Temperature before mixing with other fluxes, downtream from the substation heat exchanger [degree C].
PIDControllerValve pid; // To control the valve opening, to get the desired mass flow.
// PIDControllerCarla pid;
Valve* valve;
// Done in order to have the case where the valve is controlled manually
float Targetkv; // Added by Max
bool ImposedValve; // Added by Max
// Control directly the mass flow instead of going through the valve
bool ImposedMassFlow;
MassFlowSetpoint* massFlowSetpoint;
void setPrimarySideOutputTemp(float outputTemp){primarySideOutputTemp=outputTemp;}
public:
static Substation* createNewSubstation(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
Substation(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
~Substation() override { delete valve; /*logStream << "Destructor of Substation" << endl;*/ }
void writeXML(ofstream& file, string tab){ file << tab << "Substation saving not supported yet" << endl; }
string getLabel() { return "Substation"; }
float getPrimarySideOutputTemp() { return primarySideOutputTemp; }
float getDesiredMassFlow() { return desiredMassFlow; }
virtual void setThermalPowerNeeded(double tPN) override;
/**
* Returns value of thermal power provided to the user, must compute it beforehand using computeHeatExchanged().
* @param thermalPowerNeeded (for other EnergyConversionSystems class, eventually change this)
* @return Thermal power that the substation can provide to the user.
*/
virtual double getThermalPower(double sourceTemp) override;
virtual double getFuelConsumption(double time, double thermalPower, double sourceTemp) override;
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp) override;
/**
* @brief mc Formula to compute primary network side mass flow rate.
* @param thermalPowerNeeded (positive or negative) [W]
* @param designThermalPower (always positive) [W]
* @param m_c_n Design mass flow [kg/s]
* @return Primary network side mass flow rate [kg/s]
*/
virtual double mc(double thermalPowerNeeded, double designThermalPower, double m_c_n);
Building* getBuilding() { return pBuilding; }
void setDEC(DistrictEnergyCenter* dec) { pDEC = dec; }
void setNode(SubstationNodePair* node) { pNode = node; }
/**
* Computes the heat exchanged for a given primary side mass flow and input temperature. So computes thermalPowerExchanged and primarySideOutputTemp.
*/
virtual void computeHeatExchanged(float const& primarySideCp, float const& primarySideRho, float const& primarySideInputTemp, float const& primarySideMassFlow, float const& primarySidePressureDiff, Climate* pClim, unsigned int day, unsigned int hour);
virtual float maxKv(float const& rho);
virtual void updateControlVariable(float const& massFlow, float const& deltaP, float const& rho, float& sumDeltaRpm, float& sumRpm, float& sumDeltaKv, float& sumKv, float const& learningRate, float const& massFlowSupplyToReturn);
float relativeErrorMassFlow(float const& massFlow) { return (massFlow-desiredMassFlow)/desiredMassFlow; }
virtual void errorMassFlow(float const& massFlow, float& relErr, float& absErr, float& sumErr);
virtual float computeDesignMassFlow();
/**
* Gives the number of graph edges that the substation is made up of. Eg 1 edge if the substation is only a valve, 3 edges if the substation is a valve, a pipe and a differential pressure regulator.
*/
virtual int nbEdges() { return 1; } // A plain substation has only a valve.
virtual bool hasRegEle() { return false; } // A plain substation has only a valve.
virtual float computePressureDiffControlElement(float pressureDiffSubstationNodePair) { return pressureDiffSubstationNodePair; } // All pressure loss is in the control element (valve).
virtual void computePressureDiffAndDerivative(vector<float>::const_iterator m, float const& rho, vector<float>::iterator deltaP, vector<float>::iterator dDeltaP_dm);
float computeOutputTemp(float const& inputTemp, float const& thermalPowerExchanged, float const& massFlow, float const& pressureDiff, float const& rho, float const& cp);
virtual void updateDesiredMassFlow(float const& cp, float const& primarySideReturnTemp, Climate* pClim, unsigned int day, unsigned int hour); // Only prosumers need this information, not substations that only consume.
virtual void recordTimeStep() { }
virtual void eraseRecords(unsigned int keepValue) { }
virtual void eraseRecords_back() { }
virtual void writeTHHeaderText(fstream& textFile, string prefix) { }
virtual void writeTHResultsText(fstream& textFile, unsigned int i) { }
};
//end of contents added by Dapeng
class RegulatingElement {
private:
float targetRegulatedPathPressureDiff; // [Pa]
float pressureDiff; // [Pa]
public:
RegulatingElement(TiXmlHandle hdl);
~RegulatingElement() { }
float getTargetRegulatedPathPressureDiff() { return targetRegulatedPathPressureDiff; }
float getPressureDiff() { return pressureDiff; }
void setPressureDiff(float const& p) { pressureDiff = p; }
void subtractPressure(float const& press) { pressureDiff -= press; }
};
class RegulatedPressureSubstation : virtual public Substation {
private:
RegulatingElement* regEle;
public:
RegulatedPressureSubstation(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
~RegulatedPressureSubstation() { delete regEle; }
virtual float maxKv(float const& rho) override { return 3600.f*computeDesignMassFlow()*1.1/(rho*sqrt(regEle->getTargetRegulatedPathPressureDiff()*0.00001f)); } // At the target pressure, the max valve opening can let through the nominal mass flow times 1.1 (this factor is added in case of imprecisions).
virtual int nbEdges() override { return 2; } // There is a valve and a differential pressure regulator.
virtual bool hasRegEle() override { return true; } // There is a valve and a differential pressure regulator.
virtual float computePressureDiffControlElement(float pressureDiffSubstationNodePair) override { return pressureDiffSubstationNodePair - regEle->getPressureDiff(); } // Total pressure loss = valve + regulating element pressure losses. (the control element is the valve)
virtual void computePressureDiffAndDerivative(vector<float>::const_iterator m, float const& rho, vector<float>::iterator deltaP, vector<float>::iterator dDeltaP_dm) override;
};
class ProsumerSubstation : public Substation {
private:
TemperatureSetpoint* temperatureSetpoint; // Determines the target temperature.
PressureSetpoint* pressureSetpoint; // Determines the target pressure.
Pump* pump;
Valve* pumpFlowControlValve;
bool producerModeOn;
float pumpElectricPower;
// bool turnOfPumpFlowControlValve;
void deleteDynAllocated();
bool isHeatSource();
float computeSolarThermalPower(float const& targetSupplyTemp, float const& primarySideReturnTemp, Climate* pClim, unsigned int day, unsigned int hour);
float minDesiredPumpFlow();
public:
ProsumerSubstation(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
~ProsumerSubstation() { deleteDynAllocated(); }
virtual void setThermalPowerNeeded(double tPN) override;
virtual double getThermalPower(double sourceTemp) override;
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp) override;
virtual void updateControlVariable(float const& massFlow, float const& deltaP, float const& rho, float& sumDeltaRpm, float& sumRpm, float& sumDeltaKv, float& sumKv, float const& learningRate, float const& massFlowSupplyToReturn) override;
virtual void computeHeatExchanged(float const& primarySideCp, float const& primarySideRho, float const& primarySideInputTemp, float const& primarySideMassFlow, float const& primarySidePressureDiff, Climate* pClim, unsigned int day, unsigned int hour) override;
virtual void computePressureDiffAndDerivative(vector<float>::const_iterator m, float const& rho, vector<float>::iterator deltaP, vector<float>::iterator dDeltaP_dm) override;
virtual void updateDesiredMassFlow(float const& cp, float const& primarySideReturnTemp, Climate* pClim, unsigned int day, unsigned int hour) override;
void setProsumerSolarThermal();
virtual void errorMassFlow(float const& massFlow, float& relErr, float& absErr, float& sumErr) override;
bool getProducerMode(){return producerModeOn;}
void setProducerMode(bool power) {producerModeOn = power;}
virtual void recordTimeStep() override { Substation::recordTimeStep(); setProsumerSolarThermal(); } // setProsumerSolarThermal
virtual void eraseRecords(unsigned int keepValue) override { Substation::eraseRecords(keepValue); }
virtual void eraseRecords_back() override { Substation::eraseRecords_back(); }
};
// Added by Max
class SubstationHeatPump: public ProsumerSubstation {
private:
HeatPump* heatPump;
public:
SubstationHeatPump(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
~SubstationHeatPump() override { /*logStream << "Destructor of SubstationHP" << endl;*/ }
void writeXML(ofstream& file, string tab) override{ file << tab << "SubstationHeatPump saving not supported yet" << endl; }
string getLabel() override{ return "SubstationHeatPump"; }
virtual double getThermalPower(double sourceTemp) override;
virtual double getElectricConsumption(double time, double thermalPower, double sourceTemp) override;
HeatPump* getHeatPump(){return heatPump;};
//double mc(double thermalPowerNeeded, double sourceTemp);
float computeDesignMassFlow() override;
void setThermalPowerNeeded(double tPN) override;
void updateDesiredMassFlow(float const& cp, float const& primarySideReturnTemp, Climate* pClim, unsigned int day, unsigned int hour) override;
virtual void computeHeatExchanged(float const& primarySideCp, float const& primarySideRho, float const& primarySideInputTemp, float const& primarySideMassFlow, float const& primarySidePressureDiff, Climate* pClim, unsigned int day, unsigned int hour) override;
double logMeanTemperatureDifference(float Tin,float Tout);
};
//Added by Max
class SubstationHeatPump2stages: public SubstationHeatPump{
double targetTemp2; // The target temperature for heating the surface.
double heatPumpElectricPower2;
double etaTech2;
// We suppose etatech is identical for both stages.
public:
SubstationHeatPump2stages(TiXmlHandle hdl, Building* pBui, unsigned int beginD, unsigned int endD, ostream* pLogStr = &std::cout);
void writeXML(ofstream& file, string tab) override{ file << tab << "SubstationHP2stages saving not supported yet" << endl; }
string getLabel() override{ return "SubstationHP2stages"; }
double getThermalPower(double sourceTemp) override;
double getElectricConsumption(double time, double thermalPower, double sourceTemp) override;
double getHeatProduced(double workDHW, double workHS, double sourceTemp, double outputTemp);
vector<double> getWorkNeeded(double thermalPower, double sourceTemp, double outputTemp);
virtual void computeHeatExchanged(float const& primarySideCp, float const& primarySideRho, float const& primarySideInputTemp, float const& primarySideMassFlow, float const& primarySidePressureDiff, Climate* pClim, unsigned int day, unsigned int hour) override;
virtual void updateDesiredMassFlow(float const& cp, float const& primarySideReturnTemp, Climate* pClim, unsigned int day, unsigned int hour) override;
};
class TemperatureSetpoint {
public:
static TemperatureSetpoint* createNewTemperatureSetpoint(TiXmlHandle hdl);
TemperatureSetpoint() { }
virtual ~TemperatureSetpoint() { }
virtual float computeTargetTemperature(Climate* pClimate, unsigned int day, unsigned int hour) = 0;
virtual float getInitTemp() = 0;
};
class ConstantTemperatureSetpoint: public TemperatureSetpoint {
private:
float targetSupplyTemp;
public:
ConstantTemperatureSetpoint(TiXmlHandle hdl);
~ConstantTemperatureSetpoint() override { }
virtual float computeTargetTemperature(Climate* pClimate, unsigned int day, unsigned int hour) override { return targetSupplyTemp; }
virtual float getInitTemp() override { return targetSupplyTemp; }
};
class AffineTemperatureSetpoint : public TemperatureSetpoint {
protected:
float lowExtTemp, highExtTemp, lowExtTempSupplyTemp, highExtTempSupplyTemp;
public:
AffineTemperatureSetpoint(TiXmlHandle hdl);
~AffineTemperatureSetpoint() override { }
virtual float computeTargetTemperature(Climate* pClimate, unsigned int day, unsigned int hour) override;
virtual float getInitTemp() override { return highExtTempSupplyTemp; }
float avgExtTempLast24Hours(Climate* pClimate, unsigned int day, unsigned int hour);
};
class AffineWinterConstantSummerSetpoint : public AffineTemperatureSetpoint {
private:
bool notYetActivated;
bool summerModeOn;
float startSummerTempThreshold, endSummerTempThreshold;
public:
AffineWinterConstantSummerSetpoint(TiXmlHandle hdl);
~AffineWinterConstantSummerSetpoint() override { }
virtual float computeTargetTemperature(Climate* pClimate, unsigned int day, unsigned int hour) override;
};
class ImposedValuesOrConstantSetpoint : public TemperatureSetpoint {
private:
map<string, float> imposedValues; // Stores values if one wants to impose the supply temperature. Format map["d42h4"]=75.
float constantTempIfNoImposed;
bool hasImposedValue(unsigned int day, unsigned int hour, float& retValue);
public:
ImposedValuesOrConstantSetpoint(TiXmlHandle hdl);
~ImposedValuesOrConstantSetpoint() override { }