Extract and store results from multibody simulations with Altair Compose
MotionSolve plot files (.plt) are produced when running multibody simulations. These files contain results such as displacements, velocities and accelerations (and much more) from the bodies present in the file.
A single PLT file can contain dozens of different datatypes (data like displacement, force, torque, etc.), requests (entities present in the model from which data is to be extracted. E.g., a specific piece in an assembly) and components (e.g., X, Y, Z, magnitude, etc.), so peering into a file manually to look at every produced result can be lengthy.
With Altair Compose and its dedicated libraries for reading and handling CAE files (both from Altair and third-party products) reading and storing (with or without previously post-processing data) all the contents from a PLT file into a CSV can be done in a few steps. Let’s look at how to do it:
First the user is prompted for the PLT file to read and the directory in which to write data using uigetfile and uigetdir. The desired directory is created with mkdir.
close all, clear, clc
% Choose plt file and desired location for outputs
[name, filepath, ~] = uigetfile('*.plt', 'Please select file location');
filename = strcat(filepath, name);
parentDir = uigetdir(cd, 'Please select output directory location');
cd(parentDir);
% Create directory for containing all datatype outputs
outputDir = name(1:end-4);
mkdir(cd, outputDir);
Next, a list of all available data types in the file is created using gettypelist, and the time vector from the simulation is extracted with readcae. squeeze is used to avoid matrices with redundant dimensions, e.g., dimension with just one element, like a 2x2x1 3-dimensional matrix (which would be turned into a 2x2 2-dimensional matrix).
% Get all available datatypes
datatypes = gettypelist(filename);
% Get time
t = squeeze(readcae(filename, 'Time', 'Time', 'Time', [], 1));
Afterwards, a for loop can be used to cycle through all present data types (except “Time” and “Index”, as we don’t care about these in our results). For each data type, a subdirectory is created at the output location and its corresponding requests and components are extracted into lists with the help of getreqlist and getcomplist, respectively.
% Go through each datatype
for i = 1:numel(datatypes)
% Skip if datatype is "Time" or "Index"
if strcmp(datatypes{i}, 'Time') || strcmp(datatypes{i}, 'Index')
continue
end
% Current datatype
datatype = datatypes{i};
% Create directory for containing all requests in this datatype
mkdir(['./' outputDir], datatype);
currentOutputDir = ['./' outputDir '/' datatype];
% Get requests and components for this datatype
requests = getreqlist(filename, datatype);
components = getcomplist(filename, datatype);
For each request present in each datatype, a CSV file is created. This file will store the results present in the PLT file that correspond to this request and all its components. The output file’s name is set using strcat for string concatenation (e.g. request1.csv) and fopen created the file and opens it in write mode.
% Go through each request
for j = 1:numel(requests)
% Current request
request = requests{j};
% Matrix for storing data from all components
data = t;
% Open csv to write data
outputFile = strcat(currentOutputDir, '/', request(5:end), '.csv');
[fid msg] = fopen(outputFile, 'w');
Each component in the current request is extracted from the file and stored in a data matrix, in which all components, and the time vector, occupy a column.
% Go through each component in this request
for k = 1:numel(components)
% Current component
component = components{k};
% Read data for current request & component
data = [data, squeeze(readcae(filename, datatype, request, component, [], 1))];
end
Having all relevant data from the current request, functions from the Compose FileIO library make it straightforward to put the results in a CSV file. Note that both functions are used because csvwrite cannot write string values into a file, so the headers are written afterwards using xlswrite.
% First line saved for headers
headers = NaN(1, numel(components) + 1);
% Write data & close current csv
csvwrite(fid, [headers; data]);
fclose(fid);
% Write component names as headers (xls functions are required to write strings into files)
tcell{1} = 'Time';
headers = [tcell components];
% Open, write headers & close file
fid = xlsopen(outputFile, 1);
xlswrite(fid, headers);
xlsclose(fid);
end
end
And that’s it! With a simple script, all available results are extracted from a PLT file and stored in an ordered way, in a file format readable by anyone, which can be further used in a CAE workflow.