Peano
Loading...
Searching...
No Matches
finiteelement.py
Go to the documentation of this file.
1"""Define various DG finite elements. These finite elements essentially allow us to evaluate
2the local basis functions at an arbitrary point of the referent-domain for the respective element.
3This reference element can be either a reference cell [-1,+1] x [-1,+1] or a reference
4interval [-1,+1].
5
6We use the following elements:
7
8 * DGScalarElement: scalar-valued functions such as pressure defined in cells
9 * DGVectorElement: vector-valued functions such as velocity or momentum defined in cells: to be implemented later. Now use scalar elements for individual components of a vector
10 * DGFacetElement: scalar-valued functions such as the function lambda that arises from hyrbidisation
11
12"""
13
14from abc import ABC, abstractmethod
15import numpy as np
16import itertools
17#from basis import Basis1d
18from .nodal_basis import NodalBasisGaussLegendre
19from .quadrature import GaussianQuadrature, Quadrature2d
20# from nodal_basis import NodalBasisGaussLegendre
21# from quadrature import GaussianQuadrature, Quadrature2d
22
23class FiniteElement(ABC):
24 """Defines a finite element which describes the local function space on a reference element"""
25
26 def __init__(self):
27 """Initialise object"""
28
29 @property
30 @abstractmethod
31 def ndof(self):
32 """return number of unknowns"""
33 # implement in derived classes
34
35 @abstractmethod
36 def evaluate(self, k, x_local):
37 """Evaluate the k-th basis function at the point x_local
38
39 :arg k: index of basis function
40 :arg x_local: local position in cell or on facet
41 """
42 # implement in derived classes
43
44 @abstractmethod
45 def evaluate_derivative(self, k, direction, x_local):
46 """Evaluate the derivatibe k-th basis function at the point x_local in the
47 direction dir which can be 0 (x-direction) or 1 (y-direction)
48
49 :arg k: index of basis function
50 :arg direction: direction (0 or 1)
51 :arg x_local: local position in cell or on facet
52 """
53 # implement in derived class
54
55 @abstractmethod
56 def nodes(self):
57 """Compute nodal points on reference entity"""
58 # implement in derived class
59
60
61class DGScalarElement(FiniteElement):
62 """Scalar DG finite element on cells
63
64 Scalar valued Discontinuous Galerkin functions on reference cell [-1,+1] x [-1,+1]
65 """
66
67 def __init__(self, dim, degree):
68 """Initialise object
69
70 :arg degree: polynomial degree
71 """
72 #self.basis = Basis1d(degree)
73 self.dim = dim
74 self.degree = degree
76
77 @property
78 def ndof(self):
79 """return number of unknowns"""
80 return (self.degree + 1) ** self.dim
81
82 def evaluate(self, k, x_local):
83 """Evaluate the k-th basis function at the point x_local = (xi,eta)
84 2D basis functions are enumerated as follows
85 !!! So far, for 2D only
86
87 y
88 |
89 2 | 6 7 8 k = i + j * (self.basis.degree+1)
90 j 1 | 3 4 5 => i = k % (self.basis.degree+1)
91 0 | 0 1 2 j = k // (self.basis.degree+1)
92 - - - - x
93 0 1 2
94 i
95
96 :arg k: index of basis function
97 :arg x_local: position (xi,eta) in [-1,+1] x [-1,+1]
98 """
99 i, j = k % (self.degree + 1), k // (self.degree + 1)
100 return self.basis.evaluate(self.degree, i, x_local[0]) * self.basis.evaluate(self.degree, j, x_local[1])
101 # i, j = k % (self.basis.degree + 1), k // (self.basis.degree + 1)
102 # return self.basis.evaluate(i, x_local[0]) * self.basis.evaluate(j, x_local[1])
103
104 def evaluate_derivative(self, k, direction, x_local):
105 """Evaluate the derivative of k-th basis function at the point x_local = (xi,eta) in the
106 direction dir which can be 0 (x-direction) or 1 (y-direction)
107
108 :arg k: index of basis function
109 :arg direction: direction (0 or 1)
110 :arg x_local: position (xi,eta) in [-1,+1] x [-1,+1]
111 """
112 i, j = k % (self.degree + 1), k // (self.degree + 1)
113 if direction == 0:
114 return self.basis.evaluate_derivative(self.degree, i, x_local[0]) * self.basis.evaluate(self.degree, j, x_local[1])
115 elif direction == 1:
116 return self.basis.evaluate(self.degree, i, x_local[0]) * self.basis.evaluate_derivative(self.degree, j, x_local[1])
117 else:
118 raise ValueError("Direction can only be 0 (x-direction) or 1 (y-direction)")
119
120 @property
121 def nodes(self):
122 """Compute nodal points on reference entity"""
123
124 nodes = []
125
126 index_set = itertools.product(range(self.degree + 1), repeat=self.dim) # create tuples for possible indices combinations
127 for index in index_set:
128 # reverse (0,1,2) to (2,1,0)
129 # required as itertools.product() generates tuples like (0,0), (0,1), (0,2)
130 # -- with the last index advancing faster, but we need (0,0), (1,0), (2,0)
131 #index = next(index_set)
132 reverse_index = tuple(reversed(index))
133 node_coordinates = [self.basis.node1d(self.degree, idx) for idx in reverse_index]
134 nodes.append(np.asarray(node_coordinates))
135
136 return nodes
137
138
140 """Scalar DG finite element on facets
141
142 Scalar valued Discontinuous Galerkin functions on reference interval [-1,+1]
143 """
144
145 def __init__(self, dim, degree):
146 """Initialise object
147
148 :arg degree: polynomial degree
149 """
150 # self.basis = Basis1d(degree)
151 self.dim = dim
152 self.degree = degree
154
155 @property
156 def ndof(self):
157 """return number of unknowns"""
158 return (self.degree + 1) ** (self.dim - 1)
159
160 def evaluate(self, k, x_local):
161 """Evaluate the k-th basis function at the point x_local = (xi,eta)
162
163 :arg k: index of basis function
164 :arg x_local: position xi in [-1,+1]
165 """
166 return self.basis.evaluate(self.degree, k, x_local)
167
168 def evaluate_derivative(self, k, x_local):
169 """Evaluate the derivative k-th basis function at the point x_local = xi
170
171 :arg k: index of basis function
172 :arg x_local: position xi in [-1,+1]
173 """
174 return self.basis.evaluate_derivative(self.degree, k, x_local)
175
176 @property
177 def nodes(self):
178 """Compute nodal points on reference facet"""
179 return self.basis.nodal_points(self.degree)
evaluate_derivative(self, k, x_local)
Evaluate the derivative k-th basis function at the point x_local = xi.
evaluate(self, k, x_local)
Evaluate the k-th basis function at the point x_local = (xi,eta)
evaluate_derivative(self, k, direction, x_local)
Evaluate the derivative of k-th basis function at the point x_local = (xi,eta) in the direction dir w...
evaluate(self, k, x_local)
Evaluate the k-th basis function at the point x_local = (xi,eta) 2D basis functions are enumerated as...
Defines a finite element which describes the local function space on a reference element.
nodes(self)
Compute nodal points on reference entity.
evaluate(self, k, x_local)
Evaluate the k-th basis function at the point x_local.
evaluate_derivative(self, k, direction, x_local)
Evaluate the derivatibe k-th basis function at the point x_local in the direction dir which can be 0 ...