Engineers tasked to improve products are finding that it isn't enough to optimize each individual part. To further optimize their products, they must consider how their designs interact with other parts of the system.
Multiphysics and co-simulations are ideal ways to address this challenge. However, interactions across disciplines, departments, businesses and partners introduce new communication challenges due to disparate engineering software and in-house codes.
The functional mock-up interface (FMI) enables model-based systems engineering (MBSE) collaboration between original equipment manufacturers (OEMs), suppliers, inter-company departments, businesses and partners. It gives these organizations a way to effectively, and safely, export complex systems as functional mock-up units (FMUs). FMUs act as black boxes so engineers can connect disparate software into one system simulation.
How FMI and FMU Integrate into CFX
There are four basic steps to leverage FMI and FMU functionality in CFX:
- Export an FMU from a system modeling tool
- Import the FMU into CFX, creating a new CFX Expression Language (CEL) function for accessing FMU outputs
- Use the CEL function where needed — on its own or in combination with other functions, variables and expressions
- Solve the co-simulation or multiphysics problem
Those familiar with CEL will immediately recognize the power of connecting it to CFX. CEL is an algebraic expression language based on compound unit arithmetic. All real-valued CFX inputs are CEL expressions — such as boundary conditions, materials, source terms, monitors and more. The autogenerated FMU CEL function expresses the output variables from the FMU in the units declared by the FMU. This allows FMU outputs to be leveraged anywhere expressions are allowed within CFX — which is virtually every real-valued input.
CEL also provides access to results, such as:
- Mass fraction
CEL expressions are evaluated when and where they are needed. CEL variable modifiers provide access to gradients, time derivatives and more. There is also a variety of callback functions to integrate, average and probe variables at specific regions. Most importantly, CEL does not require any programming; the inclusion of FMU CEL functions further reduces this need.
FMUs can be exported from a wide array of commercial and open source tools to model everything from rigid body dynamics, control systems, exhaust, flow networks and more. As an open standard, it can also be leveraged by in-house developers interested in sharing custom proprietary systems.
The possible ways engineers can use FMI is mind-blowing, especially considering the rapidly expanding list of software that is compliant with the standard. The marriage of FMI with CEL opens up this functionality to CFX users.
How to Set Up an FMI Co-simulation in ANSYS CFX
A water tank control system can be used to show how to set up an FMI co-simulation in CFX.
The single-tank control system monitors the water level in a tank and sends a signal to open or close a valve when it gets too high.
The FMU includes one input (tank level), one output (valve state) and two parameters (minimum and maximum water levels).
The CFX model is hooked up to a tank and a neighboring reservoir that is filled with air and water. A constant flow of water is supplied at the base of the tank and a conditional interface between the tank and reservoir serves as the valve.
To create a CEL function for the control system, import an instance of the FMU by selecting the “WaterTank_Control.fmu” file. The default CEL function name is derived from the FMU filename, however a shorter name is more convenient. So, replace the default name “WaterTank Control” with “TankControl.” The next step is to define the FMU inputs.
Defining FMU Parameters and Variables in CFX
FMU parameters are static parameters passed to the FMU at the start of the simulation run. Values can be entered directly or as expressions of other constants, but they cannot be a function of the solution. The Tank_Control FMU also takes inputs for the target max and min water levels. These values remain fixed for the duration of the run.
FMU input variables are the dynamic inputs to the FMU. They must resolve to a single value and are updated as the simulation proceeds. In this case the input variable is the height of water in the tank.
To supply the water level to the FMU, write a CEL expression to integrate the volume fraction of water in the tank. Use the volume fraction to obtain the total volume of water within the tank. Then divide by the cross-sectional area at the base of tank to get the tank’s water level.
TankLevel = volumeInt(Water.Volume Fraction)@Tank / area()@Tank Base
Since this expression depends on a solution variable — the water’s volume fraction (Water.Volume Fraction) — it will update at every timestep, returning the current tank water level.
The next step is to use the output from the FMU to control the valve. For reference, the FMU output variables are displayed in the function’s basic settings. Output from the FMU is accessed by appending the value name to the function name.
<fmu function>.<fmu variable>()
In this scenario, TankControl.valve() returns the state of the valve — a dimensionless value from the FMU which returns 0 if the valve is closed and 1 if it is open.
How to Make Use of FMU Outputs
The interface between the tank and reservoir will serve as the valve by enabling “Conditional Connection Control.” The “Specified Open State” option takes a logical expression as an input to control this valve. It will let water flow when the expression is true and apply a wall to block flow when false.
The following logical expression provides the necessary input for the Conditional Connection Control:
TankControl.valve() > 0
The model is ready to go; however, it’s recommended to monitor the FMU inputs, outputs and their effects to ensure the setup and FMU are behaving as expected.
Since the output from the FMU is an expression, use it wherever it is needed. To see when the valve is open or closed, simply add TankControl.valve() to the monitors. Monitors can also be set up for the tank level using a similar expression for the water level in the reservoir.
Output from the monitors show the tank’s water level increasing up to the maximum level specified. At this point, the FMU function, TankControl.valve(), changes from 0 to 1 and discharges the tank, confirming the interface is behaving as expected.
Once the minimum level is reached, TankControl.valve() returns a zero and the tank begins to fill once again. As this process is repeated, the reservoir level increases with each discharge from the reservoir and remains constant in between. The monitors confirm that the FMU and setup are operating as expected.
How FMI Allows CFX to Handle the FMU’s Internal Data
The FMI standard also includes details on how FMUs and FMIs should handle internal data. This is important when a simulation is stopped and then allowed to resume.
For example, consider what would happen if the tank control model is stopped and then restarted. The only input to the FMU is the tank level and the current time — passed to the FMU behind the scenes by the solver.
The tank level at the end of the run will be between the specified maximum and minimum. The level alone is not sufficient to determine whether the tank is filling or discharging.
To address this, the FMU keeps track of whether the valve is open or closed. When the CFX solver stops, the FMU streams CFX the data it needs to assess the valve’s status. CFX knows nothing about the data, it simply adds it to the results file. Upon restart, the solver streams this data back to the FMU.
While the water tank example centered around transient calculations, FMUs can be used in steady state, transient, and even harmonic analysis. To learn more ways to leverage CEL in CFX, take some ANSYS CFX Customization Training.
To learn more about FMI, chat about interesting applications of this workflow and share stories, visit ANSYS at the Turbo Expo.