Step 4: Primary Loop
Complete input file for this step: 04_loop.i

Figure 1: Model diagram
In this step, we will complete the primary loop and set up a simple PID controller for the pump so that it maintains the prescribed mass flow rate.
Close the Loop
We add two pipes for the bottom section of the primary loop with a pump in the middle. A pump is a junction-like component that connects to two flow channels corresponding to its inlet and outlet.
[jct5]
type = VolumeJunction1Phase
position = '1 0 0'
connections = 'down_pipe:out bottom_b:in'
volume = 1e-3
[]
[bottom_b]
type = FlowChannel1Phase
position = '1 0 0'
orientation = '-1 0 0'
length = 0.5
n_elems = 5
A = ${fparse pi * pipe_dia * pipe_dia / 4.}
D_h = ${pipe_dia}
[]
[pump]
type = Pump1Phase
position = '0.5 0 0'
connections = 'bottom_b:out bottom_a:in'
volume = 1e-3
A_ref = ${fparse pi * pipe_dia * pipe_dia / 4.}
head = 0
[]
[bottom_a]
type = FlowChannel1Phase
position = '0.5 0 0'
orientation = '-1 0 0'
length = 0.5
n_elems = 5
A = ${fparse pi * pipe_dia * pipe_dia / 4.}
D_h = ${pipe_dia}
[]
The pump component needs 2 more parameters to be specified: reference area A_ref
, and head
, which is the pump head.
Control Logic
Control logic is a system that allows users to monitor the simulation and change its parameters while it is running.
The system consists of 3 layers:
input layer: which brings values from the simulation inside the control logic system
execution layer: which performs the prescribed operations
output layer: that feeds the values back into simulation
All control logic blocks should be included in the top-level [ControlLogic]
block.
Setup PID
A PID control requires several values as an input: set point set_point
, input value input
, initial value initial_value
, and three constants K_p
, K_i
, and K_d
, which are the coefficients for the proportional, integral, and derivative terms, respectively.
For the input value, we set up a postprocessor m_dot_pump
with type ADFlowJunctionFlux1Phase
which will be measuring the outlet mass flow rate from the pump.
[m_dot_pump]
type = ADFlowJunctionFlux1Phase
boundary = core_chan:in
connection_index = 1
equation = mass
junction = jct6
[]
A set point will be our desired mass flow rate specified by the global parameter m_dot_in
. To bring this value into the control logic system, we need to use GetFunctionValueControl
block like so:
[set_point]
type = GetFunctionValueControl
function = ${m_dot_in}
[]
This value will be available in the control logic system as set_point:value
(in general control_block_name:value
).
Then, we add the PID control block as follows:
[pid]
type = PIDControl
initial_value = 0
set_point = set_point:value
input = m_dot_pump
K_p = 250
K_i = 0.5
K_d = 0
[]
The value computed by the PID control is available in the control logic system under the name pid:output
, where pid
is the name of the block.
As a last step, we need to feed this value back into the system. That can be done via SetComponentRealValueControl
block.
[set_pump_head]
type = SetComponentRealValueControl
component = pump
parameter = head
value = pid:output
[]
The parameter to control is specified via a component
and parameter
parameters, which are the component name and the parameter name of that component we want to modify.