#!/usr/bin/env python # coding: utf-8 # # Interoperation with ANDES # One of the most interesting feature of AMS is its interoperation with dynamic simulator ANDES. # # Interoperation includes compatible case conversion and data exchange, thus it facilitates dispatch-dynamic co-simulation using AMS and ANDES. # In[1]: import numpy as np import andes import ams import datetime # In[2]: print("Last run time:", datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")) print(f'andes:{andes.__version__}') print(f'ams:{ams.__version__}') # In[3]: ams.config_logger(stream_level=20) # ## Dispatch # In[4]: sp = ams.load(ams.get_case('ieee14/ieee14_uced.xlsx'), setup=True, no_output=True,) # In[5]: sp.RTED.init() # In[6]: sp.RTED.run(solver='CLARABEL') # ## Convert to ANDES # The built-in ANDES interface can convert an AMS case to ANDES case in memory. # # The bridge between AMS and converted ANDES is the shared power flow devices, Bus, PQ, PV, Slack, Line, and Shunt. # In[7]: sa = sp.to_andes(setup=True, addfile=andes.get_case('ieee14/ieee14_full.xlsx')) # If you wish to add devices to the converted ANDES system, set `setup=False` to skip the ANDES setup process. # # As indicated by the output information, in the conversion process, ANDES power flow devices will be overwritten by AMS ones, if exists. # # Upon a successful conversion, you are ready to enjoy full capability of ANDES. # ``help`` command can give a quick reference. # In[8]: help(sp.to_andes) # ## Interoperation with ANDES # In the interface class ``dyn``, the link table is stored in ``dyn.link``. # # It describes the mapping relationships between power flow devices and dynamic devices. # In[9]: sp.dyn.link # ### Send # As there is a gap between DC-based dispatch and AC-based TDS, a conversion is required to ensure the TDS initialization. # In[10]: sp.RTED.dc2ac() # In the RTED routine, there are two mapping dictionaries to define the data exchange, namely, `map1` for receiving data from ANDES and `map2` for sending data to ANDES. # In[11]: sp.RTED.map2 # In[12]: sp.dyn.send(adsys=sa, routine='RTED') # ### Run ANDES # Sometimes, the ANDES TDS initialization may fail due to inapproriate limits. # # Here, we alleviate the `TGOV1` limit issue by enlarging the `Pmax` and `Pmin` to the same value. # In[13]: sa.TGOV1.alter(src='VMAX', idx=sa.TGOV1.idx.v, value=100*np.ones(sa.TGOV1.n)) sa.TGOV1.alter(src='VMIN', idx=sa.TGOV1.idx.v, value=np.zeros(sa.TGOV1.n)) # Run power flow. # In[14]: sa.PFlow.run() # Try to init TDS. # In[15]: _ = sa.TDS.init() # Run TDS. # In[16]: sa.TDS.config.no_tqdm = True # disable progress bar sa.TDS.run() # ### Receive # In[17]: sp.RTED.map1 # In[18]: sp.dyn.receive(adsys=sa, routine='RTED') # The RTED parameter ``pg0``, is retrieved from ANDES as the corresponding generator output power. # In[19]: sp.RTED.pg0.v