diff --git a/docs/examples/read.rst b/docs/examples/read.rst index 8963cbf..b0ca2ed 100644 --- a/docs/examples/read.rst +++ b/docs/examples/read.rst @@ -1,2 +1,219 @@ Reading a file ============== + +This example demonstrates how to read data from an ExodusII file. + +Opening a file +-------------- + +To read an existing ExodusII file, create a ``File`` object with ``FileAccess::READ``: + +.. code-block:: cpp + + #include "exodusIIcpp/exodusIIcpp.h" + + using namespace exodusIIcpp; + + // Open file for reading + File file("mesh.e", FileAccess::READ); + +The file handle will automatically initialize by calling the constructor, which opens the file and reads the metadata. + +Reading mesh information +------------------------ + +Once the file is open, you can query basic mesh information: + +.. code-block:: cpp + + // Get spatial dimension + int dim = file.get_dim(); + + // Get counts + int num_nodes = file.get_num_nodes(); + int num_elements = file.get_num_elements(); + int num_blocks = file.get_num_element_blocks(); + + // Get title + std::string title = file.get_title(); + +Reading coordinates +------------------- + +To read node coordinates: + +.. code-block:: cpp + + // Read all coordinate data from the file + file.read_coords(); + + // Get the coordinates + const std::vector & x = file.get_x_coords(); + const std::vector & y = file.get_y_coords(); + const std::vector & z = file.get_z_coords(); + +Reading element blocks +---------------------- + +To read element block information: + +.. code-block:: cpp + + // Read all element blocks + file.read_blocks(); + + // Get all blocks + const std::vector & blocks = file.get_element_blocks(); + + // Loop over all blocks and print information + for (const auto & block : blocks) { + std::cout << "Block ID: " << block.get_id() << std::endl; + std::cout << "Block name: " << block.get_name() << std::endl; + std::cout << "Number of elements: " << block.get_num_elements() << std::endl; + std::cout << "Element type: " << block.get_element_type() << std::endl; + std::cout << "Nodes per element: " << block.get_num_nodes_per_element() << std::endl; + + // Access connectivity + const std::vector & connectivity = block.get_connectivity(); + std::cout << "Connectivity size: " << connectivity.size() << std::endl; + + // Get individual element connectivity + if (block.get_num_elements() > 0) { + std::vector elem_nodes = block.get_element_connectivity(0); + std::cout << "First element nodes: "; + for (int node : elem_nodes) { + std::cout << node << " "; + } + std::cout << std::endl; + } + } + +You can also access individual blocks by index: + +.. code-block:: cpp + + // Access block by index + const ElementBlock & block = file.get_element_block(0); + +Reading node and side sets +--------------------------- + +To read node and side sets: + +.. code-block:: cpp + + // Read node sets + file.read_node_sets(); + const std::vector & node_sets = file.get_node_sets(); + + // Read side sets + file.read_side_sets(); + const std::vector & side_sets = file.get_side_sets(); + + // Get side set node list + std::vector node_count_list; + std::vector node_list; + file.get_side_set_node_list(side_set_id, node_count_list, node_list); + +Reading time step data +---------------------- + +To read time-dependent data: + +.. code-block:: cpp + + // Read time values + file.read_times(); + + // Get number of time steps and time values + int num_times = file.get_num_times(); + const std::vector & times = file.get_times(); + +Reading variables +----------------- + +To read variable names and values: + +.. code-block:: cpp + + // Get variable names + std::vector nodal_var_names = file.get_nodal_variable_names(); + std::vector elem_var_names = file.get_elemental_variable_names(); + std::vector global_var_names = file.get_global_variable_names(); + + // Read nodal variable values for a specific time step and variable + int time_step = 1; // 1-based indexing + int var_index = 1; // 1-based indexing + std::vector values = file.get_nodal_variable_values(time_step, var_index); + + // Read elemental variable values for a specific block + int block_id = 1; + std::vector elem_values = file.get_elemental_variable_values(time_step, var_index, block_id); + + // Read global variable values + std::vector global_values = file.get_global_variable_values(time_step); + +Reading all data at once +------------------------ + +For convenience, you can read all data in one call: + +.. code-block:: cpp + + // Read all mesh and variable data + file.read(); + +Closing the file +---------------- + +The file is automatically closed when the ``File`` object goes out of scope. You can also explicitly close it: + +.. code-block:: cpp + + file.close(); + +Complete example +---------------- + +Here's a complete example that opens a file, reads mesh and time step data, and prints information: + +.. code-block:: cpp + + #include "exodusIIcpp/exodusIIcpp.h" + #include + + using namespace exodusIIcpp; + + int main() + { + // Open file + File file("mesh.e", FileAccess::READ); + + // Print basic info + std::cout << "Title: " << file.get_title() << std::endl; + std::cout << "Dimension: " << file.get_dim() << std::endl; + std::cout << "Nodes: " << file.get_num_nodes() << std::endl; + std::cout << "Elements: " << file.get_num_elements() << std::endl; + + // Read and print time steps + file.read_times(); + std::cout << "Time steps: " << file.get_num_times() << std::endl; + + // Read nodal variable names + std::vector var_names = file.get_nodal_variable_names(); + for (size_t i = 0; i < var_names.size(); ++i) { + std::cout << "Variable " << (i + 1) << ": " << var_names[i] << std::endl; + } + + // Read and print first variable at first time step + if (var_names.size() > 0 && file.get_num_times() > 0) { + std::vector values = file.get_nodal_variable_values(1, 1); + std::cout << "First 5 values of first variable: "; + for (size_t i = 0; i < std::min(values.size(), size_t(5)); ++i) { + std::cout << values[i] << " "; + } + std::cout << std::endl; + } + + return 0; + } diff --git a/docs/examples/write.rst b/docs/examples/write.rst index f78a2bb..3e38da2 100644 --- a/docs/examples/write.rst +++ b/docs/examples/write.rst @@ -1,2 +1,322 @@ 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``: + +.. code-block:: cpp + + #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: + +.. code-block:: cpp + + // 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()``: + +.. code-block:: cpp + + // For 1D meshes + std::vector x = { 0.0, 1.0, 2.0, 3.0, 4.0 }; + file.write_coords(x); + + // For 2D meshes + std::vector x = { 0.0, 1.0, 0.0, 1.0, 0.5 }; + std::vector y = { 0.0, 0.0, 1.0, 1.0, 0.5 }; + file.write_coords(x, y); + + // For 3D meshes + std::vector x = { 0.0, 1.0, 0.0, 1.0, 0.5 }; + std::vector y = { 0.0, 0.0, 1.0, 1.0, 0.5 }; + std::vector 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: + +.. code-block:: cpp + + // Connectivity for block 1: 2 TRI3 elements + // Triangle 1: nodes 1, 2, 5 + // Triangle 2: nodes 2, 3, 5 + std::vector 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 connect2 = { 1, 2, 4, 5, 2, 3, 4, 5 }; + file.write_block(2, + "QUAD4", + 2, + connect2); + + // Write block names (optional) + std::vector block_names = { "Triangles", "Quads" }; + file.write_block_names(block_names); + +Writing node sets +----------------- + +Define node sets (groups of nodes): + +.. code-block:: cpp + + // Node set 1: nodes 1 and 2 + std::vector node_set_1 = { 1, 2 }; + file.write_node_set(1, node_set_1); + + // Write node set names (optional) + std::vector node_set_names = { "Left Edge" }; + file.write_node_set_names(node_set_names); + +Writing side sets +----------------- + +Define side sets (groups of element sides): + +.. code-block:: cpp + + // Side set 1: side 1 of element 1, side 2 of element 2 + std::vector elem_list = { 1, 2 }; + std::vector side_list = { 1, 2 }; + file.write_side_set(1, elem_list, side_list); + + // Write side set names (optional) + std::vector side_set_names = { "Bottom Edge" }; + file.write_side_set_names(side_set_names); + +Writing information records +---------------------------- + +Add metadata information records: + +.. code-block:: cpp + + std::vector 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: + +.. code-block:: cpp + + // Define time step 1 at time 0.0 + file.write_time(1, 0.0); + + // Write nodal variable names + std::vector 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 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 velocity = { 0.0, 1.0, 2.0, 1.5, 0.5 }; + file.write_nodal_var(1, 2, velocity); + + // Write elemental variable names + std::vector elem_var_names = { "Stress" }; + file.write_elem_var_names(elem_var_names); + + // Write elemental variable values for block 1 + std::vector 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 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: + +.. code-block:: cpp + + // Time step 2 + file.write_time(2, 1.0); + + std::vector displacement_t2 = { 0.1, 0.2, 0.4, 0.3, 0.1 }; + file.write_nodal_var(2, 1, displacement_t2); + + std::vector velocity_t2 = { 1.0, 2.0, 4.0, 3.0, 1.0 }; + file.write_nodal_var(2, 2, velocity_t2); + + std::vector 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: + +.. code-block:: cpp + + // 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: + +.. code-block:: cpp + + // Update after writing all data for this time step + file.update(); + +Close the file when done: + +.. code-block:: cpp + + // 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``: + +.. code-block:: cpp + + // 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: + +.. code-block:: cpp + + #include "exodusIIcpp/exodusIIcpp.h" + #include + + 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 x = { 0.0, 1.0, 1.0, 0.0 }; + std::vector y = { 0.0, 0.0, 1.0, 1.0 }; + file.write_coords(x, y); + file.write_coord_names(); + + // Write element block + std::vector connect = { 1, 2, 3, 4 }; + file.write_block(1, "QUAD4", 1, connect); + std::vector block_names = { "Material 1" }; + file.write_block_names(block_names); + + // Write time step 1 + file.write_time(1, 0.0); + std::vector var_names = { "Temperature" }; + file.write_nodal_var_names(var_names); + std::vector 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 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; + }