Non-Linear Set of Equations on Model using Modelica.Media - modelica

I'm trying to model a natural convection case using Modelica.Media package and I've set up a simple grid of 6x6 fixed-volume zones (code attached) which implements mass and energy conservation. Those zones are connected to a no-flow boundary condition model and communicate through a flow model.
But when simulating it, I got a set of non-linear equations during all the steps, related to the calculation of the state p, h, Xi of each zone (figure attached).
Do you know I can set it up to avoid that? Maybe a different set of initial conditions? Any help is much appreciated!
model Zone
replaceable package Medium = Modelica.Media.Interfaces.PartialMedium annotation(choicesAllMatching = true);
Medium.BaseProperties medium(p(start=101325, fixed=false),
T(start=293.15, fixed=false));
Test.Port portT(redeclare package Medium = Medium);
Test.Port portB(redeclare package Medium = Medium);
Test.Port portL(redeclare package Medium = Medium);
Test.Port portR(redeclare package Medium = Medium);
parameter Medium.AbsolutePressure P_ambient = 101325;
Medium.Temperature T_ambient = Units.Conversions.from_degC(20);
Medium.MassFraction X_ambient[Medium.nX] = Medium.X_default;
...
initial equation
medium.p = P_ambient;
medium.T = T_ambient;
medium.Xi = X_ambient[1:Medium.nXi];
equation
...
m = V * medium.d;
U = m * medium.u;
mXi = m * medium.Xi;
der(m) = portL.mf + portR.mf + portT.mf + portB.mf;
der(U) = portL.hf + portR.hf + portT.hf + portB.hf + portL.q + portR.q + portT.q + portB.q;
der(mXi) = portL.mXif + portR.mXif + portT.mXif + portB.mXif;
On the flow model, I`m using
portI.mf = mf;
portI.hf = semiLinear(portI.mf, portI.h, portJ.h);
portI.mXif = semiLinear(portI.mf, portI.Xi, portJ.Xi);
portI.q = q;
portI.mf + portJ.mf = 0;
portI.hf + portJ.hf = 0;
portI.q + portJ.q = 0;
portI.mXif + portJ.mXif = zeros(Medium.nXi);
Connector
Medium.Temperature T;
flow Units.HeatFlowRate q;
Medium.AbsolutePressure p;
flow Medium.MassFlowRate mf;
Medium.SpecificEnthalpy h;
flow Medium.EnthalpyFlowRate hf;
Medium.MassFraction Xi[Medium.nXi];
flow Medium.MassFlowRate mXif[Medium.nXi];
Non Linear Warning Image

I've just found the problem, my set of equations was not complete and initialization was not helpful at all.

Related

Balancing local models Modelica

I have a local model, which when I check in Dymola claims to have 35 variables and 34 unknowns, while when I check exactly the same model in OMEdit it is balanced at 34/34. In determining what counts as a variable, do all inputs and outputs get included?
Below is my model:
model HeatStorage
extends PentakomoPlant.Interfaces.StorageFluidHeat;
parameter SI.Diameter D = 18.667 "Diameter";
parameter SI.Height H = 20 "Height";
parameter Boolean enable_losses = false "= true enable thermal losses with environment"
parameter SI.CoefficientOfHeatTransfer alpha = 1 "Constant heat transfer coefficient with the ambient"
parameter Boolean use_L = false "= true to display level as output variable"
parameter Real L_start = 0 "Start value of level in %"
parameter SI.Temperature T_start = from_degC(300) "Start value of temperature"
parameter SI.Temperature T_max = from_degC(550) "Maximum tank temperature"
parameter SI.Temperature T_set = from_degC(300) "Tank Heater Temperature Set-Point"
parameter SI.Power W_max = 30e8 "Hot Tank Heater Capacity"
parameter SI.Efficiency e_ht = 0.99 "Tank Heater Efficiency"
SI.Volume V;
SI.Mass m;
Medium.BaseProperties medium;
SI.Area A;
SI.HeatFlowRate Q_losses;
Medium.ThermodynamicState state_i = Medium.setState_pTX(medium.p, T_start);
SI.Power W_net;
SI.Power W_loss;
Modelica.Blocks.Interfaces.RealOutput L if use_L "Tank level in %"
Modelica.Blocks.Interfaces.RealInput T_amb if enable_losses
Modelica.Blocks.Interfaces.RealInput Q_heater
SI.HeatFlowRate Q_PB "Heat Flow to PowerBlock";
SI.HeatFlowRate Q_desal "Heat Flow to Desalination";
protected
parameter SI.Volume V_t = H * pi * D ^ 2 / 4;
Modelica.Blocks.Interfaces.RealOutput L_internal;
initial equation
medium.h = Medium.specificEnthalpy(state_i);
m = Medium.density(state_i) * V_t;
equation
if use_L then
connect(L_internal, L);
end if;
if enable_losses then
connect(T_amb_internal, T_amb);
Q_losses = -0.939 * exp(to_degC(medium.T) * 0.005111) * 1000;//*5/7;
else
T_amb_internal = Medium.T_default;
Q_losses = 0;
end if;
fluid_a.p = medium.p;
fluid_b.p = medium.p;
fluid_a.h_outflow = medium.h;
fluid_b.h_outflow = medium.h;
der(m) = fluid_a.m_flow + fluid_b.m_flow;
m * der(medium.h) + der(m) * medium.h = Q_losses + Q_PB + Q_desal + W_net + fluid_a.m_flow * inStream(fluid_a.h_outflow) + fluid_b.m_flow * medium.h;
V = m / medium.d;
L_internal = 100 * (max(medium.T, T_set) - T_set) / (T_max - T_set);
A = 2 * pi * (D / 2) * H;
W_net = Q_heater;
W_loss = W_net / e_ht;
//PowerBlock
heat_PB.Q_flow = Q_PB;
heat_DS.Q_flow = Q_desal;
heat_PB.T = medium.T;
heat_DS.T = medium.T;
end HeatStorage;
With:
partial model StorageFluidHeat
extends SolarTherm.Icons.StorageModel;
Modelica.Fluid.Interfaces.FluidPort_a fluid_a(redeclare package Medium = Medium)
Modelica.Fluid.Interfaces.FluidPort_b fluid_b(redeclare package Medium = Medium)
replaceable package Medium = SolarTherm.Media.MoltenSalt.MoltenSalt_base
constrainedby Modelica.Media.Interfaces.PartialMedium
"Medium in the component"
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b heat_PB
Modelica.Thermal.HeatTransfer.Interfaces.HeatPort_b heat_DS
end StorageFluidHeat;
And (for the base properties of the medium):
redeclare model extends BaseProperties(final standardOrderComponents=true)
"Base properties of medium"
equation
d = rho_T(T);
h = state.h;
u = h - p/d;
MM = 0.091438;
R = 8.3144/MM;
state.p = p;
T = T_h(h);
end BaseProperties;
I am struggling to find where the extra variable may be, or why it might be different when using Dymola/OMEdit.
I have tried following the advice from ELmqvist about balancing models, so in counting variables would I be right in assuming (For this model):
8 x Specialised class variables
3 x Inputs
2 x Output
7 x Medium Base Property Variables
2 x 5 x Fluid port Variables
2 x 2 x Heat port Variables
= 34 variables
Am I missing something?
The model is not complete with all libraries to enable testing (assumedly there are similar issues with other media), so this will be an incomplete answer.
In addition it seems likely that some equations and variables could be removed to simplify the model.
But there are some concerns with the model:
T_amb_internal is unused and undeclared; that looks odd.
You normally need equations for two intensive properties for simple medium: e.g. p, h or p, T. Here medium.h is determined due to the differential equations, but not medium.p. (The mass also has a differential equation and can vary.)
Note that testing of a local model can be tricky - and you should preferably include it in a test-circuit as well.

The method of characteristics for two dimensional advection equation

Given the following function to solve the two-dimensional advection equation in a rectangle:
function qnew = SemiLagrAdvect(u,v,q,qS,qN,qW,qE)
global N M
global dx dy
global dt Re
u = reshape(u,N,M);
v = reshape(v,N,M);
q = reshape(q,N,M);
%...embedding
qq = zeros(N+2,M+2);
qq(2:N+1,2:M+1) = q;
%...set the ghost values (four edges)
qq(1,2:M+1) = 2*qW-qq(2,2:M+1);
qq(N+2,2:M+1) = 2*qE-qq(N+1,2:M+1);
qq(2:N+1,1) = 2*qS-qq(2:N+1,2);
qq(2:N+1,M+2) = 2*qN-qq(2:N+1,M+1);
%...set the ghost values (four corners)
qq(1,1) = -qq(2,2);
qq(N+2,1) = -qq(N+1,2);
qq(N+2,M+2) = -qq(N+1,M+1);
qq(1,M+2) = -qq(2,M+1);
q1 = qq(2:N+1,2:M+1);
q2p = qq(3:N+2,2:M+1);
q2m = qq(1:N,2:M+1);
q3p = qq(2:N+1,3:M+2);
q3m = qq(2:N+1,1:M);
q4pp = qq(3:N+2,3:M+2);
q4mm = qq(1:N,1:M);
q4pm = qq(3:N+2,1:M);
q4mp = qq(1:N,3:M+2);
xi = -u*dt/dx;
eta = -v*dt/dy;
Q2 = q2p.*(xi>0) + q2m.*(xi<0);
Q3 = q3p.*(eta>0) + q3m.*(eta<0);
Q4 = q4pp.*((xi>0) & (eta>0)) + q4mm.*((xi<0) & (eta<0)) + ...
q4pm.*((xi>0) & (eta<0)) + q4mp.*((xi<0) & (eta>0));
qnew = (1-abs(xi)).*(1-abs(eta)).*q1 + ...
abs(xi).*(1-abs(eta)).*Q2 + ...
abs(eta).*(1-abs(xi)).*Q3 + ...
abs(xi).*abs(eta).*Q4;
qnew = qnew(:);
Having elementary knowledge in MATLAB, how can I modify it to solve the equation in a composite domain?
you need to use continuity on the interface.Depending on your method.
In the method of characteristics the interface is part of the initial curve.
S
I'm

Weird results in approximation of a function with neural networks

I am trying to approximate a function (the right hand side of a differential equation) of the form ddx=F(x,dx,u) (where x,dx,u are scalars and u is constant) with an RBF neural network. I have the function F as a black box (I can feed it with initial x,dx and u and take x and dx for a timespan I want) and during training (using sigma-modification) I am getting the following response plotting the real dx vs the approximated dx.
Then I save the parameters of the NN (the centers and the stds of the gaussians, and the final weights) and perform a simulation using the same initial x,dx and u as before and keeping, of course, the weights stable this time. But I get the following plot.
Is that logical? Am I missing something?
The training code is as follows:
%load the results I got from the real function
load sim_data t p pd dp %p is x,dp is dx and pd is u
real_states = [p,dp];
%down and upper limits of the variables
p_dl = 0;
p_ul = 2;
v_dl = -1;
v_ul = 4;
pd_dl = 0;%pd is constant each time,but the function should work for different pds
pd_ul = 2;
%number of gaussians
nc = 15;
x = p_dl:(p_ul-p_dl)/(nc-1):p_ul;
dx = v_dl:(v_ul-v_dl)/(nc-1):v_ul;
pdx = pd_dl:(pd_ul-pd_dl)/(nc-1):pd_ul;
%centers of gaussians
Cx = combvec(x,dx,pdx);
%stds of the gaussians
B = ones(1,3)./[2.5*(p_ul-p_dl)/(nc-1),2.5*(v_ul-v_dl)/(nc-1),2.5*(pd_ul-pd_dl)/(nc-1)];
nw = size(Cx,2);
wdx = zeros(nw,1);
state = real_states(1,[1,4]);%there are also y,dy,dz and z in real_states (ignored here)
states = zeros(length(t),2);
timestep = 0.005;
for step=1:length(t)
states(step,:) = state;
%compute the values of the sigmoids
Sx = exp(-1/2 * sum(((([real_states(step,1);real_states(step,4);pd(1)]*ones(1,nw))'-Cx').*(ones(nw,1)*B)).^2,2));
ddx = -530*state(2) + wdx'*Sx;
edx = state(2) - real_states(step,4);
dwdx = -1200*edx * Sx - 4 * wdx;
wdx = wdx + dwdx*timestep;
state = [state(1)+state(2)*timestep,state(2)+ddx*timestep];
end
save weights wdx Cx B
figure
plot(t,[dp(:,1),states(:,2)])
legend('x_d_o_t','x_d_o_t_h_a_t')
The code used to verify the approximation is the following:
load sim_data t p pd dp
real_states = [p,dp];
load weights wdx Cx B
nw = size(Cx,2);
state = real_states(1,[1,4]);
states = zeros(length(t),2);
timestep = 0.005;
for step=1:length(t)
states(step,:) = state;
Sx = exp(-1/2 * sum(((([real_states(step,1);real_states(step,4);pd(1)]*ones(1,nw))'-Cx').*(ones(nw,1)*B)).^2,2));
ddx = -530*state(2) + wdx'*Sx;
state = [state(1)+state(2)*timestep,state(2)+ddx*timestep];
end
figure
plot(t,[dp(:,1),states(:,2)])
legend('x_d_o_t','x_d_o_t_h_a_t')

Poor fit using nlinfit and fminsearch in Matlab

I have some reference data against which I want to fit some model data. I have developed a 5-param model for this purpose. The job now is to optimize the model params using Matlab. However, I have very poor fit for ref vs model data (r^2 in the range 0.6 only). I tried using fminsearch and nlinfit algorithms.
One probable reason might be that my params are not of similar order of magnitude (while 1 param is of range e-09, another is ~e03). I am unsure whether to use scaling/normalization of params, and if so how to go about it. Can anyone help?
Here's my code for your perusal:
voltage = xlsread('co_content_29_07_avik.xlsx','A9:A99'); % voltage
current = xlsread('co_content_29_07_avik.xlsx','B9:B99'); % current
% Cell characteristics from manufacturer's datasheet
V_oc = 0.665; %V
I_sc = 5.75; %A
V_mp = 0.56; % V
I_mp = 5.35; % A
a = 1.2 % educated guess
% Calculate thermal voltage
k = 1.3806e-23; %Boltzmann constant - Joule/Kelvin
T = 298;
q = 1.602e-19; %electron charge - Coulomb
n_cell = 1; % no. of cells
V_t = n_cell*k*T/q;
% Calculate unoptimized cell parameters (R_s, R_sh, I_0, I_ph, n)
A = a*V_t/I_mp;
B = -(V_mp*(2*I_mp - I_sc)/(V_mp*I_sc + V_oc*(I_mp - I_sc)));
C = -((2*V_mp - V_oc)/a*V_t) + (V_mp*I_sc - V_oc*I_mp)/(V_mp*I_sc + V_oc*(I_mp - I_sc));
D = (V_mp-V_oc)/(a*V_t);
R_s = A*lambertw((B*exp(C) - (D+C)))
R_sh_num = (V_mp-I_mp*R_s)*(V_mp - R_s*(I_sc-I_mp) - a*V_t);
R_sh_den = (V_mp-I_mp*R_s)*(I_sc-I_mp) - a*V_t*I_mp;
R_sh = R_sh_num/R_sh_den
I_0 = (I_sc*(R_sh + R_s) - V_oc)/(R_sh*exp(V_oc/(a*V_t)))
I_ph = (R_sh+R_s)*I_sc/R_sh
len = length(voltage);
for i=1:1:len
non_exp1 = R_s*R_sh*I_0/(a*V_t*(R_s + R_sh));
lambexp1 = R_sh*(R_s*I_ph + R_s*I_0 + voltage(i,1))/(a*V_t*(R_s + R_sh));
lambarg1 = non_exp1*exp(lambexp1);
firstterm1 = -voltage(i,1)/(R_s + R_sh);
midterm1 = -(lambertw(lambarg1)*a*V_t/R_s);
third1 = R_sh*(I_0 + I_ph)/(R_s + R_sh);
I_1(i,1) = firstterm1 + midterm1 + third1;
end
% Optimize using fminsearch algo
fun = #(p) sum((current - (voltage/(p(1)+p(2)) - (lambertw((p(1)*p(2)*p(3))/(p(5)*V_t*(p(1)+p(2)))))*exp((p(2)*(p(1)*p(4)+p(1)*p(3)+voltage))/(p(5)*V_t*(p(1)+p(2))))*p(5)*V_t/p(1) + (p(2)*(p(3)+p(4))/(p(1)+p(2))))).^2);
% initial guess for param
pguess = [0.005,4.75,0.000000001,5.75,1.2];
%optimize
[x,fval,exitflag,output] = fminsearch(fun,pguess,optimset('MaxFunEvals',1000))

no oscillation after put in pid controller

I have a problem regarding putting a PID controller in my simulink file.
In my simulink file, i used pid controller to control my process. I used s-function as my process block diagram.
According Ziegler-Nichols method, for the first step we set k equal to the smallest value (0.5) so I put 0.5 in my proportional value . but there is no different between the result with controller and without controller.Even i increase or decrease proportional value.
Why this problem occur? hope someone can help me.Thank you.
my block diagram is look like below picture.refer to this picture
http://s1009.photobucket.com/albums/af218/syarinazulkifeli/?action=view&current=Untitled-1.png
Here is my s-function file:
function [sys,x0,str,ts]= reactor_sfcn(t,x,u,flag)
switch flag
case 0
[sys,x0,str,ts]=mdlInitializeSizes;
case 1,
sys = mdlDerivatives(t,x,u);
case 3,
sys = mdlOutputs(t,x,u);
case 9
sys =[];
end
function [sys,x0,str,ts] = mdlInitializeSizes()
s = simsizes;
s.NumContStates = 11;
s.NumDiscStates = 0;
s.NumOutputs = 11;
s.NumInputs = 1;
s.DirFeedthrough = 0;
s.NumSampleTimes = 1;
sys = simsizes(s) ;
x0 = [0.0258,0,0,0,0,0,0,0,8.83,303.15,303.15];
str=[] ;
ts = [0 0];
function sys = mdlDerivatives (t,x,u)
Tjo = u;
sys = reactor(t,x,Tjo);
function sys = mdlOutputs(t,x,u)
% sys(1)=x(1);
% sys(2)=x(2);
% sys(3)=x(3);
% sys(4)=x(4);
% sys(5)=x(5);
% sys(6)=x(6);
% sys(7)=x(7);
% sys(8)=x(8);
% sys(9)=x(9);
% sys(10)=x(10);
% sys(11)=x(11);
sys = x;
Link of s-function file
function DXDT = reactor(t,x,Tjo)
% -------------------------------------------- %
% Parameters definition
% -------------------------------------------- %
I = x(1); X = x(2); P0 = x(3);
P1 = x(4); P2 = x(5); Q0 = x(6);
Q1 = x(7); Q2 = x(8); M = x(9);
Tjo = x(10); T = x(11);
% ---------------------------------------
% Constants
% =======================================
%constant
M0 = 8.83;
I0 = 0.0258;
Qh = 60.44;
MMWm = 100.3;
U0 = 55.1;
% Densities
dp = 1200;
dm = 968-1.225*(T-273.15);
Rhoc = 998;
% volume expansion factor
Fev = (dm - dp)./dp ;
% volume fraction
Fvm = (1 - X)./(1 + Fev*X);
Fvp = X*(1-Fev)./(1+Fev*X);
% Total reactant mixture density
Rho = dm*Fvm + dp*Fvp;
% Reactor and jacket volume
Vc = 2;
V = 2;
% Reactor dimension
At =3.1416*0.15*0.113;
% coolant flow rate
Mc = 0.41/18;
%
Cpc = 77.22;
Cp = 199.13;
% Average coolant temperature
Tji = 303.15;
Tj =(Tji+Tjo)/2;
% Overall heat transfer coeff
alpha = 0.4;
U = U0-alpha*X;
delHp = 57800;
% ---------------------------------------
% Rates of reaction
% =======================================
% Fujita-Doolittle equation
Tgp = 114 +273.25 ;
A = 0.168-8.21e-6*(T-Tgp)^2;
B = 0.03;
g = exp(2.303*Fvm/(A + B*Fvm));
% Dissociation rate
F = 0.58;
Kd = (6.32e16*exp(-15.43e3/T));
% Propagation rate
Tep = 5.4814e-16*exp(13982/T);
Kp0 = 2.952e7*exp(-4353/(1.987*T));
Kp = (Kp0*g)./(g + (Tep*P0.*Kp0));
% Termination rate
Tet = (1.1353e-22*exp(17420/T))./I0;
Kt0 = 5.88e9*exp(-701/(1.987*T));
Kt = (Kt0*g)./(g + (Tet*P0.*Kt0));
Ktc = 0;
Ktd = Kt ;
% -------------------------------------------- %
% ODE's
% -------------------------------------------- %
dIdt = -Kd*I - ((Fev*I.*P0.*(1 - X)*Kp)./(1 + Fev*X));
dXdt = Kp*(1 - X).*P0;
dP0dt = (-Fev*P0.*P0.*(1 - X)./(1 + Fev*X)).*Kp + 2*F*Kd*I - Kt*P0.*P0;
dP1dt = (-Fev*P0.*P1.*(1 - X)./(1 + Fev*X)).*Kp + 2*F*Kd*I - Kt*P0.*P1 + (Kp*M0*(1 - X)./(1 + Fev*X)).*P0;
dP2dt = (-Fev*P0.*P2.*(1 - X)./(1 + Fev*X)).*Kp + 2*F*Kd*I - Kt*P0.*P2 + (Kp*M0*(1 - X)./(1 + Fev*X)).*(2*P1 + P0);
dQ0dt = (-Fev*P0.*Q0.*(1 - X)./(1 + Fev*X)).*Kp + Ktd*P0.*P0 + 0.5*Ktc*P0.*P0;
dQ1dt = (-Fev*P0.*Q1.*(1 - X)./(1 + Fev*X)).*Kp + Ktd*P0.*P1 + Ktc*P0.*P1;
dQ2dt = (-Fev*P0.*Q2.*(1 - X)./(1 + Fev*X)).*Kp + Ktd*P0.*P2 + Ktc*(P1.*P0 + P1.^2);
dMdt = (-Kp*P0*M0*(1 - X)./(1 + Fev*X)).*((Fev*(1 - X)./(1 + Fev*X)) + 1);
Rm = (-delHp)*dMdt;
dTjodt = (Mc*Cpc*(Tji-Tjo)+ U*At*(T-Tj))/(Vc*Rhoc*Cpc/18);
dTdt = (Qh+(Rm*V*MMWm)-(U*At*(T-Tj)))/(V*Rho*Cp);
DXDT =[dIdt;dXdt;dP0dt;dP1dt;dP2dt;dQ0dt;dQ1dt;dQ2dt;dMdt;dTjodt;dTdt];
First I woult check if the s-function for the process is working as expected. Disconnect the PID controller and connect a step, ramp or a sin block. This could give you a hint if the block for the process is OK and how large the static coefficient is.
A second hint: the Ziegler-Nichols method says one should increase the Kp until the system gets marginaly stable. Have you tested only one value for the proportional gain? Depending on the plant 0.5 can be really small value and way under the levels you need to control the system.
You change the Kp term but there is no change...did you give the system a step command? Is the actual and desired signal error being fed back to the PID controller? If these are satisfied and the system is still insensitive to Kp you may need to go through your model block by block to find the issue. Also, why are you modelling your plant with an S function? Implementing these can be tricky. I would much rather see the plant model in diagram form, or at least in embedded m.
For the step input I would recommend this link or google it. You need to set the Kp fairly high and then give it a step command input to destabilize the system and then vary Kp until it's stable and measure the period of oscillation.
I put together a toy model for you to test, I am inclined as well to beleive your s-function is at fault here. If you want to post/send the sfunction, I'd be glad to look at it. However, if you want to learn Ziegler-Nichols, start with a very simple model and follow the steps in the Ziegler-Nichols process. Here's the output for some of my data with a Kp = 200 and a plant of 1/(s+1):
So you can see the oscillation above. Kp = 200 is way too high, you'd have to reduce it quite a bit for Ziegler-Nichols, but I just wanted to give you an example.
EDIT I downloaded your readtor_sfcn and reactor function into two files named
reactor_sfcn.m and reactor.m Right away, I can tell why you never see any
change in the input. In the reactor_sfcn mdlDerivatives, you pass the input
to the system u as the third parameter to the reactor function. In the
reactor function I can see that the third parameter, Tjo is never read,
but overwritten with x(10). So, if Tjo is supposed to be the input parameter
it shouldn't also be a state. That will be up to you to solve that problem,
it is specific to your implementation of the plant. I've got a test model
I've used to look at your files, I'll try to put it somewhere you can get
access to it soon, but it likely won't be as useful as you analyzing what
the plant is supposed to be doing. Hope this helps!
Thanks!