Best way for passing abstract type data via path variables in Dyad

Hello, I have a question about the proper usage of path variables in MTK and Dyad.

To calculate heat transfer coefficient(HTC) and pressure drop(dP), the specific type and geometry of the heat exchanger(HX) are crucial. My idea was to pass the abstract device object itself through the connector using a path variable.

I started by adding path device::AbstractHX to my fluid connector.

# Connector for fluids
connector FluidPort
    # Potential
    potential p::Pressure
    # Flow
    flow m_flow::MassFlowRate
    # Stream property
    stream h_outflow::SpecificEnthalpy
    # Information shared through the circuit
    path medium::AbstractMedium
    path device::AbstractHX # Passing the device object
end

This would allow me to access the device’s properties within my calculation functions, like so:

HTC(medium::AbstractMedium, hx::AbstractHX, p, h, mdot, Q_heat) = Models.htc(medium, hx, Mediums.State(p=p, h=h), mdot, Q_heat)
dP(medium::AbstractMedium, hx::AbstractHX, p, h, mdot) = Models.dP(medium, hx,  Mediums.State(p=p, h=h), mdot)

However, I realized that a path variable propagates throughout an entire connected circuit. This presents a challenge: when a heat exchanger is connected to a different component type, like a compressor, the single device path variable creates a type conflict. It cannot simultaneously represent a heat exchanger in one part of the circuit and a compressor in another. To resolve this, I’ve considered two potential solutions.

Solution 1: Create a separate DevicePort

# In my library (jl)
abstract type AbstractDevice end
abstract type AbstractHX <: AbstractDevice end
abstract type AbstractComp <: AbstractDevice end

# A connector only for the device (dyad)
connector DevicePort
    path device::AbstractDevice
end

Solution 2: Create a PureFluidPort

# In my library (jl)
abstract type AbstractDevice end
abstract type AbstractHX <: AbstractDevice end
abstract type AbstractComp <: AbstractDevice end

# A connector for fluid and device (dyad)
connector FluidPort
    ...
    path medium::AbstractMedium
    path device::AbstractDevice
end

#  A connector only for fluid
connector PureFluidPort
    ...
    path medium::AbstractMedium
end

Solution 1, using a DevicePort, failed to generate MTK files, likely because a connector with only path variables is invalid.

While Solution 2 is a possible workaround, bundling component-specific data within a FluidPort feels like a design compromise that violates separation of concerns.

What is the recommended design pattern in MTK for making component-specific parameters available to connection-level calculations? Is there a way to make the dedicated connector approach (Solution 1) work correctly?

I’m not sure I understand the motivation here, what do you mean by passing a device through a connector? You typically instantiate components: the motivation for the path is pass a common parameter only through all components that use that particular connector type.

e.g., the typical case is for flow of a medium through connected components.

I’m not sure I understand the motivation here, what do you mean by passing a device through a connector?

I’m using ModelingToolkit to simulate heat pump systems (mainly for performance and control analysis) used in our lab. For systems like VRF that include multiple indoor and outdoor units, even if the same FTHX model structure is used, the applicable correlations depend on the refrigerant, geometry, and operating conditions. Similarly, when a vapor compression system (VCS) is used for water heating, plate or shell-and-tube heat exchangers can also be introduced. In other words, the type and geometry of HX act as parameters that determine correlations for heat transfer coefficient and pressure drop.

I found out that the inner/outer concept in Modelica corresponds to the path variable mechanism in ModelingToolkit (and Dyad). Specifically, I thought the combination of a path variable and continuity allows a symbolic object (e.g., a Julia struct representing a refrigerant cell or a momentum-control valve in a staggered FVM) to be propagated through the connection.

In Richter’s PhD thesis (2008), the inner/outer mechanism is described as follows:

The inner/outer-concept is a very elegant way to provide information to models further down in the instance hierarchy.

The most important ones are
-To propagate fluid property information from the basic cells to the heat transfer and pressure drop models
-To provide geometric data to all levels of the heat exchanger models

Based on this, I assumed that through the path variable, not only the medium but also the geometry and even abstract device objects (such as heat exchangers, compressors) could be propagated downstream.

The motivation for the path is to pass a common parameter only through all components that use that particular connector type.

Then, I think Solution 2 might be the right answer for using the path variable for certain devices. At the device level, a connector that contains both medium and device is used to propagate medium and device, while at the device boundary, a connector that contains only medium information can be used.

[Reference]

  1. Richter, C. C. (2008). Proposal of new object-oriented equation-based model libraries for thermodynamic systems (Doctoral dissertation, Braunschweig, Techn. Univ., Diss., 2008).

The path qualifier is actually more like the replaceable package construct used for fluid modeling although you can use it as well to do things that are done with inner/outer in Modelica. But I would generally just use normal parameter propagation for device information. The idea behind path is to provide a means of propagating information based on physical connections but only if that is an intuitive way to do it.

Thanks for the explanation :grinning_face: Limiting FluidPort to just carrying the medium seems like the most clear and simple approach.