We’ll start our discussion of component models by building some component models in the heat transfer domain. These models will allow us to recreate the models we saw previously, but this time using component models to represent each of the various effects. Investing the time to make component models will then allow us to easily combine the underlying physical behavior to create models for a wide variety of thermal systems.

In our previous discussion on Simple Domains we described how a thermal connector could be described. For the component models in this section, we will utilize the thermal connector models from the Modelica Standard Library. These connectors are defined as follows:

```
within Modelica.Thermal.HeatTransfer;
package Interfaces "Connectors and partial models"
partial connector HeatPort "Thermal port for 1-dim. heat transfer"
Modelica.SIunits.Temperature T "Port temperature";
flow Modelica.SIunits.HeatFlowRate Q_flow
"Heat flow rate (positive if flowing from outside into the component)";
end HeatPort;
connector HeatPort_a "Thermal port for 1-dim. heat transfer (filled rectangular icon)"
extends HeatPort;
annotation ...
end HeatPort_a;
connector HeatPort_b "Thermal port for 1-dim. heat transfer (unfilled rectangular icon)"
extends HeatPort;
annotation ...
end HeatPort_b;
end Interfaces;
```

Careful inspection of these connector definitions shows that
`HeatPort_a`

and `HeatPort_b`

are identical in terms of their
content to the `HeatPort`

model. The only difference is that
`HeatPort_a`

and `HeatPort_b`

have distinguishing graphical icons.

The component models presented in the remainder of this section will utilize these connector definitions.

When building component models, the goal is to create component models
that implement (only) one physical effect (*e.g.,* capacitance,
convection). By implementing component models in this way, we will
see that they can then be combined in any infinite number of different
configurations without the need to add any more equations. This kind
of reuse of equations makes the model developer more productive and
avoids opportunities to introduce errors.

Our first component model will be a model of lumped thermal capacitance with uniform temperature distribution. The equation we wish to associate with this component model is:

The Modelica model (with the `Icon`

annotation removed) representing
this equation is quite simple:

```
within ModelicaByExample.Components.HeatTransfer;
model ThermalCapacitance "A model of thermal capacitance"
parameter Modelica.SIunits.HeatCapacity C "Thermal capacitance";
parameter Modelica.SIunits.Temperature T0 "Initial temperature";
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a node
annotation ...
initial equation
node.T = T0;
equation
C*der(node.T) = node.Q_flow;
end ThermalCapacitance;
```

where `C`

is the thermal capacitance and `T0`

is the initial
temperature.

Note the presence of the `node`

connector in this model. This is
how the `ThermalCapacitance`

component model interacts with the
“outside world”. We will use the temperature at the `node`

,
`node.T`

to represent the temperature of the thermal capacitance.
The `flow`

variable, `node.Q_flow`

, represents the flow of heat
**into** the thermal capacitance. We can see this when looking at the
equation for the thermal capacitance:

```
C*der(node.T) = node.Q_flow;
```

Note that when `node.Q_flow`

is positive, the temperature of the
thermal capacitance, `node.T`

, will increase. This confirms that we
have followed the Modelica convention that `flow`

variables on a
connector represent a flow of the conserved quantity, heat in this
case, into the component (a more thorough discussion of
Accounting will be presented shortly).

Using this model alone, we can already build a simple “system” model as follows:

```
within ModelicaByExample.Components.HeatTransfer.Examples;
model Adiabatic "A model without any heat transfer"
ThermalCapacitance cap(C=0.12, T0(displayUnit="K") = 363.15)
"Thermal capacitance component"
annotation ...
end Adiabatic;
```

This model contains only the thermal capacitance element (as indicated
by the declaration of the variable `cap`

of type
`ThermalCapacitance`

) and no other heat transfer elements (*e.g.,*
conduction, convection, radiation). Ignore the `Placement`

annotation for the moment, we’ll provide a complete explanation in a
later section on Component Model Annotations.

Using the graphical annotations in the model (some of which were left out of the previous listing) it can be rendered as:

Since no heat enters or leaves the thermal capacitance component,
`cap`

, the temperature of the capacitance remains constant as shown
in the following plot:

To quickly add some heat transfer, we could define another component
model to represent heat transfer to some ambient temperature. Such a
model could be represented in Modelica (again, without the `Icon`

annotation) as follows:

```
within ModelicaByExample.Components.HeatTransfer;
model ConvectionToAmbient "An overly specialized model of convection"
parameter Modelica.SIunits.CoefficientOfHeatTransfer h;
parameter Modelica.SIunits.Area A;
parameter Modelica.SIunits.Temperature T_amb "Ambient temperature";
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
annotation ...
equation
port_a.Q_flow = h*A*(port_a.T-T_amb) "Heat transfer equation";
end ConvectionToAmbient;
```

This model includes parameters for the heat transfer coefficient,
`h`

, the surface area, `A`

and the ambient temperature, `T_amb`

.
This model is attached to other heat transfer elements through the
connector `port_a`

.

Again, we must pay close attention to the sign convention. Recall
from our previous discussion of Thermal Capacitance that
Modelica follows a sign convention that a positive value for a
`flow`

variable represents flow into the component. In particular,
let’s take a close look at the equation in the `ConvectionToAmbient`

model:

```
port_a.Q_flow = h*A*(port_a.T-T_amb) "Heat transfer equation";
```

Note that when `port_a.T`

is greater than `T_amb`

, the sign of
`port_a.Q_flow`

is positive. That means heat is flowing
**into** this component. In other words, when `port_a.T`

is greater
than `T_amb`

, this component will **take heat away** from
`port_a`

(and, conversely, when `T_amb`

is greater than
`port_a.T`

, it will **inject heat into** `port_a`

).

Having such a component model available enables us to combine it with
the `ThermalCapacitance`

model and simulate a system just like we
modeled in some of our earlier heat transfer examples using the following Modelica code:

```
within ModelicaByExample.Components.HeatTransfer.Examples;
model CoolingToAmbient "A model using convection to an ambient condition"
ThermalCapacitance cap(C=0.12, T0(displayUnit="K") = 363.15)
"Thermal capacitance component"
annotation ...
ConvectionToAmbient conv(h=0.7, A=1.0, T_amb=298.15)
"Convection to an ambient temprature"
annotation ...
equation
connect(cap.node, conv.port_a) annotation ...
end CoolingToAmbient;
```

In this model, we see two components have been declared, `cap`

and
`conv`

. The parameters for each of these components are also
specified when they are declared. The following is a schematic for
the `CoolingToAmbient`

model:

But what is really remarkable about this model is the equation section:

```
equation
connect(cap.node, conv.port_a) annotation ...
```

This statement introduces one of the most important features in
Modelica. Note that statement appears within an `equation`

section. While the `connect`

operator looks like a function, it is
much more than that. It represents the equations that should be
generated to model the interaction between the two specified
connectors, `cap.node`

and `conv.port_a`

.

In this context, a connection does two important things. The first thing it does is to generate an equation that equates the “across” variables on either connector. In this case, that means the following equation:

```
cap.node.T = conv.port_a.T "Equating across variables";
```

In addition, a connection generates an equation for all the through
variables as well. The equation that is generated is a conservation
equation. You can think of this conservation equation as a
generalization of Kirchoff’s current law to any conserved quantity.
Basically, it represents the fact that the connection itself has no
“storage” ability and that whatever amount of the conserved quantity,
in this case heat, that flows out of one component must go into the
other(s). So in this case, the connect statement will generate the
following equation with respect to the `flow`

variables:

```
cap.node.Q_flow + conv.port_a.Q_flow = 0 "Sum of heat flows must be zero";
```

Note the sign convention here. All the `flow`

variables are summed.
We will examine more complex cases shortly where multiple components
are interacting. But in this simple case, with only two components,
we see clearly that if one value for `Q_flow`

is positive, the other
must be negative. In other words, if heat is flowing out of one
component, it must be flowing into another. These conservation
equations ensure that we have a proper accounting of conserved
quantities throughout our network and that no amount of the conserved
quantity gets “lost”.

A very simple way to summarize the behavior of a connection, in the
context of a thermal problem, is to **think of a connection as a
perfectly conducting element with no thermal capacitance**.

If we simulate the `CoolingToAmbient`

model above, we get the
following temperature trajectory:

There is one slight issue with the `CoolingToAmbient`

model. We
mentioned earlier that when building component models it is best to
isolate each individual physical effect to its own component. But we’ve
actually lumped two different effects into one component. As we will
see in a moment, this limits the reusability of the component models.
But first, let’s refactor the code to separate these effects out and
then we’ll revisit the system level model using these new components.

The first new component is a `Convection`

model. In this case, we
won’t make any assumptions about the temperature at either end.
Instead, we’ll only assume that each is connected to something with an
appropriate thermal connector. The result is a model like this one:

```
within ModelicaByExample.Components.HeatTransfer;
model Convection "Modeling convection between port_a and port_b"
parameter Modelica.SIunits.CoefficientOfHeatTransfer h;
parameter Modelica.SIunits.Area A;
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a port_a
annotation ...
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b port_b
annotation ...
equation
port_a.Q_flow + port_b.Q_flow = 0 "Conservation of energy";
port_a.Q_flow = h*A*(port_a.T-port_b.T) "Heat transfer equation";
end Convection;
```

This model contains two equations. The first equation:

```
port_a.Q_flow + port_b.Q_flow = 0 "Conservation of energy";
```

represents the fact that this component does not store heat. The
equation enforces the constraint that whatever heat flows in from one
connector must flow out from the other (which is exactly the same
behavior we saw from the `connect`

statement earlier in this
section). The next equation:

```
port_a.Q_flow = h*A*(port_a.T-port_b.T) "Heat transfer equation";
```

captures the heat transfer relationship for convection by expressing the relationship between the flow of heat through this component and the temperatures on either end.

Number of equations

All our previous models had one connector and one equation. The
`Convection`

model has two connectors. As a result, it has two
equations. A simple rule of thumb is that you need as many
equations as connectors. But keep in mind that this rule of thumb
assumes that you are using connectors with only one through
variable on them and no “internal variables” in your model
(*e.g.,* `protected`

variables). The upcoming section on
Component Models will provide a more comprehensive discussion on
determining how many equations a component requires.
Specifically, it will provide guidance on how to build so-called
Balanced Components.

Now that we have the convection model, we need something to represent
the ambient conditions. We need something like a thermal capacitance
model, but one that maintains a constant temperature. Imagine if we
took the `ThermalCapacitance`

model and gave a very large value for
its capacitance, `C`

. Then we’d have something that changed
temperature very slowly. But what we want is something that doesn’t
change temperature at all, as if it had a `C`

value that was
infinitely large.

This kind of model comes up frequently and it is commonly called an “infinite reservoir” model. Typically, such a model is characterized by the fact that no matter how much of the conserved quantity (heat in this case) flows into or out of the component, the across variable remains constant. In an electrical context, such a model would represent electrical ground. In a mechanical context, it would represent a mechanical ground (something that didn’t change position, regardless of how much force was applied).

We will represent our ambient conditions using the
`AmbientConditions`

model:

```
within ModelicaByExample.Components.HeatTransfer;
model AmbientCondition
"Model of an \"infinite reservoir\" at some ambient temperature"
parameter Modelica.SIunits.Temperature T_amb "Ambient temperature";
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_a node annotation ...
equation
node.T = T_amb;
end AmbientCondition;
```

Since we are talking about the heat transfer domain, this model is an infinite reservoir for heat and no matter how much heat flows into or out of this component, its temperature remains the same.

Using these new `Convection`

and an `AmbientCondition`

models, we
can reconstruct our simple system level heat transfer model using
the following:

```
within ModelicaByExample.Components.HeatTransfer.Examples;
model Cooling "A model using generic convection to ambient conditions"
ThermalCapacitance cap(C=0.12, T0(displayUnit="K") = 363.15)
"Thermal capacitance component"
annotation ...
Convection convection(h=0.7, A=1.0)
annotation ...
AmbientCondition amb(T_amb(displayUnit="K") = 298.15)
annotation ...
equation
connect(convection.port_a, cap.node) annotation ...
connect(amb.node, convection.port_b) annotation ...
end Cooling;
```

When rendered, the model looks like this:

This may not seem like much of an improvement. Although we went to
the trouble to break up the `ConvectionToAmbient`

model into individual
`Convection`

and `AmbientTemperature`

models, we still end up with
the same fundamental behavior, *i.e.,*

The big benefit of breaking down `ConvectionToAmbient`

into
`Convection`

and `AmbientTemperature`

models is the ability to
recombine them in different ways. The following schematic is just one
example of how the handful of fundamental components we’ve constructed
so far can be rearranged to form an entirely new (and more complex)
model:

In fact, with these components we can now make **arbitrarily complex**
networks of components and still never have to worry about formulating
the associated equations that describe their dynamics. Everything
that is required to do this has already been captured in our component
models. This allows us to focus on the process of creating and
designing our system and leave the tedious, time-consuming and error
prone work of manipulating equations behind.