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, 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) -> EmbeddedTrefftzFES:
 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) -> EmbeddedTrefftzFES:
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    return hermite
171
172
173def Hermite3D(
174    mesh: ngsolve.comp.Mesh,
175    dirichlet: HermiteDirichlet,
176    check_mesh: bool = True,
177    stats: dict | None = None,
178) -> EmbeddedTrefftzFES:
179    """
180    Implementation of the Hermite element in 3D
181
182    `check_mesh`: test, if the `mesh` is compatible with this space
183
184    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
185
186    # Raises
187    - ValueError, if the mesh is not 3D
188    - ValueError, if the mesh is not tetrahedral
189    """
190    if check_mesh:
191        throw_on_wrong_mesh_dimension(mesh, 3)
192        throw_on_wrong_mesh_eltype(mesh, TET)
193
194    fes = L2(mesh, order=3)
195    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
196    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
197    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
198    deriv_z_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_z)
199    midpoint_value_space = FacetFESpace(mesh, order=0)
200
201    conformity_space = (
202        vertex_value_space
203        * deriv_x_value_space
204        * deriv_y_value_space
205        * deriv_z_value_space
206        * midpoint_value_space
207    )
208
209    u = fes.TrialFunction()
210    (u_, u_dx, u_dy, u_dz, u_m) = conformity_space.TrialFunction()
211    (v_, v_dx, v_dy, v_dz, v_m) = conformity_space.TestFunction()
212
213    dVertex = dx(element_vb=BBBND)
214
215    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
216    dMidpoint = dx(intrules={TRIG: midpoint_intrule}, element_vb=BND)
217
218    cop_lhs = (
219        u * v_ * dVertex
220        + del_x(u) * v_dx * dVertex
221        + del_y(u) * v_dy * dVertex
222        + del_z(u) * v_dz * dVertex
223        + u * v_m * dMidpoint
224    )
225    cop_rhs = (
226        u_ * v_ * dVertex
227        + u_dx * v_dx * dVertex
228        + u_dy * v_dy * dVertex
229        + u_dz * v_dz * dVertex
230        + u_m * v_m * dVertex
231    )
232
233    embedding = TrefftzEmbedding(
234        cop=cop_lhs,
235        crhs=cop_rhs,
236        ndof_trefftz=0,
237        stats=stats,
238    )
239
240    hermite = EmbeddedTrefftzFES(embedding)
241    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.EmbeddedTrefftzFES:
 47def Hermite(
 48    mesh: ngsolve.comp.Mesh,
 49    dirichlet: str | HermiteDirichlet = "",
 50    check_mesh: bool = True,
 51    stats: dict | None = None,
 52) -> EmbeddedTrefftzFES:
 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.EmbeddedTrefftzFES:
107def Hermite2D(
108    mesh: ngsolve.comp.Mesh,
109    dirichlet: HermiteDirichlet,
110    check_mesh: bool = True,
111    stats: dict | None = None,
112) -> EmbeddedTrefftzFES:
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    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.EmbeddedTrefftzFES:
174def Hermite3D(
175    mesh: ngsolve.comp.Mesh,
176    dirichlet: HermiteDirichlet,
177    check_mesh: bool = True,
178    stats: dict | None = None,
179) -> EmbeddedTrefftzFES:
180    """
181    Implementation of the Hermite element in 3D
182
183    `check_mesh`: test, if the `mesh` is compatible with this space
184
185    `stats`: use the `stats` flag of the `TrefftzEmbeddin` method
186
187    # Raises
188    - ValueError, if the mesh is not 3D
189    - ValueError, if the mesh is not tetrahedral
190    """
191    if check_mesh:
192        throw_on_wrong_mesh_dimension(mesh, 3)
193        throw_on_wrong_mesh_eltype(mesh, TET)
194
195    fes = L2(mesh, order=3)
196    vertex_value_space = H1(mesh, order=1, dirichlet=dirichlet.vertex_value)
197    deriv_x_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_x)
198    deriv_y_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_y)
199    deriv_z_value_space = H1(mesh, order=1, dirichlet=dirichlet.deriv_z)
200    midpoint_value_space = FacetFESpace(mesh, order=0)
201
202    conformity_space = (
203        vertex_value_space
204        * deriv_x_value_space
205        * deriv_y_value_space
206        * deriv_z_value_space
207        * midpoint_value_space
208    )
209
210    u = fes.TrialFunction()
211    (u_, u_dx, u_dy, u_dz, u_m) = conformity_space.TrialFunction()
212    (v_, v_dx, v_dy, v_dz, v_m) = conformity_space.TestFunction()
213
214    dVertex = dx(element_vb=BBBND)
215
216    midpoint_intrule = IntegrationRule(points=[(1 / 3, 1 / 3)], weights=[1])
217    dMidpoint = dx(intrules={TRIG: midpoint_intrule}, element_vb=BND)
218
219    cop_lhs = (
220        u * v_ * dVertex
221        + del_x(u) * v_dx * dVertex
222        + del_y(u) * v_dy * dVertex
223        + del_z(u) * v_dz * dVertex
224        + u * v_m * dMidpoint
225    )
226    cop_rhs = (
227        u_ * v_ * dVertex
228        + u_dx * v_dx * dVertex
229        + u_dy * v_dy * dVertex
230        + u_dz * v_dz * dVertex
231        + u_m * v_m * dVertex
232    )
233
234    embedding = TrefftzEmbedding(
235        cop=cop_lhs,
236        crhs=cop_rhs,
237        ndof_trefftz=0,
238        stats=stats,
239    )
240
241    hermite = EmbeddedTrefftzFES(embedding)
242    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