Writing a file
This example demonstrates how to create and write data to an ExodusII file.
Creating a file
To create a new ExodusII file, create a File object with FileAccess::WRITE:
#include "exodusIIcpp/exodusIIcpp.h"
using namespace exodusIIcpp;
// Create a new file
File file("output.e", FileAccess::WRITE);
Initializing the file structure
Before writing any data, you must initialize the file with mesh dimensions and counts. This defines the overall structure of the mesh:
// Initialize file with:
// - title: descriptive name
// - num_dims: spatial dimension (1, 2, or 3)
// - num_nodes: total number of nodes
// - num_elems: total number of elements
// - num_elem_blks: number of element blocks
// - num_node_sets: number of node sets
// - num_side_sets: number of side sets
file.init("My Mesh",
3, // 3D
10, // 10 nodes
5, // 5 elements
2, // 2 element blocks
1, // 1 node set
0); // 0 side sets
Writing coordinates
Write node coordinates to the file. The number of coordinates must match the number of nodes specified in init():
// For 1D meshes
std::vector<double> x = { 0.0, 1.0, 2.0, 3.0, 4.0 };
file.write_coords(x);
// For 2D meshes
std::vector<double> x = { 0.0, 1.0, 0.0, 1.0, 0.5 };
std::vector<double> y = { 0.0, 0.0, 1.0, 1.0, 0.5 };
file.write_coords(x, y);
// For 3D meshes
std::vector<double> x = { 0.0, 1.0, 0.0, 1.0, 0.5 };
std::vector<double> y = { 0.0, 0.0, 1.0, 1.0, 0.5 };
std::vector<double> z = { 0.0, 0.0, 0.0, 0.0, 1.0 };
file.write_coords(x, y, z);
// Write coordinate names (optional)
file.write_coord_names();
Writing element blocks
Define and write element blocks. Each block contains elements of the same type:
// Connectivity for block 1: 2 TRI3 elements
// Triangle 1: nodes 1, 2, 5
// Triangle 2: nodes 2, 3, 5
std::vector<int> connect1 = { 1, 2, 5, 2, 3, 5 };
file.write_block(1, // block ID
"TRI3", // element type
2, // number of elements
connect1);
// Connectivity for block 2: 2 QUAD4 elements
// Quad 1: nodes 1, 2, 4, ?
// Quad 2: nodes 2, 3, 4, ?
std::vector<int> connect2 = { 1, 2, 4, 5, 2, 3, 4, 5 };
file.write_block(2,
"QUAD4",
2,
connect2);
// Write block names (optional)
std::vector<std::string> block_names = { "Triangles", "Quads" };
file.write_block_names(block_names);
Writing node sets
Define node sets (groups of nodes):
// Node set 1: nodes 1 and 2
std::vector<int> node_set_1 = { 1, 2 };
file.write_node_set(1, node_set_1);
// Write node set names (optional)
std::vector<std::string> node_set_names = { "Left Edge" };
file.write_node_set_names(node_set_names);
Writing side sets
Define side sets (groups of element sides):
// Side set 1: side 1 of element 1, side 2 of element 2
std::vector<int> elem_list = { 1, 2 };
std::vector<int> side_list = { 1, 2 };
file.write_side_set(1, elem_list, side_list);
// Write side set names (optional)
std::vector<std::string> side_set_names = { "Bottom Edge" };
file.write_side_set_names(side_set_names);
Writing information records
Add metadata information records:
std::vector<std::string> info = {
"Generated by my simulation",
"Date: 2024-01-01",
"Author: John Doe"
};
file.write_info(info);
Writing time steps and variables
To write time-dependent data, define variable names and write values for each time step:
// Define time step 1 at time 0.0
file.write_time(1, 0.0);
// Write nodal variable names
std::vector<std::string> nodal_var_names = { "Displacement", "Velocity" };
file.write_nodal_var_names(nodal_var_names);
// Write nodal variable values for time step 1
// Variable 1 (Displacement) values for all nodes
std::vector<double> displacement = { 0.0, 0.1, 0.2, 0.15, 0.05 };
file.write_nodal_var(1, // time step
1, // variable index
displacement);
// Variable 2 (Velocity) values for all nodes
std::vector<double> velocity = { 0.0, 1.0, 2.0, 1.5, 0.5 };
file.write_nodal_var(1, 2, velocity);
// Write elemental variable names
std::vector<std::string> elem_var_names = { "Stress" };
file.write_elem_var_names(elem_var_names);
// Write elemental variable values for block 1
std::vector<double> stress_block1 = { 100.0, 150.0 };
file.write_elemental_variable_values(1, // time step
1, // variable index
1, // block ID
stress_block1);
// Write global variables
std::vector<std::string> global_var_names = { "Total Energy" };
file.write_global_var_names(global_var_names);
// Write global variable value for time step 1
file.write_global_var(1, // time step
1, // variable index
1000.0); // value
Writing additional time steps
To write more time steps, repeat the process:
// Time step 2
file.write_time(2, 1.0);
std::vector<double> displacement_t2 = { 0.1, 0.2, 0.4, 0.3, 0.1 };
file.write_nodal_var(2, 1, displacement_t2);
std::vector<double> velocity_t2 = { 1.0, 2.0, 4.0, 3.0, 1.0 };
file.write_nodal_var(2, 2, velocity_t2);
std::vector<double> stress_block1_t2 = { 200.0, 250.0 };
file.write_elemental_variable_values(2, 1, 1, stress_block1_t2);
file.write_global_var(2, 1, 2000.0);
Partial writes
For very large files, you can write variables in parts rather than all at once:
// Write nodal variable values node by node
for (int i = 0; i < num_nodes; ++i) {
file.write_partial_nodal_var(time_step, // time step
var_index, // variable index
block_id, // block ID
i + 1, // node index (1-based)
values[i]); // value
}
// Write elemental variable values element by element
for (int i = 0; i < num_elements; ++i) {
file.write_partial_elem_var(time_step, // time step
var_index, // variable index
block_id, // block ID
i + 1, // element index (1-based)
elem_values[i]); // value
}
Updating and closing
After writing all data for a time step, call update() to finalize the data:
// Update after writing all data for this time step
file.update();
Close the file when done:
// Close the file explicitly
file.close();
// Or let it close automatically when the File object goes out of scope
Appending to an existing file
To add new time steps to an existing file, use FileAccess::APPEND:
// Open existing file for appending
File file("output.e", FileAccess::APPEND);
// Read existing time steps to determine the next time step number
file.read_times();
int next_time_step = file.get_num_times() + 1;
// Write new time step data
file.write_time(next_time_step, 2.0);
file.write_nodal_var(next_time_step, 1, new_displacement);
file.update();
file.close();
Complete example
Here’s a complete example that creates a simple 2D mesh with time-dependent data:
#include "exodusIIcpp/exodusIIcpp.h"
#include <iostream>
using namespace exodusIIcpp;
int main()
{
// Create file
File file("simple.e", FileAccess::WRITE);
// Initialize: 2D mesh, 4 nodes, 1 quad element, 1 block, no sets
file.init("Simple Quad", 2, 4, 1, 1, 0, 0);
// Write coordinates
std::vector<double> x = { 0.0, 1.0, 1.0, 0.0 };
std::vector<double> y = { 0.0, 0.0, 1.0, 1.0 };
file.write_coords(x, y);
file.write_coord_names();
// Write element block
std::vector<int> connect = { 1, 2, 3, 4 };
file.write_block(1, "QUAD4", 1, connect);
std::vector<std::string> block_names = { "Material 1" };
file.write_block_names(block_names);
// Write time step 1
file.write_time(1, 0.0);
std::vector<std::string> var_names = { "Temperature" };
file.write_nodal_var_names(var_names);
std::vector<double> temp_t1 = { 100.0, 200.0, 250.0, 150.0 };
file.write_nodal_var(1, 1, temp_t1);
file.update();
// Write time step 2
file.write_time(2, 1.0);
std::vector<double> temp_t2 = { 150.0, 250.0, 300.0, 200.0 };
file.write_nodal_var(2, 1, temp_t2);
file.update();
file.close();
std::cout << "File created successfully!" << std::endl;
return 0;
}