ngstSpaceKit.demo
Spaces in ngstSpaceKit.demo are already natively implemented in NGSolve.
Their implementation here is purely for educational purposeses.
1""" 2Spaces in `ngstSpaceKit.demo` are already natively implemented in NGSolve. 3Their implementation here is purely for educational purposeses. 4""" 5 6import ngsolve 7from ngsolve import ( 8 BND, 9 L2, 10 TET, 11 TRIG, 12 Discontinuous, 13 FacetFESpace, 14 HCurl, 15 NormalFacetFESpace, 16 VectorL2, 17 dx, 18 specialcf, 19) 20from ngstrefftz import ( 21 EmbeddedTrefftzFES, 22 L2EmbTrefftzFESpace, 23 TrefftzEmbedding, 24 VectorL2EmbTrefftzFESpace, 25) 26 27import ngstSpaceKit 28from ngstSpaceKit.mesh_properties import ( 29 throw_on_wrong_mesh_dimension, 30 throw_on_wrong_mesh_eltype, 31) 32 33 34def CrouzeixRaviart( 35 mesh: ngsolve.comp.Mesh, 36 dirichlet: str = "", 37 check_mesh: bool = True, 38 stats: dict | None = None, 39) -> L2EmbTrefftzFESpace: 40 r""" 41 This is an implementation of the Crouzeix-Raviart element via an embedded Trefftz FESpace. 42 This implementation is done for illustrative purposes, 43 as ngsolve already implements the Crouzeix-Raviart element with: 44 ```python 45 fes_cr = FESpace('nonconforming', mesh) 46 ``` 47 48 `check_mesh`: test, if the `mesh` is compatible with this space 49 50 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 51 52 # Raises 53 - ValueError, if the mesh is not 2D 54 - ValueError, if the mesh is not triangular 55 56 # Conforming Trefftz Formulation 57 - $\mathbb{V}_h := \mathbb{P}^{1, \text{disc}}(\mathcal{T}_h)$ 58 - $\mathbb{Z}_h := \mathbb{P}^0(\mathcal{F}_h)$ 59 - \begin{align} 60 \mathcal{C}_K(v_h, z_h) := \int_{\partial K} v_h z_h \;dx, \\\\ 61 \mathcal{D}_K(y_h, z_h) := \int_{\partial K} y_h z_h \;dx 62 \end{align} 63 """ 64 if check_mesh: 65 throw_on_wrong_mesh_dimension(mesh, 2) 66 throw_on_wrong_mesh_eltype(mesh, TRIG) 67 68 fes = L2(mesh, order=1) 69 conformity_space = FacetFESpace(mesh, order=0, dirichlet=dirichlet) 70 71 u = fes.TrialFunction() 72 73 uc, vc = conformity_space.TnT() 74 75 cop_l = u * vc * dx(element_vb=BND) 76 cop_r = uc * vc * dx(element_vb=BND) 77 78 embedding = TrefftzEmbedding(cop=cop_l, crhs=cop_r, stats=stats) 79 80 cr = EmbeddedTrefftzFES(embedding) 81 assert type(cr) is L2EmbTrefftzFESpace, ( 82 "The cr space should always be an L2EmbTrefftzFESpace" 83 ) 84 return cr 85 86 87def H1( 88 mesh: ngsolve.comp.Mesh, 89 order: int, 90 dirichlet: str = "", 91 stats: dict | None = None, 92) -> L2EmbTrefftzFESpace: 93 r""" 94 This is an implementation for illustrative purposes, ngsolve already implements the H1 space. 95 The H1 space is implemented via an embedded Trefftz FESpace. 96 Note, that the conformity space is the ngsolve.H1 space, 97 which is only used for point evaluations the the mesh vertices. 98 99 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 100 101 # Conforming Trefftz Formulation 102 - $\mathbb{V}_h := \mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)$ 103 - $\mathbb{Z}_h := \mathbb{P}^k(\mathcal{T}_h)$ 104 - \begin{align} 105 \mathcal{C}_K(v_h, z_h) &:= \int_K v_h z_h \;dx, \\\\ 106 \mathcal{D}_K(y_h, z_h) &:= \int_K y_h z_h \;dx 107 \end{align} 108 """ 109 fes = L2(mesh, order=order) 110 cfes = ngsolve.H1(mesh, order=order, dirichlet=dirichlet) 111 112 u, v = fes.TnT() 113 uc, vc = cfes.TnT() 114 115 # cop_l = u * vc * dx(element_vb=BBND) 116 # cop_r = uc * vc * dx(element_vb=BBND) 117 cop_l = u * vc * dx() 118 cop_r = uc * vc * dx() 119 120 embedding = TrefftzEmbedding( 121 cop=cop_l, 122 crhs=cop_r, 123 ndof_trefftz=0, 124 stats=stats, 125 ) 126 127 h1 = EmbeddedTrefftzFES(embedding) 128 assert type(h1) is L2EmbTrefftzFESpace, ( 129 "The h1 space should always be an L2EmbTrefftzFESpace" 130 ) 131 132 return h1 133 134 135def BDM( 136 mesh: ngsolve.comp.Mesh, 137 order: int, 138 dirichlet: str = "", 139 check_mesh: bool = True, 140 stats: dict | None = None, 141) -> VectorL2EmbTrefftzFESpace: 142 r""" 143 This BDM space is tailored to mimic the ngsolve implementation of the BDM space: 144 ```python 145 fes_bdm = HDiv(mesh, order=order, RT=False) 146 ``` 147 Therefore, this implementation has no practical advantage over the ngsolve implementation, 148 and merely serves as a demonstration. 149 150 See `ngstSpaceKit.HDiv` for an H(div) conforming space, that is not implemented by ngsolve. 151 152 `check_mesh`: test, if the `mesh` is compatible with this space 153 154 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 155 156 # Raises 157 - ValueError, if `order == 0` 158 - ValueError, if the mesh is not 2D or 3D 159 - ValueError, if the mesh is not triangular (2D) or consists of tetrahedra (3D) 160 161 # Conforming Trefftz Formulation 162 - $\mathbb{V}_h := [\mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)]^d$ 163 - $\mathbb{Z}_h := [\mathbb{P}^k(\mathcal{F}_h)]^d \times \mathcal{N}_1^{k-1}(\mathcal{T}_h)$ 164 - \begin{align} 165 \mathcal{C}_K(v_h, (z_h^\text{facet}, z_h^\text{vol})) &:= 166 \int_{\partial K} v_h \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K v_h z_h^\text{vol} \;dx, \\\\ 167 \mathcal{D}_K((y_h^\text{facet}, y_h^\text{vol}), (z_h^\text{facet}, z_h^\text{vol})) &:= 168 \int_{\partial K} y_h^\text{facet} \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K y_h^\text{vol} z_h^\text{vol} \;dx 169 \end{align} 170 """ 171 172 if check_mesh: 173 throw_on_wrong_mesh_dimension(mesh, [2, 3]) 174 throw_on_wrong_mesh_eltype(mesh, [TRIG, TET]) 175 176 if order == 0: 177 raise ValueError("BDM needs order >= 1") 178 if order == 1: 179 return ngstSpaceKit.HDiv(mesh, order=1) 180 181 fes = VectorL2(mesh, order=order) 182 183 conformity_space = NormalFacetFESpace( 184 mesh, order=order, dirichlet=dirichlet 185 ) * Discontinuous( 186 HCurl(mesh, order=order - 1, type1=True, dirichlet=dirichlet) 187 ) 188 189 u = fes.TrialFunction() 190 191 (uc_edge, uc_vol), (vc_edge, vc_vol) = conformity_space.TnT() 192 193 n = specialcf.normal(mesh.dim) 194 195 cop_l = u * n * vc_edge * n * dx(element_vb=BND) 196 cop_r = uc_edge * n * vc_edge * n * dx(element_vb=BND) 197 198 cop_l += u * vc_vol * dx 199 cop_r += uc_vol * vc_vol * dx 200 201 embedding = TrefftzEmbedding(cop=cop_l, crhs=cop_r, stats=stats) 202 203 bdm = EmbeddedTrefftzFES(embedding) 204 assert type(bdm) is VectorL2EmbTrefftzFESpace, ( 205 "The bdm space should always be a VectorL2EmbTrefftzFESpace" 206 ) 207 208 return bdm
35def CrouzeixRaviart( 36 mesh: ngsolve.comp.Mesh, 37 dirichlet: str = "", 38 check_mesh: bool = True, 39 stats: dict | None = None, 40) -> L2EmbTrefftzFESpace: 41 r""" 42 This is an implementation of the Crouzeix-Raviart element via an embedded Trefftz FESpace. 43 This implementation is done for illustrative purposes, 44 as ngsolve already implements the Crouzeix-Raviart element with: 45 ```python 46 fes_cr = FESpace('nonconforming', mesh) 47 ``` 48 49 `check_mesh`: test, if the `mesh` is compatible with this space 50 51 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 52 53 # Raises 54 - ValueError, if the mesh is not 2D 55 - ValueError, if the mesh is not triangular 56 57 # Conforming Trefftz Formulation 58 - $\mathbb{V}_h := \mathbb{P}^{1, \text{disc}}(\mathcal{T}_h)$ 59 - $\mathbb{Z}_h := \mathbb{P}^0(\mathcal{F}_h)$ 60 - \begin{align} 61 \mathcal{C}_K(v_h, z_h) := \int_{\partial K} v_h z_h \;dx, \\\\ 62 \mathcal{D}_K(y_h, z_h) := \int_{\partial K} y_h z_h \;dx 63 \end{align} 64 """ 65 if check_mesh: 66 throw_on_wrong_mesh_dimension(mesh, 2) 67 throw_on_wrong_mesh_eltype(mesh, TRIG) 68 69 fes = L2(mesh, order=1) 70 conformity_space = FacetFESpace(mesh, order=0, dirichlet=dirichlet) 71 72 u = fes.TrialFunction() 73 74 uc, vc = conformity_space.TnT() 75 76 cop_l = u * vc * dx(element_vb=BND) 77 cop_r = uc * vc * dx(element_vb=BND) 78 79 embedding = TrefftzEmbedding(cop=cop_l, crhs=cop_r, stats=stats) 80 81 cr = EmbeddedTrefftzFES(embedding) 82 assert type(cr) is L2EmbTrefftzFESpace, ( 83 "The cr space should always be an L2EmbTrefftzFESpace" 84 ) 85 return cr
This is an implementation of the Crouzeix-Raviart element via an embedded Trefftz FESpace. This implementation is done for illustrative purposes, as ngsolve already implements the Crouzeix-Raviart element with:
fes_cr = FESpace('nonconforming', mesh)
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
Conforming Trefftz Formulation
- $\mathbb{V}_h := \mathbb{P}^{1, \text{disc}}(\mathcal{T}_h)$
- $\mathbb{Z}_h := \mathbb{P}^0(\mathcal{F}_h)$
- \begin{align} \mathcal{C}_K(v_h, z_h) := \int_{\partial K} v_h z_h \;dx, \\ \mathcal{D}_K(y_h, z_h) := \int_{\partial K} y_h z_h \;dx \end{align}
88def H1( 89 mesh: ngsolve.comp.Mesh, 90 order: int, 91 dirichlet: str = "", 92 stats: dict | None = None, 93) -> L2EmbTrefftzFESpace: 94 r""" 95 This is an implementation for illustrative purposes, ngsolve already implements the H1 space. 96 The H1 space is implemented via an embedded Trefftz FESpace. 97 Note, that the conformity space is the ngsolve.H1 space, 98 which is only used for point evaluations the the mesh vertices. 99 100 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 101 102 # Conforming Trefftz Formulation 103 - $\mathbb{V}_h := \mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)$ 104 - $\mathbb{Z}_h := \mathbb{P}^k(\mathcal{T}_h)$ 105 - \begin{align} 106 \mathcal{C}_K(v_h, z_h) &:= \int_K v_h z_h \;dx, \\\\ 107 \mathcal{D}_K(y_h, z_h) &:= \int_K y_h z_h \;dx 108 \end{align} 109 """ 110 fes = L2(mesh, order=order) 111 cfes = ngsolve.H1(mesh, order=order, dirichlet=dirichlet) 112 113 u, v = fes.TnT() 114 uc, vc = cfes.TnT() 115 116 # cop_l = u * vc * dx(element_vb=BBND) 117 # cop_r = uc * vc * dx(element_vb=BBND) 118 cop_l = u * vc * dx() 119 cop_r = uc * vc * dx() 120 121 embedding = TrefftzEmbedding( 122 cop=cop_l, 123 crhs=cop_r, 124 ndof_trefftz=0, 125 stats=stats, 126 ) 127 128 h1 = EmbeddedTrefftzFES(embedding) 129 assert type(h1) is L2EmbTrefftzFESpace, ( 130 "The h1 space should always be an L2EmbTrefftzFESpace" 131 ) 132 133 return h1
This is an implementation for illustrative purposes, ngsolve already implements the H1 space. The H1 space is implemented via an embedded Trefftz FESpace. Note, that the conformity space is the ngsolve.H1 space, which is only used for point evaluations the the mesh vertices.
stats: use the stats flag of the TrefftzEmbeddin method
Conforming Trefftz Formulation
- $\mathbb{V}_h := \mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)$
- $\mathbb{Z}_h := \mathbb{P}^k(\mathcal{T}_h)$
- \begin{align} \mathcal{C}_K(v_h, z_h) &:= \int_K v_h z_h \;dx, \\ \mathcal{D}_K(y_h, z_h) &:= \int_K y_h z_h \;dx \end{align}
136def BDM( 137 mesh: ngsolve.comp.Mesh, 138 order: int, 139 dirichlet: str = "", 140 check_mesh: bool = True, 141 stats: dict | None = None, 142) -> VectorL2EmbTrefftzFESpace: 143 r""" 144 This BDM space is tailored to mimic the ngsolve implementation of the BDM space: 145 ```python 146 fes_bdm = HDiv(mesh, order=order, RT=False) 147 ``` 148 Therefore, this implementation has no practical advantage over the ngsolve implementation, 149 and merely serves as a demonstration. 150 151 See `ngstSpaceKit.HDiv` for an H(div) conforming space, that is not implemented by ngsolve. 152 153 `check_mesh`: test, if the `mesh` is compatible with this space 154 155 `stats`: use the `stats` flag of the `TrefftzEmbeddin` method 156 157 # Raises 158 - ValueError, if `order == 0` 159 - ValueError, if the mesh is not 2D or 3D 160 - ValueError, if the mesh is not triangular (2D) or consists of tetrahedra (3D) 161 162 # Conforming Trefftz Formulation 163 - $\mathbb{V}_h := [\mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)]^d$ 164 - $\mathbb{Z}_h := [\mathbb{P}^k(\mathcal{F}_h)]^d \times \mathcal{N}_1^{k-1}(\mathcal{T}_h)$ 165 - \begin{align} 166 \mathcal{C}_K(v_h, (z_h^\text{facet}, z_h^\text{vol})) &:= 167 \int_{\partial K} v_h \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K v_h z_h^\text{vol} \;dx, \\\\ 168 \mathcal{D}_K((y_h^\text{facet}, y_h^\text{vol}), (z_h^\text{facet}, z_h^\text{vol})) &:= 169 \int_{\partial K} y_h^\text{facet} \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K y_h^\text{vol} z_h^\text{vol} \;dx 170 \end{align} 171 """ 172 173 if check_mesh: 174 throw_on_wrong_mesh_dimension(mesh, [2, 3]) 175 throw_on_wrong_mesh_eltype(mesh, [TRIG, TET]) 176 177 if order == 0: 178 raise ValueError("BDM needs order >= 1") 179 if order == 1: 180 return ngstSpaceKit.HDiv(mesh, order=1) 181 182 fes = VectorL2(mesh, order=order) 183 184 conformity_space = NormalFacetFESpace( 185 mesh, order=order, dirichlet=dirichlet 186 ) * Discontinuous( 187 HCurl(mesh, order=order - 1, type1=True, dirichlet=dirichlet) 188 ) 189 190 u = fes.TrialFunction() 191 192 (uc_edge, uc_vol), (vc_edge, vc_vol) = conformity_space.TnT() 193 194 n = specialcf.normal(mesh.dim) 195 196 cop_l = u * n * vc_edge * n * dx(element_vb=BND) 197 cop_r = uc_edge * n * vc_edge * n * dx(element_vb=BND) 198 199 cop_l += u * vc_vol * dx 200 cop_r += uc_vol * vc_vol * dx 201 202 embedding = TrefftzEmbedding(cop=cop_l, crhs=cop_r, stats=stats) 203 204 bdm = EmbeddedTrefftzFES(embedding) 205 assert type(bdm) is VectorL2EmbTrefftzFESpace, ( 206 "The bdm space should always be a VectorL2EmbTrefftzFESpace" 207 ) 208 209 return bdm
This BDM space is tailored to mimic the ngsolve implementation of the BDM space:
fes_bdm = HDiv(mesh, order=order, RT=False)
Therefore, this implementation has no practical advantage over the ngsolve implementation, and merely serves as a demonstration.
See ngstSpaceKit.HDiv for an H(div) conforming space, that is not implemented by ngsolve.
check_mesh: test, if the mesh is compatible with this space
stats: use the stats flag of the TrefftzEmbeddin method
Raises
- ValueError, if
order == 0 - ValueError, if the mesh is not 2D or 3D
- ValueError, if the mesh is not triangular (2D) or consists of tetrahedra (3D)
Conforming Trefftz Formulation
- $\mathbb{V}_h := [\mathbb{P}^{k, \text{disc}}(\mathcal{T}_h)]^d$
- $\mathbb{Z}_h := [\mathbb{P}^k(\mathcal{F}_h)]^d \times \mathcal{N}_1^{k-1}(\mathcal{T}_h)$
- \begin{align} \mathcal{C}_K(v_h, (z_h^\text{facet}, z_h^\text{vol})) &:= \int_{\partial K} v_h \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K v_h z_h^\text{vol} \;dx, \\ \mathcal{D}_K((y_h^\text{facet}, y_h^\text{vol}), (z_h^\text{facet}, z_h^\text{vol})) &:= \int_{\partial K} y_h^\text{facet} \cdot n \; z_h^\text{facet} \cdot n \;dx + \int_K y_h^\text{vol} z_h^\text{vol} \;dx \end{align}