Introduction
This article will explain some ways in which text files can be read into Dymola models. The article is intended for those seeking that specific information (go directly to summary of functions) and any student, or professional as yet new to Modelica, Dymola, and/or CAE software in general, interested in reading text files while running Dymola models.
Why Read In Files
There are a number of motivations for wanting to read text files.
- The most obvious is that there is some data in a file, and you want access to it.
- This is may be easy when the file is the right format, and can be read “natively” by your software, but this may not always be the case.
- A text file is legible to you, the user. You can amend it casually (occasionally I receive an email asking whether Modelica is “acasual” rather than “acausal”) & rerun your script while debugging.
Reading Text from CAE Software
Often, engineering software has a convenient facility to read a selection of file types. It is also routine as many readers will well know, to use “translator” modules which read (for instance) one CAD format into an alternate CAD software, or structural analysis system.
- In the case of Dymola, a “native” file would be a .mat file, because the software has been designed to conform to that industry standard.
- In essence a .mat file is a binary file. You need to create an application to read it, or use a general purpose numerical analysis system such as the open-source Octave – learn more or even participate at: https://www.gnu.org/software/octave/about.html
- When it comes to CAE software, translator modules can be costly, and add considerably to the overhead of using the software.
Often, it’s useful to be able to read a file that was written using general purpose software, or which you just typed out yourself, if need be. Such files are often text files. There is certainly not always facility to read these, because CAE software is usually more concerned with results.
There are many great advantages to text files. One also notes that the simulation logs, and input scripts for FEA software are also often simply text files. Better still these are often written automatically in a fixed format with various headers and sections which can be “found” by your models & functions, using some logical, albeit cumbersome string manipulation. It can be invaluable to be able to check data against these kinds of files.
Other advantages include:
- You can read a text file visually. This means you can test that code is working as you write it, to be certain that terms, especially ones which can’t (yet) be plotted, are as you expect.
- Such code checking is incredibly useful, whether programming a proprietary parametric design language, Modelica, Python, or anything else, and there are circumstances where the model might not be working properly, but functions you’ve made can be called separately to make sure they’re doing what they’re meant to, writing files full of helpful intermediate information.
Reader Functions
The purpose of this article is to illustrate the uses of, and syntax for a handful of key functions included in the Modelica Standard Library:
Modelica.Utilities.Streams.countLines
Purpose
This function uses external code to count the lines in a file. It is useful because it provides an avenue by which to size an array to hold the content of the file in a way which suits the user.
Syntax
Below an example is shown of an array being sized by a call to this function. Note that this will only work in the context of another function, rather than within a model.
Modelica Code | Notes |
---|---|
String holdTxt[ Modelica.Utilities.Streams.countLines( pPath+fs2+pName) ]; |
The countlines function is used here to dimension an array. |
Modelica.Utilities.Streams.readFile
Purpose
This function reads the characters stored in a text file into a String array. Every line becomes an entry in the array. You need to define an array ahead of time as usual. It can be seen here that the array is set up with unknown dimensionality. Assigning it the value of the function output determines the dimension. However, one cannot do this within a model.
Syntax
Below a function is printed which goes to a location on the machine & reads a text file. The result of this is a vector of strings, each entry of which is one of the lines of the file.
Modelica Code | Notes |
---|---|
function reader input String pName = "sourcefile.txt"; input String pPath = ""; input Integer n=1; input String dumpFile="reader_out.txt"; output String dump=""; |
Filename has a default Command path defaults to null. An input which tells the function which line should be the output from the function. In a function, setting a variable value on declaration acts as specification of a default.
Not so in model. |
// parameter String f_ = "f_.txt"; parameter String fs2 = "/"; protected String holdTxt[:]; String cmdPth=""; pre> |
Stroke in a string. Its function as a comment marker causes problems in composing strings. In a function (exclusively), the output of a function can become the sole source of the information for the dimension of an array. |
algorithm cmdPth:= pPath+fs2+pName; holdTxt:=Modelica.Utilities.Streams.readFile(cmdPth); Modelica.Utilities.Files.remove(f_); |
A command path is composed.Remove() deletes any file of identical name. |
Modelica.Utilities.Streams.print(cmdPth,f_); Modelica.Utilities.Streams.print( "line "+ String(n)+ " was output to file "+ f_, f_); Modelica.Utilities.Streams.print(pName,f_); |
The file is printed. You can read this text file. |
Modelica.Utilities.Streams.close(f_); dump:=holdTxt[n]; end reader; |
The output for the function is assigned the value, choosing the line specified in the input. |
The reader file listed above is written with several arguments. Note especially the integer signifying which line of the file to output.
Modelica.Utilities.Strings.scanReal / scanInteger / scanBoolean
Purpose
These functions are very useful. While we’re used to writing out numbers as strings, for example, into a text file (see article) these let us “read” some text not only in the sense of reading & registering the characters but in the sense of “understanding” that they signify a numerical value.
Syntax
Below the model is provided with which the function already shown can be called. Within this model there are several items which could just as easily have been included in the function. We have a reminder here that the equation section will be calculated at every time-step, and therefore any command to read scan a string and/or write it down in a text file will yield a result at each step. This could well be what is intended, and indeed, a main reason to put the scanReal() part in your model, not in the function, but here we’ve restricted it to the last time-step to more easily see what comes out, using when terminal() then.
Modelica Code | Notes |
---|---|
model caller_ext parameter String chkFile = "f_.txt"; String my_str ; Integer my_Int ; Real my_Rea ; Integer my_Int2 ; Real my_Rea2 ; Integer tail_1; Integer tail_2; Integer tail_3; Integer tail_4; |
Note that this is the same filename as the function uses to write its data to. The name is the same, but the variable that holds it has a different name in the model & the file is accessed separately. |
equation my_str=reader("target2_file.txt", "F:\TESTER",3); |
The variable is assigned the result of the function. Notice the filename for reading by the function, the path & which line to output from the function, are inputs entered in the same order they’re declared in, inside the reading function. |
(my_Int,tail_1)= Modelica.Utilities.Strings.scanInteger( my_str, 1, true); (my_Rea,tail_2)= Modelica.Utilities.Strings.scanReal( my_str, 1, true); (my_Int2,tail_3)= Modelica.Utilities.Strings.scanInteger( my_str, 2, true); (my_Rea2,tail_4)= Modelica.Utilities.Strings.scanReal( my_str, 2, true); |
Here, the my_Int receives whatever integer is read by scanInteger. The tail variable receives the integer index of the first character in the string the machine cannot read as part of the integer. Similarly the real scanner. |
when terminal() then assert( Modelica.Utilities.Files.exist( chkFile), "oops", level = AssertionLevel.error); Modelica.Utilities.Streams.print(my_str,chkFile); |
“assert” will throw an error if the condition is not met. The error text is an argument. Here “oops”. In this case the condition is the existence of the file. |
Modelica.Utilities.Streams.print( String(my_Int)+ " "+ String(tail_1), chkFile); Modelica.Utilities.Streams.print( String(my_Rea)+ " "+ String(tail_2), chkFile); Modelica.Utilities.Streams.print( String(my_Int2)+ " "+ String(tail_3), chkFile); Modelica.Utilities.Streams.print( String(my_Rea2)+ " "+ String(tail_4), chkFile); Modelica.Utilities.Streams.close(chkFile); end when; end caller_ext; |
These longwinded lines serve simply to write out a concatenation of strings, to the chkFile.txt file, for the user to examine. Note that these files will be written to the working directory, despite the path that was given to find the source file. These are distinct concepts! |
Results
If the above model & function are run, we can get information in text form to be read & understood by Dymola file reading functions. Try using a file of your own, and filling it with some data, such as several rows of numbers, and reading it in. Experiment with using Dymola to pick them up from the text and for example, add them together, having used scanReal to have the machine actually interpret the data.
Ensure the command path and file names correspond to the ones you’re using.
Summary
We have seen how the reading of text files in Dymola can help in the checking of the workings of models or functions. We have also seen some examples of how to handle the strings that result, and functions which convert the strings of characters into meaningful values.
Several functions exist that inspect the metadata of text files, extract the content, and process the information carried therein, to convert it back into numbers from a string of characters. Using these you can read data, and obtain information.
If you’re a student interested in using the Dymola software for your college coursework, or if you want to learn more about programming parametric engineering models in Modelica, then contact Claytex support (support@claytex.com).
Written by: Sas Harrison – Systems Engineer
Please get in touch if you have any questions or have got a topic in mind that you would like us to write about. You can submit your questions / topics via: Tech Blog Questions / Topic Suggestion