File: interpolatetest.py

package info (click to toggle)
dune-functions 2.10.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,544 kB
  • sloc: cpp: 14,241; python: 661; makefile: 3
file content (74 lines) | stat: -rw-r--r-- 2,260 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later

import numpy as np

import dune.grid
from dune.grid import cartesianDomain
from dune.grid import yaspGrid
import dune.functions

from dune.generator import algorithm
from io import StringIO


# Compute a mask vector identifying only the DOFs
# contained in the subspace.
def subspaceMask(basis):
    mask = np.zeros(len(basis))
    localView = basis.localView()
    for element in basis.gridView.elements:
        localView.bind(element)
        tree = localView.tree()
        treeSize = len(tree)
        treeOffset = tree.localIndex(0)
        for i in range(treeOffset, treeOffset + treeSize):
            mask[localView.index(i)[0]] = 1
    return mask

# Manually convert function to std::function
def asStdFunction(f):
    code="""
    #include<utility>
    #include<functional>
    #include<dune/common/fvector.hh>
    template <class F>
    auto run(F f) {
      using Range = typename F::Range;
      using Domain = typename F::Domain;
      return std::function<Range(Domain)>(std::move(f));
    }
    """
    return dune.generator.algorithm.run("run",StringIO(code), f)


# Check if individual basis functions are interpolated correctly
def checkBasisFunctionInterpolation(basis):
    mask = subspaceMask(basis)
    coeffTol = 1e-10;
    ei = np.zeros(len(basis))
    y = np.zeros(len(basis))
    for i in range(len(basis)):
      ei[i] = 1
      ei *= mask
      f = asStdFunction(basis.asFunction(ei))
      basis.interpolate(y,f)
      if (np.linalg.norm(y-ei) > coeffTol):
          raise ValueError("FE basis function is not interpolated correctly.")
      ei[i] = 0


# Test interpolation of constant function
# Since we cannot deduce a range type automatically,
# a prototype needs to be passed.
def checkConstantInterpolation(basis, rangePrototype):
    mask = subspaceMask(basis)
    coeffTol = 1e-10;
    one = rangePrototype
    one *= 0
    one += 1
    f = lambda x : one
    x = np.zeros(len(basis))
    basis.interpolate(x,f)
    if (np.linalg.norm(x-mask) > coeffTol):
        raise ValueError("Interpolation of constant function yields wrong result.")