storage.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import numpy as np
  2. import numba
  3. from typing import Tuple
  4. @numba.njit
  5. def storage_iterate(dE, capacity, efficiency, n):
  6. storage = np.zeros(n)
  7. for i in np.arange(1, n):
  8. if dE[i] >= 0:
  9. dE[i] *= efficiency
  10. storage[i] = np.maximum(0, np.minimum(capacity, storage[i-1]+dE[i-1]))
  11. return storage
  12. class StorageModel:
  13. def __int__(self):
  14. pass
  15. class MultiStorageModel(StorageModel):
  16. def __init__(self,
  17. storage_capacities: np.ndarray,
  18. storage_max_loads=np.ndarray,
  19. storage_max_deliveries=np.ndarray,
  20. storage_efficiencies=np.ndarray
  21. ):
  22. self.storage_max_loads = np.array(storage_max_loads)
  23. self.storage_max_deliveries = np.array(storage_max_deliveries)
  24. self.storage_capacities = np.array(storage_capacities)*self.storage_max_loads
  25. self.storage_efficiencies = np.array(storage_efficiencies)
  26. self.n_storages = len(self.storage_capacities)
  27. assert len(storage_max_loads) == self.n_storages
  28. assert len(storage_max_deliveries) == self.n_storages
  29. assert len(storage_efficiencies) == self.n_storages
  30. def run(self, power_delta: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
  31. T = len(power_delta)
  32. available_power = power_delta
  33. excess_power = np.maximum(0, available_power)
  34. deficit_power = np.maximum(0, -available_power)
  35. storage_try_load = np.zeros((self.n_storages, T))
  36. storage_try_delivery = np.zeros((self.n_storages, T))
  37. storage = np.zeros((self.n_storages, T))
  38. storage_impact = np.zeros((self.n_storages, T))
  39. dE_storage = np.zeros((self.n_storages, T))
  40. for i in range(self.n_storages):
  41. storage_try_load[i] = np.minimum(excess_power, self.storage_max_loads[i])
  42. storage_try_delivery[i] = np.minimum(deficit_power, self.storage_max_deliveries[i])
  43. dE_storage[i] = storage_try_load[i]-storage_try_delivery[i]
  44. storage[i] = storage_iterate(
  45. dE_storage[i], self.storage_capacities[i], self.storage_efficiencies[i], T
  46. )
  47. # impact of storage on the available power
  48. storage_impact[i] = -np.diff(storage[i], append=0)
  49. storage_impact[i] = np.multiply(
  50. storage_impact[i],
  51. np.where(storage_impact[i] < 0, 1/self.storage_efficiencies[i], 1)
  52. )
  53. available_power += storage_impact[i]
  54. excess_power = np.maximum(0, available_power)
  55. deficit_power = np.maximum(0, -available_power)
  56. return storage, storage_impact