From fc5fca955e37510d4f21cba27e102ea1c60b1b55 Mon Sep 17 00:00:00 2001 From: Koa Wells Date: Mon, 17 Apr 2023 14:41:43 -0400 Subject: [PATCH] Update ep to include hot water, update how results are saved, update requirements.txt --- energy_validation.py | 154 +++++++++++++++++-------- requirements.txt | 2 +- results/energy_validation_results.xlsx | Bin 10656 -> 0 bytes 3 files changed, 107 insertions(+), 49 deletions(-) delete mode 100644 results/energy_validation_results.xlsx diff --git a/energy_validation.py b/energy_validation.py index 74f16c6..b86edb2 100644 --- a/energy_validation.py +++ b/energy_validation.py @@ -5,6 +5,7 @@ from pathlib import Path import pandas as pd import platform import os +import xlsxwriter from hub.imports.geometry_factory import GeometryFactory from hub.imports.weather_factory import WeatherFactory @@ -28,14 +29,40 @@ class EnergyValidation: self.climate_file = Path(f'{self.storage_path}/{self.climate_file_name}.cli').resolve() self.meb_folder = Path('./results/meb').resolve() self.ep_folder = Path('./results/ep').resolve() - self.result_file = Path('./results/energy_validation_results.xlsx').resolve() + + self.result_file = Path(f'./results/{datetime.datetime.now().strftime("%m-%d-%Y_%H-%M-%S")}' + f'_energy_validation_results.xlsx').resolve() + results_xlsx = xlsxwriter.Workbook(self.result_file) + simulation_data_worksheet = results_xlsx.add_worksheet('Simulation data') + metadata_worksheet = results_xlsx.add_worksheet('Metadata') + bold = results_xlsx.add_format({'bold': True}) + + simulation_data_worksheet.write('A1', 'Building', bold) + simulation_data_worksheet.write('B1', 'Month', bold) + simulation_data_worksheet.write('C1', 'Heating demand (kWh/m2)', bold) + simulation_data_worksheet.write('D1', 'Cooling demand (kWh/m2)', bold) + simulation_data_worksheet.write('E1', 'Appliances demand (kWh/m2)', bold) + simulation_data_worksheet.write('F1', 'Lighting demand (kWh/m2)', bold) + simulation_data_worksheet.write('G1', 'Domestic hot water demand (kWh/m2)', bold) + simulation_data_worksheet.write('H1', 'Source of simulation (kWh/m2)', bold) + + metadata_worksheet.write('A1', 'Building id', bold) + metadata_worksheet.write('B1', 'Storeys', bold) + metadata_worksheet.write('C1', 'M2 per storey', bold) + metadata_worksheet.write('D1', 'Total m2', bold) + metadata_worksheet.write('E1', 'Total m3', bold) + metadata_worksheet.write('F1', 'Year building', bold) + metadata_worksheet.write('G1', 'Type of building', bold) + + results_xlsx.close() if platform.system() == 'Windows': self.encoding = 'windows-1252' else: self.encoding = 'utf-8' - def _sort_buildings(self, buildings_to_simulate): + @staticmethod + def _sort_buildings(buildings_to_simulate): sorted_buildings = {} for building in buildings_to_simulate: code_utili = building['properties']['CODE_UTILI'] @@ -123,12 +150,13 @@ class EnergyValidation: index=False, header=False, ) + def _save_ep_results(self, demand, building_area, building_name): demand.drop('Date/Time', axis=1, inplace=True) # convert from J to kWh/m^2 - demand *= 2.77778e-7/building_area + demand *= (2.77778e-7/building_area) - # replace indexes with month/day/year format + # insert date in month/day/year format months = [ '1/1/2023', '2/1/2023', @@ -146,15 +174,20 @@ class EnergyValidation: demand.insert(0, 'month', months) - # insert building_name to first column + # insert building_name demand.insert(0, 'building_name', building_name) - # TODO: add water usage once working from ep - demand['water_usage'] = 'NA' + # insert hot water demand + demand['water_usage'] = demand.iloc[:,5] - demand.iloc[:,2] # add simulation source as ep demand['source'] = 'ep' + # drop unneeded columns + demand.drop(4) + demand.drop(5) + demand.drop(6) + # last, but not least, append our lovely reformatted data to the results spreadsheet with pd.ExcelWriter(self.result_file, engine='openpyxl', if_sheet_exists='overlay', mode='a') as writer: demand.to_excel( @@ -215,53 +248,78 @@ class EnergyValidation: city.climate_file = self.climate_file city.name = f'{building_id}_energy_validation' - # starting sra - print(f'{building_id} starting sra') - ExportsFactory('sra', city, self.tmp_folder, - weather_file=self.weather_file, weather_format='epw').export() - sra_file = (self.tmp_folder / f'{city.name}_sra.xml').resolve() - sra_start = datetime.datetime.now() - Sra(sra_file, self.tmp_folder).run() - sra_end = datetime.datetime.now() - sra_start - ResultFactory('sra', city, self.tmp_folder).enrich() + try: + # starting sra + print(f'{building_id} starting sra') + ExportsFactory('sra', city, self.tmp_folder, + weather_file=self.weather_file, weather_format='epw').export() + sra_file = (self.tmp_folder / f'{city.name}_sra.xml').resolve() + sra_start = datetime.datetime.now() + Sra(sra_file, self.tmp_folder).run() + sra_end = datetime.datetime.now() - sra_start + ResultFactory('sra', city, self.tmp_folder).enrich() - # run meb - print(f'{building_id} starting meb') - for building in city.buildings: - building.attic_heated = 0 - building.basement_heated = 1 + # run meb + print(f'{building_id} starting meb') + for building in city.buildings: + building.attic_heated = 0 + building.basement_heated = 1 - EnergyBuildingsExportsFactory('insel_monthly_energy_balance', city, self.tmp_folder).export() - meb_start = datetime.datetime.now() - Meb(self.tmp_folder).run() - meb_end = datetime.datetime.now() - meb_start - ResultFactory('insel_meb', city, self.tmp_folder).enrich() - results = MEBResults(city, Path('./results/meb/').resolve()) - results.print() + EnergyBuildingsExportsFactory('insel_monthly_energy_balance', city, self.tmp_folder).export() + meb_start = datetime.datetime.now() + Meb(self.tmp_folder).run() + meb_end = datetime.datetime.now() - meb_start + ResultFactory('insel_meb', city, self.tmp_folder).enrich() + results = MEBResults(city, Path('./results/meb/').resolve()) + results.print() - # save meb results to energy_validation_results - total_m2 = city.buildings[0].internal_zones[0].thermal_zones[0].total_floor_area - meb_results = pd.read_csv(Path(f'{self.meb_folder}/demand.csv').resolve(), - encoding=self.encoding) - meb_metadata = pd.read_csv(Path(f'{self.meb_folder}/metadata.csv').resolve(), - encoding=self.encoding) - self._save_meb_results(meb_results, meb_metadata, total_m2) + # run energyplus + print(f'{building_id} starting energy plus') + idf_file = EnergyBuildingsExportsFactory('idf', city, self.ep_folder).export() + ep_start = datetime.datetime.now() + idf_file.run() + ep_end = datetime.datetime.now() - ep_start - # run energyplus - print(f'{building_id} starting energy plus') - idf_file = EnergyBuildingsExportsFactory('idf', city, self.ep_folder).export_debug() - ep_start = datetime.datetime.now() - idf_file.run() - ep_end = datetime.datetime.now() - ep_start + # save meb results to energy_validation_results + total_m2 = city.buildings[0].internal_zones[0].thermal_zones[0].total_floor_area + meb_results = pd.read_csv(Path(f'{self.meb_folder}/demand.csv').resolve(), + encoding=self.encoding) + meb_metadata = pd.read_csv(Path(f'{self.meb_folder}/metadata.csv').resolve(), + encoding=self.encoding) + self._save_meb_results(meb_results, meb_metadata, total_m2) - # save ep results to energy_validation_results - ep_results = pd.read_csv(Path(f'{self.ep_folder}/{building_id}_energy_validation_mtr.csv').resolve(), - encoding=self.encoding) - self._save_ep_results(ep_results, total_m2, city.buildings[0].name) + # save ep results to energy_validation_results + ep_results = pd.read_csv(Path(f'{self.ep_folder}/{building_id}_energy_validation_out.csv').resolve(), + encoding=self.encoding) + self._save_ep_results(ep_results, total_m2, city.buildings[0].name) - print(f"{building_id} sra time: {sra_end}") - print(f"{building_id} meb time: {meb_end}") - print(f"{building_id} ep time: {ep_end}") + print(f"{building_id} sra time: {sra_end}") + print(f"{building_id} meb time: {meb_end}") + print(f"{building_id} ep time: {ep_end}") + + except: + building_with_error = pd.DataFrame([ + building_id, + 'NA', + 'NA', + 'NA', + 'NA', + 'NA', + 'NA', + 'NA', + 'NA' + ]).transpose() + print(building_with_error) + + # with pd.ExcelWriter(self.result_file, engine='openpyxl', if_sheet_exists='overlay', + # mode='a') as writer: + # building_with_error.to_excel( + # writer, + # startrow=writer.sheets['Simulation data'].max_row, + # sheet_name='Simulation data', + # index=False, + # header=False, + # ) if cleanup is True: [os.remove(os.path.join(self.tmp_folder, file)) for file in os.listdir(self.tmp_folder)] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index a06638e..6b4f9ff 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -cerc-hub +xlsxwriter \ No newline at end of file diff --git a/results/energy_validation_results.xlsx b/results/energy_validation_results.xlsx deleted file mode 100644 index 492338e364179577bb3859b6f833b91babd1dbba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10656 zcmeHtWmH_-vULZ7JHdjxy9IX$E)BsQn&7U%-66PZ2n2U`53UI=!7aG!*C*$`n{&A5 z{r-NuyL*hiyGQR?y?c#0t7=u1q739q3;;9$761T{0KOy_E?U0;01}`8fL8!m2rW?? zYe$f^qn?VJEyzKK(bdY5IQJz4bv6J3eE)xs|HCWL6F+3##f&O`m2is^Q~%CTU+EpD zuQ<^VR^d6MwmUJF*MJfAy(blPQIWJTY@W3tMP}ob>srbWS1Y+nzmWOn)Qe(5x(=!G znzWe%&s*)~N{BdHX`G{M6FebKLLEJ%f;51-VqJGC2Th>+s1m0>l&XNwr;LPA>7BpQ8?dGhwC`y6tG^Ih0IZaS* z*B;Ce6;I)Y#v?cmV#YagG_G)zrvY%DnUOMwZA-dJGhvKLh=E#SQ(`6SK4YVr=Y8CI%FR zk3ZE1(7nBSKVdW)8IrvW%tLPF>QMM8itp%6H35?+A7%Ri^Rjf_B*`~`m=bAaWZr4F zoxlt}UB}sUI|9O~s9xLf^wRRKR5qAB;!|5u*>hc)?^zg`k6Cj-fX8g%6ML^9mUyFg1iX~`tMBWL{Zf+gia|4qur zyrzdM31P>aI>Ha> zS{CgWU$8~eZsyEh2!xfajbCWbGVTOaOrr6oILb8Cy38Tu?PFdEySQycbg>JhquzSWybpt(gXLuUIPi zjYieR-k^^zSKWeF;Xfr4B#+Gw2?+o+Km!0M;5%F`nOtn_EevgJEdGdUdGB;=7KkxC zvud7vTwPem?a+&NNAUGI0Z;u>u5&2Xzpgu@BI1+Of%csh78JJ)lX1OtSc z;TT)Wfg;+fA+gPL%5X@Dk(Crz%r#nTv~;eA@FX6Eu;J?g@!IB#qCtlxO!(yPxcdqIaHGrIE0n=ImOV0Tl_^2fO7UV*OlG!2Kp!emLr_s6;?@Kmb zNAx{KN(gI4ssf3Rh$f)lui&&bE=y9h)lQ1H6bYQLrpI?l+HGSuo|9&+k|2%<-*X!5 z@6{#3m(Uwnh762oj9y`F8g^T35(#}J;4_wpjhG`Yd1)Y>z2N4W)fbKejK|8o?#5w=6tn?{iUu5G%h?y(}`$}WZRst!52YE__|M5_}B}VL5MhzpVB0$mI;hc2w`0P`))-=}`saa8;c~=VG@e z={&ac-g)sTQa!6`!d3q5(3~TmHuA0|%fVIOlq;O?Ecpmxx#tOaK7hB=Q*ktKmrT$Z z3%8(lI7{c61*ZZkBid99`+#$A>V^*&#SH%f9gD32d)@4m?Iqse)*Bk+Lk(wxkf>gnx zV*>DFPwFV|&Ra4$M0PHR8U~49i(>n%_su>yT6=*5$$#oax-j414<)??YX%np`vR<& zKcmcFRr5a)=LI++1Y7yPeYC`mnD;Ov1{?*p`A@Xk#Xc$y^0?Ckw$?4cFjt}n%UK!~ z3cB5;#vgK4? zSy9T!#5p!=A+KQEEJRw!1=LUJ_K#Q5!e<8wWXmM=^$R=T8qxWep)`qWY~5r;v~y&q znuTR3p}K70_IM!<+}K#HupS(sG2t|m?j$)|tGrQNt(tv<+%goV^`_bJG zsUap{hp$FnAk+9#`JQdqkhR{T>*F`H5rlpf0iMrnT1*rU)wGDwo_n{IbnGL7m-ebp zdkFu;oJ;BX&?j(WvJdvOIABWr%hNiTf)tL++ zp*B`=iXS~FDoUy~lCAJ#sm(|$YI8@CCnf_;7^7alne`BOI`QqDQsOXWib!Z;U`7&& z5F2u$S&;Mf_Ry1KjVLj)8o*r&gUAZ#RTzpU!h*4?tHbIdA+D+GsCCeh5813$9ENUs z#Soz~PrbGJ-7@57g#Kr5DGqY@?s#fSEf30#EyAEO+JWBcEnW&ummr)8W|)%&O=st9 z8ZQ)img*&^S7q;DLTWAZc-^Qa!nVuPRPpMpJFa5-B0hccW%IM(ppS8 z{0Kui7YsYzT&ZbrqCCpos!4MPe07rG<(xtJZJAy1~QI{0*6DZ97@%F>{G4mMY+ zUu79_=3Q3^KuO7LAmh%d*B1MoZGNgvGI{k`1$B&U|Lm*{sxX6i97ZI+pb6)ASEM`x3{wK6C9V)6w~7tSj!gk;x?Iac@u>xP@qgf_`1Dr{6O5((Vuts zq2;n9Y!~LAMAO{5JdXu-wY=bO{}<7){wbOTuxP+(9o+>1{R#}TFTUc}qCMKd<##{p zTAd@{RGIVZ9Dv_kj%Gjl$KzE|yCNnZWv#FopV-H8@Yq@fnA^+x!ICXAzY8%*ThBTw zoRupNe+h?KZLuSk9{vx)|MpC0Cd%;|5{CVhFdp|rskT6X>E%bO_$?v8@n~ZX4eK6vnB6t-b<~Y1AAf6&lX-nr@*-P zCIJtc0e(_AorhMLgIHe-*kFUC8Ijp!EN)PY->)PTYYI_35ro%_9uCB9oV#0%uVAN;c6}l%=c#Sx8YBz!}Mru-7sJ>trraAfiNTdbCEHh=y z>fQyTGI8hQnv*BY6WKR5>*LLf;yWw4W_)ZC(AM?zD{}uLu;p(hd4iRMwDlE!^!5z* zGgeD#RXq2~vaA@~kd9=VLky&=49(p~fB%z56{CVu)oWPD$!Si_kvjOw);5o>!x;|^Xb@vkVf#)C z8h#PGeO%eY`?s?He`=`{8?{XytfM~SKZ;nt0+6FA$O^>t>-;PB9B7P$1c}so9t}rc zvr9BVH8M+9x=Eg9DXr;@6#n+HwV>cC)9b^TdTolQ{OJ+1$>dXs z-WFWc>>dh|@eybsIO`h(`g@s$EH8UBs{z>lS;!kP%bY|aDeeVYtX|lln1&7$F5eZ( zhFZLfa+v_F^UYN4`CFIx5^6V#Ae>6Z+y#1EbtakKn z2y1yy-Sp@(-5I}ONwSitl zg>l%bhHz@`)t&{4DOhxyAaqLo1{E44>37%V0=|#=WMOs8ta%AK`l0H0z)M%do&njq zd%EmzZ-|*P`Q0Cnch7>``Mu9~Zo2iV8f$4~tYIjWl@Gr~>peX@U@z;nKOXO$yxEc*j9)pm|wsrNIoVBtvoLKVRS?pZs3c2 zck)6oqla0fCsqh;$N9_Q&{qguE#kc{r;49l3;61NP%V7z7IRHRCynG$DdiHCP>V(p z&NwbSt3|0p$H%srvP*GijiJq<<1rS8jM625t8KPywKd>eWCdsoDGWU{pR03HxxG>} zf}prrG-PvzpLI>PBJ}(awcI~sibB+0p908OBWf5j)CD3Am_Hp^wkq%bV)2dN!~|&`!*SSR_?>4X75NYg$eV`ILeL@eK_v* z0uJiq25dvyjT365`UwOF(j|0XN8eqf>%RcS7Fm3!u}^}f16`fOTUETbvGa4qq7Fq{ z$-BW7Tawn{+DupZkP(F}x5@#rNwg6@MKc4n!yMb(F0~&CtMNYR1JPdTmWc=$<}V9M zO;nBMFGfkPQ#q397vsqo*6k<-saWTu#}PF}K}#L!VX_x0u56UqMtQ+bbeLJ=rFZgY zuF;WG^6wi{oP4JYQaFq0r zMKE;V2k6eFs82YmPblsso_8eiPNT0WC3u=u zq0z7r&z@~B5(UjdoRq4;my%L>yocBNrq&#`o|cT=;^x&3PWOx}bR*fc7Iv<3gY#>t zOzUeGgT&X^Rl#EMJlb*cgU~E7$?owz40;US2}tY{__xwspxbS?Pu!;c?SD33&uud^lxs`EkC9`!y!AF z8M201Y#QPf0sUN-=rx6Le(!x!}@Z?2f39}?U%Mg!i(2lC&56nTU zD-LwVQ5|}y(B5;RMOoF4QPM`9+P{6FZ7?qGY*yYs!+5y9$uJU#79K9EH;i5T<94l0 zd(Ok|2#q-7u68h6!^+t_(4>~1`em#9r}2aDJb}8UT1QA9mMSLj`Hox3kdWuUSu5_p zfv>f%*Mc>t0C|1V_yUt4&HJSu?;-nvn9fLllg87y4RB@NT=!@G@w_-qp0;QH2;To) zf=0sKOid{O}gIAOo?`J2@@nYlSn8JX>ry6so9$ zs4NEmBxKLsCksq#j40OL-LP(lT($k;w^jVZd3t@{g$ zSYiO3l(I)QQrp0Cn-s3Y>bZeTp)i0X4Z|j~5W8#vLyK0@;j=mIk366zDx_AcU7Dsc zkn=Kj)q2&fk`6Ym;jMbe8a}G<`Ba%RJcYU8Y^t3JG69xEuKJ=)-lXw}ulas(o=_># zKA`pk;-rRN4_e81ky1h}@UrC3A{*Gv`i! z&=z_!LkD8(YGm#3owY4PNV+s036i1)H4cT`j6D*) zvljOok)%Wl;RkR0Jrbp`DYmqd*YGl6pNZj(aE~SqG!%Y2B^8&AU38S<>vjZBt zGq;Xs?I|iAhgq>)M*68`SHN`q8T*9*q!IJ==)PF_PrmzvZynq^8J87p$EEt ztI;C!O&E@kMje$K{{lmwKy=1&KXtaf6kXN&)`@HK+SDx>!<>AFKdY;!i93iV1S9J^ zk!A2*Wu&myS&naFfOpLleXrnQ;?Y)dGoP)=vi(-T47>f-g#D)2kDvCngWI~ROONS% zlTXKDE-M&2WP;l4_=NWSazhiAl>%WvDZH)b-A0$5VGtFL+N zPrst5+BLLW3KY-q`>7kDuy9YBm+4Jo>@g@p@M#T z{a|ZD`$afhtsO>%BAqb@BMOSWiLc`u+Z^1OOA(7Q-18uqX+z0jzuY&mQFeumk*4O> zsJ*-yNWo-3Baz@~_x#9LV*D6q>yfG2g;J^+9B9gU_P^WNGl0rwX5V-z2&W3ThD*d^ z?ZuN%+n(P}n`RMQfnJf;2Om^fWpLz(EOQ)>GNyS(ln;=Fmu8drqLAUZ$Ylbt>0W9A zv{o8x2m>E^1TlR}@1|9#*TS9>l7!P*+`2CZUWeMPRx?~{5P3_yGHBaOF)4PA^TK-? zzj2d}y=1!xFJvxpw>wlY%xKfR`Nv+_t|4}b8hDjW!K;i0E@T?p7%AG@*g7y7+1P{r za7o~f*?;SoVERSG%7Lkd5pX5BNOCG*7aK&RAw~Ow7U7E!>6efUPMdA6go;kdKivcyj42uw{(>QF-rAH!6HTH0|34g@A8eS&xC(xur#?iHq* znVB0UB(iv}>`gD$U(R;K#Z#2fjL$a)>08d>nwygyDe7vQD=TkDn*`zwF7LqG;`VPh zK)>a7!l>`4cpb9ivtcR3c_iTs7-g3HBFr5gN8P!i3zJ{xjqEu1RRf{k#-l)VktMBK z7k`nL4tm|WIkGN}F=#AnHRbP_6%{s>d^;Yvb^3_0B65m3 zD5>h1%b!GNR-=!(0_4{)ECWUClx8Baj$(WegN#>W?MnY#R-Ym~_6Y{FksMs>LH#Qm z4Qy@yOGYpY|8=CtDk!WoqxK%roe+?&6pCu(yxYVfc?{_$rLFC7v!#p-G&v;-;V=IHs<1h@0euGXSj@Qmw(rdQKVt-3I=orj7T3jMea%qG7cX)t%g~ zP{FGZgvcOKC#ey3tP+yis3R$r-v@1)Xq**K+XKy2Yey#fPQ(9ArzPGw{kEGIiCzDW z486jFXg1C(Y=S5D8pQnVPumx5avhpFwWZb2T&+Ms^;eLAVbu#6!UY>DDxubaCU^`- zPGuW4@8}?r%atq2I?!luxD~HpA0`v^$;`f;55Ot{oA-gb(1CC*cXf;-e~A z=HwLpsk!z=PsHOBZj97`F;1{3_l3O0oz@tPC~Z`vX9sL-fKg8^DEM5Rf#lSs2eSJs z?^=mvwNp1wH9AgyHp~W$@ii^si3iEG#RDFH?Y=E!1QDJ9VbMDzv?0g%ZYX3(r>sOg z9U^-j{}uh4A2)hCPu*wNyBBl4^nznkg;Z=5g6;KQ;N0y$dqQ3Qd&%@*@}h%XDR?^Q zFRs+d!O_O*zx@3l_5uKTF`d@_%!ooqahE7chwMR#ShU%+FY*W}X zwyC;n-cTy`wODZQ#}`S(ASxmF9*}(70ma6al*l+m%aH7pa~NX2(6$v=q~Iqb1K~qa zsL)6I18Ifpen2bwviz&Wx3~XSdb1Tmq3cszmfyW>Ip(ppNz3|-1 z^HS<>E4}EytUNEQJ~!}uGx*zp8163vzqf|Zq0iIf-%u-pKcUZ)<>waup8Ea90{~Nm z0Kk7Fg3sZ9kJW#L8<6}3{;$aW9Q}7^`ByX{`CrgR|8|{