Coverage for src/methodsnm/forms.py: 81%
73 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-27 13:22 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-27 13:22 +0000
1from abc import ABC, abstractmethod
2import numpy as np
3from numpy import array
4from methodsnm.trafo import *
5from methodsnm.mesh import *
6from scipy import sparse
8class Form(ABC):
9 integrals = None
10 fes = None
11 def __init__(self):
12 raise NotImplementedError("Not implemented")
14 def add_integrator(self, integrator):
15 self.integrals.append(integrator)
17 def __iadd__(self, integrator):
18 self.add_integrator(integrator)
19 return self
21class LinearForm(Form):
23 vector = None
24 def __init__(self, fes=None):
25 self.fes = fes
26 self.integrals = []
28 def assemble(self):
29 self.vector = np.zeros(self.fes.ndof)
30 mesh = self.fes.mesh
31 for elnr, verts in enumerate(mesh.elements()):
32 trafo = mesh.trafo(elnr)
33 fe = self.fes.finite_element(elnr)
34 dofs = self.fes.element_dofs(elnr)
35 for integral in self.integrals:
36 self.vector[dofs] += integral.compute_element_vector(fe, trafo)
39class BilinearForm(Form):
41 matrix = None
42 def __init__(self, fes=None, fes_test=None, fes_trial=None):
43 if fes is None and (fes_test is None or fes_trial is None) or all([f is not None for f in [fes,fes_test,fes_trial]]):
44 raise Exception("Invalid arguments, specify either `fes` or `fes_test` and `fes_trial`")
45 if fes_test is None:
46 fes_test = fes
47 fes_trial = fes
49 self.fes_trial = fes_trial
50 self.fes_test = fes_test
51 self.fes = fes_test
52 self.integrals = []
54 def assemble(self):
55 self.matrix = sparse.lil_matrix((self.fes_test.ndof, self.fes_trial.ndof))
56 mesh = self.fes.mesh
57 for elnr, verts in enumerate(mesh.elements()):
58 trafo = mesh.trafo(elnr)
59 fe_test = self.fes_test.finite_element(elnr)
60 dofs_test = self.fes_test.element_dofs(elnr)
61 fe_trial = self.fes_trial.finite_element(elnr)
62 dofs_trial = self.fes_trial.element_dofs(elnr)
63 elmat = np.zeros((len(dofs_test), len(dofs_trial)))
64 for integral in self.integrals:
65 elmat += integral.compute_element_matrix(fe_test, fe_trial, trafo)
66 for i, dofi in enumerate(dofs_test):
67 for j, dofj in enumerate(dofs_trial):
68 self.matrix[dofi,dofj] += elmat[i,j]
69 self.matrix = self.matrix.tocsr()
72from methodsnm.intrule import select_integration_rule
73from numpy.linalg import det
74def compute_difference_L2(uh, uex, mesh, intorder=5):
75 sumint = 0
76 for elnr in range(len(mesh.elements())):
77 trafo = mesh.trafo(elnr)
78 intrule = select_integration_rule(intorder, trafo.eltype)
79 uhvals = uh.evaluate(intrule.nodes, trafo)
80 uexvals = uex.evaluate(intrule.nodes, trafo)
81 diff = np.zeros(len(intrule.nodes))
82 diff = (uhvals - uexvals)**2
83 F = trafo.jacobian(intrule.nodes)
84 w = array([abs(det(F[i,:,:])) * intrule.weights[i] for i in range(F.shape[0])])
85 sumint += np.dot(w, diff)
86 return np.sqrt(sumint)