Tags and keywords
The Modelica By Example target code is:
within ModelicaByExample.Components.BlockDiagrams.Examples;
model NewtonCooling "Newton cooling system modeled with blocks"
import Modelica.SIunits.Conversions.from_degC;
parameter Real h = 0.7 "Convection coefficient";
parameter Real A = 1.0 "Area";
parameter Real m = 0.1 "Thermal mass";
parameter Real c_p = 1.2 "Specific heat";
parameter Real T_inf = from_degC(25) "Ambient temperature";
Components.Integrator T(y0=from_degC(90))
annotation ...
Components.Gain gain(k=-1)
annotation ...
Components.Constant ambient(k=T_inf)
annotation ...
Components.Sum sum(nin=2)
annotation ...
Components.Gain gain1(k=h*A/(m*c_p))
annotation ...
equation
connect(T.y, gain.u) annotation ...
connect(sum.y, gain1.u) annotation ...
connect(gain.y, sum.u[2]) annotation ...
connect(ambient.y, sum.u[1]) annotation ...
connect(gain1.y, T.u) annotation ...
end NewtonCooling;
The Modelica By Example page also gives this patch diagram:
This page contains content quoted, copied, or adapted for educational purposes from the Modelica By Example tutorials for educational purposes. The original © copyright is retained by Dr. Michael M. Tiller.
Looks pretty simply, right? The only tricky part is that the gain factor k
of gain1
is initialised from other parameters owned by the same model/block:
Components.Gain gain1(k=h*A/(m*c_p))
It turns out that MagicDraw/Cameo handles this fine if you use an OpaqueExpression on the Slot of the instance that supplies the Context-Specific Value for the 'start'. Setting an OpaqueExpression on a Slot in the tool is a bit fiddly:
The exported Modelica code for the SysML/SysPhS block NewtonCoolingWithBlocks
is:
model NewtonCoolingWithBlocks
NewtonCoolingWithBlocks _NewtonCoolingWithBlocks;
model NewtonCoolingWithBlocks
Gain gain(k.start=-1.0,k.fixed=true);
Integrator t(y.start=363.15,y.fixed=true);
parameter ConvectionCoefficient h(start=0.7,fixed=true);
parameter Area a(start=1.0,fixed=true);
parameter Mass m(start=0.1,fixed=true);
parameter SpecificHeat c_p(start=1.2,fixed=true);
parameter Temperature _t_inf(start=298.15,fixed=true);
Gain gain1(k.start=h*a/(m*c_p),k.fixed=true);
Constant ambient(k.start=298.15,k.fixed=true);
Add add;
parameter Real kGain1(start=h*a/(m*c_p),fixed=true);
equation
connect(add.y,gain1.u);
connect(gain1.y,t.u);
connect(t.y,gain.u);
connect(gain.y,add.u1);
connect(ambient.y,add.u2);
end NewtonCoolingWithBlocks;
model Gain
extends SISO;
parameter Real k;
equation
y=k*u;
end Gain;
model Integrator
extends SISO;
parameter Real _y0;
equation
der(y)=u;
end Integrator;
type ConvectionCoefficient=Real(unit="W/(m2.K)");
type Area=Real(unit="m2");
type Mass=Real(unit="kg");
type SpecificHeat=Real(unit="J/(K.kg)");
type Temperature=Real(unit="K");
model Constant
extends SO;
parameter Real k;
equation
y=k;
end Constant;
model Add
extends DISO;
equation
y=u1+u2;
end Add;
model SISO
Modelica.Blocks.Interfaces.RealInput u;
Modelica.Blocks.Interfaces.RealOutput y;
end SISO;
model SO
Modelica.Blocks.Interfaces.RealOutput y;
end SO;
model DISO
Modelica.Blocks.Interfaces.RealInput u1;
Modelica.Blocks.Interfaces.RealOutput y;
Modelica.Blocks.Interfaces.RealInput u2;
end DISO;
end NewtonCoolingWithBlocks;
The parameter _t_inf
is «UNUSED», the start value is defined directly on the rSig
within the y
Port of Integrator
, but you can't see it because of:
You may have noticed that instead of using the Modelica from_degC()
function the Celsius to Kelvin offsets have been done by hand. You're most welcome to get all disco and do it with a SysML ConstraintBlock as an exercise.