Append new results from a CSV into an H3D file with Altair Compose
Altair Compose features libraries for handling CAE result files, including H3D files, which are commonly used to contain model data and results. With Compose, you can read, handle, and write H3D files.
Let’s have a look at a common use case. You might have an existing H3D file and want to add data that you post-processed in Compose. This data may be contained in another file format. In this example, we will use a CSV as the source of our new data.
First, let’s ask the user for the H3D file to append data to and the CSV files containing the new data. Function uigetfile opens a popup menu from which the user can select one or more files (using the shift key). strcat concatenates the path and the name of the file, so we can use it in the rest of our script.
close all, clear, clc
% Select inputs
[h3dName, h3dPath, ~] = uigetfile('*.h3d', 'Select H3D File');
cd(h3dPath);
h3dFile = strcat(h3dPath, h3dName);
[csvNames, csvPath, ~] = uigetfile('*.csv', 'Select CSV Files');
csvFiles = strcat(csvPath, csvNames);
Once the inputs are known, we can copy the H3D file (just to keep the original as well) and open it in append mode with createh3dfile. Append mode means existing data (and model if present) is not erased from the file.
% Copy H3D file & open it for appending data
h3dOutput = [h3dName(1:end-4), '_copy.h3d'];
copyfile(h3dFile, h3dOutput, 'f');
fid = createh3dfile(h3dOutput, 'append');
Next, we will get info from the file in an ordered way. We get the only subcase present first with getsubcaselist, and then, we will enter a for loop to get info on each datatype present (getfilteredtypelist returns all present datatypes except for time and index data), the requests (i.e., elements and nodes associated to that datatype, obtained using getreqlist) and, depending on the requests, whether we must bind the new data to elements or to nodes.
% Get subcase name
subcase = getsubcaselist(h3dFile){1};
% Go through each datatype present in H3D
datatypes = getfilteredtypelist(h3dFile, 1);
for i = 1:numel(datatypes)
% Get datatype, requests in it & assign bind accordingly
datatype = datatypes{i};
requestList = getreqlist(h3dFile, subcase, datatype);
if strncmpi(requestList{1}, 'N', 1)
bind = 'node';
else
bind = 'elem';
end
Now we must read the data we want to append from the CSV files and arrange it accordingly. In this case, the first column contains requests, while the second column contains its value.
% Read data from CSV
data = csvread(csvFiles);
requests = data(:,1);
values = data(:,2);
The last step before writing data into the file is to define new datatype and subcase IDs. Think of this as telling in which part of the file to store the new data. We assign a name to new datatypes and subcases (must be done in this order).
% Create new datatype ID and write data into it
datatypeID = createh3ddatatype(fid, [datatype, '_appended'], 'scalar', bind);
new_subcase = [subcase, '_', datatype, '_appended'];
subcaseID = createh3dsubcase(fid, new_subcase, new_subcase);
Finally, we call writeh3ddata to write our values on each of our requests in the datatype and subcase desired and, once the for loop is finished, we close the H3D file.
% Write new data in file
R = writeh3ddata(fid, new_subcase, 1, datatypeID, 0, 0, requests, values);
end
% Close H3D file
closeh3dfile(fid);
And that’s it! As you can see, writing new subcases in an already existing H3D file is straightforward. Try it on you own with the files provided and then build your own usecase. There’s many ways in which to take this further!