Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

# This file is part of the pyMOR project (http://www.pymor.org). 

# Copyright Holders: Rene Milk, Stephan Rave, Felix Schindler 

# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause) 

 

from __future__ import absolute_import, division, print_function 

 

import numpy as np 

 

from pymor.grids.interfaces import AffineGridInterface 

from pymor.grids.referenceelements import triangle 

 

 

class TriaGrid(AffineGridInterface): 

    '''Basic implementation of a triangular grid on a rectangular domain. 

 

    The global face, edge and vertex indices are given as follows :: 

 

                 6---10----7---11----8 

                 | \     6 | \     7 | 

                 3   14    4   15    5 

                 | 2     \ | 3     \ | 

                 3----8----4----9----5 

                 | \     4 | \     5 | 

                 0   12    1   13    2 

                 | 0    \  | 1     \ | 

                 0----6----1----7----2 

 

    Parameters 

    ---------- 

    num_intervals 

        Tuple `(n0, n1)` determining a grid with `n0` x `n1` codim-0 entities. 

    domain 

        Tuple `(ll, ur)` where `ll` defines the lower left and `ur` the upper right 

        corner of the domain. 

    ''' 

 

    dim = 2 

    dim_outer = 2 

    reference_element = triangle 

 

    def __init__(self, num_intervals=(2, 2), domain=[[0, 0], [1, 1]]): 

        self.num_intervals = num_intervals 

        self.domain = np.array(domain) 

 

        self.x0_num_intervals = num_intervals[0] 

        self.x1_num_intervals = num_intervals[1] 

        self.x0_range = self.domain[:, 0] 

        self.x1_range = self.domain[:, 1] 

        self.x0_width = self.x0_range[1] - self.x0_range[0] 

        self.x1_width = self.x1_range[1] - self.x1_range[0] 

        self.x0_diameter = self.x0_width / self.x0_num_intervals 

        self.x1_diameter = self.x1_width / self.x1_num_intervals 

        n_elements = self.x0_num_intervals * self.x1_num_intervals * 2 

 

        # TOPOLOGY 

        self.__sizes = (n_elements, 

                        ((self.x0_num_intervals + 1) * self.x1_num_intervals + 

                         (self.x1_num_intervals + 1) * self.x0_num_intervals + 

                         int(n_elements / 2)), 

                        (self.x0_num_intervals + 1) * (self.x1_num_intervals + 1)) 

 

        # calculate subentities -- codim-0 

        edge_hoffset = (self.x0_num_intervals + 1) * self.x1_num_intervals 

        edge_doffset = edge_hoffset + self.x0_num_intervals * (self.x1_num_intervals + 1) 

        E0V = ((np.arange(self.x1_num_intervals, dtype=np.int32) * (self.x0_num_intervals + 1))[:, np.newaxis] + 

               np.arange(self.x0_num_intervals, dtype=np.int32)).ravel() 

        E0H = np.arange(n_elements / 2, dtype=np.int32) + edge_hoffset 

        E0D = np.arange(n_elements / 2, dtype=np.int32) + edge_doffset 

 

        E1V = E0V + 1 

        E1H = E0H + self.x0_num_intervals 

        E1D = E0D 

 

        codim0_subentities = np.vstack((np.vstack((E0D, E0V, E0H)).T, np.vstack((E1D, E1V, E1H)).T)) 

 

        # calculate subentities -- codim-1 

 

        V0 = E0V[:, np.newaxis] + np.array([0, 1, self.x0_num_intervals + 1], dtype=np.int32) 

        V1 = E0V[:, np.newaxis] + np.array([self.x0_num_intervals + 2, self.x0_num_intervals + 1, 1], np.int32) 

        codim1_subentities = np.vstack((V0, V1)) 

        self.__subentities = (codim0_subentities, codim1_subentities) 

 

        # GEOMETRY 

 

        # embeddings 

        x0_shifts0 = np.arange(self.x0_num_intervals) * self.x0_diameter + self.x0_range[0] 

        x1_shifts0 = np.arange(self.x1_num_intervals) * self.x1_diameter + self.x1_range[0] 

        x0_shifts1 = x0_shifts0 + self.x0_diameter 

        x1_shifts1 = x1_shifts0 + self.x1_diameter 

        B = np.vstack((np.array(np.meshgrid(x0_shifts0, x1_shifts0)).reshape((2, -1)).T, 

                       np.array(np.meshgrid(x0_shifts1, x1_shifts1)).reshape((2, -1)).T)) 

        A0 = np.tile(np.diag([self.x0_diameter, self.x1_diameter]), (n_elements / 2, 1, 1)) 

        A1 = - A0 

        A = np.vstack((A0, A1)) 

        self.__embeddings = (A, B) 

 

    def __str__(self): 

        return (('Tria-Grid on domain [{xmin},{xmax}] x [{ymin},{ymax}]\n' + 

                 'x0-intervals: {x0ni}, x1-intervals: {x1ni}\n' + 

                 'faces: {faces}, edges: {edges}, vertices: {vertices}') 

                .format(xmin=self.x0_range[0], xmax=self.x0_range[1], 

                        ymin=self.x1_range[0], ymax=self.x1_range[1], 

                        x0ni=self.x0_num_intervals, x1ni=self.x1_num_intervals, 

                        faces=self.size(0), edges=self.size(1), vertices=self.size(2))) 

 

    def size(self, codim=0): 

        assert 0 <= codim <= 2, 'Invalid codimension' 

        return self.__sizes[codim] 

 

    def subentities(self, codim, subentity_codim): 

        assert 0 <= codim <= 2, 'Invalid codimension' 

        assert codim <= subentity_codim <= 2, 'Invalid subentity codimension' 

        if codim == 0: 

            if subentity_codim == 0: 

                return np.arange(self.size(0), dtype='int32')[:, np.newaxis] 

            else: 

                return self.__subentities[subentity_codim - 1] 

        else: 

            return super(TriaGrid, self).subentities(codim, subentity_codim) 

 

    def embeddings(self, codim=0): 

        if codim == 0: 

            return self.__embeddings 

        else: 

            return super(TriaGrid, self).embeddings(codim) 

 

    @staticmethod 

    def test_instances(): 

        '''Used for unit testing.''' 

        return [TriaGrid((2, 4)), TriaGrid((1, 1)), TriaGrid((42, 42))]