How to setup library-application including extend/redeclare in OpenModelica? - openmodelica

I have Modelica code divided in a small library DEMO_v11.mo and an application D11_APP7.mo The application code include parts that adapt interface of the library to the application using: import-extend-redeclare. It all works in JModelica. Now I want to set it up in OpenModelica but I do not know how to handle my two different files. Browsing through the documentation I could find little help.
I have before managed to bring in a library and in OpenModelica add graphical notation and then compose a new model based on components from the library.
However, now I need to do a more “advanced” import that extend-redeclare the imported models. Thus my problem is how to do this more “advanced” part.
Appreciate some advice, or suggestion on where to read.

The answer to this questions I have found is both easy and difficult.
The easy part is that you should in OpenModelica load both the library and application code in the same way using command “File/Open Modelica/Library File(s). Then the library and the application land side by side, sort of. The icons for them appear in the pane to the left and below the MSL library Modelica. The application code can then import (and redeclare) from both the loaded library and from MSL if needed in a similar way.
The difficult part is that here seems to be bugs in OpenModelica when you refer to models in two (or more) steps instead of one. This question I discuss with OpenModelica support.
A code that works to import as described above are library DEMO_v15 and application D15_app7 and shown below (and slightly modified from DEMO_v11 and D11_app7 mentioned and described in another thread).
package DEMO_v15
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium2
replaceable constant String name = "Two components" "Medium name";
replaceable constant Integer nc = 2 "Number of substances";
replaceable type Concentration = Real[nc] "Substance conc";
replaceable constant Real[nc] mw = {10, 20} "Substance weight";
constant Integer A = 1 "Substance index";
constant Integer B = 2 "Substance index";
end Medium2;
package Medium3
import M2 = DEMO_v15.Medium2;
extends M2
(name="Three components" "Medium name",
nc=3 "Number of substances",
mw = cat(1,M2.mw,{30}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
end Medium3;
connector LiquidCon3
Medium3.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon3;
// ---------------------------------------------------------------------------------------------
// Equipment dependent on the medium
// ---------------------------------------------------------------------------------------------
package Equipment
replaceable connector LiquidCon
end LiquidCon;
model PumpType
LiquidCon inlet, outlet;
RealInput Fsp;
equation
inlet.F = Fsp;
connect(outlet, inlet);
end PumpType;
model FeedtankType
LiquidCon outlet;
constant Integer medium_nc = size(outlet.c,1);
parameter Real[medium_nc] c_in (each unit="kg/m3")
= {1.0*k for k in 1:medium_nc} "Feed inlet conc";
parameter Real V_0 (unit="m3") = 100 "Initial feed volume";
Real V(start=V_0, fixed=true, unit="m3") "Feed volume";
equation
for i in 1:medium_nc loop
outlet.c[i] = c_in[i];
end for;
der(V) = outlet.F;
end FeedtankType;
model HarvesttankType
LiquidCon inlet;
constant Integer medium_nc = size(inlet.c,1);
parameter Real V_0 (unit="m3") = 1.0 "Initial harvest liquid volume";
parameter Real[medium_nc] m_0
(each unit="kg/m3") = zeros(medium_nc) "Initial substance mass";
Real[medium_nc] c "Substance conc";
Real[medium_nc] m
(start=m_0, each fixed=true) "Substance mass";
Real V(start=V_0, fixed=true, unit="m3") "Harvest liquid volume";
equation
for i in 1:medium_nc loop
der(m[i]) = inlet.c[i]*inlet.F;
c[i] = m[i]/V;
end for;
der(V) = inlet.F;
end HarvesttankType;
end Equipment;
// ---------------------------------------------------------------------------------------------
// Control
// ---------------------------------------------------------------------------------------------
package Control
block FixValueType
RealOutput out;
parameter Real val=0;
equation
out = val;
end FixValueType;
end Control;
// ---------------------------------------------------------------------------------------------
// Adaptation of package Equipment to Medium3
// ---------------------------------------------------------------------------------------------
// package Equipment3 = Equipment(redeclare connector LiquidCon=LiquidCon3); // Just shorter
package Equipment3
import DEMO_v15.Equipment;
extends Equipment(redeclare connector LiquidCon=LiquidCon3);
end Equipment3;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
model Test
Medium3 medium;
Equipment3.FeedtankType feedtank;
Equipment3.HarvesttankType harvesttank;
Equipment3.PumpType pump;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end DEMO_v15;
And application code:
encapsulated package D15_app7
// ---------------------------------------------------------------------------------------------
// Interfaces
// ---------------------------------------------------------------------------------------------
import Modelica.Blocks.Interfaces.RealInput;
import Modelica.Blocks.Interfaces.RealOutput;
package Medium7
import M2 = DEMO_v15.Medium2;
extends M2
(name = "Seven components" "Medium name",
nc = 7 "Number of substances",
mw = cat(1,M2.mw,{30,40,50,60,70}) "Substance weight",
redeclare type Concentration = Real[nc] "Substance conc");
constant Integer C = 3 "Substance index";
constant Integer D = 4 "Substance index";
constant Integer E = 5 "Substance index";
constant Integer F = 6 "Substance index";
constant Integer G = 7 "Substance index";
end Medium7;
connector LiquidCon7
Medium7.Concentration c "Substance conc";
flow Real F (unit="m3/s") "Flow rate";
end LiquidCon7;
// ---------------------------------------------------------------------------------------------
// Adaptation of library DEMO_v15 to Medium7
// ---------------------------------------------------------------------------------------------
package Equipment7
import DEMO_v15.Equipment;
extends Equipment(redeclare connector LiquidCon=LiquidCon7);
end Equipment7;
// ---------------------------------------------------------------------------------------------
// Examples of systems
// ---------------------------------------------------------------------------------------------
import DEMO_v15.Control;
model Test
Medium7 medium; // Instance not necessary but helpful for user interface
Equipment7.PumpType pump;
Equipment7.FeedtankType feedtank;
Equipment7.HarvesttankType harvesttank;
Control.FixValueType Fsp(val=0.2);
equation
connect(feedtank.outlet, pump.inlet);
connect(pump.outlet, harvesttank.inlet);
connect(Fsp.out, pump.Fsp);
end Test;
end D15_app7;

Related

FiPy Setting outflow condition the correct way

I need some help with a quiete simple problem in FiPy. My goal is to simulate a fluid flowing through a concrete block while phase change.
But first of all I tried to do a simple 1D simulation assumed a fluid massflow and a constant wall temperature without any phase change.
from fipy import *
from fipy.meshes import CylindricalGrid2D, Grid1D
import matplotlib.pyplot as plt
import numpy as np
#%%
L = 1.5 #length transfer surface
bS = 0.75 #wide
AV = L * bS #transfer surface
tS0 = 350. #tWall
rhoWF = 880. #density fluid
mWF = 0.036 #mass flow
u = 5e-4 #Fluid speed
hWF = mWF / AV / rhoWF / u #height "fluid block"
nx = 50
VWF = hWF * L * bS/nx #fluid volumen
lambdaWF = 0.6 # thermal conductivity
alpha = 500. #heat transfer coefficient
tWF0 = 371.
mesh = Grid1D(dx=L/nx, nx=nx)
tWF = CellVariable(name="Fluid",
mesh=mesh,
value= tWF0,
hasOld=True)
tS = CellVariable(name="storage",
mesh=mesh,
value=tS0,
hasOld=True)
sourceWF=CellVariable(name="source Fluid", #Variable der Konvektion
mesh=mesh,
value=0.)
cvrho = CellVariable(name = 'cprho',#Fluid
mesh = mesh,
value = rhoWF * 4215.2,
hasOld = True)
tWF.constrain(tWF0, mesh.facesLeft()) #constant inlet temperature
t = 6*3600. #time
timeStepDuration = 1e2
#outflow boundary condition
outlet = mesh.facesRight
ConvCoeff = FaceVariable(mesh,value=u,rank=1)
exteriorCoeff = FaceVariable(mesh,value=0.,rank=1)
exteriorCoeff.setValue(value=ConvCoeff, where=outlet)
ConvCoeff.setValue(0., where=outlet)
residual1 = 1.
elapsedTime = 0.
tWFall = np.zeros(nx)[None,:]
while elapsedTime < t:
tWF.updateOld()
it = 0 #iterations
while residual1> 1e-2:
sourceWF.value = - AV / nx * alpha*(tWF - tS)/ cvrho / VWF #this will be a variable convection source
eq1 = HybridConvectionTerm(coeff=ConvCoeff) + TransientTerm(coeff=1.) == \
+ sourceWF\
- ImplicitSourceTerm(exteriorCoeff.divergence) \
#+ DiffusionTerm(coeff= lambdaWF / cvrho) #not necessary(?)
residual1 = eq1.sweep(dt = timeStepDuration, var = tWF)
print('res1: ' + str(residual1) )
it += 1
if it > 10:
raise ValueError (r'MaxIter reached')
elapsedTime += timeStepDuration ; print('t= ' + str(round(elapsedTime,2)))
residual1 = 1.
tWFall = np.r_[tWFall, tWF.value[None,:]] #value collection
#%% outlet fluid temperature and storage temperature
plt.plot(np.linspace(0,t/3600.,int(t/timeStepDuration)), tWFall[1:,-1], label=r'$\vartheta_{WF}$')
plt.legend()
I would expect a constant fluid outlet temperature because of the constant wall temperature and constant fluid inlet temperature. I have not defined the wall temperature as a boundary condition because some day I would like to analyse heat conduction and variable temperature gradients too. Running my mwe you can see that the fluid temperature at the outlet declines.
Could someone please help at this case?
Thanks in advance!
I changed the script around and it seem to give a constant temperature of 371.0. See this link.
The sourceWF term has been removed. I was unsure what this was for, but I think it would take time for the wall temperature to adjust to this.
The equation declaration has been moved outside the loop. This is the correct way to use FiPy, but shouldn't impact the results in this case.

Instantiate OpenModelica model inside package from command line (omc)

I am trying to create the flat modelica code of a model, which is inside a package from the command line using open modelica (omc).
If I have a .mo-file which contains just one model I can easily create the instantiation by
omc myModel.mo > myModel.mof
The question is if I have this file:
package TestPackage
model TestModel2
Real y;
end TestModel2;
model TestModel
Real x(start=1);
TestModel2 a;
equation
x=a.y;
der(x)=a.y;
end TestModel;
end TestPackage;
how do i create the flat code for TestModel?
(Using OMEdit I get the correct code by instantiating TestModel:
class TestPackage.TestModel
Real x(start = 1.0);
Real a.y;
equation
x = a.y;
der(x) = a.y;
end TestPackage.TestModel;
)
Basically as I said in the comment +i=Path.To.Model:
adrpo#dev MINGW64 ~/dev/OpenModelica/build/bin
$ ./omc +i=TestPackage.TestModel myModel.mo
class TestPackage.TestModel
Real x(start = 1.0);
Real a.y;
equation
x = a.y;
der(x) = a.y;
end TestPackage.TestModel;

Verilog code for Clarke and Park transformations

I want to write verilog code for Clarke and Park transformations for the implementation of a foc algorithm. I am new to verilog and I am failing to understand how to write the code for such complex equations which involve cos,sin functions and real numbers. Can someone please give me a start? The verilog code I tried to write is below.
timescale 1ns/1ps
module clarke_park(iR_i,iY_i,iB_i,theta,iD_o,iQ_o);
output real iD_o;
output real iQ_o;
input real iR_i;
input real iY_i;
input real iB_i;
real k = 0.66;
output real ialpha;
output real ibeta;
output real iY_r;//real part
output real iY_c;//complex part
output real iB_r;
output real iB_c;
output real ibeta_r;
output real ibeta_c;
function sin(input real theta);
function cos(input real theta);
iY_r = -1*(iY_i)*(0.5);
iY_c = (iY_i)*(0.866);
iB_r = -1*(iB_i)*(0.5);
iB_c = -1*(iB_i)*(0.866);
ialpha = k*iR;
ibeta_r = k*(0.866)*(iY_r-iB_r);
ibeta_c = k*(0.866)*(iY_c-iB_c);
real a1 = sin(theta);
real a2 = cos(theta);
iD_r = (a1*(ialpha)) + ((sin(theta))*(ibeta_r));
iD_c = a2*(ibeta_c);
iQ_r = - (1*a2*(ialpha)) + (a1*(ibeta_r));
iQ_c = a1*(ibeta_c);
endfunction
assign iD_o = {iD_r,iD_c};
assign iQ_o = {iQ_r,iQ_c};
endmodule
I would start with something like this:
module clarke_park(
output real iD_o,
output real iQ_o,
input real iR_i,
input real iY_i,
input real iB_i,
output real ialpha,
output real ibeta,
output real iY_r,//real part
output real iY_c,//complex part
output real iB_r,
output real iB_c,
output real ibeta_r,
output real ibeta_c
);
localparam k = 0.66;
Not sure what you are trying to do with the functions. but something like:
but note you have not defined theta, it was in you port list but then not defined as input or a real.
real a1;
real a2;
always #* begin
iY_r = -1*(iY_i)*(0.5);
iY_c = (iY_i)*(0.866);
iB_r = -1*(iB_i)*(0.5);
iB_c = -1*(iB_i)*(0.866);
ialpha = k*iR;
ibeta_r = k*(0.866)*(iY_r-iB_r);
ibeta_c = k*(0.866)*(iY_c-iB_c);
a1 = $sin(theta);
a2 = $cos(theta);
iD_r = (a1*(ialpha)) + ((sin(theta))*(ibeta_r));
iD_c = a2*(ibeta_c);
iQ_r = - (1*a2*(ialpha)) + (a1*(ibeta_r));
iQ_c = a1*(ibeta_c);
end
$cos and $sin are described in section 20.8 of ieee 1800-2012.

Use topographical sort with alloy 4.2

I'm trying to use topological sort to find two different sequential schedules that follow their prereqs. When I execute the code no instances are found and I'm not sure why. Here's my code:
open util/relation
abstract sig Course {
prereq: set Course, -- c->d in prereq if c is a prerequisite of d
s1, s2: set Course -- two sequential course schedules
}
one sig cs1121, cs1122, cs1141, cs2311, cs2321,
cs3000, cs3141, cs3311, cs3331, cs3411, cs3421, cs3425 extends Course { }
fact {
no prereq.cs1121
prereq.cs1122 = cs1121
prereq.cs1141 = cs1122
prereq.cs2311 = cs1121
prereq.cs2321 = cs1122
prereq.cs3000 = cs3141
prereq.cs3141 = cs2311
prereq.cs3141 = cs2321
prereq.cs3311 = cs2311
prereq.cs3331 = cs1141
prereq.cs3331 = cs2311
prereq.cs3331 = cs2321
prereq.cs3411 = cs1141
prereq.cs3411 = cs3421
prereq.cs3421 = cs1122
prereq.cs3425 = cs2311
prereq.cs3425 = cs2321
}
-- is the given schedule a topological sort of the prereq relation?
pred topoSort [schedule: Course->Course] {
(all c: Course | lone c.schedule and lone schedule.c) -- no branching in the schedule
and totalOrder[*schedule, Course] -- and it's a total order
and prereq in ^schedule -- and it obeys the prerequisite graph
}
pred show {
s1.irreflexive and s2.irreflexive -- no retaking courses!
s1.topoSort and s2.topoSort -- both schedules are topological sorts of the prereq relation
s1 != s2 -- the schedules are different
}
run show
Switch the solver (under the Options menu) to MiniSAT with Unsat Core, then look at the core. You'll see it highlights
prereq.cs3141 = cs2311
prereq.cs3141 = cs2321
which contradicts your no branching rule.

μ-Law algorithm implementation

Here is Mu-Law encoder taken from NAudio. The question is how is this formula same with the code? I can understand that MuLawCompressTable is actually the Log but I dont get the thing about mantissa why it is taken as is.
private const int cBias = 0x84;
private const int cClip = 32635;
private static readonly byte[] MuLawCompressTable = new byte[256]
{
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
public static byte LinearToMuLawSample(short sample)
{
//We get the sign
int sign = (sample >> 8) & 0x80;
if (sign != 0)
sample = (short)-sample;
if (sample > cClip)
sample = cClip;
sample = (short)(sample + cBias);
int exponent = (int)MuLawCompressTable[(sample >> 7) & 0xFF];
int mantissa = (sample >> (exponent + 3)) & 0x0F;
int compressedByte = ~(sign | (exponent << 4) | mantissa);
return (byte)compressedByte;
}
They are different. See the Wikipedia page on mu-law, http://en.wikipedia.org/wiki/Mulaw
There are two forms of this algorithm—an analog version, and a quantized digital version.
You quote the formula for the "analog" version - a compressive mapping from -1..1 to -1..1, which emphasizes the basic idea of mu-law, i.e. that the quantized value encodes more detail (uses a smaller quantization step) for smaller values, so the introduced quantization error is roughly proportional to the overall amplitude of the signal.
The "digital" version is a piecewise-linear approximation to this basic idea, with some additional shifts to further simplify processing.
Here's a plot comparing the two. You can see the stairsteps in the green line (mu_digital) corresponding to the discrete 7-bit values, and you also spot the different linear sections approximating the smooth blue line.

Resources