diff --git a/.github/scripts/insert_doc_links.py b/.github/scripts/insert_doc_links.py
new file mode 100644
index 0000000..7bd88ed
--- /dev/null
+++ b/.github/scripts/insert_doc_links.py
@@ -0,0 +1,34 @@
+"""Replace the links to other crates in documentation strings.
+
+This can be run before building the docs with the `--no-deps` flag to make the links work
+in the generated docs
+"""
+
+import os
+import re
+
+
+def _insert_doc_links(content):
+ content = re.sub(r"(\s)\[ndelement\](\s|\n)", r"\1[ndelement](https://bempp.github.io/ndelement/rust/ndelement/)\1", content)
+ return content
+
+
+def insert_doc_links(folder):
+ for file in os.listdir(folder):
+ if not file.startswith("."):
+ file_path = os.path.join(folder, file)
+ if os.path.isdir(file_path):
+ insert_doc_links(file_path)
+ elif os.path.isfile(file_path) and file.endswith(".rs"):
+ with open(file_path) as f:
+ content = f.read()
+ with open(file_path, "w") as f:
+ f.write(_insert_doc_links(content))
+
+
+root_dir = os.path.join(os.path.join(
+ os.path.dirname(os.path.realpath(__file__)),
+ ".."), "..")
+insert_doc_links(os.path.join(root_dir, "src"))
+insert_doc_links(os.path.join(root_dir, "examples"))
+insert_doc_links(os.path.join(root_dir, "tests"))
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index b6ec04d..2453fa3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -24,8 +24,15 @@ jobs:
mpi: "mpich"
- uses: actions/checkout@v4
+ - name: Set up Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: 3.14
+ - name: Insert doc links
+ run: python .github/scripts/insert_doc_links.py
+
- name: Build docs
- run: cargo +nightly doc --no-deps -Zunstable-options -Zrustdoc-scrape-examples --all-features
+ run: RUSTDOCFLAGS="--html-in-header katex-header.html" cargo +nightly doc --no-deps -Zunstable-options -Zrustdoc-scrape-examples --all-features
- name: Make index page
run: echo "
" > target/doc/index.html
diff --git a/Cargo.toml b/Cargo.toml
index 8240770..056da7e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -50,6 +50,7 @@ cbindgen = "0.29.2"
[package.metadata.docs.rs]
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
+rustdoc-args = [ "--html-in-header", "katex-header.html" ]
[lints.clippy]
wildcard_imports = "forbid"
diff --git a/README.md b/README.md
index 69f9d95..a2779e1 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
# ndgrid
[](https://crates.io/crates/ndgrid)
-[](https://docs.rs/ndgrid/latest/ndgrid/)
ndgrid is an open-source library written in Rust for n-dimensional grids/meshes.
@@ -25,7 +24,6 @@ cargo test
Examples of use can be found in the [examples folder](examples/).
## Getting help
-Documentation of the latest release of ndgrid can be found on [docs.rs](https://docs.rs/ndgrid/latest/ndgrid/).
Documentation of the latest development version of ndgrid can be found at [bempp.github.io/ndgrid/ndgrid](https://bempp.github.io/ndgrid/ndgrid).
Errors in the library should be added to the [GitHub issue tracker](https://github.com/bempp/ndgrid/issues).
diff --git a/katex-header.html b/katex-header.html
new file mode 100644
index 0000000..da412ac
--- /dev/null
+++ b/katex-header.html
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/src/geometry/single_element/entity_geometry.rs b/src/geometry/single_element/entity_geometry.rs
index 1879426..7fe6efa 100644
--- a/src/geometry/single_element/entity_geometry.rs
+++ b/src/geometry/single_element/entity_geometry.rs
@@ -66,6 +66,7 @@ impl Geometry for SingleElementEntityGeometry<'
fn point_count(&self) -> usize {
self.geometry.cells().shape()[0]
}
+
fn degree(&self) -> usize {
self.geometry.element().lagrange_superdegree()
}
diff --git a/src/grid/local_grid/single_element/builder.rs b/src/grid/local_grid/single_element/builder.rs
index 1fa6736..6e74f3f 100644
--- a/src/grid/local_grid/single_element/builder.rs
+++ b/src/grid/local_grid/single_element/builder.rs
@@ -18,6 +18,28 @@ use rlst::rlst_dynamic_array;
use std::collections::{HashMap, HashSet};
/// Grid builder for a single element grid
+///
+/// The following gives an example of creating a new grid consisting
+/// of a single triangle.
+///
+/// ```
+/// use ndgrid::traits::Builder;
+/// use ndgrid::SingleElementGridBuilder;
+/// use ndelement::types::ReferenceCellType;
+///
+/// // The geometric dimension of our space is 3.
+/// let gdim = 3;
+///
+/// // We are building a two dimensional surface triangle grid within a three dimensional space.
+/// // Our grid will have three points and one `Triangle` cell of order 1.
+/// let mut builder = SingleElementGridBuilder::new_with_capacity(gdim, 3, 1, (ReferenceCellType::Triangle, 1));
+/// builder.add_point(0, &[0.0, 0.0, 0.0]);
+/// builder.add_point(1, &[1.0, 0.0, 0.0]);
+/// builder.add_point(2, &[0.0, 1.0, 0.0]);
+/// builder.add_cell(0, &[0, 1, 2]);
+///
+/// let grid = builder.create_grid();
+/// ```
#[derive(Debug)]
pub struct SingleElementGridBuilder {
gdim: usize,
diff --git a/src/lib.rs b/src/lib.rs
index 6585fd0..237ea1e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,38 +4,29 @@
//!
//! ## Creating a grid with `ndgrid`
//!
-//! To explain the library we use the following example of a grid consisting of two triangles that together form the unit rectangle.
-//! To that effect we introduce the following boundary vertices.
+//! To demonstrate the library, we use an example grid consisting of two triangles that together form the unit square.
+//! We introduce the following points. As we will make a grid of second oder elements, we include points at the midpoint
+//! of each edge as well as at the vertices of the square
//! - Point 0: (0, 0)
//! - Point 1: (1, 0)
//! - Point 2: (0, 1)
//! - Point 3: (1, 1)
-//!
-//! To make matters more interesting we will define a grid of second order elements.
-//! This means that each edge of the triangle also has a middle point. The corresponding points are
-//! given as follows:
-//!
//! - Point 4: (0.5, 0.5)
//! - Point 5: (0.0, 0.5)
//! - Point 6: (0.5, 0.0)
//! - Point 7: (0.5, 1.0)
//! - Point 8: (1.0, 0.5)
//!
-//! The order of points for each element is the same as the one on [defelement.org](https://defelement.org).
+//! The order of points for each cell follows the point ordering of the
+//! [Lagrange element on DefElement](https://defelement.org/elements/lagrange.html).
//! For second order triangles we use
//! [this ordering](https://defelement.org/elements/examples/triangle-lagrange-equispaced-2.html).
+//! Following this ordering, the two cells of our example grid are:
//!
-//! `ndgrid` does an important distinction between points and topological vertices. The boundary points
-//! of the triangle are called vertices and determine the connectivity relationship of this triangle with other
-//! triangles. Topologically, the two triangles are defined through the points 0, 1, 2 for the first triangle
-//! and 1, 3, 2 for the second triangle. However, the full cell definition is
//! - Cell 1: 0, 1, 2, 4, 5, 6
//! - Cell 2: 1, 3, 2, 7, 4, 8
//!
-//! in terms of the points.
-//!
-//! Let us generate the corresponding data structures.
-//!
+//! In order to create our grid using ndgrid, we first create a grid builder.
//! ```
//! use ndgrid::traits::Builder;
//! use ndelement::types::ReferenceCellType;
@@ -46,14 +37,21 @@
//! (ReferenceCellType::Triangle, 2),
//! );
//! ```
-//! The [SingleElementGridBuilder] is for grids that
-//! only use a single element type. The first parameter is the geometric dimension. Here we choose 2,
-//! meaning the grid lives in two-dimensionals pace. The next parameter is the number of points, 9 in this case,
-//! and the third parameter is the number of cells, which is also 2 here.
-//! The element type is [ReferenceCellType::Triangle](ndelement::types::ReferenceCellType::Triangle).
-//! The order of the triangles is 2.
-//!
-//! We now add the definitions of the points and cells.
+//!
+//! The [SingleElementGridBuilder] is for grids that only use a single element type. The parameters passed when
+//! initialising the build are:
+//!
+//! - The geometric dimension: our example grid lives in two-dimensional space, so we use 2.
+//! - The number of points: 9 for our example grid.
+//! - The number of cells: 2 for our example grid.
+//! - The cell type and element degree: for our example, this is ([ReferenceCellType::Triangle](ndelement::types::ReferenceCellType::Triangle), 2)
+//! as our geometry cells are triangles and we use quadratic geometry for each triangle.
+//!
+//! If we did not know the number of points and cells that we will include in out grid when creating ths builder,
+//! we could instead use the function [SingleElementGridBuilder::new] when initialising the grid.
+//!
+//! Now that we have created a grid builder, we can add the points and cells:
+//!
//! ```
//! # use ndgrid::traits::Builder;
//! # use ndelement::types::ReferenceCellType;
@@ -73,8 +71,8 @@
//! builder.add_point(7, &[0.5, 1.0]);
//! builder.add_point(8, &[1.0, 0.5]);
//!
-//! builder.add_cell(0, &[0, 1, 2, 4, 5, 6]);
-//! builder.add_cell(1, &[1, 3, 2, 7, 4, 8]);
+//! builder.add_cell(1, &[0, 1, 2, 4, 5, 6]);
+//! builder.add_cell(2, &[1, 3, 2, 7, 4, 8]);
//! ```
//! Finally, we generate the grid.
//! ```
@@ -95,24 +93,34 @@
//! # builder.add_point(6, &[0.5, 0.0]);
//! # builder.add_point(7, &[0.5, 1.0]);
//! # builder.add_point(8, &[1.0, 0.5]);
-//!
-//! # builder.add_cell(0, &[0, 1, 2, 4, 5, 6]);
-//! # builder.add_cell(1, &[1, 3, 2, 7, 4, 8]);
+//! #
+//! # builder.add_cell(1, &[0, 1, 2, 4, 5, 6]);
+//! # builder.add_cell(2, &[1, 3, 2, 7, 4, 8]);
//! let grid = builder.create_grid();
//! ```
+//!
//! ## Querying the grid
//!
-//! A grid is a hierarchy of entities. The highest dimension entities are the cells. Each cell consists of subentities,
-//! which are faces, edges, etc. For each entity there are two types of information, the topology information and the
-//! geometry information. The topology describes how entities are connected. The geometry describes how entities related
-//! to their associated physical points. Each entity is associated with an `index`. Indices are unique within the class
-//! of entities, that is there is a point with index 0 and a cell with index 0 but no two points with index 0. Points and
-//! cells also have an associated `id`. `ids` are the indices provided by the user with the `add_point` or `add_cell`
-//! methods in the grid builder. These ids will usually be different from the internal indices of entities.
+//! A grid is a hierarchy of entities. We follow the standard name conventions for entities of a given topological dimension:
+//! 0-, 1-, 2- and 3-dimensional entities and called vertices, edges, faces and volumes (respectively).
+//! The highest dimensional entities are called cells. If $d$ the (topological) dimension of the cells,
+//! then $d-1$-, $d-2$- and $d-3$-dimensional entities are called facets, ridges and peaks (respectively).
+//!
+//! For each entity there are two types of information: the topology and the geometry.
+//! The topology describes how entities are connected. The geometry describes how entities are positioned in physical space.
+//! As the topology is only concerned with the connectivity between entities, it only includes the cell's points that are at
+//! the vertices of a cell (eg for the triangle cells in our grid, the topology onle includes the first three points for each cell).
+//! In the geometry, all the points that define the cell are stored.
//!
-//! The following code extracts all topological vertices for each cell and prints the corresponding physical coordinates.
+//! Each entity has an associated `index`. Indices are unique within entities of a given type:
+//! there is a vertex with index 0 and a cell with index 0 but there cannot be two vertices with index 0. Points and
+//! cells may also have an associated `id`: these are the values provided by the user when using the `add_point` or `add_cell`
+//! methods in the grid builder. These ids are not guaranteed to be equal to the indices of the entities.
+//!
+//! The following code extracts the vertices of each cell and prints their corresponding physical coordinates.
//! ```
//! # use ndgrid::traits::Builder;
+//! use ndgrid::traits::{Grid, Entity, Topology, Geometry, Point};
//! # use ndelement::types::ReferenceCellType;
//! # let mut builder = ndgrid::SingleElementGridBuilder::::new_with_capacity(
//! # 2,
@@ -129,11 +137,11 @@
//! # builder.add_point(6, &[0.5, 0.0]);
//! # builder.add_point(7, &[0.5, 1.0]);
//! # builder.add_point(8, &[1.0, 0.5]);
-//!
-//! # builder.add_cell(0, &[0, 1, 2, 4, 5, 6]);
-//! # builder.add_cell(1, &[1, 3, 2, 7, 4, 8]);
+//! #
+//! # builder.add_cell(1, &[0, 1, 2, 4, 5, 6]);
+//! # builder.add_cell(2, &[1, 3, 2, 7, 4, 8]);
//! # let grid = builder.create_grid();
-//! use ndgrid::traits::{Grid, Entity, Topology, Geometry, Point};
+//!
//! for cell in grid.entity_iter(ReferenceCellType::Triangle) {
//! for vertex in cell.topology().sub_entity_iter(ReferenceCellType::Point) {
//! let vertex = grid.entity(ReferenceCellType::Point, vertex).unwrap();
@@ -154,26 +162,19 @@
//! }
//! }
//! ```
-//! Let us dissect what is going on here. First, we iteratre through the cells of the grid.
-//! For this we use the [Grid::entity_iter](crate::traits::Grid::entity_iter) function.
-//! For each cell we then access the topology information via [Entity::topology](crate::traits::Entity::topology)
-//! and iterate through the point subentities via [Topology::sub_entity_iter](crate::traits::Topology::sub_entity_iter).
-//! This gives us the vertices of the triangles. The topology information only considers the points that define the topology.
-//! So the middle points on each edge which are necessary for the order of the triangle, are not returned. Also, the iterator
-//! returns integer indices of entities. To convert an entity index to an actual entity use the
-//! [Grid::entity](crate::traits::Grid::entity) function. We now want to get the actual physical coordinate of a vertex.
-//! Since the geometric dimension is 2 we instantiate an array `[f64; 2]` for this. We now call on the vertex the
-//! [Entity::geometry](crate::traits::Entity::geometry) function to obtain its geometry information. We then
-//! call [Geometry::points](crate::traits::Geometry::points) to get an iterator to all physical points
-//! associated with the vertex. Since a vertex only has one associated physical point (namely the vertex itself) we just
-//! call `next` once on this iterator to get the actual point. Finally, we call [Point::coords](crate::traits::Point::coords)
-//! to get the values of the physical coordinate.
-//!
-//!
-//!
-//!
-//!
//!
+//! This snippets starts by using [Grid::entity_iter](crate::traits::Grid::entity_iter) to iterate through each
+//! cell (ie each entity that is a triangle).
+//! For each cell, we then access the topology information via [Entity::topology](crate::traits::Entity::topology)
+//! and iterate through the vertices (ie the subentities that are points) using [Topology::sub_entity_iter](crate::traits::Topology::sub_entity_iter).
+//! This iterators gives us the index of each vertex: to convert an entity index to an entity, we use [Grid::entity](crate::traits::Grid::entity).
+//! We now want to get the actual physical coordinate of a vertex.
+//! Since the geometric dimension is 2 we instantiate an array `[f64; 2]` for this. We use
+//! [Entity::geometry](crate::traits::Entity::geometry) to obtain the geometry for the vertex, then use
+//! [Geometry::points](crate::traits::Geometry::points) to get an iterator over the physical points
+//! associated with the vertex. Since a vertex has only one associated physical point, we
+//! call `next` once on this iterator to get the point. Finally, we call [Point::coords](crate::traits::Point::coords)
+//! to get the values of the physical coordinate.
#![cfg_attr(feature = "strict", deny(warnings), deny(unused_crate_dependencies))]
#![warn(missing_docs)]
diff --git a/src/traits/builder.rs b/src/traits/builder.rs
index 5adb5cf..9e10a9b 100644
--- a/src/traits/builder.rs
+++ b/src/traits/builder.rs
@@ -11,28 +11,6 @@ use std::hash::Hash;
///
/// After instantiation points and cells can be added.
/// To build the actual grid call [Builder::create_grid].
-///
-/// The following gives an example of creating a new grid consisting
-/// of a single triangle.
-///
-/// ```
-/// use ndgrid::traits::Builder;
-/// use ndgrid::SingleElementGridBuilder;
-/// use ndelement::types::ReferenceCellType;
-///
-/// // The geometric dimension of our space is 3.
-/// let gdim = 3;
-///
-/// // We are building a two dimensional surface triangle grid within a three dimensional space.
-/// // Our grid will have three points and one `Triangle` cell of order 1.
-/// let mut builder = SingleElementGridBuilder::new_with_capacity(gdim, 3, 1, (ReferenceCellType::Triangle, 1));
-/// builder.add_point(0, &[0.0, 0.0, 0.0]);
-/// builder.add_point(1, &[1.0, 0.0, 0.0]);
-/// builder.add_point(2, &[0.0, 1.0, 0.0]);
-/// builder.add_cell(0, &[0, 1, 2]);
-///
-/// let grid = builder.create_grid();
-/// ```
pub trait Builder {
/// Type used as identifier of different entity types
type EntityDescriptor: Debug + PartialEq + Eq + Clone + Copy + Hash;