Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
fd8cf04
fem: generalized jacobian measure using the area formula
Pawel024 Jan 15, 2026
3995dab
fem: completed base implementation of segments embedded in 2d
Pawel024 Jan 17, 2026
5ae76d1
fem: copy block_mass and block_grad_grad tests for embedded segments
Pawel024 Jan 20, 2026
e30e749
fem: copy tests from isoparametric_segment.cc for embedded segments
Pawel024 Jan 20, 2026
b943365
fem: add tests for gradient values and arc length to isoparametric_em…
Pawel024 Jan 20, 2026
d408726
fem: update block tests for embedded segments to use a diagonal segment
Pawel024 Jan 20, 2026
01741b6
fem: update paths to match fields redesign
Pawel024 Jan 23, 2026
4fe4832
fem: formatting edits
Pawel024 Jan 23, 2026
c1e17e2
tests/fem: formatting edits
Pawel024 Jan 23, 2026
b313d85
fem: replace hardcoded dimension values with the variable dim
Pawel024 Jan 23, 2026
2b9e098
fem: make base isoparametric segment class a template of the dimension
Pawel024 Jan 23, 2026
f3f3451
fem: update elements api to select the right simplex based on degree …
Pawel024 Jan 27, 2026
e81d32d
fem: expose volume form from manifold and pass it to the element classes
Pawel024 Jan 27, 2026
69a068c
fem: replace the jacobian_measure utility with element.volume_element
Pawel024 Jan 27, 2026
9ce302e
fem: update jacobian calculation in element classes to work for diffe…
Pawel024 Jan 27, 2026
e3210e7
tensor: add as_column_matrix factory, apply in IsoparametricSegmentP1…
Pawel024 Jan 27, 2026
7f96cf6
fem: use pyre::tensor::col and tensor::dyadic properly to avoid repet…
Pawel024 Jan 27, 2026
31c7e73
fem: contravariant gradient computation with the riemannian formula -…
Pawel024 Jan 27, 2026
4a08b11
tests/fem: adapt tests to work with the new elements API
Pawel024 Jan 27, 2026
e6d974a
fem: remove division by factorial in volume element computation, it's…
Pawel024 Jan 28, 2026
ff1f5c4
tests/fem: use a clockwise-rotated normal field to get positive volum…
Pawel024 Jan 28, 2026
4a1daa8
benchmarks: update the poisson benchmark to use the new elements api
Pawel024 Jan 28, 2026
65259dc
fem: update comments to use "n-simplex" instead of "nth order simplex…
Pawel024 Jan 28, 2026
fe3d6fc
Merge remote-tracking branch 'origin/main' into fem-1d-embedded-in-2d
Pawel024 Jan 29, 2026
0f27c1b
test/fem: test integration with volume form on arbitrary segments
Pawel024 Feb 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .cmake/mito_tests_mito_lib.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ mito_test_driver(tests/mito.lib/geometry/cell_directors.cc)
mito_test_driver(tests/mito.lib/geometry/point.cc)
mito_test_driver(tests/mito.lib/geometry/euclidean_metric_2D.cc)
mito_test_driver(tests/mito.lib/geometry/euclidean_metric_3D.cc)
mito_test_driver(tests/mito.lib/geometry/euclidean_submanifold_metric_2D.cc)
mito_test_driver(tests/mito.lib/geometry/euclidean_submanifold_metric_3D.cc)
mito_test_driver(tests/mito.lib/geometry/cube_volume.cc)
mito_test_driver(tests/mito.lib/geometry/metric.cc)
Expand All @@ -47,8 +48,10 @@ mito_test_driver(tests/mito.lib/discrete/mesh_field.cc)
# fem
mito_test_driver(tests/mito.lib/fem/block_grad_grad.cc)
mito_test_driver(tests/mito.lib/fem/block_grad_grad_segment.cc)
mito_test_driver(tests/mito.lib/fem/block_grad_grad_embedded_segment.cc)
mito_test_driver(tests/mito.lib/fem/block_mass.cc)
mito_test_driver(tests/mito.lib/fem/block_mass_segment.cc)
mito_test_driver(tests/mito.lib/fem/block_mass_embedded_segment.cc)
mito_test_driver(tests/mito.lib/fem/shape_functions_triangle_construction.cc)
mito_test_driver(tests/mito.lib/fem/shape_functions_triangle_p1.cc)
mito_test_driver(tests/mito.lib/fem/shape_functions_triangle_p2.cc)
Expand All @@ -57,6 +60,7 @@ mito_test_driver(tests/mito.lib/fem/localize_field.cc)
mito_test_driver(tests/mito.lib/fem/fem_field.cc)
mito_test_driver(tests/mito.lib/fem/shape_functions_segment_p1.cc)
mito_test_driver(tests/mito.lib/fem/isoparametric_segment.cc)
mito_test_driver(tests/mito.lib/fem/isoparametric_embedded_segment.cc)

# io
mito_test_driver(tests/mito.lib/io/summit_mesh_reader_2D.cc)
Expand Down
5 changes: 3 additions & 2 deletions benchmarks/mito.lib/pdes/poisson.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ using coordinates_t = mito::geometry::coordinates_t<2, mito::geometry::CARTESIAN
using cell_t = mito::geometry::triangle_t<2>;
// second degree finite elements
constexpr int degree = 2;
// assemble the finite element type
using finite_element_t = mito::fem::isoparametric_simplex_t<degree, cell_t>;

// the reference simplex
using reference_simplex_t = mito::geometry::reference_triangle_t;
Expand Down Expand Up @@ -59,6 +57,9 @@ main()
// create the body manifold
auto manifold = mito::manifolds::manifold(mesh, coord_system);

// assemble the finite element type
using finite_element_t = mito::fem::isoparametric_simplex_t<degree, decltype(manifold)>;

// get the boundary mesh
auto boundary_mesh = mito::mesh::boundary(mesh);

Expand Down
4 changes: 2 additions & 2 deletions lib/mito/fem/blocks/GradGradBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ namespace mito::fem::blocks {
constexpr auto w =
element_type::canonical_element_type::area * quadrature_rule.weight(q);

// precompute the common factor
auto factor = w * tensor::determinant(element.jacobian()(xi));
// precompute the common factor using the element's volume element
auto factor = w * element.volume_element()(xi);

// loop on the nodes of the element
tensor::constexpr_for_1<n_nodes>([&]<int a>() {
Expand Down
4 changes: 2 additions & 2 deletions lib/mito/fem/blocks/L2NormBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ namespace mito::fem::blocks {
constexpr auto w =
element_type::canonical_element_type::area * quadrature_rule.weight(q);

// precompute the common factor
auto factor = w * tensor::determinant(element.jacobian()(xi));
// precompute the common factor using the element's volume element
auto factor = w * element.volume_element()(xi);

// populate the elementary contribution to the matrix
elementary_contribution += factor * _function(xi) * _function(xi);
Expand Down
4 changes: 2 additions & 2 deletions lib/mito/fem/blocks/MassBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ namespace mito::fem::blocks {
constexpr auto w =
element_type::canonical_element_type::area * quadrature_rule.weight(q);

// precompute the common factor
auto factor = w * tensor::determinant(element.jacobian()(xi));
// precompute the common factor using the element's volume element
auto factor = w * element.volume_element()(xi);

// loop on the nodes of the element
tensor::constexpr_for_1<n_nodes>([&]<int a>() {
Expand Down
4 changes: 2 additions & 2 deletions lib/mito/fem/blocks/SourceTermBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ namespace mito::fem::blocks {
constexpr auto w =
element_type::canonical_element_type::area * quadrature_rule.weight(q);

// precompute the common factor
auto factor = w * tensor::determinant(element.jacobian()(xi));
// precompute the common factor using the element's volume element
auto factor = w * element.volume_element()(xi);

// loop on the nodes of the element
tensor::constexpr_for_1<n_nodes>([&]<int a>() {
Expand Down
53 changes: 43 additions & 10 deletions lib/mito/fem/elements/IsoparametricSegment.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,52 @@


// DESIGN NOTES
// Class {IsoparametricSegment} represents a first order simplex (segment) equipped with parametric
// coordinates.
// Class {IsoparametricSegment} represents a 1-simplex equipped with parametric
// coordinates. Template parameters:
// - coordsT: The coordinate type (determines ambient dimension D and coordinate system)
// - VolumeFormT: The type of the volume form (N-form for integration)
// This design supports segments in any coordinate system and any embedding (N=D
// for non-embedded, N<D for embedded manifolds).


namespace mito::fem {

template <geometry::coordinates_c coordsT, class VolumeFormT>
class IsoparametricSegment : public utilities::Invalidatable {
public:
// the dimension of the physical space
static constexpr int dim = 1;
// dimension of the parametric space
static constexpr int N = 1;
// ambient dimension from coordinate type
static constexpr int D = coordsT::dim;

// the Jacobian is a D×N matrix (for a segment: D×1, a column vector)
using jacobian_type = tensor::matrix_t<D, N>;

// the metric space provides g, g_inv for this coordinate system
using metric_space_type = geometry::metric_space<coordsT>;

// the discretization node type
using discretization_node_type = discrete::discretization_node_t;
// the underlying cell type
using cell_type = geometry::segment_t<dim>;
using cell_type = geometry::segment_t<D>;

protected:
// cartesian coordinates in 1D
using coordinates_type = geometry::coordinates_t<1, geometry::CARTESIAN>;
// the coordinate system type
// coordinate types
using coordinates_type = coordsT;
using coordinate_system_type = geometry::coordinate_system_t<coordinates_type>;
// the vector type
using vector_type = tensor::vector_t<1>;
using vector_type = tensor::vector_t<D>;
// volume form type
using volume_form_type = VolumeFormT;

public:
// the default constructor
constexpr IsoparametricSegment(
const cell_type & cell, const coordinate_system_type & coord_system) :
const cell_type & cell, const coordinate_system_type & coord_system,
const volume_form_type & volume_form) :
_cell(cell),
_coord_system(coord_system),
_volume_form(volume_form),
_x0{ coord_system.coordinates(cell.nodes()[0]->point()) - coordinates_type{} },
_x1{ coord_system.coordinates(cell.nodes()[1]->point()) - coordinates_type{} }
{}
Expand All @@ -59,11 +77,26 @@ namespace mito::fem {
// get the geometric simplex
constexpr auto cell() const noexcept -> const cell_type & { return _cell; }

protected:
// access to metric tensor at a point (for gradient computation)
static constexpr auto g(const coordinates_type & x) { return metric_space_type::g(x); }

static constexpr auto g_inv(const coordinates_type & x)
{
return metric_space_type::g_inv(x);
}

protected:
// QUESTION: do we need to maintain a reference to the geometric simplex?
// a const reference to the geometric simplex
const cell_type & _cell;

// a const reference to the coordinate system
const coordinate_system_type & _coord_system;

// the volume form (received from manifold/discretizer)
const volume_form_type & _volume_form;

// the coordinates of the discretization nodes of the segment
const vector_type _x0;
const vector_type _x1;
Expand Down
48 changes: 39 additions & 9 deletions lib/mito/fem/elements/IsoparametricTriangle.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,52 @@


// DESIGN NOTES
// Class {IsoparametricTriangle} represents a second order simplex equipped barycentric coordinates.
// Class {IsoparametricTriangle} represents a 2-simplex equipped with barycentric
// coordinates. Template parameters:
// - coordsT: The coordinate type (determines ambient dimension D and coordinate system)
// - VolumeFormT: The type of the volume form (N-form for integration)
// This design supports triangles in any coordinate system and any
// embedding (N=D for non-embedded, N<D for embedded manifolds).


namespace mito::fem {

template <geometry::coordinates_c coordsT, class VolumeFormT>
class IsoparametricTriangle : public utilities::Invalidatable {
public:
// the dimension of the physical space
static constexpr int dim = 2;
// dimension of the parametric space
static constexpr int N = 2;
// ambient dimension from coordinate type
static constexpr int D = coordsT::dim;

// the Jacobian is a D×N matrix (for a triangle: D×2)
using jacobian_type = tensor::matrix_t<D, N>;

// the metric space provides g, g_inv for this coordinate system
using metric_space_type = geometry::metric_space<coordsT>;

// the discretization node type
using discretization_node_type = discrete::discretization_node_t;
// the underlying cell type
using cell_type = geometry::triangle_t<dim>;
using cell_type = geometry::triangle_t<D>;

protected:
// cartesian coordinates in 2D
using coordinates_type = geometry::coordinates_t<2, geometry::CARTESIAN>;
// the coordinate system type
// coordinate types
using coordinates_type = coordsT;
using coordinate_system_type = geometry::coordinate_system_t<coordinates_type>;
// the vector type
using vector_type = tensor::vector_t<2>;
using vector_type = tensor::vector_t<D>;
// volume form type
using volume_form_type = VolumeFormT;

public:
// the default constructor
constexpr IsoparametricTriangle(
const cell_type & cell, const coordinate_system_type & coord_system) :
const cell_type & cell, const coordinate_system_type & coord_system,
const volume_form_type & volume_form) :
_cell(cell),
_coord_system(coord_system),
_volume_form(volume_form),
_x0{ coord_system.coordinates(cell.nodes()[0]->point()) - coordinates_type{} },
_x1{ coord_system.coordinates(cell.nodes()[1]->point()) - coordinates_type{} },
_x2{ coord_system.coordinates(cell.nodes()[2]->point()) - coordinates_type{} }
Expand Down Expand Up @@ -63,13 +81,25 @@ namespace mito::fem {
// get the mapping from parametric coordinates to physical coordinates
constexpr auto parametrization() const { return _cell.parametrization(_coord_system); }

protected:
// access to metric tensor at a point (for gradient computation)
static constexpr auto g(const coordinates_type & x) { return metric_space_type::g(x); }

static constexpr auto g_inv(const coordinates_type & x)
{
return metric_space_type::g_inv(x);
}

protected:
// a const reference to the geometric simplex
const cell_type & _cell;

// a const reference to the coordinate system
const coordinate_system_type & _coord_system;

// the volume form (received from manifold/discretizer)
const volume_form_type & _volume_form;

// the coordinates of the discretization nodes of the triangle
const vector_type _x0;
const vector_type _x1;
Expand Down
6 changes: 1 addition & 5 deletions lib/mito/fem/elements/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@


namespace mito::fem {

// type alias for convenient access to the isoparametric simplex type
template <int degree, geometry::geometric_simplex_c geometricSimplexT>
using isoparametric_simplex_t = typename isoparametric_simplex<degree, geometricSimplexT>::type;

// no specializations needed here - see elements_library.h for the unified API
}


Expand Down
55 changes: 55 additions & 0 deletions lib/mito/fem/elements/elements_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,64 @@
#pragma once


// DESIGN NOTES:
// This file provides the main user-facing API for selecting finite elements.
// Users specify only the polynomial degree and manifold type:
//
// using element_t = mito::fem::isoparametric_simplex_t<degree, ManifoldT>;
//
// The type system automatically extracts:
// - Coordinate type (coordsT) from ManifoldT::coordinates_type
// - Volume form type (VolumeFormT) from ManifoldT::volume_form_type
// - Cell dimensionality to select segment vs triangle


#include "seg1/public.h"
#include "tri1/public.h"
#include "tri2/public.h"


namespace mito::fem {

template <int degree, class ManifoldT>
struct isoparametric_simplex;

// specialization for degree 1, 1D manifolds (segments)
template <class ManifoldT>
requires(ManifoldT::cell_type::order == 1) // 1D cell (segment)
struct isoparametric_simplex<1, ManifoldT> {
using coordinates_type = typename ManifoldT::coordinates_type;
using volume_form_type = typename ManifoldT::volume_form_type;

using type = IsoparametricSegmentP1<coordinates_type, volume_form_type>;
};

// specialization for degree 1, 2D manifolds (triangles)
template <class ManifoldT>
requires(ManifoldT::cell_type::order == 2) // 2D cell (triangle)
struct isoparametric_simplex<1, ManifoldT> {
using coordinates_type = typename ManifoldT::coordinates_type;
using volume_form_type = typename ManifoldT::volume_form_type;

using type = IsoparametricTriangleP1<coordinates_type, volume_form_type>;
};

// specialization for degree 2, 2D manifolds (triangles)
template <class ManifoldT>
requires(ManifoldT::cell_type::order == 2) // 2D cell (triangle)
struct isoparametric_simplex<2, ManifoldT> {
using coordinates_type = typename ManifoldT::coordinates_type;
using volume_form_type = typename ManifoldT::volume_form_type;

using type = IsoparametricTriangleP2<coordinates_type, volume_form_type>;
};

// convenience alias - primary way users specify element types
// usage: isoparametric_simplex_t<degree, decltype(manifold)>
template <int degree, class ManifoldT>
using isoparametric_simplex_t = typename isoparametric_simplex<degree, ManifoldT>::type;

} // namespace mito::fem


// end of file
7 changes: 4 additions & 3 deletions lib/mito/fem/elements/forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ namespace mito::fem {
template <class elementT, discretization_t discretizationT>
struct Discretizer;

// struct storing the type of an isoparametric simplex of polynomial degree {degree} on a
// geometric simplex of type {geometricSimplexT}
template <int degree, geometry::geometric_simplex_c geometricSimplexT>
// struct storing the type of an isoparametric simplex of polynomial degree {degree}
// on a manifold of type {ManifoldT}
// the manifold type encapsulates the coordinate system, volume form, and cell type
template <int degree, class ManifoldT>
struct isoparametric_simplex;

}
Expand Down
Loading
Loading