I'm trying to create a model in OpenModelica which contains several other components (pipes, reservoirs). Currently I'm modifying a pipe in the Modelica.Fluid-library using a staggered grid, and need to determine the smallest step size dx in the entire model.
Is it possible to do the following?
Calculate dx_1 in pipe 1 and dx_2 in pipe 2.
Send dx_1 and dx_2 to an array in a global model (similar to Modelica.Fluid.System).
Determine the smallest dx = min(dx_1, dx_2) and send back to both pipe 1 and pipe 2.
I have calculated both dx_1 in pipe 1 and dx_2 in pipe 2, and created an array in a data storage model similar to Fluid.System. I am, however, struggling with sending the step sizes to the data storage model, and sending them back again after determining the smallest dx.
Is this even possible? How would one go about to do so?
Yes, there are several possibilities.
As you mention, the pipes can access variables/parameters in the data storage model if this is instantiated as inner in your global model and declared as outer in each pipe model. As with the Modelica.Fluid models referring to Fluid.System, the pipes can access dx_minin the data storage model.
This is a code example, loosely based on your question:
model Pipe
outer DataStorage dataStorage;
Real dx_min = dataStorage.dx_min;
Real dx "calculated in this model";
...
end Pipe;
model DataStorage
parameter Integer nPipes;
input Real dx_array[nPipes];
Real dx_min=min(dx_array);
...
end DataStorage;
model GlobalModel
Pipe pipe1;
Pipe pipe2;
inner DataStorage dataStorage(nPipes=2, dx_array={pipe1.dx, pipe2.dx});
...
end GlobalModel;
You should beware of the variability of the different "dx's" as you cannot assign a time-varying "dx" to a "dx" declared as a parameter.
If the only purpose of the DataStorage model is to take the minimum entry in an array then you could also put its three lines of code in GlobalModel, reducing the code to:
model Pipe
input Real dx_min;
Real dx "calculated in this model";
...
end Pipe;
model GlobalModel
parameter Integer nPipes=2;
Real dx_array[nPipes]={pipe1.dx, pipe2.dx};
Real dx_min=min(dx_array);
Pipe pipe1(dx_min=dx_min);
Pipe pipe2(dx_min=dx_min);
...
end GlobalModel;
Related
I have a model using a timeTable which represents a variable evolution. I would like to initialize a subcomponent's parameter with the first value of the table (time = 0 second).
The table's values are read from a .txt file. The idea would be to have a command as follow :
parameter Real InitialValue = timeTable.y[2](for timeTable.y[1] = 0)
Is there a command to do so ?
In some cases another option is to initialize the parameter at the output value of that table-component when starting the simulation:
model Demo
Modelica.Blocks.Sources.TimeTable timeTable(table=[0,1; 2,3]);
parameter Real initialValue(fixed=false);
initial equation
initialValue = timeTable.y;
end Demo;
This works for all variants in the same way, but only for the initial value. It is triggered by having fixed=false for a parameter and then giving an initial equation for it.
The solution depends on the block you are using and how the data is defined. Note that there is no easy solution for .txt files, so I recommend using .mat files instead.
1. Data from model
If you don't read from a file it is quite easy.
The data is stored as matrix in the parameter table and we can use array indexing to access it:
model Demo
Modelica.Blocks.Sources.TimeTable timeTable(table=[0,1; 2,3]);
parameter Real initialValue = timeTable.table[1, 2];
end Demo;
This works for both, the Modelica.Blocks.Sources.TimeTable and the CombiTimeTable found in the same package.
2. Data from .mat file
The MSL provides functions to access .mat files. You have to get the table size before you can read the data.
See the code below how this can be done.
model Demo2
import Modelica.Utilities.Streams.{readMatrixSize, readRealMatrix};
parameter String fileName = "C:/tmp/table.mat";
parameter String tableName = "tab1";
parameter Real initialValue = (readRealMatrix(fileName=fileName, matrixName=tableName, nrow=matrixSize[1], ncol=matrixSize[2]))[1, 2];
Modelica.Blocks.Sources.CombiTimeTable combiTimeTable(
tableOnFile=true,
tableName=tableName,
fileName=fileName)
annotation (Placement(transformation(extent={{-10,-10},{10,10}})));
protected
final parameter Integer matrixSize[2] = readMatrixSize(fileName, tableName);
end Demo2;
Note that we don't store the whole table in a variable. Instead,
we read it and access the element of intereset with [1, 2]. This requires putting brackets around the function call.
I am dynamically storing data from different data recorders in timetables, nested in a structure DATA, such as DATA.Motor (timetable with motor data), DATA.Actuators (timetable with actuators data) and so on.
My objective is to have a function that synchronizes and merges these timetables so I can work with one big timetable.
I am trying to use synchronize to merge and synchronize those timetables:
fields = fieldnames(DATA);
TT = synchronize(DATA.(fields{1:end}));
but get the following error:
Expected one output from a curly brace or dot indexing expression, but there were 3 results.
This confuses me because DATA.(fields{1}) return the timetable of the first field name of the DATA structure.
Any thought on how I can solve this is greatly appreciated.
The problem here is that fields{1:end} is returning a "comma-separated list", and you're not allowed to use one of those as a struct dot-index expression. I.e. it's as if you tried the following, which is not legal:
DATA.('Motor','Actuators')
One way to fix this is to pull out the values from DATA into a cell array, and then you can use {:} indexing to generate the comma-separated list as input to synchronize, like this:
DATA = struct('Motor', timetable(datetime, rand), ...
'Actuators', timetable(datetime, rand));
DATA_c = struct2cell(DATA);
TT = synchronize(DATA_c{:});
I have a simulink model which I am running through a function , all the values to the blocks are assigned from within the function using assignin() function , now I want to retrieve the resulting data which is which is automatically saved in the workspace after simulation(I am using 'To workspace' block which stores the simulated result in a vector) , now I want to retrieve this data right after the simulation with the function. I used evalin() to retrieve the data from the workspace but it doesn't seem to work as it says the variable is undefined
I found the solution to the problem , Before I simulate the data I should enable the signal logging for the output first , then assign the simulation output to a variable as an object
FO =sim(filename,time);
after that I can retrieve the data variable to which the singal was logged from the simulation object
FT = FO.get('FT');
this works even with in a function unlike the 'To workspace' block
I am trying to find a better solution to calculation using data stored in table. I have a large table with many variables (100+) from which I select smaller sub-table with only two observations and their difference for smaller selection of variables. Thus, the resulting table looks for example similarly to this:
air bbs bri
_________ ________ _________
test1 12.451 0.549 3.6987
test2 10.2 0.47 3.99
diff 2.251 0.078999 -0.29132
Now, I need to multiply the ‘diff’ row with various coefficients that differ between variables. I can get the same result with the following code:
T(4,:) = array2table([T.air(3)*0.2*0.25, T.bbs(3)*0.1*0.25, T.bri(3)*0.7*0.6/2]);
However, I need more flexible solution since the selection of variables will differ between applications. I was thinking that better solution might be using either varfun or rowfun and speficic function that would assign correct coefficients/equations based on variable names:
T(4,:) = varfun(#func, T(3,:), 'InputVariables', {'air' 'bbs' 'bri'});
or
T(4,:) = rowfun(#func, T(3,:), 'OutputVariableNames', T.Properties.VariableNames);
However, the current solution I have is similarly inflexible as the basic calculation above:
function [air_out, bbs_out, bri_out] = func(air, bbs, bri)
air_out = air*0.2*0.25;
bbs_out = bbs*0.1*0.25;
bri_out = bri*0.7*0.6/2;
since I need to define every input/output variable. What I need is to assign in the function coefficients/equations for every variable and the ability of the function to apply it only to the variables that are present in the specific sub-table.
Any suggestions?
I have the following MATLAB code that is used to aid in creating a wireless sensor network:
for i=1:n
S(i).xb=rand*0.5*xm;
S(i).yb=rand*0.5*ym;
S(i).E=Eo;
S(i).G=0;
S(i).type='N';
S(i).id=i;
S(i).D=dist(BS.x,BS.y,S(i).xb,S(i).yb);
S(i).Etx=Eelec*k+Eamp*k*S(i).D^2;
plot(S(i).xb,S(i).yb,'o');
end
plot(BS.x,BS.y,'rx');
In this program, why are there dots in the code? For example, S(i).xb=rand*0.5*xm;. Can anyone explain this to me?
In this code, S will be an array of structures. Each structure will contain the following member variables:
xb
yb
E
G
type
id
D
Etx
Doing S(i).xb = rand*0.5*xm; will first create a structure within the array S at location i that contains a single member xb. This will be assigned the value of rand*0.5*xm. The rest of the statements will keep appending more variables to the same structure at location i in the array.
After, if you wish to access the member variable at location i for the array S, you would still do S(i).xb, or S(i).yb, etc.
Essentially, you can think of S as having an array of elements where each element has 8 fields within the element. You'd access a field by using the ..