forked from mfrasquet/SHIPcal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Ressspi.py
1128 lines (900 loc) · 58.1 KB
/
Ressspi.py
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
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 12 19:54:51 2016
Version record:
- (1.1.1) Significant change in IAM function to allow Pitch/Azimuth/Roll
- (1.1.5) OperationOilSimple included
- (1.1.8) 5/1/2019 Modify code to allow offline simulations with other collectors,
a very simple cost model has been included, this simplistic model will change
in future versions, thanks to Jose Escamilla for his comments.
- (1.1.9) 26/6/2019 Included savings Graph. Corrected savingsFraction = solarNetFraction.
Included boiler_eff for tacking care of energy before boiler (Energy_Before), which is different
to energy after the boiler (Demand)
- (1.1.10) 9/9/2019 New finance functions
@author: Miguel Frasquet
"""
#Standard Libs
import sys
import os
import numpy as np
import pandas as pd
from iapws import IAPWS97
#Place to import Ressspi Libs
from General_modules.func_General import DemandData,waterFromGrid,thermalOil,reportOutputOffline
from General_modules.demandCreator_v1 import demandCreator
from General_modules.fromDjangotoRessspi import djangoReport
from Solar_modules.EQSolares import SolarData
from Solar_modules.EQSolares import theta_IAMs_v2
from Solar_modules.EQSolares import IAM_calc
#from Solar_modules.iteration_process import flow_calc, flow_calcOil
#from Solar_modules.iteration_process import IT_temp,IT_tempOil
from Integration_modules.integrations import *
from Plot_modules.plottingRessspi import *
from Finance_modules.FinanceModels import Turn_key,ESCO,SP_plant_costFunctions
def ressspiSIM(ressspiReg,inputsDjango,plots,imageQlty,confReport,modificators,desginDict,simControl,pk):
#%%
#Sender identity. Needed for use customized modules or generic modules (Solar collectors, finance, etc.)
sender=confReport['sender']
if sender=='solatom': #The request come from Solatom's front-end www.ressspi.com
sys.path.append(os.path.dirname(os.path.dirname(__file__))+'/ressspi_solatom/') #SOLATOM
version="1.1.10" #Ressspi version
lang=confReport['lang'] #Language
#Paths
if ressspiReg==-2: #Simulation called from ReSSSPI front-end
plotPath=os.path.dirname(os.path.dirname(__file__))+'/ressspi/ressspiForm/static/results/' #FilePath for images when called by www.ressspi.com
if ressspiReg==0: #Simulation called from terminal
plotPath=""
if ressspiReg==1: #Simulation called from other front-ends (use positive integers)
plotPath=""
#Input Control ---------------------------------------
#Modifiers to control extraordinary situations
mofINV=modificators['mofINV'] #Investment modificator to include: Subsidies, extra-costs, etc. [-]
mofDNI=modificators['mofDNI'] #DNI modificator to take into correct Meteonorm data if necessary [-]
mofProd=modificators['mofProd'] #Production modificator to include: Dusty environments, shadows, etc. [-]
#Pre-design of the solar field
num_loops=desginDict['num_loops'] #Number of loops of the solar plant [-]
n_coll_loop=desginDict['n_coll_loop'] #Number of modules connected in series per loop [-]
type_integration=desginDict['type_integration'] #Type of integration scheme from IEA Task 49
almVolumen=desginDict['almVolumen'] #Storage capacity [litres]
#Simulation Control ---------------------------------------
#In order to include the financial study
finance_study=simControl['finance_study']
#Initial step of the simulation
mes_ini_sim=simControl['mes_ini_sim']
dia_ini_sim=simControl['dia_ini_sim']
hora_ini_sim=simControl['hora_ini_sim']
#Final step of the simulation
mes_fin_sim=simControl['mes_fin_sim']
dia_fin_sim=simControl['dia_fin_sim']
hora_fin_sim=simControl['hora_fin_sim']
#%%
# ------------------------------------- INPUTS --------------------------------
if ressspiReg==-2: #Simulation called from front-end -> www.ressspi.com
## ENERGY DEMAND
[inputs,annualConsumptionkWh,reg,P_op_bar,monthArray,weekArray,dayArray]=djangoReport(inputsDjango)
file_demand=demandCreator(annualConsumptionkWh,dayArray,weekArray,monthArray)
arraysConsumption={'dayArray':dayArray,'weekArray':weekArray,'monthArray':monthArray}
inputs.update(arraysConsumption)
## PROCESS
fluidInput=inputs['fluid'] #Type of fluid
T_out_C=inputs['outletTemp'] #High temperature [ºC]
T_in_C=inputs['inletTemp'] #Low temperature [ºC]
P_op_bar=P_op_bar #[bar]
## FINANCE
businessModel=inputs['businessModel'] #Type of business model
fuel=inputs['currentFuel'] #Type of fuel used
Fuel_price=inputs['fuelPrice'] #Price of fossil fuel [€/kWh]
co2TonPrice=inputs['co2TonPrice'] #[€/ton]
co2factor=inputs['co2factor'] #[-]
## METEO
meteoDB = pd.read_csv(os.path.dirname(os.path.dirname(__file__))+"/ressspi_solatom/METEO/meteoDB.csv", sep=',')
locationFromRessspi=inputs['location']
localMeteo=meteoDB.loc[meteoDB['Provincia'] == locationFromRessspi, 'meteoFile'].iloc[0]
file_loc=os.path.dirname(os.path.dirname(__file__))+"/ressspi_solatom/METEO/"+localMeteo
Lat=meteoDB.loc[meteoDB['Provincia'] == locationFromRessspi, 'Latitud'].iloc[0]
Huso=meteoDB.loc[meteoDB['Provincia'] == locationFromRessspi, 'Huso'].iloc[0]
if ressspiReg==1: #Simulation called from external front-end (not ReSSSPI). Available from 1 to inf+
## ENERGY DEMAND
[inputs,annualConsumptionkWh,reg,P_op_bar,monthArray,weekArray,dayArray]=djangoReport(inputsDjango)
file_demand=demandCreator(annualConsumptionkWh,dayArray,weekArray,monthArray)
arraysConsumption={'dayArray':dayArray,'weekArray':weekArray,'monthArray':monthArray}
inputs.update(arraysConsumption)
## PROCESS
fluidInput=inputs['fluid'] #Type of fluid
T_out_C=inputs['outletTemp'] #High temperature [ºC]
T_in_C=inputs['inletTemp'] #Low temperature [ºC]
P_op_bar=P_op_bar #[bar]
## FINANCE
businessModel=inputs['businessModel'] #Type of business model
fuel=inputs['currentFuel'] #Type of fuel used
Fuel_price=inputs['fuelPrice'] #Price of fossil fuel [€/kWh]
co2TonPrice=inputs['co2TonPrice'] #[€/ton]
co2factor=inputs['co2factor'] #[-]
## METEO (free available meteo sets)
locationFromFrontEnd=inputs['location']
meteoDB = pd.read_csv(os.path.dirname(__file__)+"/Meteo_modules/meteoDB.csv", sep=',')
localMeteo=meteoDB.loc[meteoDB['Provincia'] == locationFromFrontEnd, 'meteoFile'].iloc[0]
file_loc=os.path.dirname(__file__)+"/Meteo_modules/"+localMeteo
Lat=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Latitud'].iloc[0]
Huso=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Huso'].iloc[0]
if ressspiReg==0: #Simulation called from Python file
## TO BE IMPLEMENTED Not used for the moment, it will change in future versions
surfaceAvailable=500 #Surface available for the solar plant
orientation="NS"
inclination="flat"
shadowInput="free"
distanceInput=15 #From the solar plant to the network integration point [m]
terreno="clean_ground"
## ENERGY DEMAND
dayArray=[0,0,0,0,0,0,0,1/10,1/10,1/10,1/10,1/10,1/10,1/10,1/10,1/10,1/10,1/10,0,0,0,0,0,0] #12 hours day profile
weekArray=[0.143,0.143,0.143,0.143,0.143,0.143,0.143] #No weekends
monthArray=[1/12,1/12,1/12,1/12,1/12,1/12,1/12,1/12,1/12,1/12,1/12,1/12] #Whole year
totalConsumption=180000 #[kWh]
file_demand=demandCreator(totalConsumption,dayArray,weekArray,monthArray)
## PROCESS
fluidInput="oil" #"water" "steam" "oil"
T_out_C=200 #High temperature [ºC]
T_in_C=20 #Low temperature [ºC]
P_op_bar=25 #[bar]
## FINANCE
businessModel="turnkey"
fuel="Gasoil-B" #Type of fuel
Fuel_price=0.05 #Price of fossil fuel [€/kWh]
co2TonPrice=0 #[€/TonCo2]
co2factor=1 #Default value 1, after it will be modified [-]
localMeteo="Fargo_SAM.dat" #Be sure this location is included in Ressspi DB
## METEO
if sender=='solatom': #Use Solatom propietary meteo DB
meteoDB = pd.read_csv(os.path.dirname(os.path.dirname(__file__))+"/ressspi_solatom/METEO/meteoDB.csv", sep=',')
file_loc=os.path.dirname(os.path.dirname(__file__))+"/ressspi_solatom/METEO/"+localMeteo
Lat=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Latitud'].iloc[0]
Huso=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Huso'].iloc[0]
else:
meteoDB = pd.read_csv(os.path.dirname(__file__)+"/Meteo_modules/meteoDB.csv", sep=',')
file_loc=os.path.dirname(__file__)+"/Meteo_modules/"+localMeteo
Lat=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Latitud'].iloc[0]
Huso=meteoDB.loc[meteoDB['meteoFile'] == localMeteo, 'Huso'].iloc[0]
# -------------------------------------------------
#CO2 factors of the different fuels availables
if fuel in ["NG","LNG"]:
co2factor=.2/1000 #[TonCo2/kWh] #https://www.engineeringtoolbox.com/co2-emission-fuels-d_1085.html
if fuel in ['Fueloil2','Fueloil3','Gasoil-B','Gasoil-C']:
co2factor=.27/1000 #[TonCo2/kWh] #https://www.engineeringtoolbox.com/co2-emission-fuels-d_1085.html
if fuel in ['Electricity']:
co2factor=.385/1000 #[TonCo2/kWh] #https://www.eia.gov/tools/faqs/faq.php?id=74&t=11
if fuel in ['Propane','Butane','Air-propane']:
co2factor=.22/1000 #[TonCo2/kWh] #https://www.engineeringtoolbox.com/co2-emission-fuels-d_1085.html
if fuel in ['Biomass']:
co2factor=.41/1000 #[TonCo2/kWh] #https://www.engineeringtoolbox.com/co2-emission-fuels-d_1085.html
# --------------------------------------------------------------------------------------
#%%
# -----------------------------------------------
#Collector
if sender=='solatom': #Using Solatom Collector
from Solatom_modules.solatom_param import solatom_param
type_coll=20 #Solatom 20" fresnel collector - Change if other collector is used
IAM_file='Solatom.csv'
IAM_folder=os.path.dirname(os.path.dirname(__file__))+"/ressspi_solatom/IAM_files/"
REC_type=1
D,Area_coll,rho_optic_0,huella_coll,Long,Apert_coll=solatom_param(type_coll)
else: #Using other collectors (to be filled with customized data)
IAM_file='defaultCollector.csv'
IAM_folder=os.path.dirname(__file__)+"/Collector_modules/"
REC_type=1 #Type of receiver used (1 -> Schott receiver tube)
Area_coll=26.4 #Aperture area of collector per module [m²]
rho_optic_0=0.75583 #Optical eff. at incidence angle=0 [º]
Long=5.28 #Longitude of each module [m]
IAMfile_loc=IAM_folder+IAM_file
beta=0 #Inclination not implemented [-]
orient_az_rad=0 #Orientation not implemented [-]
roll=0 #Roll not implemented [-]
Area=Area_coll*n_coll_loop #Area of aperture per loop [m²]
Area_total=Area*num_loops #Total area of aperture [m²]
#Process control
T_in_C_AR_mes=np.array([8,9,11,13,14,15,16,15,14,13,11,8]) #When input process is water from the grid. Ressspi needs the monthly average temp of the water grid
T_in_C_AR=waterFromGrid(T_in_C_AR_mes) # [ºC]
#Process parameters
lim_inf_DNI=200 #Minimum temperature to start production [W/m²]
m_dot_min_kgs=0.08 #Minimum flowrate before re-circulation [kg/s]
coef_flow_rec=2 #Multiplier for flowrate when recirculating [-]
# ---------------------------------------------------------------------
# --------------------------- SIMULATION ------------------------------
# ---------------------------------------------------------------------
num_modulos_tot=n_coll_loop*num_loops
#Solar Data
output,hour_year_ini,hour_year_fin=SolarData(file_loc,Lat,Huso,mes_ini_sim,dia_ini_sim,hora_ini_sim,mes_fin_sim,dia_fin_sim,hora_fin_sim)
"""
Output key:
output[0]->month of year
output[1]->day of month
output[2]->hour of day
output[3]->hour of year
output[4]->W - rad
output[5]->SUN_ELV - rad
output[6]->SUN AZ - rad
output[7]->DECL - rad
output[8]->SUN ZEN - rad
output[9]->DNI - W/m2
output[10]->temp -C
output[11]->step_sim
"""
T_in_flag=1 #Flag 1 si la temperatura es constante (circuito cerrado); 0 si se toma agua de red (circuito abierto con reposicion)
#Renombramos variables y las transformamos para trabajar mas comodo
# month=output[:,0]
# day_month=output[:,1]
# hour_day=output[:,2]
# hour_year= output[:,3]
# W=output[:,4]
SUN_ELV=output[:,5] #[rad]
SUN_AZ=output[:,6] #[rad]
#DECL=output[:,7] - #[rad]
#SUN_ZEN=output[:,8] #[rad]
DNI=output[:,9] *mofDNI # [W/m²]
# DNI_positive_hours=(0 < DNI).sum()
temp=output[:,10]+273 #[K] Ambient temperature
step_sim=output [:,11]
steps_sim=len(output) #Numero de steps en la simulacion
meteoDict={'DNI':DNI.tolist(),'localMeteo':localMeteo}
Boiler_eff=0.8 #Boiler efficiency to take into account the excess of fuel consumed
#Demand of energy before the boiler
Energy_Before=DemandData(file_demand,mes_ini_sim,dia_ini_sim,hora_ini_sim,mes_fin_sim,dia_fin_sim,hora_fin_sim) #kWh
Energy_Before_annual=sum(Energy_Before)
#Demand of energy after the boiler
Demand=Boiler_eff*Energy_Before #kWh
#Preparation of variables depending on the scheme selected
#Variable init
sat_liq=0 #Not used
sat_vap=0 #Not used
x_design=0 #Not used
outProcess_h=0 #Not used
energStorageMax=0 #kWh
energyStored=0 #kWh
porctSensible=0 #Not used
T_out_HX_C=0 #ot used
energStorageMax=0 #kWh
T_out_process_C=0 #Not used
T_in_process_C=0 #Not used
outProcess_s=0 #Not used
hProcess_out=0 #Not used
in_s=0
out_s=0
h_in=0
h_out=0
if type_integration=="SL_L_RF":
heatFactor=.5 #Proportion of temperature
DELTA_T_HX=5 #Degrees for DELTA in the heat Exchanger
P_op_Mpa=P_op_bar/10
T_in_K=T_in_C+273
T_in_process_C=T_in_C
T_in_process_K=T_in_C+273
inputProcessState=IAPWS97(P=P_op_Mpa, T=T_in_process_K)
hProcess_in=inputProcessState.h
#Heat Exchanger design DELTAT
T_in_C=T_in_C+DELTA_T_HX
T_in_K=T_in_C+273
if fluidInput!="oil":
if T_out_C>IAPWS97(P=P_op_Mpa, x=0).T-273: #Make sure you are in liquid phase
T_out_C=IAPWS97(P=P_op_Mpa, x=0).T-273
T_out_K=T_out_C+273
T_out_process_K=T_out_K
T_out_process_C=T_out_K-273 #Temp out the process
outputProcessState=IAPWS97(P=P_op_Mpa, T=T_out_process_K)
outProcess_s=outputProcessState.s
hProcess_out=outputProcessState.h
T_out_HX_K=(T_in_process_K+(T_out_K-T_in_process_K)*heatFactor)
T_out_HX_C=T_out_HX_K-273
outputHXState=IAPWS97(P=P_op_Mpa, T=T_out_HX_K)
# outHX_s=outputHXState.s #Not used?
hHX_out=outputHXState.h
#Our design point will be heat the fluid at x%
T_out_K=(T_in_process_K+(T_out_K-T_in_process_K)*heatFactor)+DELTA_T_HX
T_out_C=T_out_K-273
inputState=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=inputState.h
in_s=inputState.s
in_x=inputState.x
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
T_av_process_K=(T_in_process_K+T_out_process_K)/2
if type_integration=="SL_L_P" or type_integration=="PL_E_PM":
P_op_Mpa=P_op_bar/10
T_in_K=T_in_C+273
T_in_process_C=T_in_C
T_in_process_K=T_in_K
if fluidInput!="oil":
inputState=IAPWS97(P=P_op_Mpa, T=T_in_process_K)
# sProcess_in=inputState.s
hProcess_in=inputState.h
if T_out_C>IAPWS97(P=P_op_Mpa, x=0).T-273: #Make sure you are in liquid phase
T_out_C=IAPWS97(P=P_op_Mpa, x=0).T-273
T_out_K=T_out_C+273
T_out_process_K=T_out_K
T_out_process_C=T_out_C
if fluidInput!="oil":
outputProcessState=IAPWS97(P=P_op_Mpa, T=T_out_process_K)
outProcess_s=outputProcessState.s
hProcess_out=outputProcessState.h
inputState=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=inputState.h
in_s=inputState.s
in_x=inputState.x
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
if type_integration=="SL_L_S" or type_integration=="SL_L_S3":
T_max_storage=95+273 #MAx temperature storage
T_min_storage=80+273 #MIN temperature storage to supply to the process
flow_rate_design_kgs=3 #Design flow rate
P_op_Mpa=P_op_bar/10
T_in_K=T_in_C+273
T_ini_storage=T_in_K #Initial temperature of the storage
if T_out_C>IAPWS97(P=P_op_Mpa, x=0).T-273: #Make sure you are in liquid phase
T_out_C=IAPWS97(P=P_op_Mpa, x=0).T-273-5
T_out_K=T_out_C+273
inputState=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=inputState.h
in_s=inputState.s
in_x=inputState.x
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
#Storage calculations for water
energyStored=0 #Initial storage
T_avg_K=(T_in_K+T_out_K)/2
tempAlm=T_out_K-273
almacenamiento=IAPWS97(P=P_op_Mpa, T=T_out_K) #Propiedades en el almacenamiento
almacenamiento_CP=almacenamiento.cp #Capacidad calorifica del proceso KJ/kg/K
almacenamiento_rho=almacenamiento.v #volumen específico del agua consumida en m3/kg
storage_max_energy=(almVolumen*(1/1000)*(1/almacenamiento_rho)*almacenamiento_CP*(T_out_K))/3600 #Storage capacity in kWh
almacenamiento=IAPWS97(P=P_op_Mpa, T=T_in_K) #Propiedades en el almacenamiento
almacenamiento_CP=almacenamiento.cp #Capacidad calorifica del proceso KJ/kg/K
almacenamiento_rho=almacenamiento.v #volumen específico del agua consumida en m3/kg
storage_ini_energy=(almVolumen*(1/1000)*(1/almacenamiento_rho)*almacenamiento_CP*(T_in_K))/3600 #Storage capacity in kWh
energStorageMax=storage_max_energy-storage_ini_energy
if type_integration=="SL_L_PS":
P_op_Mpa=P_op_bar/10
T_in_K=T_in_C+273
if fluidInput!="oil":
if T_out_C>IAPWS97(P=P_op_Mpa, x=0).T-273: #Make sure you are in liquid phase
T_out_C=IAPWS97(P=P_op_Mpa, x=0).T-273
T_out_K=T_out_C+273
tempAlm=T_out_K-273
inputState=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=inputState.h
in_s=inputState.s
in_x=inputState.x
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
#Storage calculations for water
energyStored=0 #Initial storage
T_avg_K=(T_in_K+T_out_K)/2
almacenamiento=IAPWS97(P=P_op_Mpa, T=T_avg_K) #Propiedades en el almacenamiento
almacenamiento_CP=almacenamiento.cp #Capacidad calorifica del proceso KJ/kg/K
almacenamiento_rho=almacenamiento.v #volumen específico del agua consumida en m3/kg
energStorageMax=(almVolumen*(1/1000)*(1/almacenamiento_rho)*almacenamiento_CP*(T_out_K-T_in_K))/3600 #Storage capacity in kWh
else:
T_out_K=T_out_C+273
tempAlm=T_out_K-273
energyStored=0 #Initial storage
T_av_K=(T_in_K+T_out_K)/2
[rho_av,Cp_av,k_av,Dv_av,Kv_av,thermalDiff_av,Prant_av]=thermalOil(T_av_K)
energStorageMax=(almVolumen*(1/1000)*(rho_av)*Cp_av*(T_out_K-T_in_K))/3600 #Storage capacity in kWh
if type_integration=="SL_S_FW":
P_op_Mpa=P_op_bar/10
energStorageMax=0 #kWh
energyStored=0 #kWh
T_in_K=T_in_C+273
initial=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=initial.h #kJ/kg
in_x=initial.x
sat_liq=IAPWS97(P=P_op_Mpa, x=0)
sat_vap=IAPWS97(P=P_op_Mpa, x=1)
h_sat_liq=sat_liq.h
h_sat_vap=sat_vap.h
sensiblePart=h_sat_liq-h_in
latentPart=h_sat_vap-h_sat_liq
total=h_sat_vap-h_in
porctSensible=sensiblePart/total
porctLatent=latentPart/total
Demand2=Demand*porctSensible
T_out_K=IAPWS97(P=P_op_Mpa, x=0).T-5 #Heating point
T_out_C=T_out_K-273
in_s=initial.s
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
if type_integration=="SL_S_FWS":
P_op_Mpa=P_op_bar/10
T_out_K=IAPWS97(P=P_op_Mpa, x=0).T #Heating point
T_out_C=T_out_K-273
outputState=IAPWS97(P=P_op_Mpa, T=T_out_K)
out_s=outputState.s
h_out=outputState.h
if T_in_flag==1:
T_in_K=T_in_C+273
else:
T_in_K=np.average(T_in_C_AR)+273
initial=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=initial.h #kJ/kg
in_s=initial.s
in_x=initial.x
sat_liq=IAPWS97(P=P_op_Mpa, x=0)
sat_vap=IAPWS97(P=P_op_Mpa, x=1)
h_sat_liq=sat_liq.h
h_sat_vap=sat_vap.h
sensiblePart=h_sat_liq-h_in
latentPart=h_sat_vap-h_sat_liq
PreHeatedPart=h_out-h_in
total=h_sat_vap-h_in
porctSensible=sensiblePart/total
porctLatent=latentPart/total
porctPreHeated=PreHeatedPart/total
# Demand2=Demand*porctSensT_in_Kible
Demand2=Demand*porctPreHeated
T_avg_K=(T_in_K+T_out_K)/2
tempAlm=T_out_K-273
almacenamiento=IAPWS97(P=P_op_Mpa, T=T_avg_K) #Propiedades en el almacenamiento
almacenamiento_CP=almacenamiento.cp #Capacidad calorifica del proceso KJ/kg/K
almacenamiento_rho=almacenamiento.v #volumen específico del agua consumida en m3/kg
energStorageMax=almVolumen*(1/1000)*(1/almacenamiento_rho)*almacenamiento_CP*(T_out_K-T_in_K)/3600 #Storage capacity in kWh
energyStored=0 #Initial storage
if type_integration=="SL_S_PD":
x_design=0.4
P_op_Mpa=P_op_bar/10
almVolumen=0 #litros
energStorageMax=0 #kWh
energyStored=0 #kWh
T_in_K=T_in_C+273 #Temp return of condensates
initial=IAPWS97(P=P_op_Mpa, T=T_in_K)
h_in=initial.h #kJ/kg
in_s=initial.s
sat_liq=IAPWS97(P=P_op_Mpa, x=0)
outputState=IAPWS97(P=P_op_Mpa, x=x_design)
T_out_K=outputState.T
T_out_C=outputState.T-273 #Temperature of saturation at that level
out_s=outputState.s
h_out=outputState.h
outputProcessState=IAPWS97(P=P_op_Mpa, x=1)
outProcess_s=outputProcessState.s
outProcess_h=outputProcessState.h
hProcess_out=outProcess_h
#Not used
porctSensible=0
sat_vap=0 #Not used
T_in_process_C=0 #Not used
T_out_process_C=T_out_C #Not used
T_out_HX_C=0 #Not used
integrationDesign={'x_design':x_design,'porctSensible':porctSensible,'almVolumen':almVolumen,'energStorageMax':energStorageMax,
'T_out_process_C':T_out_process_C,'T_in_process_C':T_in_process_C,'T_out_HX_C':T_out_HX_C}
#Declaracion de variables
theta_transv_rad=np.zeros(steps_sim)
theta_i_rad=np.zeros(steps_sim)
theta_i_deg=np.zeros(steps_sim)
theta_transv_deg=np.zeros(steps_sim)
IAM_long=np.zeros(steps_sim)
IAM_t=np.zeros(steps_sim)
IAM=np.zeros(steps_sim)
T_in_K=np.zeros(steps_sim)
T_out_K=np.zeros(steps_sim)
flow_rate_kgs=np.zeros(steps_sim)
Perd_termicas=np.zeros(steps_sim)
flow_rate_rec=np.zeros(steps_sim)
bypass=list()
h_in_kJkg=np.zeros(steps_sim)
Q_prod=np.zeros(steps_sim)
Q_prod_lim=np.zeros(steps_sim)
Q_prod_rec=np.zeros(steps_sim)
Q_defocus=np.zeros(steps_sim)
SOC=np.zeros(steps_sim)
Q_charg=np.zeros(steps_sim)
Q_discharg=np.zeros(steps_sim)
Q_useful=np.zeros(steps_sim)
h_out_kJkg=np.zeros(steps_sim)
flowToHx=np.zeros(steps_sim)
flowToMix=np.zeros(steps_sim)
flowDemand=np.zeros(steps_sim)
T_toProcess_K=np.zeros(steps_sim)
T_toProcess_C=np.zeros(steps_sim)
T_alm_K=np.zeros(steps_sim)
storage_energy=np.zeros(steps_sim)
for i in range(0,steps_sim):
theta_transv_deg[i],theta_i_deg[i]=theta_IAMs_v2(SUN_AZ[i],SUN_ELV[i],beta,orient_az_rad,roll)
theta_i_deg[i]=abs(theta_i_deg[i])
if sender=='solatom': #Using Solatom IAMs
from Solatom_modules.solatom_param import optic_efficiency_N
IAM[i]=optic_efficiency_N(theta_transv_deg[i],theta_i_deg[i],n_coll_loop) #(theta_transv_deg[i],theta_i_deg[i],n_coll_loop):
IAM_long[i]=0
IAM_t[i]=0
else:
#Cálculo del IAM long y transv
if SUN_ELV[i]>0:
[IAM_long[i]]=IAM_calc(theta_i_deg[i],0,IAMfile_loc) #Longitudinal
[IAM_t[i]]=IAM_calc(theta_transv_deg[i],1,IAMfile_loc) #Transversal
IAM[i]=IAM_long[i]*IAM_t[i]
else:
IAM_long[i]=0
IAM_t[i]=0
IAM[i]=IAM_long[i]*IAM_t[i]
if i==0: #Condiciones iniciales
bypass.append("OFF")
Q_prod[i]=0
T_in_K[i]=temp[0] #Ambient temperature
T_out_K[i]=0+273
if type_integration=="SL_L_S" or type_integration=="SL_L_S3":
T_alm_K[i]=T_ini_storage
storage_energy[0]=storage_ini_energy
# SOC[i]=100*(T_alm_K[i]-273)/(T_max_storage-273)
SOC[i]=100*energyStored/energStorageMax
else:
if DNI[i]>lim_inf_DNI :#tengo suficiente radiacion o tengo demanda OPERATION
if type_integration=="SL_L_PS":
#SL_L_PS Supply level with liquid heat transfer media Parallel integration with storeage pg52
if fluidInput!="oil":
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i-1],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageWaterSimple(Q_prod[i],energyStored,Demand[i],energStorageMax)
else:
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationOilSimple(bypass,T_in_K[i-1],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageOilSimple(Q_prod[i],energyStored,Demand[i],energStorageMax)
if type_integration=="SL_L_S" or type_integration=="SL_L_S3":
#SL_L_PS Supply level with liquid heat transfer media Parallel integration with storeage pg52
if fluidInput!="oil":
[T_out_K[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_kgs[i]]=operationOnlyStorageWaterSimple(T_max_storage,T_alm_K[i-1],P_op_Mpa,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,flow_rate_design_kgs)
[T_alm_K[i],storage_energy[i],Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputOnlyStorageWaterSimple(P_op_Mpa,T_min_storage,T_max_storage,almVolumen,T_out_K[i],T_alm_K[i-1],Q_prod[i],energyStored,Demand[i],energStorageMax,storage_energy[i-1],storage_ini_energy)
else:
pass
# [T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i]]=operationOilSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
# [Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageOilSimple(Q_prod[i],energyStored,Demand[i],energStorageMax)
if type_integration=="SL_L_P" or type_integration=="PL_E_PM":
#SL_L_P Supply level with liquid heat transfer media Parallel integration pg52
if fluidInput!="oil":
flowDemand[i]=Demand[i]/(hProcess_out-hProcess_in)
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageWaterSimple(Q_prod[i],Demand[i])
else:
T_av_process_K=(T_out_process_K+T_in_process_K)/2
[rho_av,Cp_av,k_av,Dv_av,Kv_av,thermalDiff_av,Prant_av]=thermalOil(T_av_process_K)
flowDemand[i]=Demand[i]/(Cp_av*(T_out_process_K-T_in_process_K))
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationOilSimple(bypass,T_in_K[i-1],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageOilSimple(Q_prod[i],Demand[i])
if type_integration=="SL_L_RF":
#SL_L_RF Supply level with liquid heat transfer media return boost integration pg52
if fluidInput!="oil":
flowDemand[i]=Demand[i]/(hProcess_out-hProcess_in)
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
if newBypass=="REC":
flowToHx[i]=0 #Valve closed no circulation through the HX. The solar field is recirculating
else:
#HX simulation
Q_prodProcessSide=Q_prod[i]*.9
flowToHx[i]=Q_prodProcessSide/(hHX_out-hProcess_in)
flowToMix[i]=flowDemand[i]-flowToHx[i]
if flowToHx[i]==0:
T_toProcess_K[i]=T_in_process_K
else:
#Brach to mix
toMixstate=IAPWS97(P=P_op_Mpa, T=T_out_K[i])
#Mix
T_av_HX_K=(T_in_process_K+T_out_HX_K)/2
toProcessstate=IAPWS97(P=P_op_Mpa, T=T_av_HX_K)
T_toProcess_C[i]=(flowToMix[i]*hProcess_in+flowToHx[i]*toMixstate.h)/(flowDemand[i]*toProcessstate.cp)
T_toProcess_K[i]=T_toProcess_K[i]+273
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageWaterSimple(Q_prod[i],Demand[i])
else:
[rho_av,Cp_av,k_av,Dv_av,Kv_av,thermalDiff_av,Prant_av]=thermalOil(T_av_process_K)
flowDemand[i]=Demand[i]/(Cp_av*(T_out_process_K-T_in_process_K))
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationOilSimple(bypass,T_in_K[i-1],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
if newBypass=="REC":
flowToHx[i]=0 #Valve closed no circulation through the HX. The solar field is recirculating
else:
#HX simulation
Q_prodProcessSide=Q_prod[i]*.9
flowToHx[i]=Q_prodProcessSide/(Cp_av*(T_out_HX_K-T_in_process_K))
flowToMix[i]=flowDemand[i]-flowToHx[i]
#Exit of the heat Echanger
[rho_toHX,Cp_toHX,k_toHX,Dv_toHX,Kv_toHX,thermalDiff_toHX,Prant_toHX]=thermalOil(T_out_HX_K)
#Brach to mix
[rho_toMix,Cp_toMix,k_toMix,Dv_toMix,Kv_toMix,thermalDiff_toMix,Prant_toMix]=thermalOil(T_in_process_K)
#Mix
#T_av_HX_K=(T_in_process_K+T_out_HX_K)/2 #Ok when are more or less the same flowrate
T_av_HX_K=T_in_process_K*(flowToMix[i]/flowDemand[i])+T_out_HX_K*(flowToHx[i]/flowDemand[i]) #When temperatures are very different
[rho_av_HX,Cp_av_HX,k_av_HX,Dv_av_HX,Kv_av_HX,thermalDiff_av_HX,Prant_av_HX]=thermalOil(T_av_HX_K)
if flowToHx[i]==0:
T_toProcess_K[i]=T_in_process_K
else:
T_toProcess_K[i]=(flowToMix[i]*Cp_toMix*T_in_process_K+flowToHx[i]*Cp_toHX*T_out_HX_K)/(flowDemand[i]*Cp_av_HX)
T_toProcess_C[i]=T_toProcess_K[i]-273
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageOilSimple(Q_prod[i],Demand[i])
if type_integration=="SL_S_FW":
#SL_S_FW Supply level with steam for solar heating of boiler feed water without storage
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageWaterSimple(Q_prod[i],Demand2[i])
if type_integration=="SL_S_FWS":
#SL_S_FW Supply level with steam for solar heating of boiler feed water with storage
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageWaterSimple(Q_prod[i],energyStored,Demand2[i],energStorageMax)
if type_integration=="SL_S_PD":
#SL_S_PD Supply level with steam for direct steam generation
[T_out_K[i],flow_rate_kgs[i],Perd_termicas[i],Q_prod[i],T_in_K[i],flow_rate_rec[i],Q_prod_rec[i],newBypass]=operationWaterSimple(bypass,T_in_flag,T_in_K[i-1],T_in_C_AR[i],T_out_K[i-1],T_in_C,P_op_Mpa,bypass[i-1],T_out_C,temp[i],REC_type,theta_i_rad[i],DNI[i],Long,IAM[i],Area,n_coll_loop,rho_optic_0,num_loops,mofProd,coef_flow_rec,m_dot_min_kgs,Q_prod_rec[i-1])
[Q_prod_lim[i],Q_defocus[i],Q_useful[i]]=outputWithoutStorageWaterSimple(Q_prod[i],Demand[i])
else: #No hay radiación ni demanda NO OPERATION
if type_integration=="SL_L_S" or type_integration=="SL_L_S3":
#SL_L_PS Supply level with liquid heat transfer media Parallel integration with storeage pg52
[T_out_K[i],Q_prod[i],T_in_K[i],SOC[i],T_alm_K[i],storage_energy[i]]=offOnlyStorageWaterSimple(T_alm_K[i-1],energStorageMax,energyStored,T_alm_K[i-1],storage_energy[i-1])
if Demand[i]>0:
[T_alm_K[i],storage_energy[i],Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputOnlyStorageWaterSimple(P_op_Mpa,T_min_storage,T_max_storage,almVolumen,T_out_K[i],T_alm_K[i-1],Q_prod[i],energyStored,Demand[i],energStorageMax,storage_energy[i-1],storage_ini_energy)
if type_integration=="SL_L_PS":
#SL_L_PS Supply level with liquid heat transfer media Parallel integration with storeage pg52
[T_out_K[i],Q_prod[i],T_in_K[i],SOC[i]]=offStorageWaterSimple(bypass,T_in_flag,T_in_C_AR[i],T_in_K[i-1],energStorageMax,energyStored)
if Demand[i]>0:
[Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageWaterSimple(Q_prod[i],energyStored,Demand[i],energStorageMax)
if type_integration=="SL_L_P" or type_integration=="PL_E_PM" or type_integration=="SL_L_RF":
#SL_L_P Supply level with liquid heat transfer media Parallel integration pg52
[T_out_K[i],Q_prod[i],T_in_K[i]]=offWaterSimple(bypass,T_in_flag,T_in_C_AR[i],T_in_K[i-1])
if type_integration=="SL_S_FW":
#SL_S_FW Supply level with steam for solar heating of boiler feed water without storage
[T_out_K[i],Q_prod[i],T_in_K[i]]=offWaterSimple(bypass,T_in_flag,T_in_C_AR[i],T_in_K[i-1])
if type_integration=="SL_S_FWS":
#SL_S_FWS Supply level with steam for solar heating of boiler feed water with storage
[T_out_K[i],Q_prod[i],T_in_K[i],SOC[i]]=offStorageWaterSimple(bypass,T_in_flag,T_in_C_AR[i],T_in_K[i-1],energStorageMax,energyStored)
if Demand2[i]>0:
[Q_prod_lim[i],Q_prod[i],Q_discharg[i],Q_charg[i],energyStored,SOC[i],Q_defocus[i],Q_useful[i]]=outputStorageWaterSimple(Q_prod[i],energyStored,Demand2[i],energStorageMax)
if type_integration=="SL_S_PD":
#SL_S_PD Supply level with steam for direct steam generation
[T_out_K[i],Q_prod[i],T_in_K[i]]=offWaterSimple(bypass,T_in_flag,T_in_C_AR[i],T_in_K[i-1])
processDict={'T_in_flag':T_in_flag,'T_in_C_AR':T_in_C_AR.tolist(),'T_toProcess_C':T_toProcess_C.tolist()}
#---- ANUAL SUMMARY -----------------------------------------------
Production_max=sum(Q_prod) #Produccion total en kWh. Asumiendo que se consume todo lo producido
Production_lim=sum(Q_prod_lim) #Produccion limitada total en kWh
Demand_anual=sum(Demand) #Demanda energética anual
solar_fraction_max=100*Production_max/Demand_anual #Fracción solar maxima
tonCo2Saved=Production_lim*co2factor #Tons of Co2 saved
totalDischarged=(sum(Q_discharg))
# totalCharged=(sum(Q_charg))
Utilitation_ratio=100*((sum(Q_prod_lim))/(sum(Q_prod)))
improvStorage=(100*sum(Q_prod_lim)/(sum(Q_prod_lim)-totalDischarged))-100 #Assuming discharged = Charged
solar_fraction_lim=100*(sum(Q_prod_lim))/Demand_anual
# Energy_module_max=Production_max/num_modulos_tot
# operation_hours=np.nonzero(Q_prod)
DNI_anual_irradiation=sum(DNI)/1000 #kWh/year
# Optic_rho_average=(sum(IAM)*rho_optic_0)/steps_sim
Perd_term_anual=sum(Perd_termicas)/(1000) #kWh/year
annualProdDict={'Q_prod':Q_prod.tolist(),'Q_prod_lim':Q_prod_lim.tolist(),'Demand':Demand.tolist(),'Q_charg':Q_charg.tolist(),
'Q_discharg':Q_discharg.tolist(),'Q_defocus':Q_defocus.tolist(),'solar_fraction_max':solar_fraction_max,
'solar_fraction_lim':solar_fraction_lim,'improvStorage':improvStorage,'Utilitation_ratio':Utilitation_ratio,
'flow_rate_kgs':flow_rate_kgs.tolist()}
if finance_study==1 and steps_sim==8759:
#---- FINANCIAL SIMULATION INPUTS ---------------------------------
#Fixed parameters
IPC=2.5 # Annual increase of the price of money in %
fuelIncremento=3.5 # Annual increase of fuel price in %
n_years_sim=25 #Number of years for the simulation
incremento=IPC/100+fuelIncremento/100
if co2TonPrice>0:
CO2=1 #Flag to take into account co2 savings in terms of cost per ton emitted
else:
CO2=0 #Flag to take into account co2 savings in terms of cost per ton emitted
if ressspiReg==-2: #If ReSSSPI front-end is calling, then it uses Solatom propietary cost functions
from Solatom_modules.Solatom_finance import SOL_plant_costFunctions
[Selling_price,Break_cost,OM_cost_year]=SOL_plant_costFunctions(num_modulos_tot,type_integration,almVolumen,fluidInput)
else: #If othe collector is selected, it uses default cost functions
#This function calls the standard cost functions, if necessary, please modify them within the function
[Selling_price,Break_cost,OM_cost_year]=SP_plant_costFunctions(num_modulos_tot,type_integration,almVolumen,fluidInput)
Selling_price=Selling_price*mofINV
#---- FINANCE ---------------------------------------------------------
if CO2==1:
co2Savings=tonCo2Saved*co2TonPrice
else:
co2Savings=0
if businessModel=="Llave en mano" or businessModel=="Turnkey project" or businessModel=="turnkey":
[LCOE,IRR,IRR10,AmortYear,Acum_FCF,FCF,Energy_savings,OM_cost,fuelPrizeArray,Net_anual_savings]=Turn_key(Production_lim,Fuel_price,Boiler_eff,n_years_sim,Selling_price,OM_cost_year,incremento,co2Savings)
if lang=="spa":
TIRscript="TIR para el cliente"
Amortscript="<b>Amortización: </b> Año "+ str(AmortYear)
TIRscript10="TIR para el cliente en 10 años"
if lang=="eng":
TIRscript="IRR for the client"
Amortscript="<b>Payback: </b> Year "+ str(AmortYear)
TIRscript10="IRR for the client 10 years"
#Modelo tipo ESE
if businessModel=="Compra de energia" or businessModel=="ESCO" or businessModel=="Renting":
priceReduction=0.8
#From financing institution poit of view
[IRR,IRR10,AmortYear,Acum_FCF,FCF,BenefitESCO,OM_cost,fuelPrizeArray,Energy_savings,Net_anual_savings]=ESCO(priceReduction,Production_lim,Fuel_price,Boiler_eff,n_years_sim,Selling_price,OM_cost_year,incremento,co2Savings)
if lang=="spa":
TIRscript="TIR para la ESE"
Amortscript="<b>Ahorro en precio actual combustible: </b>"+str(round(100*(1-priceReduction)))+"%"
if lang=="eng":
TIRscript="IRR for the ESCO"
Amortscript="<b>Savings in fuel cost: </b>"+str(round(100*(1-priceReduction)))+"%"
#Form client point of view
AmortYear=0
Selling_price=0 #No existe inversión
FCF[0]=0
Energy_savingsList=[]
OMList=[]
fuelPrizeArrayList=[]
Acum_FCFList=[]
for i in range(0,len(Acum_FCF)):
if Acum_FCF[i]<0:
Acum_FCFList.append("("+str(int(abs(Acum_FCF[i])))+")")
else:
Acum_FCFList.append(str(int(Acum_FCF[i])))
for i in range(0,len(fuelPrizeArray)):
Energy_savingsList.append(round(Net_anual_savings[i]))
OMList.append(OM_cost[i])
fuelPrizeArrayList.append(fuelPrizeArray[i])
finance={'AmortYear':AmortYear,'finance_study':finance_study,'CO2':CO2,'co2Savings':co2Savings,
'fuelPrizeArrayList':fuelPrizeArrayList,'Acum_FCFList':Acum_FCFList,'Energy_savingsList':Energy_savingsList,
'TIRscript':TIRscript,'TIRscript10':TIRscript10,'Amortscript':Amortscript,
'co2TonPrice':co2TonPrice,'fuelIncremento':fuelIncremento,'IPC':IPC,'Selling_price':Selling_price,
'IRR':IRR,'IRR10':IRR10,'tonCo2Saved':tonCo2Saved,'OM_cost_year':OMList}
else:
n_years_sim=0 #No finance simulation
Acum_FCF=np.array([]) #No finance simulation
FCF=np.array([]) #No finance simulation
AmortYear=0 #No finance simulation
Selling_price=0 #No finance simulation
#%%
# ---------------------------------------------------------------------
# --------------------------- PLOT CONSOLE ----------------------------
# ---------------------------------------------------------------------
plotVars={'lang':lang,'Production_max':Production_max,'Production_lim':Production_lim,
'Perd_term_anual':Perd_term_anual,'DNI_anual_irradiation':DNI_anual_irradiation,
'Area':Area,'num_loops':num_loops,'imageQlty':imageQlty,'plotPath':plotPath,
'Demand':Demand.tolist(),'Q_prod':Q_prod.tolist(),'Q_prod_lim':Q_prod_lim.tolist(),'type_integration':type_integration,
'Q_charg':Q_charg.tolist(),'Q_discharg':Q_discharg.tolist(),'DNI':DNI.tolist(),'SOC':SOC.tolist(),
'Q_useful':Q_useful.tolist(),'Q_defocus':Q_defocus.tolist(),'T_alm_K':T_alm_K.tolist(),
'n_years_sim':n_years_sim,'Acum_FCF':Acum_FCF.tolist(),'FCF':FCF.tolist(),'m_dot_min_kgs':m_dot_min_kgs,
'steps_sim':steps_sim,'AmortYear':AmortYear,'Selling_price':Selling_price,
'in_s':in_s,'out_s':out_s,'T_in_flag':T_in_flag,'Fuel_price':Fuel_price,'Boiler_eff':Boiler_eff,
'T_in_C':T_in_C,'T_in_C_AR':T_in_C_AR.tolist(),'T_out_C':T_out_C,
'outProcess_s':outProcess_s,'T_out_process_C':T_out_process_C,'P_op_bar':P_op_bar,
'x_design':x_design,'h_in':h_in,'h_out':h_out,'hProcess_out':hProcess_out,'outProcess_h':outProcess_h,
'Break_cost':Break_cost}
# Annual simulations
if steps_sim==8759:
if plots[0]==1: #(0) Sankey plot
image_base64,sankeyDict=SankeyPlot(sender,ressspiReg,lang,Production_max,Production_lim,Perd_term_anual,DNI_anual_irradiation,Area,num_loops,imageQlty,plotPath)
if plots[0]==0: #(0) Sankey plot -> no plotting
sankeyDict={'Production':0,'raw_potential':0,'Thermal_loss':0,'Utilization':0}
if plots[1]==1: #(1) Production week Winter & Summer
prodWinterPlot(sender,ressspiReg,lang,Demand,Q_prod,Q_prod_lim,type_integration,Q_charg,Q_discharg,DNI,plotPath,imageQlty)
prodSummerPlot(sender,ressspiReg,lang,Demand,Q_prod,Q_prod_lim,type_integration,Q_charg,Q_discharg,DNI,plotPath,imageQlty)
if plots[2]==1 and finance_study==1: #(2) Plot Finance
financePlot(sender,ressspiReg,lang,n_years_sim,Acum_FCF,FCF,m_dot_min_kgs,steps_sim,AmortYear,Selling_price,plotPath,imageQlty)
if plots[3]==1: #(3)Plot of Storage first week winter & summer
storageWinter(sender,ressspiReg,lang,Q_prod,Q_charg,Q_prod_lim,Q_useful,Demand,Q_defocus,Q_discharg,type_integration,T_alm_K,SOC,plotPath,imageQlty)
storageSummer(sender,ressspiReg,lang,Q_prod,Q_charg,Q_prod_lim,Q_useful,Demand,Q_defocus,Q_discharg,type_integration,T_alm_K,SOC,plotPath,imageQlty)
if plots[4]==1: #(4) Plot Prod months
output_excel=prodMonths(sender,ressspiReg,Q_prod,Q_prod_lim,DNI,Demand,lang,plotPath,imageQlty)
if plots[15]==1: #(14) Plot Month savings
output_excel2=savingsMonths(sender,ressspiReg,Q_prod_lim,Energy_Before,Fuel_price,Boiler_eff,lang,plotPath,imageQlty)
# Non-annual simulatios (With annual simuations you cannot see anything)
if steps_sim!=8759:
if plots[5]==1: #(5) Theta angle Plot
thetaAnglesPlot(sender,ressspiReg,step_sim,steps_sim,theta_i_deg,theta_transv_deg,plotPath,imageQlty)
if plots[6]==1: #(6) IAM angles Plot
IAMAnglesPlot(sender,ressspiReg,step_sim,IAM_long,IAM_t,IAM,plotPath,imageQlty)
if plots[7]==1: #(7) Plot Overview (Demand vs Solar Radiation)
demandVsRadiation(sender,ressspiReg,lang,step_sim,Demand,Q_prod,Q_prod_lim,Q_prod_rec,steps_sim,DNI,plotPath,imageQlty)
if plots[8]==1: #(8) Plot flowrates & Temp & Prod
flowRatesPlot(sender,ressspiReg,step_sim,steps_sim,flow_rate_kgs,flow_rate_rec,num_loops,flowDemand,flowToHx,flowToMix,m_dot_min_kgs,T_in_K,T_toProcess_C,T_out_K,T_alm_K,plotPath,imageQlty)
if plots[9]==1: #(9)Plot Storage non-annual simulation
storageAnnual(sender,ressspiReg,SOC,Q_useful,Q_prod,Q_charg,Q_prod_lim,step_sim,Demand,Q_defocus,Q_discharg,steps_sim,plotPath,imageQlty)
# Property plots
if fluidInput!="oil": #WATER
if plots[10]==1: #(10) Mollier Plot for s-t for Water
mollierPlotST(sender,ressspiReg,lang,type_integration,in_s,out_s,T_in_flag,T_in_C,T_in_C_AR,T_out_C,outProcess_s,T_out_process_C,P_op_bar,x_design,plotPath,imageQlty)
if plots[11]==1: #(11) Mollier Plot for s-h for Water
mollierPlotSH(sender,ressspiReg,lang,type_integration,h_in,h_out,hProcess_out,outProcess_h,in_s,out_s,T_in_flag,T_in_C,T_in_C_AR,T_out_C,outProcess_s,T_out_process_C,P_op_bar,x_design,plotPath,imageQlty)
if fluidInput=="oil":
if plots[12]==1:
rhoTempPlotOil(sender,ressspiReg,lang,T_out_C,plotPath,imageQlty) #(12) Plot thermal oil properties Rho & Cp vs Temp
if plots[13]==1:
viscTempPlotOil(sender,ressspiReg,lang,T_out_C,plotPath,imageQlty) #(13) Plot thermal oil properties Viscosities vs Temp
# Other plots
if plots[14]==1: #(14) Plot Production
productionSolar(sender,ressspiReg,lang,step_sim,DNI,m_dot_min_kgs,steps_sim,Demand,Q_prod,Q_prod_lim,Q_charg,Q_discharg,type_integration,plotPath,imageQlty)