Advanced H3D Writing Tips


Altair Compose can be leveraged in your CAE workflow to read, custom process and write simulation-obtained data from previous steps of your process. Handling CAE data is especially easy when using H3D files, which are Altair Compressed Binary Files, because Compose supports several libraries for reading and writing this file format.

 

The CAE Writers Library documentation showcases how to use its commands, and contains several good examples on how to get started leveraging each of them. However, you might reach a point in which the customization of the H3D files you need to create requires defining stress data with lots of components associated to it or, even more so, you need to custom define components of a data type. I’ve scripted a couple of examples addressing exactly that.

 

  1. Writing stress data

 

Standard stress datatypes in H3D files contain the following components:

 

 

So, if you want to write stress data and have all these components, all you have to do is to define a 3D tensor with the values for XX, YY, ZZ, XY, YZ and ZX, Compose will take care of calculating the rest. Let’s look at how to do this in a script and let’s also review how to define different layers and pools for the file.

 

Let’s start by defining the names of the files we will be handling and opening the H3D file for writing.

 

close all, clear, clc

 

% Source & new H3D files

inputH3d = '.\bezel.h3d';

outputH3d = '.\bezel_new.h3d';

 

% Open H3D output file

fid = createh3dfile(outputH3d, 'new');

 

Next, let’s define the names of the subcase and datatype we will read, and let’s get all the elements (nodes in this case) present in the model.

 

% Extract specific subcase and datatype, all requests

subcase = 'Subcase 1 (Step_X)';

datatype = 'Element Stresses (2D & 3D) (2D)';

requests = getreqlist(inputH3d, subcase, datatype);

 

The proper reading of data from the file can be done now. This file contains data arranged in two layers, Z1 and Z2, so we will extract the data needed for reconstruction for both layers.

 

% Data is defined in two layers: Z1 & Z2. Extract XX, YY, ZZ, XY, YZ, ZX

components = {'XX', 'YY', 'ZZ', 'XY', 'YZ', 'ZX'};

dataZ1 = readcae(inputH3d, subcase, datatype, [], cellfun(@(comp) strcat(comp, ' (Z1)'), components, 'uniformoutput', false), [], 1);

dataZ2 = readcae(inputH3d, subcase, datatype, [], cellfun(@(comp) strcat(comp, ' (Z2)'), components, 'uniformoutput', false), [], 1);

 

Note: Even though an explicit string assignment would have been simpler, to showcase a nice way to use it, I purposely used cellfun for declaring components for each layer.

 

Now, before writing data into the file, we must define the structure we want for it. Namely, layers, pools, datatypes and subcases are defined.

 

% Create layers

lidx1 = createh3dlayer(fid, 'Z1');

lidx2 = createh3dlayer(fid, 'Z2');

 

% Create a pool

pidx1 = createh3dpool(fid, '2D');

 

% Create datatype ID for new subcases

datatypeID = createh3ddatatype(fid, 'Element Stresses (2D & 3D)', '3Dtensor', 'elem', 'layers', [lidx1, lidx2], 'pools', [pidx1]);

 

% Create subcase ID with a single timestep = 0

subcaseID = createh3dsubcase(fid, subcase, [0]);

 

We also need a matrix of all elements into which data will be written to, so let’s convert the cell with names into the pure element IDs. Afterwards, we can write the data and close the file.

 

% Convert requests from string to number

requests = cellfun(@(request) str2num(request(2:end)), requests);

 

% Write data

R = writeh3ddata(fid, subcaseID, 1, datatypeID, lidx1, 0, requests, dataZ1, pidx1);

R = writeh3ddata(fid, subcaseID, 1, datatypeID, lidx2, 0, requests, dataZ2, pidx1);

 

% Close H3D

closeh3dfile(fid);

 

Once this is done, you can examine the newly created file and look at the available components. Writing the six main components, the rest is handled automatically, and we can visualize them using the CAE Reader:

 

A screenshot of a computerDescription automatically generated

 

If you want to write stress data with other components (or data with any components you want), the next script will be useful.

 

  1. Writing data with custom datatypes

 

The method for writing a datatype with custom components is straightforward, each component is written as a new, scalar datatype with a common syntax: datatypeName:componentName, so, if we want to define a datatype called Custom datatype with five components called: Component A, Component B, Component C, Component D and Component E, we need to define five different datatype as:

 

 

These will be bundled together as a single datatype. Let’s look at how to do this in a script. Same as the previous script, we start by defining the name of the file we want to create, opening it as an H3D for writing and defining each datatype. In this case I’m using cellfun to concatenate the datatype and each component together and define a datatype for each one in a single line.

 

close all, clear, clc

 

% Output H3D file

filename = '.\Custom components data.h3d';

 

% Open H3D

fid = createh3dfile(filename, 'new');

 

% Define subcase, datatype and components

subcase = 'Subcase 1';

datatypeName = 'Custom datatype';

components = {'Component A', 'Component B', 'Component C', 'Component D', 'Component E'};

 

% Define a datatype for each component

datatypeIDs = cellfun(@(component) createh3ddatatype(fid, [datatypeName, ':', component], 'scalar', 'elem'), components);

 

The rest of the process should go on as normal, let’s define a subcase, build a list of requests, elements 1 to 100 in this case, and create some mock data to write into the file with 100 rows (one for each element) and 5 columns (one for each component).

 

% Create subcase ID with a single timestep = 1

subcaseID = createh3dsubcase(fid, subcase, [1]);

 

% Define model elements' IDs

nReqs= 100;

requests = 1:nReqs;

 

% Create mock data for file

data = rand(nReqs, numel(components));

 

Finally, we just have to write the data for each component and close the file.

 

% Write each component in file

for i = 1:numel(components)

     

      % Write data

      R = writeh3ddata(fid, subcaseID, 1, datatypeIDs(i), 0, 0, requests, data(:,i));

     

end

 

% Close H3D

closeh3dfile(fid);

 

We should be able to use the CAE Reader to inspect the file and look at the single datatype present, containing all the components we defined:

 

A screenshot of a computerDescription automatically generated

 

Hope you incorporate these techniques into your workflows and can write custom H3D files in any way you want. Try it on your own data!