Log In Sign Up

Ai4EComponentLib.jl: A Component-base Model Library in Julia

by   Yuebao Yang, et al.

Ai4EComponentLib.jl(Ai4EComponentLib) is a component-base model library based on Julia language, which relies on the differential equation solver DifferentialEquations.jl and the symbolic modeling tool Modelingtoolkit.jl. To handle problems in different physical domains, Ai4EComponentLib tries to build them with component-base model. Supported by a new generation of symbolic modeling tools, models built with Ai4EComponentLib are more flexible and scalable than models built with traditional tools like Modelica. This paper will introduce the instance and general modeling methods of Ai4EComponentLib model library.


Captum: A unified and generic model interpretability library for PyTorch

In this paper we introduce a novel, unified, open-source model interpret...

Neuro-symbolic partial differential equation solver

We present a highly scalable strategy for developing mesh-free neuro-sym...

FunGrim: a symbolic library for special functions

We present the Mathematical Functions Grimoire (FunGrim), a website and ...

A Proposal for a Revision of ISO Modula-2

The Modula-2 language was first specified in [Wir78] by N. Wirth at ETH ...

Living a discrete life in a continuous world: Reference with distributed representations

Reference is a crucial property of language that allows us to connect li...

ModelingToolkit: A Composable Graph Transformation System For Equation-Based Modeling

Getting good performance out of numerical equation solvers requires that...

Neural-Symbolic Solver for Math Word Problems with Auxiliary Tasks

Previous math word problem solvers following the encoder-decoder paradig...

1 Motivation

In the field of modeling and simulation, there are already many modeling tools, such as Modelica[tiller2001introduction], gProms[asteasuain2001dynamic], Simulink[chaturvedi2017modeling]

and so on. They play an important role in different fields, and these tools have become essential tools for scientific researchers. But that doesn’t mean they are perfect. Taking the open source Modelica as an example, Modelica has its own compiler that can compile the modeling language into C language, which is a complete solution chain for simulation problems. Its disadvantage is that it is not easy to expand and it cannot generate solutions of optimization problems (parameter identification, optimal control problems), etc. The ModelingToolkit in the Julia ecosystem solves the problem of insufficient scalability. Based on the work of ModelingToolkit, Ai4EComponentLib has built some model libraries, hoping to take advantage of its high scalability in the future.

2 Ai4EComponentLib System Design

The method of Ai4EComponentLib design system is the same with the traditional component modeling idea. But due to the high scalability of ModelingToolkit, we will look at this problem with a higher level of abstraction. The core of component-base model is the process, and the changes in energy and matter in the process. Two key points when designing the system are: internal process and external connection. To design a system is to design their processes and connections.

In a system, there are 3 components A, B and C in the system. As shown in the Figure1, each component has its own input and output nodes (such as a1, a2, etc.), and its inputs and outputs are shown by arrows.

Figure 1: System with 3 components A, B and C.

2.1 Internal Process

Each component has its own characteristics, which is reflected in the process of the reaction between the input and output in the node or the exchange of material and energy. And it varies from component to component. These components are the mapping of real world to models and are abstractions of different physical phenomena.

For example, a1, a2, a3 of Component A in the above Figure1. Inside the components, they have a specific mathematical relationship.

Here, is a general functional form, which can be a differential equation or an algebraic equation. Take a resistor component as an example, the same voltage difference is applied across a different resistor, and the current flowing through it is different. If the resistance changes with time, then the current of the system also changes with time. ”Different resistance” and ”time-varying resistance” are both characteristics of components, which are described by different equations when designing components. These equations determine what happens to ”matter and energy” as it flows through the component. Once the components in the system are designed, the function of the whole system can be determined by these components.

2.2 External connection

When building system connections, we focus on the matter and energy of the connection points.

  • If it is a circuit system. The a2 in Figure1 of the circuit system is used as the outlet of the component, and the current and voltage values are necessary attributes. And currents and voltage exist at the inlet and outlet of each component. So current and voltage are the connetor of the circuit system.

  • If it is a pipe system(without considering potential energy). The a2 in Figure1 of the pipe system is used as the outlet of the component, and the pressure and velocity of the water flow are necessary attributes. Water pressure and velocity properties exist at the inlet and outlet of each component. So pressure and velocity are the connetor of the pipe system.

The specific components needs to be build according to the physical model of the system. For example, Kirchhoff’s laws in circuits and Bernoulli’s equation for pipe system. The governing equations are the basic theory for designing the system.

In the external connection, the conservation law must generally be followed - the conservation of energy and the conservation of mass:

For state variables, such as voltage, water pressure, gas pressure. Generally there are:

For process variables such as current, water flow, gas flow. Generally there are (specify that inflow is positive and outflow is negative):

3 Case Study

3.1 Incompressible System

When the liquid in the pipe is an incompressible fluid, the governing equation of the system is Bernoulli’s equation[munson2013fluid].

Where, is pressure, is velocity, is height. Bernoulli’s equation describes the law of conservation of energy for the flow of liquid inside a pipe. The internal process of the component is the increase or decrease of energy.

3.1.1 Pipe Components

For a straight pipeline, there are generally resistance losses along the route and local resistance losses inside the component. As the liquid flows from one port of the pipe to the other, the total energy of the liquid decreases. Along the way resistance loss and local resistance loss are internal processes of the pipeline assembly. Its equation is:

Where the subscript represents the pipeline inlet, represents the pipeline outlet, represents the resistance loss along the way, and represents the local resistance loss.

Where is the friction factor, is the pipe length, and is the pipe diameter.

Where is the local resistance coefficient.

The external connection of the pipeline is mainly pressure and flow (the height is not considered). Pressure is a state variable, and flow is a process variable. Between the two components a, b, there are:

3.1.2 Centrifugal Pump Components

The internal process of a centrifugal pump is to add energy to the fluid.

where represents the added energy when passing through the centrifugal pump.

Where represent the characteristic parameters of the pump, and Equation 10 is actually the theoretical head- flow curve of the pump.

3.1.3 Components and Systems

Before building the main components of the system such as pumps and pipes, we should build the Connector in ModelingToolkit (the variables in the Connector are pressure and flow in the pipeline system). Detailed code can be viewed in the code repository.

# Component: SimplePipe(pipe with fixed friction factor f‘)
function SimplePipe(; name, L=10.0, D=25E-3, f=0.01, ρ=1.0E3, zin=0.0, zout=0.0, K_inside=0.0)
    @named in = PipeNode(z=zin)
    @named out = PipeNode(z=zout)
    ps = @parameters D = D L = L f = f K_inside = K_inside
    eqs = [
        _NodeEnergy(in, D, ρ) ~ _NodeEnergy(out, D, ρ) + _h_f(in, f, L, D) + _h_m(in, K_inside, D)
        0 ~ in.q + out.q
    compose(ODESystem(eqs, t, [], ps, name=name), in, out)
# Component: CentrifugalPump
function CentrifugalPump(; name, D=25E-3, ω=2500, c_0=4.4e-4, c_1=5.622, ρ=1.0E3)
    @named in = PipeNode()
    @named out = PipeNode()
    a_0 = c_0 * abs2 *  / 60)
    a_1 = c_1 * ω *  / 60
    ps = @parameters D = D
    eqs = [
        _NodeEnergy(in, D, ρ) + a_0 - a_1 * abs(in.q) ~ _NodeEnergy(out, D, ρ)
        0 ~ in.q + out.q
    compose(ODESystem(eqs, t, [], ps, name=name), in, out)
# Component: Sink_P
function Sink_P(; name, p=101325)
    @named port = PipeNode(z=0.0)
    eqs = [
        port.p ~ p
    compose(ODESystem(eqs, t, [], [], name=name), port)

It becomes simple and fast to build the following system from the above components, as shown in Figure2.

Figure 2: An Example of Pipe System
@named A = Sink_P()
@named B = Sink_P()
system = [A, B, Pump]
@named Pipe1 = SimplePipe(L=2.0);
push!(system, Pipe1);
@named Pipe2 = SimplePipe(L=3.0);
push!(system, Pipe2);
@named Pipe3 = SimplePipe(L=7.0);
push!(system, Pipe3);
@named Pipe4 = SimplePipe(L=9.0);
push!(system, Pipe4);
@named Pipe5 = SimplePipe(L=5.0);
push!(system, Pipe5);
@named Pipe6 = SimplePipe(L=4.0);
push!(system, Pipe6);
@named Pipe7 = SimplePipe(L=5.0);
push!(system, Pipe7);
@named Pipe8 = SimplePipe(L=1.0);
push!(system, Pipe8);
@named Pipe9 = SimplePipe(L=10.0);
push!(system, Pipe9);
@named Pipe10 = SimplePipe(L=2.0);
push!(system, Pipe10);
@named Pipe11 = SimplePipe(L=2.0);
push!(system, Pipe11);
@named Pipe12 = SimplePipe(L=3.0);
push!(system, Pipe12);
@named Pipe13 = SimplePipe(L=12.0);
push!(system, Pipe13);
@named Pipe14 = SimplePipe(L=1.0);
push!(system, Pipe14);
@named Pipe15 = SimplePipe(L=2.0);
push!(system, Pipe15);
@named Pipe16 = SimplePipe(L=3.0);
push!(system, Pipe16);
@named Pipe17 = SimplePipe(L=6.0);
push!(system, Pipe17);
@named Pipe18 = SimplePipe(L=6.0);
push!(system, Pipe18);
@named Pipe19 = SimplePipe(L=6.0);
push!(system, Pipe19);
@named Pipe20 = SimplePipe(L=1.0);
push!(system, Pipe20);
@named Pipe21 = SimplePipe(L=1.0);
push!(system, Pipe21);
@named Pipe22 = SimplePipe(L=7.0);
push!(system, Pipe22);
@named Pipe23 = SimplePipe(L=3.0);
push!(system, Pipe23);
@named Pipe24 = SimplePipe(L=3.0);
push!(system, Pipe24);
@named Pipe25 = SimplePipe(L=2.0);
push!(system, Pipe25);
eqs = [
  connect(Pipe4.out, Pipe10.out,
  connect(Pipe7.out, Pipe9.out,
  connect(Pipe12.out, Pipe8.out,
  connect(Pipe13.out, Pipe14.out,
  connect(Pipe18.out, Pipe15.out,
  connect(Pipe19.out, Pipe20.out,
  connect(Pipe21.out, Pipe22.out,
  connect(Pipe23.out, Pipe24.out,
  connect(B.port, Pipe25.out)

3.2 Thermodynamic System

3.2.1 Math work

In a thermodynamic cycle system, there are several typical internal processes[moran2017engineering].

  • Isothermal Process:

  • Isobaric Process:

  • Isentropic Process:

  • Isometric Process:

The energy changes in these processes are ultimately reflected in the pressure, density, enthalpy, entropy, and temperature of the fluid. In the thermodynamic cycle, the external connection contains these 5 state variables.

When build a thermodynamic system, although governing equations for different internal processes can be used, there will always be some discrepancies between the theoretical equations and the real world. Therefore, when building a thermal system, we can take advantage of the scalability feature of ModelingToolkit—calling an external property library. Calling the property library can reduce the error of some theoretical calculations.

Taking an isothermal process as an example, the state of the starting point of the process is known. The governing equation of its internal process is:

Then determine another state variable at the end of the process, the other states at the end can be obtained from two known states. Then there are the following 4 combinations:

Using the CoolProp property library, enter the two parameters on the left side of the equation, and we can get any parameter on the right side of the equation. Therefore, the internal equations can be replaced by the external CoolProp library.

3.2.2 Components and Systems

Taking the isenthalpic process as an example, the internal equation is:

If a parameter is given, the function choose_equations will automatically generate code that calls CoolProp through to get the values of other parameters.

function IsoenthalpyProcess(; name, inter_state=”Q_0”, fluid=”Water”)
    @assert inter_state != H IsoenthalpyProcess cant accept H. Please chose another state.”
    @named oneport = StreamPort()
    @unpack Δh, out = oneport
    eqs = [
        Δh ~ 0
    push!(eqs, chose_equations(out, inter_state, H”, fluid)…)
    return extend(ODESystem(eqs, t, [], []; name=name), oneport)

Consider the reheat cycle depicted in Figure3:

Figure 3: Reheat Rankine Cycle

The code is as follows. For more detailed, please check the code repository and documentation.

@named pump = IsentropicProcess(inter_state=”P”)
@named pump_P = DThermalStates(state=”P”, value=-1.0E5, u0=18.0E6)
@named boiler = IsobaricProcess(inter_state=”T”)
@named boiler_T = ThermalStates(state=”T”, value=550+ 273.15)
@named turbine = IsentropicProcess(inter_state=”P”)
@named turbine_P = ThermalStates(state=”P”, value=3.0e6)
@named reboiler = IsobaricProcess(inter_state=”T”)
@named reboiler_T = ThermalStates(state=”T”, value=450 + 273.15)
@named returbine = IsentropicProcess(inter_state=”P”)
@named returbine_P = ThermalStates(state=”P”, value=4.0e3)
@named condenser = IsothermalProcess(inter_state=”Q_0”)
eqs = [
  connect(pump.out,, pump_P.node)
  connect(boiler.out,, boiler_T.node)
  connect(turbine.out,, turbine_P.node)
  connect(reboiler.out,, reboiler_T.node)
  connect(returbine.out,, returbine_P.node)

4 Advantages of Component-base Models

To summarize, components are essentially equations that describe the real world. The governing equations inside the component are the most important part, which lead the change of the system. External connections describe the relationship between components by connection equations. The connection equation does not affect the real system evolution, but only assists building the system.

Components-base model are designed to disassemble large systems into small components. The advantage is that it is convenient for users to build the system, and the disadvantage is that these connection variables will consume computing resources to be simplified after the system is built. In fact, the benefits of a componentized model far outweigh the cost of consuming a little computing resources.

For example, if the system composed of components A,B,C are regarded as a whole X. Then A,B,C become the internal structure of X, and its mathematical form is also a differential algebraic equation, which is not different from the mathematical form of components A,B,C. The only difference is the number of equations. System X can be treated as a component which has three external interfaces: input interface x1, x2 and output interface x3, as the Figure4 shows.

Figure 4: System X composed of components A,B,C

Now, the system and subsystem have a complete concept of closure. If A,B,C are not a minimum system at this time, it can be further subdivided into smaller components. A,B,C can be called a subsystem of system X, and system A,B,C also has its own subsystem.

If A,B,C have only a few equations in total, then A,B,C are not required to be constructed as a subsystem of X. We directly flatten the equation inside X manually. But if A,B,C have thousands of equations, and they also have their own subsystems. Is flattening them manually still a good way?

Therefore, the problems that are divided into components is of great significance when build a giant system. Once the most critical internal structure are determined, people can concentrate on implementing the system (subsystem) at a high level of abstraction.

The rest of the simplification work is left to the computer! If people constantly flatten the equation and build the system from scratch, wouldn’t it be a waste of human resources? The value of human thinking should be reflected in the design of the system, not in the flattening of the equation.

5 Conclusion

The component-base model has its own advantages and has a broader application prospect. The callback system of ModelingToolkit and the solver of DifferentialEquations can handle simulation problems more flexibly. OptControl.jl[yang2022optcontrol] based on ModelingToolkit can transform the component model system into an optimal control problem solved by JuMP. In addition, there is SciML’s333 parameter identification toolkit and so on. With the support of the Julia community, a component-base model is not only equations for simulation, but it can also be a state space model in control problems, optimizing constraints in problems. Because the essence of components - equations can be described by the most basic Julia element - functions.