Skip to content

Commit

Permalink
Merge pull request #17 from openEDI/gadal_integration
Browse files Browse the repository at this point in the history
Gadal integration
  • Loading branch information
tarekelgindy authored Sep 13, 2022
2 parents 4217c4a + 9e35274 commit 0f7a53b
Show file tree
Hide file tree
Showing 68 changed files with 592 additions and 1,052,243 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/test-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ jobs:

steps:
- uses: actions/checkout@v2
with:
submodules: true
token: ${{ secrets.CI_TOKEN }}
- name: Set up Python ${{ matrix.python-version }}
uses: conda-incubator/setup-miniconda@v2
with:
Expand All @@ -33,7 +36,7 @@ jobs:
pip install boto3
eval `ssh-agent -s`
ssh-add - <<< '${{ secrets.SGIDAL_CLONE_KEY }}'
pip install git+ssh://[email protected]/openEDI/GADAL.git@b1dbcd003dd870ac201d686edea870a2e548e9b8
pip install git+ssh://[email protected]/openEDI/GADAL.git@v0.2.1
- name: Run example
shell: bash -l {0}
run: |
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "LocalFeeder/gadal-ieee123"]
path = LocalFeeder/gadal-ieee123
url = ../gadal-ieee123.git
7 changes: 4 additions & 3 deletions AWSFeeder/FeederSimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ class FeederConfig(BaseModel):
smartds_scenario: str
smartds_year: str
start_date: str
end_date: str
increment_value: int # increment in seconds
number_of_timesteps: int


class FeederSimulator(object):
Expand All @@ -71,7 +71,8 @@ def __init__(self, config):
self._smartds_scenario = config.smartds_scenario
self._smartds_year = config.smartds_year
self._start_date = config.start_date
self._end_date = config.end_date
self._number_of_timesteps = config.number_of_timesteps
self._increment_value = config.increment_value

self._feeder_file = None
self._circuit=None
Expand Down Expand Up @@ -225,7 +226,7 @@ def get_vnom(self):
for voltage_name in Vnom_dict.keys():
Vnom[self._name_index_dict[voltage_name]] = Vnom_dict[voltage_name]
# Vnom(1: 3) = [];
print(Vnom[self._source_indexes[0]:self._source_indexes[-1]])
logger.debug(Vnom[self._source_indexes[0]:self._source_indexes[-1]])
Vnom = np.concatenate((Vnom[:self._source_indexes[0]], Vnom[self._source_indexes[-1] + 1:]))
Vnom = np.abs(Vnom)
return Vnom
Expand Down
23 changes: 13 additions & 10 deletions AWSFeeder/component_definition.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@
"directory": "AWSFeeder",
"execute_function": "python sender_cosim.py",
"static_inputs": [
{"type": "", "port_id": "feeder_file"},
{"type": "", "port_id": "load_file"},
{"type": "", "port_id": "pv_file"},
{"type": "", "port_id": "name"},
{"type": "", "port_id": "smartds_region"},
{"type": "", "port_id": "smartds_feeder"},
{"type": "", "port_id": "smartds_scenario"},
{"type": "", "port_id": "smartds_year"},
{"type": "", "port_id": "start_date"},
{"type": "", "port_id": "run_freq_sec"},
{"type": "", "port_id": "start_time_index"}
{"type": "", "port_id": "increment_value"},
{"type": "", "port_id": "number_of_timesteps"}
],
"dynamic_inputs": [],
"dynamic_outputs": [
{"type": "", "port_id": "voltages_real"},
{"type": "", "port_id": "voltages_imag"},
{"type": "", "port_id": "powers_real"},
{"type": "", "port_id": "powers_imag"},
{"type": "", "port_id": "topology"}
{"type": "VoltagesMagnitude", "port_id": "voltages_magnitude"},
{"type": "VoltagesReal", "port_id": "voltages_real"},
{"type": "VoltagesImaginary", "port_id": "voltages_imag"},
{"type": "PowersReal", "port_id": "powers_real"},
{"type": "PowersImaginary", "port_id": "powers_imag"},
{"type": "Topology", "port_id": "topology"}
]
}
8 changes: 4 additions & 4 deletions AWSFeeder/dss_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@ def get_vnom2(dss):
test_Vnom2_dict = {AllNodeNames[ii].upper(): test_Vnom2[ii] for ii in range(len(test_Vnom2))}

test_vmag_volts_result = np.allclose(vmags, np.abs(test_Vnom2))
print('test_vmag_volts_result', test_vmag_volts_result)
logger.debug('test_vmag_volts_result', test_vmag_volts_result)

AllNodeNamesY = circuit.YNodeOrder()
yv = circuit.YNodeVArray()
test_yv = np.array([complex(yv[i], yv[i + 1]) for i in range(0, len(yv), 2)])
test_yv_dict = {AllNodeNamesY[ii]: test_yv[ii] for ii in range(len(test_yv))}
test_yv_result = np.allclose(vmags, np.abs(test_yv))
print('test_yv_result', test_yv_result)
logger.debug('test_yv_result', test_yv_result)

print('Test dictionary')
logger.debug('Test dictionary')
for i in test_yv_dict.keys():
if abs(abs(test_Vnom2_dict[i]) - abs(test_yv_dict[i])) > .0001:
print(i, abs(test_Vnom2_dict[i]), abs(test_yv_dict[i]))
logger.debug(i, abs(test_Vnom2_dict[i]), abs(test_yv_dict[i]))
# for t1, t2 in zip(np.abs(test_Vnom2), np.abs(test_yv)):
# np.testing.assert_array_almost_equal(np.abs(test_Vnom2), np.abs(test_yv),decimal=5)

Expand Down
103 changes: 61 additions & 42 deletions AWSFeeder/sender_cosim.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,22 @@
from dss_functions import snapshot_run
from FeederSimulator import FeederSimulator, FeederConfig
from pydantic import BaseModel
from typing import List
from typing import List, Tuple
import numpy as np
from datetime import datetime, timedelta
from gadal.gadal_types.data_types import Complex,Topology,VoltagesReal,VoltagesImaginary,PowersReal,PowersImaginary, AdmittanceMatrix, VoltagesMagnitude, VoltagesAngle

logger = logging.getLogger(__name__)
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.INFO)
#logger.setLevel(logging.DEBUG)

test_se = False

class Complex(BaseModel):
real: float
imag: float


class Topology(BaseModel):
y_matrix: List[List[Complex]]
phases: List[float]
base_voltages: List[float]
slack_bus: List[str]
unique_ids: List[str]


class LabelledArray(BaseModel):
array: List[float]
unique_ids: List[str]


def make_labelled_array(array, binary_mask):
(integer_ids,) = np.nonzero(binary_mask)
return LabelledArray(
array=list(array[integer_ids]), unique_ids=list(map(str, integer_ids))
)


def numpy_to_y_matrix(array):
return [
[Complex(real=element.real, imag=element.imag) for element in row]
[(element.real, element.imag) for element in row]
for row in array
]

Expand Down Expand Up @@ -71,22 +50,23 @@ def get_true_phases(angle):
elif np.abs(angle-(-3*np.pi/3))<0.2:
return -3*np.pi/3
else:
print("error")
logger.debug("error")


def go_cosim(sim, config: FeederConfig):

deltat = 0.01
fedinitstring = "--federates=1"

print("Creating Federate Info")
logger.info("Creating Federate Info")
fedinfo = h.helicsCreateFederateInfo()
h.helicsFederateInfoSetCoreName(fedinfo, config.name)
h.helicsFederateInfoSetCoreTypeFromString(fedinfo, "zmq")
h.helicsFederateInfoSetCoreInitString(fedinfo, fedinitstring)
h.helicsFederateInfoSetTimeProperty(fedinfo, h.helics_property_time_delta, deltat)
vfed = h.helicsCreateValueFederate(config.name, fedinfo)

pub_voltages_magnitude = h.helicsFederateRegisterPublication(vfed, "voltages_magnitude", h.HELICS_DATA_TYPE_STRING, "")
pub_voltages_real = h.helicsFederateRegisterPublication(vfed, "voltages_real", h.HELICS_DATA_TYPE_STRING, "")
pub_voltages_imag = h.helicsFederateRegisterPublication(vfed, "voltages_imag", h.HELICS_DATA_TYPE_STRING, "")
pub_powers_real = h.helicsFederateRegisterPublication(vfed, "powers_real", h.HELICS_DATA_TYPE_STRING, "")
Expand Down Expand Up @@ -120,14 +100,43 @@ def get_phase(name):
]

unique_ids = sim._AllNodeNames

logger.debug("y-matrix")
logger.debug(y_matrix)
logger.debug("phases")
logger.debug(phases)
logger.debug("base_voltages")
logger.debug(base_voltages)
logger.debug("slack_bus")
logger.debug(slack_bus)
logger.debug("unique_ids")
logger.debug(unique_ids)


admittancematrix = AdmittanceMatrix(
admittance_matrix = y_matrix,
ids = unique_ids
)

base_voltagemagnitude = VoltagesMagnitude(
values = [abs(i) for i in base_voltages],
ids = unique_ids
)

base_voltageangle = VoltagesAngle(
values = phases,
ids = unique_ids
)

topology = Topology(
y_matrix=y_matrix,
phases=phases,
base_voltages=base_voltages,
admittance=admittancematrix,
base_voltage_angles=base_voltageangle,
injections={},
base_voltage_magnitudes=base_voltagemagnitude,
slack_bus=slack_bus,
unique_ids=unique_ids
)


logger.info("Sending topology and saving to topology.json")
pub_topology.publish(topology.json())
with open("topology.json", "w") as f:
Expand All @@ -139,10 +148,12 @@ def get_phase(name):
current_index = 0
current_hour = 0
current_second = 0
for request_time in range(0, 100):
for request_time in range(0, config.number_of_timesteps):
while granted_time < request_time:
granted_time = h.helicsFederateRequestTime(vfed, request_time)
logger.info('start time: '+str(datetime.now()))
current_index+=1
current_timestamp = datetime.strptime(sim._start_date, '%Y-%m-%d %H:%M:%S') + timedelta(minutes = current_index*15)
current_second+=15*60
if current_second >=60*60:
current_second = 0
Expand Down Expand Up @@ -174,20 +185,27 @@ def get_phase(name):


phases = list(map(get_true_phases, np.angle(feeder_voltages)))
base_voltageangle = VoltagesAngle(
values = phases,
ids = unique_ids
)
topology = Topology(
y_matrix=y_matrix,
phases=phases,
base_voltages=base_voltages,
admittance=admittancematrix,
base_voltage_angles=base_voltageangle,
injections={},
base_voltage_magnitudes=base_voltagemagnitude,
slack_bus=slack_bus,
unique_ids=unique_ids
)
pub_topology.publish(topology.json())

print('Publish load ' + str(feeder_voltages.real[0]))
pub_voltages_real.publish(LabelledArray(array=list(feeder_voltages.real), unique_ids=sim._AllNodeNames).json())
pub_voltages_imag.publish(LabelledArray(array=list(feeder_voltages.imag), unique_ids=sim._AllNodeNames).json())
pub_powers_real.publish(LabelledArray(array=list(PQ_node.real), unique_ids=sim._AllNodeNames).json())
pub_powers_imag.publish(LabelledArray(array=list(PQ_node.imag), unique_ids=sim._AllNodeNames).json())
logger.info('Publish load ' + str(feeder_voltages.real[0]))
voltage_magnitudes = np.abs(feeder_voltages.real + 1j* feeder_voltages.imag)
pub_voltages_magnitude.publish(VoltagesMagnitude(values=list(voltage_magnitudes), ids=sim._AllNodeNames, time = current_timestamp).json())
pub_voltages_real.publish(VoltagesReal(values=list(feeder_voltages.real), ids=sim._AllNodeNames, time = current_timestamp).json())
pub_voltages_imag.publish(VoltagesImaginary(values=list(feeder_voltages.imag), ids=sim._AllNodeNames, time = current_timestamp).json())
pub_powers_real.publish(PowersReal(values=list(PQ_node.real), ids=sim._AllNodeNames, time = current_timestamp).json())
pub_powers_imag.publish(PowersImaginary(values=list(PQ_node.imag), ids=sim._AllNodeNames, time = current_timestamp).json())
logger.info('end time: '+str(datetime.now()))


h.helicsFederateDisconnect(vfed)
Expand All @@ -202,6 +220,7 @@ class FeederCosimConfig(BaseModel):
def run():
with open('static_inputs.json') as f:
parameters = json.load(f)

config = FeederConfig(**parameters)
sim = setup_sim(config)
go_cosim(sim, config)
Expand Down
Loading

0 comments on commit 0f7a53b

Please sign in to comment.