test_utils.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #******************************************************************************
  2. #******************************************************************************
  3. # import libraries
  4. import math
  5. from src import pysoleng as pse
  6. # test using "!python -m pytest -s --cov --cov-report term-missing"
  7. #******************************************************************************
  8. #******************************************************************************
  9. def tests():
  10. example_jrc_tmy()
  11. example_jrc_tmy(assume_year=2012)
  12. #******************************************************************************
  13. #******************************************************************************
  14. def example_jrc_tmy(assume_year: int = None):
  15. filename = 'tests/TMY/tmy_54.027_9.803_2005_2020.csv'
  16. (npdata,
  17. names,
  18. latitude,
  19. longitude,
  20. elevation) = pse.utils.read_jrc_tmy_csv(
  21. filename=filename,
  22. assume_year=assume_year
  23. )
  24. # try to use the data
  25. site = pse.timeplace.Location(
  26. coordinates=(latitude, longitude),
  27. crs_string='epsg:4326'
  28. )
  29. #**************************************************************************
  30. #**************************************************************************
  31. # tracking surface
  32. site_ground_reflectance = 0.6
  33. list_I_tilted_total = []
  34. list_I_tilted_beam = []
  35. list_I_tilted_sky_diffuse = []
  36. list_I_tilted_albedo = []
  37. for i, local_time in enumerate(npdata['timeUTC']):
  38. site_horizontal_total = npdata['Gh'][i]
  39. site_horizontal_diffuse = npdata['Gdh'][i]
  40. # find solar altitude and solar azimuth
  41. day_year = pse.solar.day_of_the_year(local_time, False)
  42. declination_angle = pse.solar.declination_angle_spencer1971(day_year)
  43. ast = pse.solar.lst_to_ast(local_time, site)
  44. solar_ha = pse.solar.hour_angle(ast)
  45. cos_zen_angle = pse.solar.cosine_zenith_angle(
  46. latitude*math.pi/180,
  47. declination_angle*math.pi/180,
  48. solar_ha)
  49. solar_az = pse.solar.solar_azimuth_angle(latitude*math.pi/180,
  50. declination_angle*math.pi/180,
  51. math.acos(cos_zen_angle),
  52. solar_ha)
  53. solar_alt = pse.solar.solar_altitude_angle(latitude*math.pi/180,
  54. declination_angle*math.pi/180,
  55. solar_ha)
  56. # define the new surface
  57. surface = pse.timeplace.FlatSurface(
  58. azimuth=solar_az,
  59. slope=math.pi/2-solar_alt
  60. )
  61. # compute the radiation on the tilted plane
  62. (I_tilted_total,
  63. I_tilted_beam,
  64. I_tilted_sky_diffuse,
  65. I_tilted_albedo) = pse.models.tilted_plane_irradiance_isotropic(
  66. site,
  67. surface.slope,
  68. surface.azimuth,
  69. local_time,
  70. site_ground_reflectance,
  71. site_horizontal_total,
  72. site_horizontal_diffuse)
  73. list_I_tilted_total.append(I_tilted_total)
  74. list_I_tilted_beam.append(I_tilted_beam)
  75. list_I_tilted_sky_diffuse.append(I_tilted_sky_diffuse)
  76. list_I_tilted_albedo.append(I_tilted_albedo)
  77. # compare the results
  78. dni_pysoleng = sum(list_I_tilted_beam)*3600*2.7777778E-07
  79. dni_jrcpvgis = sum(npdata['Gbn'])*3600*2.7777778E-07
  80. # print('Results for DNI:')
  81. # print('pysoleng (isotropic): '+str(dni_pysoleng)+' kWh/m2/y')
  82. # print('jrc-pvgis (?): '+str(dni_jrcpvgis)+' kWh/m2/y')
  83. # print('The error between them amounts to ' +
  84. # str(abs(dni_pysoleng-dni_jrcpvgis))+' kWh/m2/y.')
  85. assert math.isclose(dni_pysoleng,
  86. dni_jrcpvgis,
  87. abs_tol=30)
  88. #**************************************************************************
  89. #**************************************************************************
  90. # fixed plane
  91. surface = pse.timeplace.FlatSurface(
  92. azimuth=0*math.pi/180,
  93. slope=45*math.pi/180
  94. )
  95. site_ground_reflectance = 0.6
  96. list_I_tilted_total = []
  97. list_I_tilted_beam = []
  98. list_I_tilted_sky_diffuse = []
  99. list_I_tilted_albedo = []
  100. for i, local_time in enumerate(npdata['timeUTC']):
  101. site_horizontal_total = npdata['Gh'][i]
  102. site_horizontal_diffuse = npdata['Gdh'][i]
  103. #local_time = datetime.fromisoformat(time_interval)
  104. (I_tilted_total,
  105. I_tilted_beam,
  106. I_tilted_sky_diffuse,
  107. I_tilted_albedo) = pse.models.tilted_plane_irradiance_isotropic(
  108. site,
  109. surface.slope,
  110. surface.azimuth,
  111. local_time,
  112. site_ground_reflectance,
  113. site_horizontal_total,
  114. site_horizontal_diffuse)
  115. list_I_tilted_total.append(I_tilted_total)
  116. list_I_tilted_beam.append(I_tilted_beam)
  117. list_I_tilted_sky_diffuse.append(I_tilted_sky_diffuse)
  118. list_I_tilted_albedo.append(I_tilted_albedo)
  119. # sum the components
  120. true_I_tilted_total = 1136.397502028676
  121. abs_tol = 10
  122. assert math.isclose(sum(list_I_tilted_total)*3600*2.7777778E-07,
  123. true_I_tilted_total,
  124. abs_tol=abs_tol)
  125. #**************************************************************************
  126. #**************************************************************************
  127. #******************************************************************************
  128. #******************************************************************************
  129. # def test_read_tmy():
  130. # filename = 'tests/TMY/tmy_54.027_9.803_2005_2020.csv'
  131. # (npdata,
  132. # names,
  133. # latitude,
  134. # longitude,
  135. # elevation) = pse.utils.read_jrc_tmy_csv(
  136. # filename=filename)
  137. # # try to use the data
  138. # site = pse.timeplace.Location(
  139. # coordinates=(latitude, longitude),
  140. # crs_string='epsg:4326')
  141. # surface = pse.timeplace.Plane(
  142. # azimuth_zero_south_positive_west=0*math.pi/180,
  143. # slope_zero_horizontal_positive_south=45*math.pi/180)
  144. # site_ground_reflectance = 0.6
  145. # list_I_tilted_total = []
  146. # list_I_tilted_beam = []
  147. # list_I_tilted_sky_diffuse = []
  148. # list_I_tilted_albedo = []
  149. # for i, local_time in enumerate(npdata['timeUTC']):
  150. # site_horizontal_total = npdata['Gh'][i]
  151. # site_horizontal_diffuse = npdata['Gdh'][i]
  152. # #local_time = datetime.fromisoformat(time_interval)
  153. # (I_tilted_total,
  154. # I_tilted_beam,
  155. # I_tilted_sky_diffuse,
  156. # I_tilted_albedo) = pse.models.tilted_plane_irradiance_isotropic(
  157. # site,
  158. # surface,
  159. # local_time,
  160. # site_ground_reflectance,
  161. # site_horizontal_total,
  162. # site_horizontal_diffuse)
  163. # list_I_tilted_total.append(I_tilted_total)
  164. # list_I_tilted_beam.append(I_tilted_beam)
  165. # list_I_tilted_sky_diffuse.append(I_tilted_sky_diffuse)
  166. # list_I_tilted_albedo.append(I_tilted_albedo)
  167. # # sum the components
  168. # true_I_tilted_total = 1136.397502028676
  169. # abs_tol = 10
  170. # assert math.isclose(sum(list_I_tilted_total)*3600*2.7777778E-07,
  171. # true_I_tilted_total,
  172. # abs_tol=abs_tol)
  173. #******************************************************************************
  174. #******************************************************************************
  175. # def test_read_tmy_year_set():
  176. # filename = 'tests/TMY/tmy_54.027_9.803_2005_2020.csv'
  177. # sample_year = 2012
  178. # (npdata,
  179. # names,
  180. # latitude,
  181. # longitude,
  182. # elevation) = pse.utils.read_jrc_tmy_csv(
  183. # filename=filename,
  184. # assume_year=sample_year)
  185. # # try to use the data
  186. # site = pse.timeplace.Location(
  187. # coordinates=(latitude, longitude),
  188. # crs_string='epsg:4326')
  189. # surface = pse.timeplace.Plane(
  190. # azimuth_zero_south_positive_west=0*math.pi/180,
  191. # slope_zero_horizontal_positive_south=45*math.pi/180)
  192. # site_ground_reflectance = 0.6
  193. # list_I_tilted_total = []
  194. # list_I_tilted_beam = []
  195. # list_I_tilted_sky_diffuse = []
  196. # list_I_tilted_albedo = []
  197. # for i, local_time in enumerate(npdata['timeUTC']):
  198. # site_horizontal_total = npdata['Gh'][i]
  199. # site_horizontal_diffuse = npdata['Gdh'][i]
  200. # #local_time = datetime.fromisoformat(time_interval)
  201. # (I_tilted_total,
  202. # I_tilted_beam,
  203. # I_tilted_sky_diffuse,
  204. # I_tilted_albedo) = pse.models.tilted_plane_irradiance_isotropic(
  205. # site,
  206. # surface,
  207. # local_time,
  208. # site_ground_reflectance,
  209. # site_horizontal_total,
  210. # site_horizontal_diffuse)
  211. # list_I_tilted_total.append(I_tilted_total)
  212. # list_I_tilted_beam.append(I_tilted_beam)
  213. # list_I_tilted_sky_diffuse.append(I_tilted_sky_diffuse)
  214. # list_I_tilted_albedo.append(I_tilted_albedo)
  215. # # sum the components
  216. # true_I_tilted_total = 1136.397502028676
  217. # abs_tol = 10
  218. # assert math.isclose(sum(list_I_tilted_total)*3600*2.7777778E-07,
  219. # true_I_tilted_total,
  220. # abs_tol=abs_tol)
  221. #******************************************************************************
  222. #******************************************************************************
  223. def test_angle_format_conversion():
  224. format_table = {
  225. 0: (True, True),
  226. 1: (True, False),
  227. 2: (False, True),
  228. 3: (False, False)
  229. }
  230. truth_table = {
  231. 0: [0, 45, 90, 135, 180, 225, 270, 315, 360],
  232. 1: [360, 315, 270, 225, 180, 135, 90, 45, 0],
  233. 2: [0, 45, 90, 135, 180, -135, -90, -45, 0],
  234. 3: [0, -45, -90, -135, 180, 135, 90, 45, 0]
  235. }
  236. number_points = len(truth_table[0])
  237. for key in truth_table:
  238. assert len(truth_table[key]) == number_points
  239. # for each format
  240. for in_key, in_value in format_table.items():
  241. # for every other format
  242. for out_key, out_value in format_table.items():
  243. if out_key == in_key:
  244. continue
  245. # for each angle
  246. for point_index in range(number_points):
  247. # convert from the first into the second formats
  248. angle_degrees = truth_table[in_key][point_index]
  249. new_angle_degrees = pse.utils.convert_angle(
  250. angle_degrees,
  251. in_angle_positive_only=in_value[0],
  252. in_angle_positive_anticlockwise=in_value[1],
  253. out_angle_positive_only=out_value[0],
  254. out_angle_positive_anticlockwise=out_value[1]
  255. )
  256. # assert that it adds up
  257. assert math.isclose(
  258. math.cos(math.radians(new_angle_degrees)),
  259. math.cos(math.radians(truth_table[out_key][point_index]))
  260. )
  261. assert math.isclose(
  262. pse.utils.simplify_angle(
  263. new_angle_degrees,
  264. True),
  265. pse.utils.simplify_angle(
  266. truth_table[out_key][point_index],
  267. True)
  268. )
  269. #******************************************************************************
  270. #******************************************************************************
  271. def test_angle_conversion_errors():
  272. # test negative angle
  273. try:
  274. _ = pse.utils.convert_angle(
  275. -45,
  276. in_angle_positive_only=True,
  277. in_angle_positive_anticlockwise=True,
  278. out_angle_positive_only=False,
  279. out_angle_positive_anticlockwise=False
  280. )
  281. except pse.utils.AngleFormatError:
  282. assert True
  283. # test wider than 180 angle
  284. try:
  285. _ = pse.utils.convert_angle(
  286. 270,
  287. in_angle_positive_only=False,
  288. in_angle_positive_anticlockwise=True,
  289. out_angle_positive_only=False,
  290. out_angle_positive_anticlockwise=False
  291. )
  292. except pse.utils.AngleFormatError:
  293. assert True
  294. #******************************************************************************
  295. #******************************************************************************
  296. def test_angle_simplification():
  297. tests = [
  298. # degrees
  299. (90+360, True, 90),
  300. (3*360, True, 0),
  301. (270+360, True, 270),
  302. (-90+360, True, 270),
  303. (-3*360, True, 0),
  304. (-270+360, True, 90),
  305. # radians
  306. (math.pi/2+2*math.pi, False, math.pi/2),
  307. (3*2*math.pi, False, 0),
  308. (math.pi*3/2+2*math.pi, False, math.pi*3/2),
  309. (-math.pi/2+2*math.pi, False, math.pi*3/2),
  310. (-3*2*math.pi, False, 0),
  311. (-math.pi*3/2+2*math.pi, False, math.pi/2),
  312. ]
  313. for test in tests:
  314. new_angle = pse.utils.simplify_angle(
  315. test[0],
  316. test[1])
  317. assert math.isclose(new_angle, test[2])
  318. #******************************************************************************
  319. #******************************************************************************