ngstSpaceKit.hermite

  1from dataclasses import dataclass
  2
  3import ngsolve
  4from ngsolve import (
  5    BBBND,
  6    BBND,
  7    BND,
  8    H1,
  9    L2,
 10    TET,
 11    TRIG,
 12    IntegrationRule,
 13    dx,
 14)
 15from ngsolve.utils import FacetFESpace
 16from ngstrefftz import EmbeddedTrefftzFES, L2EmbTrefftzFESpace, TrefftzEmbedding
 17
 18from ngstSpaceKit.diffops import del_x, del_y, del_z
 19from ngstSpaceKit.mesh_properties import (
 20    throw_on_wrong_mesh_dimension,
 21    throw_on_wrong_mesh_eltype,
 22)
 23
 24
 25@dataclass
 26class HermiteDirichlet:
 27    """
 28    Holds the dirichlet instructions for every type of dof in the `Hermite` space separately.
 29
 30    `deriv_z` is only used in the 3D case.
 31    """
 32
 33    vertex_value: str = ""
 34    deriv_x: str = ""
 35    deriv_y: str = ""
 36    deriv_z: str = ""
 37
 38    @classmethod
 39    def clamp(cls, bnd: str) -> "HermiteDirichlet":
 40        """
 41        `bnd`: boundary where clamp conditions shall be set.
 42        """
 43        return cls(vertex_value=bnd, deriv_x=bnd, deriv_y=bnd, deriv_z=bnd)
 44
 45
 46def Hermite(
 47    mesh: ngsolve.comp.Mesh,
 48    dirichlet: str | HermiteDirichlet = "",
 49    check_mesh: bool = True,
 50    stats: dict | None = None,
 51) -> L2EmbTrefftzFESpace:
 52    r"""
 53    The Hermite element is implemented for 2D and 3D on triangles and tetrahedrons.
 54
 55    `check_mesh`: test, if the `mesh` is compatible with this space
 56
 57    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
 58
 59    # Raises
 60    - ValueError, if the mesh is neither 2D nor 3D
 61    - ValueError, if the mesh is neither triangular nor tetrahedral
 62
 63    # Conforming Trefftz Formulation for 2D
 64    - $\mathbb{V}_h := \mathbb{P}^{3, \text{disc}}(\mathcal{T}_h)$
 65    - $\mathbb{Z}_h := [\mathbb{P}^{1}(\mathcal{T}_h)]^3 \times \mathbb{P}^{0}(\mathcal{T}_h)$
 66    - \begin{align}
 67      \mathcal{C}_K(v_h&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\\\
 68          &\sum_{p \text{ is vertex}} v_h(p) z_h^\text{value}(p)
 69          + \sum_{p \text{ is vertex}} \partial_x v_h(p) z_h^\text{x}(p) \\\\
 70          &+ \sum_{p \text{ is vertex}} \partial_y v_h(p) z_h^\text{y}(p)
 71          + \sum_{m \text{ is element-midpoint}} v_h(m) z_h^\text{mid}(m), \\\\
 72      \mathcal{D}_K((y_h^\text{value}, y_h^\text{x}, y_h^\text{y}, y_h^\text{mid})&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\\\
 73          &\sum_{p \text{ is vertex}} y_h^\text{value}(p) z_h^\text{value}(p)
 74          + \sum_{p \text{ is vertex}} y_h^\text{x}(p) z_h^\text{x}(p) \\\\
 75          &+ \sum_{p \text{ is vertex}} y_h^\text{y}(p) z_h^\text{y}(p)
 76          + \sum_{m \text{ is element-midpoint}} y_h^\text{mid}(m) z_h^\text{mid}(m)
 77      \end{align}
 78    """
 79    if check_mesh:
 80        throw_on_wrong_mesh_dimension(mesh, [2, 3])
 81        throw_on_wrong_mesh_eltype(mesh, [TRIG, TET])
 82
 83    dirichlet_struct = (
 84        HermiteDirichlet(vertex_value=dirichlet)
 85        if type(dirichlet) is str
 86        else dirichlet
 87    )
 88    assert type(dirichlet_struct) is HermiteDirichlet
 89
 90    if mesh.dim == 2:
 91        return Hermite2D(
 92            mesh,
 93            dirichlet_struct,
 94            check_mesh=False,
 95            stats=stats,
 96        )
 97    else:
 98        return Hermite3D(
 99            mesh,
100            dirichlet_struct,
101            check_mesh=False,
102            stats=stats,
103        )
104
105
106def Hermite2D(
107    mesh: ngsolve.comp.Mesh,
108    dirichlet: HermiteDirichlet,
109    check_mesh: bool = True,
110    stats: dict | None = None,
111) -> L2EmbTrefftzFESpace:
112    """
113    Implementation of the Hermite element in 2D
114
115    `check_mesh`: test, if the `mesh` is compatible with this space
116
117    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
118
119    # Raises
120    - ValueError, if the mesh is not 2D
121    - ValueError, if the mesh is not triangular
122    """
123    if check_mesh:
124        throw_on_wrong_mesh_dimension(mesh, 2)
125        throw_on_wrong_mesh_eltype(mesh, TRIG)
126
127    fes = L2(mesh, order=3)
128    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
129    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
130    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
131    midpoint_value_space = L2(mesh, order=0)
132
133    conformity_space = (
134        vertex_value_space
135        * deriv_x_value_space
136        * deriv_y_value_space
137        * midpoint_value_space
138    )
139
140    u = fes.TrialFunction()
141    (u_, u_dx, u_dy, u_m) = conformity_space.TrialFunction()
142    (v_, v_dx, v_dy, v_m) = conformity_space.TestFunction()
143
144    dVertex = dx(element_vb=BBND)
145
146    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
147    dMidpoint = dx(intrules={TRIG: midpoint_intrule})
148
149    cop_lhs = (
150        u * v_ * dVertex
151        + del_x(u) * v_dx * dVertex
152        + del_y(u) * v_dy * dVertex
153        + u * v_m * dMidpoint
154    )
155    cop_rhs = (
156        u_ * v_ * dVertex
157        + u_dx * v_dx * dVertex
158        + u_dy * v_dy * dVertex
159        + u_m * v_m * dVertex
160    )
161
162    embedding = TrefftzEmbedding(
163        cop=cop_lhs,
164        crhs=cop_rhs,
165        ndof_trefftz=0,
166        stats=stats,
167    )
168
169    hermite = EmbeddedTrefftzFES(embedding)
170    assert type(hermite) is L2EmbTrefftzFESpace, (
171        "The hermite space should always be an L2EmbTrefftzFESpace"
172    )
173
174    return hermite
175
176
177def Hermite3D(
178    mesh: ngsolve.comp.Mesh,
179    dirichlet: HermiteDirichlet,
180    check_mesh: bool = True,
181    stats: dict | None = None,
182) -> L2EmbTrefftzFESpace:
183    """
184    Implementation of the Hermite element in 3D
185
186    `check_mesh`: test, if the `mesh` is compatible with this space
187
188    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
189
190    # Raises
191    - ValueError, if the mesh is not 3D
192    - ValueError, if the mesh is not tetrahedral
193    """
194    if check_mesh:
195        throw_on_wrong_mesh_dimension(mesh, 3)
196        throw_on_wrong_mesh_eltype(mesh, TET)
197
198    fes = L2(mesh, order=3)
199    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
200    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
201    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
202    deriv_z_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_z)
203    midpoint_value_space = FacetFESpace(mesh, order=0)
204
205    conformity_space = (
206        vertex_value_space
207        * deriv_x_value_space
208        * deriv_y_value_space
209        * deriv_z_value_space
210        * midpoint_value_space
211    )
212
213    u = fes.TrialFunction()
214    (u_, u_dx, u_dy, u_dz, u_m) = conformity_space.TrialFunction()
215    (v_, v_dx, v_dy, v_dz, v_m) = conformity_space.TestFunction()
216
217    dVertex = dx(element_vb=BBBND)
218
219    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
220    dMidpoint = dx(intrules={TRIG: midpoint_intrule}, element_vb=BND)
221
222    cop_lhs = (
223        u * v_ * dVertex
224        + del_x(u) * v_dx * dVertex
225        + del_y(u) * v_dy * dVertex
226        + del_z(u) * v_dz * dVertex
227        + u * v_m * dMidpoint
228    )
229    cop_rhs = (
230        u_ * v_ * dVertex
231        + u_dx * v_dx * dVertex
232        + u_dy * v_dy * dVertex
233        + u_dz * v_dz * dVertex
234        + u_m * v_m * dVertex
235    )
236
237    embedding = TrefftzEmbedding(
238        cop=cop_lhs,
239        crhs=cop_rhs,
240        ndof_trefftz=0,
241        stats=stats,
242    )
243
244    hermite = EmbeddedTrefftzFES(embedding)
245    assert type(hermite) is L2EmbTrefftzFESpace, (
246        "The hermite space should always be an L2EmbTrefftzFESpace"
247    )
248
249    return hermite
@dataclass
class HermiteDirichlet:
26@dataclass
27class HermiteDirichlet:
28    """
29    Holds the dirichlet instructions for every type of dof in the `Hermite` space separately.
30
31    `deriv_z` is only used in the 3D case.
32    """
33
34    vertex_value: str = ""
35    deriv_x: str = ""
36    deriv_y: str = ""
37    deriv_z: str = ""
38
39    @classmethod
40    def clamp(cls, bnd: str) -> "HermiteDirichlet":
41        """
42        `bnd`: boundary where clamp conditions shall be set.
43        """
44        return cls(vertex_value=bnd, deriv_x=bnd, deriv_y=bnd, deriv_z=bnd)

Holds the dirichlet instructions for every type of dof in the Hermite space separately.

deriv_z is only used in the 3D case.

HermiteDirichlet( vertex_value: str = '', deriv_x: str = '', deriv_y: str = '', deriv_z: str = '')
vertex_value: str = ''
deriv_x: str = ''
deriv_y: str = ''
deriv_z: str = ''
@classmethod
def clamp(cls, bnd: str) -> HermiteDirichlet:
39    @classmethod
40    def clamp(cls, bnd: str) -> "HermiteDirichlet":
41        """
42        `bnd`: boundary where clamp conditions shall be set.
43        """
44        return cls(vertex_value=bnd, deriv_x=bnd, deriv_y=bnd, deriv_z=bnd)

bnd: boundary where clamp conditions shall be set.

def Hermite( mesh: ngsolve.comp.Mesh, dirichlet: str | HermiteDirichlet = '', check_mesh: bool = True, stats: dict | None = None) -> ngstrefftz.L2EmbTrefftzFESpace:
 47def Hermite(
 48    mesh: ngsolve.comp.Mesh,
 49    dirichlet: str | HermiteDirichlet = "",
 50    check_mesh: bool = True,
 51    stats: dict | None = None,
 52) -> L2EmbTrefftzFESpace:
 53    r"""
 54    The Hermite element is implemented for 2D and 3D on triangles and tetrahedrons.
 55
 56    `check_mesh`: test, if the `mesh` is compatible with this space
 57
 58    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
 59
 60    # Raises
 61    - ValueError, if the mesh is neither 2D nor 3D
 62    - ValueError, if the mesh is neither triangular nor tetrahedral
 63
 64    # Conforming Trefftz Formulation for 2D
 65    - $\mathbb{V}_h := \mathbb{P}^{3, \text{disc}}(\mathcal{T}_h)$
 66    - $\mathbb{Z}_h := [\mathbb{P}^{1}(\mathcal{T}_h)]^3 \times \mathbb{P}^{0}(\mathcal{T}_h)$
 67    - \begin{align}
 68      \mathcal{C}_K(v_h&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\\\
 69          &\sum_{p \text{ is vertex}} v_h(p) z_h^\text{value}(p)
 70          + \sum_{p \text{ is vertex}} \partial_x v_h(p) z_h^\text{x}(p) \\\\
 71          &+ \sum_{p \text{ is vertex}} \partial_y v_h(p) z_h^\text{y}(p)
 72          + \sum_{m \text{ is element-midpoint}} v_h(m) z_h^\text{mid}(m), \\\\
 73      \mathcal{D}_K((y_h^\text{value}, y_h^\text{x}, y_h^\text{y}, y_h^\text{mid})&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\\\
 74          &\sum_{p \text{ is vertex}} y_h^\text{value}(p) z_h^\text{value}(p)
 75          + \sum_{p \text{ is vertex}} y_h^\text{x}(p) z_h^\text{x}(p) \\\\
 76          &+ \sum_{p \text{ is vertex}} y_h^\text{y}(p) z_h^\text{y}(p)
 77          + \sum_{m \text{ is element-midpoint}} y_h^\text{mid}(m) z_h^\text{mid}(m)
 78      \end{align}
 79    """
 80    if check_mesh:
 81        throw_on_wrong_mesh_dimension(mesh, [2, 3])
 82        throw_on_wrong_mesh_eltype(mesh, [TRIG, TET])
 83
 84    dirichlet_struct = (
 85        HermiteDirichlet(vertex_value=dirichlet)
 86        if type(dirichlet) is str
 87        else dirichlet
 88    )
 89    assert type(dirichlet_struct) is HermiteDirichlet
 90
 91    if mesh.dim == 2:
 92        return Hermite2D(
 93            mesh,
 94            dirichlet_struct,
 95            check_mesh=False,
 96            stats=stats,
 97        )
 98    else:
 99        return Hermite3D(
100            mesh,
101            dirichlet_struct,
102            check_mesh=False,
103            stats=stats,
104        )

The Hermite element is implemented for 2D and 3D on triangles and tetrahedrons.

check_mesh: test, if the mesh is compatible with this space

stats: use the stats flag of the TrefftzEmbeddin method

Raises

  • ValueError, if the mesh is neither 2D nor 3D
  • ValueError, if the mesh is neither triangular nor tetrahedral

Conforming Trefftz Formulation for 2D

  • $\mathbb{V}_h := \mathbb{P}^{3, \text{disc}}(\mathcal{T}_h)$
  • $\mathbb{Z}_h := [\mathbb{P}^{1}(\mathcal{T}_h)]^3 \times \mathbb{P}^{0}(\mathcal{T}_h)$
  • \begin{align} \mathcal{C}_K(v_h&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\ &\sum_{p \text{ is vertex}} v_h(p) z_h^\text{value}(p) + \sum_{p \text{ is vertex}} \partial_x v_h(p) z_h^\text{x}(p) \\ &+ \sum_{p \text{ is vertex}} \partial_y v_h(p) z_h^\text{y}(p) + \sum_{m \text{ is element-midpoint}} v_h(m) z_h^\text{mid}(m), \\ \mathcal{D}_K((y_h^\text{value}, y_h^\text{x}, y_h^\text{y}, y_h^\text{mid})&, (z_h^\text{value}, z_h^\text{x}, z_h^\text{y}, z_h^\text{mid})) := \\ &\sum_{p \text{ is vertex}} y_h^\text{value}(p) z_h^\text{value}(p) + \sum_{p \text{ is vertex}} y_h^\text{x}(p) z_h^\text{x}(p) \\ &+ \sum_{p \text{ is vertex}} y_h^\text{y}(p) z_h^\text{y}(p) + \sum_{m \text{ is element-midpoint}} y_h^\text{mid}(m) z_h^\text{mid}(m) \end{align}
def Hermite2D( mesh: ngsolve.comp.Mesh, dirichlet: HermiteDirichlet, check_mesh: bool = True, stats: dict | None = None) -> ngstrefftz.L2EmbTrefftzFESpace:
107def Hermite2D(
108    mesh: ngsolve.comp.Mesh,
109    dirichlet: HermiteDirichlet,
110    check_mesh: bool = True,
111    stats: dict | None = None,
112) -> L2EmbTrefftzFESpace:
113    """
114    Implementation of the Hermite element in 2D
115
116    `check_mesh`: test, if the `mesh` is compatible with this space
117
118    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
119
120    # Raises
121    - ValueError, if the mesh is not 2D
122    - ValueError, if the mesh is not triangular
123    """
124    if check_mesh:
125        throw_on_wrong_mesh_dimension(mesh, 2)
126        throw_on_wrong_mesh_eltype(mesh, TRIG)
127
128    fes = L2(mesh, order=3)
129    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
130    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
131    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
132    midpoint_value_space = L2(mesh, order=0)
133
134    conformity_space = (
135        vertex_value_space
136        * deriv_x_value_space
137        * deriv_y_value_space
138        * midpoint_value_space
139    )
140
141    u = fes.TrialFunction()
142    (u_, u_dx, u_dy, u_m) = conformity_space.TrialFunction()
143    (v_, v_dx, v_dy, v_m) = conformity_space.TestFunction()
144
145    dVertex = dx(element_vb=BBND)
146
147    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
148    dMidpoint = dx(intrules={TRIG: midpoint_intrule})
149
150    cop_lhs = (
151        u * v_ * dVertex
152        + del_x(u) * v_dx * dVertex
153        + del_y(u) * v_dy * dVertex
154        + u * v_m * dMidpoint
155    )
156    cop_rhs = (
157        u_ * v_ * dVertex
158        + u_dx * v_dx * dVertex
159        + u_dy * v_dy * dVertex
160        + u_m * v_m * dVertex
161    )
162
163    embedding = TrefftzEmbedding(
164        cop=cop_lhs,
165        crhs=cop_rhs,
166        ndof_trefftz=0,
167        stats=stats,
168    )
169
170    hermite = EmbeddedTrefftzFES(embedding)
171    assert type(hermite) is L2EmbTrefftzFESpace, (
172        "The hermite space should always be an L2EmbTrefftzFESpace"
173    )
174
175    return hermite

Implementation of the Hermite element in 2D

check_mesh: test, if the mesh is compatible with this space

stats: use the stats flag of the TrefftzEmbeddin method

Raises

  • ValueError, if the mesh is not 2D
  • ValueError, if the mesh is not triangular
def Hermite3D( mesh: ngsolve.comp.Mesh, dirichlet: HermiteDirichlet, check_mesh: bool = True, stats: dict | None = None) -> ngstrefftz.L2EmbTrefftzFESpace:
178def Hermite3D(
179    mesh: ngsolve.comp.Mesh,
180    dirichlet: HermiteDirichlet,
181    check_mesh: bool = True,
182    stats: dict | None = None,
183) -> L2EmbTrefftzFESpace:
184    """
185    Implementation of the Hermite element in 3D
186
187    `check_mesh`: test, if the `mesh` is compatible with this space
188
189    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
190
191    # Raises
192    - ValueError, if the mesh is not 3D
193    - ValueError, if the mesh is not tetrahedral
194    """
195    if check_mesh:
196        throw_on_wrong_mesh_dimension(mesh, 3)
197        throw_on_wrong_mesh_eltype(mesh, TET)
198
199    fes = L2(mesh, order=3)
200    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
201    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
202    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
203    deriv_z_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_z)
204    midpoint_value_space = FacetFESpace(mesh, order=0)
205
206    conformity_space = (
207        vertex_value_space
208        * deriv_x_value_space
209        * deriv_y_value_space
210        * deriv_z_value_space
211        * midpoint_value_space
212    )
213
214    u = fes.TrialFunction()
215    (u_, u_dx, u_dy, u_dz, u_m) = conformity_space.TrialFunction()
216    (v_, v_dx, v_dy, v_dz, v_m) = conformity_space.TestFunction()
217
218    dVertex = dx(element_vb=BBBND)
219
220    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
221    dMidpoint = dx(intrules={TRIG: midpoint_intrule}, element_vb=BND)
222
223    cop_lhs = (
224        u * v_ * dVertex
225        + del_x(u) * v_dx * dVertex
226        + del_y(u) * v_dy * dVertex
227        + del_z(u) * v_dz * dVertex
228        + u * v_m * dMidpoint
229    )
230    cop_rhs = (
231        u_ * v_ * dVertex
232        + u_dx * v_dx * dVertex
233        + u_dy * v_dy * dVertex
234        + u_dz * v_dz * dVertex
235        + u_m * v_m * dVertex
236    )
237
238    embedding = TrefftzEmbedding(
239        cop=cop_lhs,
240        crhs=cop_rhs,
241        ndof_trefftz=0,
242        stats=stats,
243    )
244
245    hermite = EmbeddedTrefftzFES(embedding)
246    assert type(hermite) is L2EmbTrefftzFESpace, (
247        "The hermite space should always be an L2EmbTrefftzFESpace"
248    )
249
250    return hermite

Implementation of the Hermite element in 3D

check_mesh: test, if the mesh is compatible with this space

stats: use the stats flag of the TrefftzEmbeddin method

Raises

  • ValueError, if the mesh is not 3D
  • ValueError, if the mesh is not tetrahedral