From 799b6d41331719888046246a50decc5249fd4205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Simonis?= Date: Tue, 3 Feb 2026 19:24:59 +0100 Subject: [PATCH] Add crate documentation --- src/lib.rs | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 122 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 03f87c8..b623fed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,23 @@ +//! The preCICE rust bindings. +//! +//! These are the official rust bindings for the [preCICE coupling library](https://precice.org). +//! +//! The methods of the [Participant] map directly to their C++ counterparts. +//! Therefore the documentation of this crate is kept relatively minimal. +//! +//! Have a deeper look at the official documentation: +//! +//! - The [official documentation](https://precice.org/docs.html) explains what preCICE is and how +//! to use it. +//! - The [API documentation](https://precice.org/dev-docs-sourcedocs.html) explains the API +//! conditions in detail. +//! +//! # Example applications +//! +//! - The crate contains a [solverdummy](https://github.com/precice/rust-bindings/tree/main/examples) as example. +//! - The tutorials contain a rust version of both participants for the [1D elastic-tube tutorial](https://precice.org/tutorials-elastic-tube-1d.html). + +#[warn(missing_docs)] #[cxx::bridge(namespace = "precice::rust")] mod ffi { unsafe extern "C++" { @@ -177,60 +197,116 @@ pub struct Participant { internal: cxx::UniquePtr, } +/// Type of vertex identifiers. +/// +/// These are returned either by +/// - manually setting vertices from coordinates using [Participant::set_mesh_vertex] and [Participant::set_mesh_vertices], or +/// - using direct api-access with [Participant::get_mesh_vertex_ids_and_coordinates]. pub type VertexID = i32; + +/// Type of thrown errors from preCICE pub type Error = cxx::Exception; impl Participant { - pub fn new(participant: &str, config: &str, rank: i32, size: i32) -> Result { + // Creates a new preCICE participant. + // + // The participant is named `participant` and is descried in the configuration file located at `config`. + // + // The communicator size and rank match the MPI terminology. + // Participants running in serial or not using MPI pass `rank = 0` and `size = 1`. + pub fn new( + participant: &str, + config: &str, + rank: i32, + size: i32, + ) -> Result { Ok(Participant { internal: ffi::create_participant(participant, config, rank, size)?, }) } // Steering Methods + + /// Initializes the participant. pub fn initialize(&mut self) -> Result<(), Error> { self.internal.pin_mut().initialize() } + + /// Advances the participant in time by the time-step-size `dt`. pub fn advance(&mut self, dt: f64) -> Result<(), Error> { self.internal.pin_mut().advance(dt) } + + /// Explicitly finalizes the participant, which is not necessary for most use-cases. pub fn finalize(&mut self) -> Result<(), Error> { self.internal.pin_mut().finalize() } // Implicit coupling + + /// Checks if the solver needs to read an iteration checkpoint. pub fn requires_reading_checkpoint(&mut self) -> Result { self.internal.pin_mut().requires_reading_checkpoint() } + + /// Checks if the solver needs to write an iteration checkpoint. pub fn requires_writing_checkpoint(&mut self) -> Result { self.internal.pin_mut().requires_writing_checkpoint() } // Status Queries + + /// Returns the spatial dimensions of a mesh. pub fn get_mesh_dimensions(&self, mesh_name: &str) -> Result { self.internal.get_mesh_dimensions(mesh_name) } + + /// Returns the spatial dimensions of a data defined on a mesh. pub fn get_data_dimensions(&self, mesh_name: &str, data_name: &str) -> Result { self.internal.get_data_dimensions(mesh_name, data_name) } + + /// Checks is the coupling is still ongoing . pub fn is_coupling_ongoing(&self) -> Result { self.internal.is_coupling_ongoing() } + + /// Checks if the previous step completed the time window. pub fn is_time_window_complete(&self) -> Result { self.internal.is_time_window_complete() } + + /// Returns the maximum time-step-size allowed by a solver at the moment of calling. + /// + /// Note that this can return [f64::INFINITY] if the participant prescribes the time-window-size + /// in a serial coupling scheme. pub fn get_max_time_step_size(&self) -> Result { self.internal.get_max_time_step_size() } // Mesh Access + /// Check if the mesh makes use of mesh connectivity. pub fn requires_mesh_connectivity_for(&self, mesh_name: &str) -> Result { self.internal.requires_mesh_connectivity_for(mesh_name) } + + /// Deletes all vertices of a mesh. pub fn reset_mesh(&mut self, mesh_name: &str) -> Result<(), Error> { self.internal.pin_mut().reset_mesh(mesh_name) } + + /// Returns the amount of vertices of a mesh. + /// + /// For a provided mesh, returns the amount of vertices. + /// + /// For a received mesh using API-access, returns the amount of vertices received. + /// This is necessary to allocate output vectors for [Participant::get_mesh_vertex_ids_and_coordinates] + pub fn get_mesh_vertex_size(&self, mesh_name: &str) -> Result { + self.internal.get_mesh_vertex_size(mesh_name) + } + + /// Add a vertex of given position to a mesh and returns a [VertexID]. pub fn set_mesh_vertex( &mut self, mesh_name: &str, @@ -238,9 +314,8 @@ impl Participant { ) -> Result { self.internal.pin_mut().set_mesh_vertex(mesh_name, position) } - pub fn get_mesh_vertex_size(&self, mesh_name: &str) -> Result { - self.internal.get_mesh_vertex_size(mesh_name) - } + + /// Add multiple vertices of given positions to a mesh and writes their [VertexID]s to `ids` . pub fn set_mesh_vertices( &mut self, mesh_name: &str, @@ -251,6 +326,8 @@ impl Participant { .pin_mut() .set_mesh_vertices(mesh_name, positions, ids) } + + /// Defines an edge between two vertices. pub fn set_mesh_edge( &mut self, mesh_name: &str, @@ -261,9 +338,13 @@ impl Participant { .pin_mut() .set_mesh_edge(mesh_name, first_vertex_id, second_vertex_id) } + + /// Defines edges between multiple vertex pairs. pub fn set_mesh_edges(&mut self, mesh_name: &str, vertices: &[VertexID]) -> Result<(), Error> { self.internal.pin_mut().set_mesh_edges(mesh_name, vertices) } + + /// Defines a triangle between three vertices. pub fn set_mesh_triangle( &mut self, mesh_name: &str, @@ -278,6 +359,8 @@ impl Participant { third_vertex_id, ) } + + /// Defines triangles between vertex triples. pub fn set_mesh_triangles( &mut self, mesh_name: &str, @@ -287,6 +370,8 @@ impl Participant { .pin_mut() .set_mesh_triangles(mesh_name, vertices) } + + /// Defines a planar quad between four vertices. pub fn set_mesh_quad( &mut self, mesh_name: &str, @@ -303,9 +388,13 @@ impl Participant { fourth_vertex_id, ) } + + /// Defines multiple planar quads between vertex quadruples. pub fn set_mesh_quads(&mut self, mesh_name: &str, vertices: &[VertexID]) -> Result<(), Error> { self.internal.pin_mut().set_mesh_quads(mesh_name, vertices) } + + /// Defines a tetrahedron between four vertices. pub fn set_mesh_tetrahedron( &mut self, mesh_name: &str, @@ -322,6 +411,8 @@ impl Participant { fourth_vertex_id, ) } + + /// Defines multiple tetrahedra between vertex quadruples. pub fn set_mesh_tetrahedra( &mut self, mesh_name: &str, @@ -334,10 +425,13 @@ impl Participant { // Data Access + /// Checks if this participant needs to provide initial data using [Participant::write_data] + /// before calling [Participant::initialize]. pub fn requires_initial_data(&mut self) -> Result { self.internal.pin_mut().requires_initial_data() } + /// Writes data to a mesh for given [VertexID]s. pub fn write_data( &mut self, mesh_name: &str, @@ -349,6 +443,8 @@ impl Participant { .pin_mut() .write_data(mesh_name, data_name, vertices, values) } + + /// Reads data values from a mesh for given [VertexID]s at a given `relative_read_dt`. pub fn read_data( &self, mesh_name: &str, @@ -363,18 +459,21 @@ impl Participant { // User Profiling + /// Starts a new user-defined profiling section. pub fn start_profiling_section(&mut self, section_name: &str) -> Result<(), Error> { self.internal .pin_mut() .start_profiling_section(section_name) } + /// Stops the last user-defined profiling section. pub fn stop_last_profiling_section(&mut self) -> Result<(), Error> { self.internal.pin_mut().stop_last_profiling_section() } // Direct Access + /// Defines a region of interest on a received mesh. pub fn set_mesh_access_region( &mut self, mesh_name: &str, @@ -384,6 +483,11 @@ impl Participant { .pin_mut() .set_mesh_access_region(mesh_name, bounding_box) } + + /// Reads [VertexID]s and coordinates of a received mesh. + /// + /// Use [Participant::get_mesh_vertex_size] and [Participant::get_mesh_dimensions] to + /// preallocate the output storage. pub fn get_mesh_vertex_ids_and_coordinates( &self, mesh_name: &str, @@ -396,6 +500,7 @@ impl Participant { // experimental: Gradient Data + /// Checks if the given data set requires gradient data. pub fn requires_gradient_data_for( &self, mesh_name: &str, @@ -404,6 +509,15 @@ impl Participant { self.internal .requires_gradient_data_for(mesh_name, data_name) } + + /// Writes vector gradient data to a mesh. + /// + /// The used format for `gradients` follows this pattern: + /// + /// | Spatial Dimensions | Scalar Data | Vectorial Data | + /// | --- | --- | --- | + /// | **2D** | s dx, s dy | x dx, y dx, x dy, y dy | + /// | **3D** | s dy, s dy, s dz | x dx, y dx, z dx, x dy, y dy, z dy, x dz, y dz, z dz | pub fn write_gradient_data( &mut self, mesh_name: &str, @@ -418,6 +532,9 @@ impl Participant { // experimental: JIT mapping + /// Reads data values from a mesh using a just-in-time data mapping. + /// + /// Values correspond to a given point in time relative to the beginning of the current time-step. pub fn write_and_map_data( &mut self, mesh_name: &str, @@ -430,6 +547,7 @@ impl Participant { .write_and_map_data(mesh_name, data_name, coordinates, values) } + /// Writes data values to a mesh using a just-in-time mapping (experimental). pub fn map_and_read_data( &self, mesh_name: &str,