Modelica (Dymola) : get a particular value of a timetable? - modelica

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.

Related

Write Matrix Data to Each Member of Datatype in HDF5 file via MATLAB

This is my first go at trying to create an HDF5 file from scratch using the Low-Level commands via MATLAB.
My issue is that I am having a hard time trying to write data to each specific member in the datatype on my dataset.
First, I create a new HDF5 file, and set the right layer of groups:
new_h5 = H5F.create('new_hdf5_file.h5','H5F_ACC_TRUNC','H5P_DEFAULT','H5P_DEFAULT');
new_h5 = H5G.create(new_h5,'first','H5P_DEFAULT','H5P_DEFAULT','H5P_DEFAULT');
new_h5 = H5G.create(new_h5,'second','H5P_DEFAULT','H5P_DEFAULT','H5P_DEFAULT');
Then, I create my datatype:
datatype = H5T.create('H5T_compound',20);
H5T.insert(datatype,'first_element',0,'H5T_NATIVE_INT');
H5T.insert(datatype,'second_element',4,'H5T_NATIVE_DOUBLE');
H5T.insert(datatype,'third_element',12,'H5T_NATIVE_DOUBLE');
Then, I format that into my dataset:
new_h5 = H5D.create(new_h5,'location',datatype,H5S.create('H5S_SCALAR'),'H5P_DEFAULT');
subset = H5D.get_type(H5D.open(new_h5,'/first/second/location'));
mem_type = H5T.get_member_type(subset,0);
I receive an error with the following command:
H5D.write(mem_type,'H5ML_DEFAULT','H5S_ALL','H5S_ALL','H5P_DEFAULT',data);
Error using hdf5lib2
Unhandled HDF5 class (H5T_NO_CLASS) encountered. It is not possible to write to this attribute or dataset.
So, I try this method instead:
new_h5 = H5D.create(new_h5,'location',datatype,H5S.create_simple(2,dims,dims),'H5P_DEFAULT'); %where dims are the dimensions of all matrices of data structure
H5D.write(mem_type,'H5ML_DEFAULT','H5S_ALL','H5S_ALL','H5P_DEFAULT',data); %where data is a structure
I receive an error with this following command:
H5D.write(mem_type,'H5ML_DEFAULT','H5S_ALL','H5S_ALL','H5P_DEFAULT',data);
Error using hdf5lib2
Attempted to transfer too many values to or from the library buffer.
When looking here for the XML tags for the error messages, it describes the above error as "illegalArrayAccess." Apparently, according to this question, you can only write to 4 members without the buffer throwing an error?
Is this correct? How can I correctly write to each member. I am about to reach my mental limit trying to figure this one out.
EDIT:
References kept here for general information:
HDF5 Compound Datatypes Example
HDF5 Compount Datatypes
H5D.write MATLAB Command
I found out why I cannot write data. I have solved the problem. I had my dimensions set incorrectly (which is code I forgot to include originally). My apologies. I had my dimensions like this:
dims = fliplr(size(data_matrix));
Where dims was a 15x250 matrix. The error was in that the buffer was unable to write a 250x15 matrix for each member, because it only had data for a 250x1 for each member.
The following code will (generically) work for writing data to each member:
new_h5 = H5F.create('new_hdf5_file.h5','H5F_ACC_TRUNC','H5P_DEFAULT','H5P_DEFAULT');
new_h5 = H5G.create(new_h5,'first','H5P_DEFAULT','H5P_DEFAULT','H5P_DEFAULT');
new_h5 = H5G.create(new_h5,'second','H5P_DEFAULT','H5P_DEFAULT','H5P_DEFAULT');
datatype = H5T.create('H5T_compound',20);
H5T.insert(datatype,'first_element',0,'H5T_NATIVE_INT');
H5T.insert(datatype,'second_element',4,'H5T_NATIVE_DOUBLE');
H5T.insert(datatype,'third_element',12,'H5T_NATIVE_DOUBLE');
dims = fliplr(size(data_matrix)); dims = [1 dims(1,2)];
new_h5 = H5D.create(new_h5,'location',datatype,H5S.create_simple(2,dims,dims),'H5P_DEFAULT');
H5D.write(new_h5,'H5ML_DEFAULT','H5S_ALL','H5S_ALL','H5P_DEFAULT',data_structure);
where data_matrix is a 15x250 matrix containing all data, and where data_structure is a sctucture containing 15 fields, each 250x1 in size.

Orange3 : String Variable

I do not manage to create an Orange table with StringVariables.
The following code:
d = Orange.data.Domain([Orange.data.StringVariable("s")])
makes this error:
TypeError: variables must be primitive
It seems that StringVariable is for metadata only. So I'm worried about this because my data has a lot of strings that it would be crazy to put in a discrete structure (each string value is different).
Is there a solution for putting strings in a table ?
Thanks in advance for the answers,
Best,
mike
This question might be old but I found it via Google and wanted to provide a simple example of how to use meta "columns".
You need to specify the meta variables the same way you specify the "normal" variables just do it inside the metas parameter inside the Domain constructor.
from Orange.data import *
taskid = StringVariable(name="taskid")
logdata = StringVariable(name="logdata")
domain = Domain([] , metas=[taskid, logdata])
data = Table(domain, [
["uuid1","some more stuff"],
["uuid2","some more stuff"]
]);
out_data = data;

Modify one odeset parameter

I am using ode15s to solve a DAE problem. I give through odeset the Mass Matrix and some more info:
opts=odeset('Mass',M,'MassSingular','yes','MStateDependence','none');
I calculate also Jpattern from a previous run. To feed it to the function, I could write once again
opts=odeset('Mass',M,'MassSingular','yes','MStateDependence','none', 'JPattern',JPat);
Is there a way to modify that single parameter and keep the rest of the structure?
I tried
opts.JPattern = JPat;
But it is not working.
You can probably do something like:
opts = odeset('Mass',M,'MassSingular','yes','MStateDependence','none');
opts = odeset(opts,'JPattern',JPat);
This is using the syntax (see the documentation):
options = odeset(oldopts,'name1',value1,...) alters an existing
options structure oldopts. This sets options equal to the existing
structure oldopts, overwrites any values in oldopts that are
respecified using name/value pairs, and adds any new pairs to the
structure. The modified structure is returned as an output argument.

Matlab - using a function mulitple times in the same workspace, to add values and fields to a structure

I have a structure such as:
specimen.trial1 = 1
I now want to add another trial to the specimen, so that
specimen.trial1 = 1
specimen.trial2 = 2
I can do this without a problem within the workspace and command window. But, if I'm using a function to calculate the numbers for each trial (with dynamic fields), the new field and value erases the previous one. Eg:
function [specimen] = dummy(trial,value)
specimen.(trial) = value
end
run the function:
[specimen] = dummy('trial1',1)
then run the function again with different inputs, but keeping the structure intact in the workspace
[specimen] = dummy('trial2',2)
Instead of getting a structure with 2 fields, I get just one with Trial2 being the only field. Does that make any sense? What would like is to use the outputs of a function to progressively add to a structure.
Thank you,
Chris
Yes it makes sense, because you're creating a new struct specimen within your function.
Solution: pass the the previous specimen to the function as well.
function [specimen] = dummy(specimen,trial,value)
specimen.(trial) = value
end
and call:
[specimen] = dummy(specimen,'trial1',1)
or alternativly leave out the assignment at all and use the following
function [output] = dummy(value)
output = value
end
and call:
[specimen.trail1] = dummy(1)
which really depends on what you actually want to do. Put passing a name to a function which uses this name to define a struct is a little pointless unless you "use" that name otherwise. Also if you want to have input-dependent dynamic names you'd also go with the first alternative

Matlab: dynamic name for structure

I want to create a structure with a variable name in a matlab script. The idea is to extract a part of an input string filled by the user and to create a structure with this name. For example:
CompleteCaseName = input('s');
USER WRITES '2013-06-12_test001_blabla';
CompleteCaseName = '2013-06-12_test001_blabla'
casename(12:18) = struct('x','y','z');
In this example, casename(12:18) gives me the result test001.
I would like to do this to allow me to compare easily two cases by importing the results of each case successively. So I could write, for instance :
plot(test001.x,test001.y,test002.x,test002.y);
The problem is that the line casename(12:18) = struct('x','y','z'); is invalid for Matlab because it makes me change a string to a struct. All the examples I find with struct are based on a definition like
S = struct('x','y','z');
And I can't find a way to make a dynamical name for S based on a string.
I hope someone understood what I write :) I checked on the FAQ and with Google but I wasn't able to find the same problem.
Use a structure with a dynamic field name.
For example,
mydata.(casename(12:18)) = struct;
will give you a struct mydata with a field test001.
You can then later add your x, y, z fields to this.
You can use the fields later either by mydata.test001.x, or by mydata.(casename(12:18)).x.
If at all possible, try to stay away from using eval, as another answer suggests. It makes things very difficult to debug, and the example given there, which directly evals user input:
eval('%s = struct(''x'',''y'',''z'');',casename(12:18));
is even a security risk - what happens if the user types in a string where the selected characters are system(''rm -r /''); a? Something bad, that's what.
As I already commented, the best case scenario is when all your x and y vectors have same length. In this case you can store all data from the different files into 2 matrices and call plot(x,y) to plot each column as a series.
Alternatively, you can use a cell array such that:
c = cell(2,nufiles);
for ii = 1:numfiles
c{1,ii} = import x data from file ii
c{2,ii} = import y data from file ii
end
plot(c{:})
A structure, on the other hand
s.('test001').x = ...
s.('test001').y = ...
Use eval:
eval(sprintf('%s = struct(''x'',''y'',''z'');',casename(12:18)));
Edit: apologies, forgot the sprintf.