MTK acausal modeling not working with @discrete_events

I’m trying to model an unsteady-state CSTR with discrete-event PI controller updates using MTK’s acausal component-based modeling framework, but I’m having trouble with @discrete_events (or @continuous_events) not being able to “see” connector variable information from outside components. Am I doing something wrong or are these begin blocks simply not supported with the acausal modeling framework yet?

@mtkmodel PIcontroller begin
    @components begin
        readingsIn = Stream()
        signalOut = ValveSignal()
    end
    @variables begin
        I_err(t) = 0 # Integral error
    end
    @parameters begin
        c_BSP = 0.32 # Desired concentration (mol/L)
        K_b = 0.0 # Bias (-)
        K_c = 9.0 # Proportional gain (-)
        K_I = 0.18 # Integral gain (-)

        eventStart = 200 # Enable PI Controller at t=200 min
        eventInterval = 30 # Update signal every 30 mins

        s = 0 # No initial signal to open valve
    end
    @equations begin
        D(I_err) ~ c_BSP - readingsIn.c_B
        signalOut.s ~ s
    end
    @discrete_events begin
        ((mod(t-eventStart,eventInterval) == 0) & (t >= eventStart)) => [s ~ K_b + K_c*(c_BSP - readingsIn.c_B) + K_I*I_err]
    end
end

I’m able to connect all my components, use @mtkbuild, create an ODEProblem(), but when I get to solve(), I get ERROR: UndefVarError: picontroller₊readingsIn₊c_B not defined. I’ve isolated this as the issue because whenever I replace readingsIn.c_B in the discrete_events block with some number, everything runs properly (although I get the wrong solution of course).

I’ve also tried something like this

@mtkmodel PIcontroller begin
    @components begin
        readingsIn = Stream()
        signalOut = ValveSignal()
    end
    @variables begin
        I_err(t) = 0 # Integral error
        B(t)
    end
    @parameters begin
        c_BSP = 0.32 # Desired concentration (mol/L)
        K_b = 0.0 # Bias (-)
        K_c = 9.0 # Proportional gain (-)
        K_I = 0.18 # Integral gain (-)

        eventStart = 200 # Enable PI Controller at t=200 min
        eventInterval = 30 # Update signal every 30 mins

        s = 0 # No initial signal to open valve
    end
    @equations begin
        D(I_err) ~ c_BSP - B
        B ~ readingsIn.c_B
        signalOut.s ~ s
    end
    @discrete_events begin
        ((mod(t-eventStart,eventInterval) == 0) & (t >= eventStart)) => [s ~ K_b + K_c*(c_BSP - B) + K_I*I_err]
    end
end

but @discrete_events can’t see B either. I’ve found that @discrete_events can only see B if I do something like D(B) ~ 0, but then I can’t do B ~ readingsIn.c_B because @mtkbuild will tell me I have too many equations. Any insight would be appreciated.

Open an issue. This may be related to another example we’ve been working on.

1 Like