Integrating an existing simulator with HELICS means teaching it to participate in a co-simulation federation as a federate. The amount of work involved depends heavily on whether you have access to the simulator’s source code, what language it is written in, and how it already manages time internally. This guide walks through the key decisions you must make before writing a single line of integration code and then shows you exactly which HELICS API calls are required to get a federate running.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/GMLC-TDC/HELICS/llms.txt
Use this file to discover all available pages before exploring further.
Questions to answer before starting
Before writing integration code, answering three questions will determine which integration pattern is right for your simulator. What language is the simulator written in? HELICS provides a native C++ API and a C API that is wrapped for Python, Julia, Java, MATLAB, and Nim. If your simulator is written in one of those languages you can call HELICS directly. If it is a compiled binary with no bindings, you will need a socket- or process-level wrapper. What kind of codebase are you working with?- Open-source simulators can be modified to call HELICS APIs directly.
- Closed-source or commercial simulators typically expose a scripting interface (Python, MATLAB, etc.) that can be used to wrap the tool.
- Simulators with no scripting API require a socket-based or command-line wrapper.
time_delta or period) so it never asks the simulator to advance to a time it cannot represent. A simulator that uses fixed one-second steps should declare "period": 1 in its configuration.
Integration patterns
- Direct API (open source)
- Scripting wrapper
- Socket / process wrapper
The cleanest integration path. You add HELICS API calls directly to the simulator’s source code and build it with the HELICS library linked in. This is the approach used by the Battery and Charger examples in the HELICS fundamental examples.
Step-by-step integration process
Identify the data boundary
Decide exactly which values your simulator will publish to the federation (outputs) and which values it needs to receive from other federates (inputs). Each published signal becomes a HELICS publication and each received signal becomes a subscription or input. Document the data type (double, complex, string, etc.) and physical units for every signal.
Write a federate JSON configuration file
Create a JSON file that describes the federate to HELICS. This file covers the federate name, core type, timing parameters, and the full list of publications and subscriptions. See the annotated example below for the complete structure.
Create the federate object
In your integration code, call one of the
FromConfig API functions to create the federate from your JSON file. Choose the function that matches the federate type:Retrieve interface handles
After creating the federate from config, fetch the publication and subscription handles so your code can use them in the time loop:
Set the terminate-on-error flag
It is strongly recommended to set this flag so your federate exits cleanly if another federate in the federation fails instead of hanging indefinitely:
Enter executing mode
This is a blocking call. Your federate will wait here until every other federate has also completed its initialization and is ready to begin. Time is at zero when this call returns.
Run the time loop
Advance through simulation time by requesting the next time step from HELICS, reading inputs, running simulator calculations, and publishing outputs:
Minimum required API calls
For a basic value federate that does nothing but publish a constant and subscribe to an input, these six calls are the minimum required:Sample JSON configuration file
The JSON file passed tohelicsCreateValueFederateFromConfig (or the message/combination equivalents) fully describes the federate and its interfaces. The file is reusable—the same simulator executable can be used as different federates just by swapping JSON files.
JSON field reference
JSON field reference
name— Required. Unique name for this federate across the entire federation. HELICS uses this as the federate’s address for message routing.coreType— The messaging technology to use (zmq,tcp,ipc,mpi). Defaults tozmq. See Federation Architectures for guidance on choosing a core type.period— Minimum time step size in seconds. HELICS will never grant the federate a time that is not a multiple ofperiod + offset.offset— Time offset from zero for the first time step. Used to stagger federates that share the same period.uninterruptible— Whenfalse(the default), HELICS can grant an earlier time than requested if data arrives that the federate should process. Set totrueto force HELICS to always wait until the requested time.terminate_on_error— Whentrue, an error in any federate causes the entire federation to terminate. Strongly recommended during development.loglevel— Logging verbosity. Valid values:no_print,error,warning,summary,connections,interfaces,timing,data,debug,trace.publications[].key— Unique identifier for this publication at the federate level. Withglobal: trueit must be unique across the entire federation.publications[].global— Whentrue, other federates subscribe using just thekeystring. Whenfalse, they must use<federate_name>/<key>.publications[].type— Data type:double,int,complex,string,boolean,vector,named_vector,json.publications[].unit— Physical unit string (e.g.,V,VA,m/s^2). HELICS performs unit conversion fordoubletypes.subscriptions[].key— The publication key this subscription will receive. If the publishing federate usesglobal: true, this is just the key. Otherwise use<federate_name>/<key>.subscriptions[].required— Whentrue, the co-simulation will fail to initialize if no federate publishes to this subscription.subscriptions[].info— Arbitrary string ignored by HELICS; typically used to pass simulator-internal configuration such as which model variable to update with the incoming value.
If the simulator you are integrating already has HELICS support (like GridLAB-D, OpenDSS, or MATPOWER), you only need to write the JSON configuration file. The simulator executable already contains the integration code.