OpenModelica updating CombiTable input in real time - modelica

I have a model in which I am using a CombiTable1D to retrieve an external input from a .txt file. The file is generated by a Python script at the moment but in the final phase of the project, it is going to be updated each second. For now, simulation takes place without a problem as the .txt file is static. Just read the file and make simulation according to the data written there.
What I want to do is to simulate a model until a certain time, let's say 100s, and then make it wait until a real time event by which the .txt file is updated for the next external input values between 100-200. The simulation should continue by getting these new values for the next 100 seconds.
As I have already been working with OMPython, it is really practical for me to edit the .txt file using Python, let's say for each 10 seconds in real time. I can now simulate the model until the time instance that I define as the refreshing point of the external input. But I couldn't figure out how to keep the state of the simulation and make it read the file once again.

Actually, this sounds like a co-simulation scenario to me. Anyway, what you could do is to extend from CombiTable1D and have something like
block CombiTable1DWithUpdate
extends Modelica.Blocks.Tables.CombiTable1D(final tableOnFile=true);
algorithm
when sample(0, 10) then
readTableData(tableID, /* force update */ true, verboseRead);
end when;
end CombiTable1DWithUpdate;

In addition the the answer I accepted, I want to give another solution which is not so efficient. For a simple model with a capacitor and resistor, I made successfull tests but with more complex models, it doesn't function properly. In a Modelica script, realTimeSimulation.mos:
outputFile := "stepResult.mat";
simulation_step := 1;
start_time := 0;
stop_time := start_time+simulation_step;
loadFile("WhereverTheFileIs.mo");
buildModel(myTestModel);
system("myTestModel-override=startTime="+String(start_time)+",stopTime="+String(stop_time)+" -r="+outputFile);
will build the model and simulate the first step until the simulation time t=1s. Later on, using Python the text file is updated. The new data for the time between t=1s and t=2s are written to the text file where I am getting the input of the model. Then another step of the simulation is made for the time between t=1s and t=2s. As a loop, it continues like forever like: actualize the data, make new simulation for the new time interval. The trick is, reading the output file created at the end of each step and giving all the variable values as the new initial conditions to the simulation, using following script:
valueList := readSimulationResultVars(outputFile);
start_time := start_time+simulation_step;
stop_time := stop_time+simulation_step;
value := val(OpenModelica.Scripting.stringVariableName(valueList[1]),start_time,outputFile);',
variableString := valueList[1] + "=" + String(value);
for i in 2:size(valueList,1) loop
value := val(OpenModelica.Scripting.stringVariableName(valueList[i]),start_time,outputFile);
variableString := variableString + "," + valueList[i] + "=" + String(value);
end for;
system("myTestModel-override startTime="+String(start_time)+",stopTime="+String(stop_time)+",variableString+" -r="+outputFile);

Related

Paraview - get current time_index in ProgrammableSource

I have an array that has exactly as many rows as there are time steps in the animation. Now I want to have the row associated to the current time step as vtkTable as output of a ProgrammableSource. My code (for the ProgrammableSource) so far looks like this:
import numpy as np
file = "table.csv"
tbl = np.genfromtxt(file, names=True, delimiter=",", autostrip=True)
for n in tbl.dtype.names:
v = tbl[n][2]
output.RowData.append(v, n)
Which currently always writes out the third line (v = tbl[n][2]). Is there a way to pass the current time step (index) in place of [2]?
The best is to make your Programmable Source timesteps aware.
So you should fill the Information Script (advanced property) to declare the list of available timesteps, and then in the main script, get current timestep and output the data you want.
See this example from the doc.

How to write a script for Wolfram SystemModeler to run several simulations?

I want to run around 100 simulations with my model changing two parameters f and TLoadand track the changes on the phase currents currentSensor.i[1] etc.
Now I'm stuck with the documentation on the Wolfram website because there is no definite explanation on how to use scripting with the SystemModeler. I found for example this link on the Wolfram site with some code but no explanation in which commandline I should use it.
I downloaded the WolframScript program and tried to open my model with wolframscript -file SMPM_VoltageSource_Inverter.mo but it says ToExpression::sntx: Invalid syntax in or before ... eventhouh my model simulates totally fine and without any errors in the SimulationCenter.
Can someone explain to me:
Is it possible to write scripts ?
If Yes:
How can I simulate my model?
How can I do a parameter sweep of f and TLoad? Is it as described in the link?
Is it possible to export data of currentSensor.i[1] as a csv-file? And how to?
Thank you for any help!
I don't know about wolfram sorry, but for OpenModelica the following works:
// to load Model from file use
// loadFile("fileName.mo");
loadString("
model M
parameter Real a = 1;
Real x;
equation
x = a * sin(time);
end M;
"); getErrorString();
buildModel(M); getErrorString();
for a in {1,2,3,4} loop
str_a := String(a); getErrorString();
system("./M -override a=" + str_a); getErrorString();
// for windows use
//system("M.exe -override a=" + str_a); getErrorString();
system("mv M_res.mat " + "M_" + str_a + ".mat");
end for;
Put this in a file named for example model.mos and call it from terminal or command line, depending on your os, with omc model.mos if you have OpenModelica installed. this should generate a csv.
EDIT: I realized the original just saves the last value of x, you might want the full output. Therefore i changed the .mos-file. Each different result will be saved in a different file, if you want to change it to csv you just have to change the generated xml.

How to perform processinng on .csv files used by my code for each person in one go without defining functions for each person in Matlab?

I have a main code named as process.m in which I define the path to 4 different .csv files for calculating values for each person. If I have a list of 30 persons and I don't want to define process.m as a function for each person, how can I do the processing for all the persons in one go. I want some idea by which process.m itself picks files for one person, then generate the results, then move to other person, pick his .csv files, generate the result and so on.
A breif outline of my code is attached here that would project the problem.
file1='Joseph_front.csv';
file2='Joseph_side.csv';
file3='Joseph_knee.csv';
file4='Joseph_back.csv';
A1=initiate2(file1); %initiate2 function reads the csv and perfoms some filtering operations on image in .csv format
A2=initiate2(file2);
A3=initiate2(file3);
A4=initiate2(file4);
%%omitted large part of code
cal(1) = p+q+r*s;
cal(2) = p+q+r+s;
cal(3) = p+q+r-s;
cal=cal'
%code to write the calculation in excel file
excelfile= 'test.xlsx';
xlswrite(excelfile,ValuesInInches,'Joseph_data',posColumn);
Describing more i want my code to process for 30 people all at once by selecting and picking the files itself, although i have done this operation by making the same code as a function for each person, but that is not very efficient as when I have to make a small change I have to make it in every function that means one change needs to be edited in 30 functions. Please suggest an efficient way to do it.
Note: All persons .csv files are named in the same manner and exist in the current folder.
I am assuming all of your files in one directory and there's no other files .
This portion of code will get the available filenames.
listFiles = dir('path of the directory');
filenames = strings; % an empty string array to save the filenames
j = 1;
for i = 1:1:length(listFiles)
if ~listFiles(i).isdir % to avoid the directory names
filenames(j,1) = listFiles(i).name;
j = j+1;
end
end
Now, there's 4 file for each person. So the loop should take 4 files at a time.
for ii = 1:4:length(filenames)
file1=filename(i);
file2=filename(i+1);
file3=filename(i+2);
file4=filename(i+3);
%% continue with your code
end

Simulink 'to file - Block' :: How to add date / time to filename

I save the data from my simulation with the to file block to a .mat file.
When I start a new simulation, Simulink will overwrite the file if I dont set a new filename in the blocks properties.
Is it possible to add automaticly the current date / time to the filename? For the later usecase, i would be to extensive to set a filename for every new simulation manually.
thank you!
You can create a callback that will be called whenever a simulation is started and update the filename pointed by the ToFile block
In your callback function (my_callback.m) :
block = find_system(bdroot,'Name','NameOfTheToFileBlock');
if ~isempty(block)
file_name = strcat('filename_', datestr(now, 'yyyy-mm-dd HH:MM:SS'), '.mat');
set_param(block{1}, 'Filename', file_name);
end
You can setup the callback programmatically that way :
set_param('your_model','StartFcn','my_callback');

Matlab saving without losing previous iteration's value

i'm trying to save values of iterations in a loop. After this function, they will execute other functions before coming to the next iteration. But the problem i'm facing is, it overwrites them and bcomes 000000. Only the last iteration values are seen. How can i fix it ? Is there a way not to use the same variable and save them ? i read about append but will have to use different var name n is not really nice to do so.
function DistanceMatrix(iteration,distance_row)
load('data.mat','oridata')
load('centroids.mat','centroids')
for i = distance_row:(distance_row+3)
for j=1:300 %no.genes
total=0;
for k=1:6
total=total+((oridata(j,k)- centroids(i,k))^2);
end
DistMatrix_Val(i,j)=sqrt(total);
end
end
save('DistanceMatrix.mat','DistMatrix_Val')
DistMatrix_Val;
GroupMatrix(iteration,distance_row)
end
This is the output. I WOULD LIKE TO STORE ALL ITERATION's value and not overwrite them. Can any1 help ?
OK. Use
load('DistanceMatrix.mat','DistMatrix_Val')
or
persistent DistMatrix_Val
just before the first load command you showed to us.
I think this is what you should do:
functon DistanceMatrix = DistanceMatrix(iteration,distance_row)
Rather than saving the variable at the end of the function, you return it.
After returning it you can include the variable in a bigger variable (for example a three dimensional Nx4x300 matrix)
If neccesary you can then save it at the end.