Setup in the External Application
EmtdcCosimulation_Channel (Structure)
A general Application Programming Interface (API) is available, enabling PSCAD/EMTDC to link to, and co-simulate with, just about any external application. Referred to as the Co-Simulation API, it is in it’s basic form, a C-language structure called EmtdcCosimulation_Channel, which houses a collection C-language functions. These functions can be used to customize an interface on the external application side. At the same time, a new master library component called the Co-Simulation Component, is utilized as the interface on the PSCAD/EMTDC-side. The Communication Fabric (ComFab) is utilized to provide the inter-application communications control architecture.

Note that the onus remains on the user to program the interface from the external application side, as all external applications differ in complexity and purpose. A complete description of the Co-Simulation API is provided in the following sections.
The values that are exchanged between PSCAD/EMTDC and the external application must be expressed as a 64-bit, floating point values.
PSCAD/EMTDC simulations are performed in the time domain, thus any data provided by an external application for co-simulation purposes, must also be able to provide time domain values (i.e. data that is associated with a time).
In order to prevent the possibility of deadlocking both PSCAD/EMTDC and the external application must provide default values, prior to any data exchanged. See the Co-Simulation Component for more.
On the PSCAD/EMTDC side, connection to the Co-Simulation API is accomplished via the Co-Simulation Component.

Example Co-Simulation Setup In PSCAD
The co-simulation component is configured to accept and provide data to the PSCAD/EMTDC simulation, as well as to provide data required by the external application.
The external application co-simulating with PSCAD/EMTDC, must setup to utilize the open source, EmtdcCosimulation_Channel interface.
To initialize the co-simulation, the external application must first call the EmtdcCosimulation_InitializeCoSimulation function, provided as part of the EmtdcCosimulation_Channel interface.
For the external application to exchange data it must use a channel provided by the EmtdcCosimulation_Channel interface. After EmtdcCosimulation_InitializeCoSimulation is called, the channel is created and configured for use. In order to retrieve the channel, call EmtdcCosimulation_FindChannel.
Once the external application has retrieved the channel, it may receive the corresponding data by using the GetValue function provided.
The external application may send data using the channel by setting each of data point via calling SetValue. After each data point is set then call Send.
When the simulation is complete, call the EmtdcCosimulation_FinalizeCosimulation function. This will ensure all memory and resources are cleaned up and that PSCAD is informed that the co-simulation is complete.
This c-language structure is open source, and may also be referred to as the Co-Simulation API. Below are descriptions of all methods and functions used.
The following methods may be utilized as needed.
(
EmtdcCosimulation_Channel* _this
, double val
, int index
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
| val | double | The value that was sent from the other application at the other end of this channel. | 
| index | int | The index location of the value being requested. | 
Return Value:
| Type | Description | 
| double | The value at the specified index for the valid time value on this channel. | 
Remarks:
This function will find the correct value and return it in as efficient time as possible. During its execution it may be reading other channel information from the same client or other time values. These values will be cached or discarded depending on the status of the channel that received the information.
The time value for the channel MUST increase over time and never decrease. For example if the previous call on this channel had a time value of 0.002 then the next call must be this value or higher. Values are discarded after they are no longer in the valid time cycle.
Each channel is independent in its cached values and time domain use when retrieving values.
The time step does not need to be synchronized with the other end of the channel in the co-simulation, and the valid value will be used for the time provided, independently of the time step of either application.
It is recommended that you do not read values at the 0 time, and to start with an initial condition rather than reading from the channel this is to prevent the possibility of dead-locking. Both application should start with initial conditions and run their first time step independently.
The maximum size of the index is one less than value returned from GetRecvSize().
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); double time = 0.000; double time_step = 0.001; 
 while (time < 1 ) { double val1 = 0; double val2 = 0; if ( time > 0 ) { channel->GetValue(channel, time, 0); channel->GetValue(channel, time, 1); } // Perform Computations . . . // Increment the time step time += time_step; } | 
(
EmtdcCosimulation_Channel* _this
, double value
, int index
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
| value | double | The value that is to be sent to the other application at the other end of this channel. | 
| index | int | The index location of the value to be sent. | 
Return Value:
None.
Remarks:
This function sets values in a cache to be sent when a call to Send() is made. This function does not send the value explicitly.
The maximum index value is one less than the return value from GetSendSize().
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); double time = 0.000; double time_step = 0.001; 
 while (time < 1 ) { // Perform Computations . . . // Set the value to be sent channel->SetValue(channel, val1, 0); channel->SetValue(channel, val2, 1); 
 // Send the cached values, they are valid until the next time step is complete channel->Send(time + time_step); 
 // Increment the time step time += time_step; } | 
(
EmtdcCosimulation_Channel* _this
double time
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
| time | double | The time value for the values sent will be valid until. | 
Return Value:
None.
Remarks:
Values are sent with this call, use SetValue() to set the values that will be sent (any unset value are defaulted to 0).
It is assumed that value validity does not overlap between messages. If the previous send was 0.001 then this send will not be valid until the 0.001 has passed, then it will be valid until whatever time was passed.
Each channel is independent in terms of valid time sent.
Good practice is to always send first then receive that value required for the next time-step.
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); double time = 0.000; double time_step = 0.001; 
 while (time < 1 ) { // Perform Computations . . . // Set the value to be sent channel->SetValue(channel, val1, 0); channel->SetValue(channel, val2, 1); 
 // Send the cached values, they are valid until the next time step is complete channel->Send(time + time_step); 
 // Increment the time step time += time_step; } | 
unsigned int GetChannelId
(
EmtdcCosimulation_Channel* _this
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
Return Value:
| Type | Description | 
| unsigned int | The channel ID. | 
Remarks:
This value will not change for the duration of the channel life.
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); 
 // Ensure channel id is as expected ASSERT(channel->GetChannelId(channel) == 10); | 
(
EmtdcCosimulation_Channel* _this
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
Return Value:
| Type | Description | 
| int | The amount of double that will be sent with each send call. | 
Remarks:
This value will not change for the duration of the channel life.
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); 
 // Ensure this channel can send the required amount of data ASSERT(channel->GetSendSize(channel) == 2); | 
(
EmtdcCosimulation_Channel* _this
)
Parameters:
| Name | Type | Description | 
| _this | (EmtdcCosimulation_Channel*) | A pointer to the structure being operated on. This parameter should always be the content from which it is called. | 
Return Value:
| Type | Description | 
| int | The amount of double that will be received in a given message. | 
Remarks:
This value will not change for the duration of the channel life.
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); 
 // Ensure this channel can send the required amount of data ASSERT(channel->>GetRecvSize(channel) == 2); | 
void EmtdcCosimulation_InitializeCosimulation
(
const char * fabric_location
, const char * hostname
, int port
, int client_id
)
Parameters:
| Name | Type | Description | 
| fabric_location | const char * | The absolute path the Communication Fabric DLL file (ComFab.dll). | 
| hostname | const char * | The Host Name or IP Address of the master process (PSCAD) that will coordinate the communication. | 
| port | int | The port the master process (PSCAD) that will coordinate the communication is listening on. | 
| client_id | int | A system wide unique ID for this process (it must be between 30000 and 65535) each process in the co-simulation must have a system wide unique ID. | 
Return Value:
None.
Remarks:
This call may take a finite amount of time to return. During this call all necessary connections are established and the required channels are constructed. The master process coordinates this entire process. This function will block until the entire system is properly configured.
This function should be call only once per process during per co-simulation.
Example:
| // Constants const char * path = "C:\\Program Files (x86)\\CommunicationFabric\\x86\\ComFab.dll"; const char * host = "localhost"; 
 // Initialize the Co-Simulation EmtdcCosimulation_InitializeCosimulation(path, host, 34343, 32000 ); | 
void EmtdcCosimulation_InitializeCosimulation
(
const char * file_name
)
Parameters:
| Name | Type | Description | 
| file_name | const char * | This a full file path to a configuration file (generated by PSCAD) that contains required connect back information. | 
Return Value:
None.
Remarks:
This call may take a finite amount of time to return. During this call all necessary connections are established and the required channels are constructed. The master process coordinates this entire process. This function will block until the entire system is properly configured.
This function should be call only once per process during per co-simulation.
Example:
| // Constants const char * path = "C:\\Users\\Public\\Documents\\cosim_30001.cfg"; 
 // Initialize the Co-Simulation EmtdcCosimulation_InitializeCosimulation(path); | 
EmtdcCosimulation_Channel * EmtdcCosimulation_FindChannel
(
unsigned int channel_id
)
Parameters:
| Name | Type | Description | 
| channel_id | unsigned int | The ID of the channel being searched for. | 
Return Value:
| Type | Description | 
| EmtdcCosimulation_Channel* | The channel containing the ID specified. (If channel exists with the ID it will return NULL) | 
Remarks:
Before this can be executed EmtdcCosimulation_InitializeCosimulation must be called.
If the co-simulation is not initialized then it will return NULL.
If no channel exists in this process with that channel ID then it will return NULL.
Example:
| // Get the channel with channel ID of 10 EmtdcCosimulation_Channel * channel = EmtdcCosimulation_FindChannel(10); | 
void EmtdcCosimulation_FinalizeCosimulation
(
void
)
Parameters:
None.
Return Value:
None.
Remarks:
This function will perform any cleanup required from the co-simulation. All EmtdcCosimulation_Channels will be de-allocated after this call.
Note: This call will inform the master process (PSCAD) that the client has finished running, then waits for PSCAD to give the go-ahead to disconnect.
Example:
| // Finalize Co-Simulation EmtdcCosimulation_FinalizeCosimulation(); |