File size: 6,859 Bytes
66c9c8a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
from typing import Any
from enum import Enum
import math

import warp as wp
import warp.types

vec6 = wp.types.vector(length=6, dtype=wp.float32)

_SQRT_2 = wp.constant(math.sqrt(2.0))
_SQRT_3 = wp.constant(math.sqrt(3.0))
_SQRT_1_2 = wp.constant(math.sqrt(1.0 / 2.0))
_SQRT_1_3 = wp.constant(math.sqrt(1.0 / 3.0))


class DofMapper:
    """Base class from mapping node degrees of freedom to function values"""

    value_dtype: type
    dof_dtype: type
    DOF_SIZE: int

    @wp.func
    def dof_to_value(dof: Any):
        raise NotImplementedError

    @wp.func
    def value_to_dof(val: Any):
        raise NotImplementedError

    def __str__(self):
        return f"{self.value_dtype.__name__}_{self.DOF_SIZE}"


class IdentityMapper(DofMapper):
    """Identity mapper"""

    def __init__(self, dtype: type):
        if dtype == float:
            dtype = wp.float32

        self.value_dtype = dtype
        self.dof_dtype = dtype

        size = warp.types.type_length(dtype)
        self.DOF_SIZE = wp.constant(size)

    @wp.func
    def dof_to_value(dof: Any):
        return dof

    @wp.func
    def value_to_dof(val: Any):
        return val


class SymmetricTensorMapper(DofMapper):
    """Orthonormal isomorphism from R^{n (n+1)} to nxn symmetric tensors,
    using usual L2 norm for vectors and half Frobenius norm, (tau : tau)/2 for tensors.
    """

    class Mapping(Enum):
        VOIGT = 0
        """Voigt ordering of vector coefficients:
            first the three diagonal terms, then off-diagonal coefficients"""
        DB16 = 1
        """Ordering that also separates normal from tangential coefficients:
           first trace, then other diagonal terms, then off-diagonal coefficients.
           See [Daviet and Bertails-Descoubes 2016]"""

    def __init__(self, dtype: type, mapping: Mapping = Mapping.VOIGT):
        self.value_dtype = dtype
        self.mapping = mapping

        if dtype == wp.mat22:
            self.dof_dtype = wp.vec3
            self.DOF_SIZE = wp.constant(3)
            if mapping == SymmetricTensorMapper.Mapping.VOIGT:
                self.dof_to_value = SymmetricTensorMapper.dof_to_value_2d_voigt
                self.value_to_dof = SymmetricTensorMapper.value_to_dof_2d_voigt
            else:
                self.dof_to_value = SymmetricTensorMapper.dof_to_value_2d
                self.value_to_dof = SymmetricTensorMapper.value_to_dof_2d
        elif dtype == wp.mat33:
            self.dof_dtype = vec6
            self.DOF_SIZE = wp.constant(6)
            if mapping == SymmetricTensorMapper.Mapping.VOIGT:
                self.dof_to_value = SymmetricTensorMapper.dof_to_value_3d_voigt
                self.value_to_dof = SymmetricTensorMapper.value_to_dof_3d_voigt
            else:
                self.dof_to_value = SymmetricTensorMapper.dof_to_value_3d
                self.value_to_dof = SymmetricTensorMapper.value_to_dof_3d
        else:
            raise ValueError("Unsupported value dtype: ", dtype)

    def __str__(self):
        return f"{self.mapping}_{self.DOF_SIZE}"

    @wp.func
    def dof_to_value_2d(dof: wp.vec3):
        a = dof[0]
        b = dof[1]
        c = dof[2]
        return wp.mat22(a + b, c, c, a - b)

    @wp.func
    def value_to_dof_2d(val: wp.mat22):
        a = 0.5 * (val[0, 0] + val[1, 1])
        b = 0.5 * (val[0, 0] - val[1, 1])
        c = 0.5 * (val[0, 1] + val[1, 0])
        return wp.vec3(a, b, c)

    @wp.func
    def dof_to_value_2d_voigt(dof: wp.vec3):
        a = _SQRT_2 * dof[0]
        b = _SQRT_2 * dof[1]
        c = dof[2]
        return wp.mat22(a, c, c, b)

    @wp.func
    def value_to_dof_2d_voigt(val: wp.mat22):
        a = _SQRT_1_2 * val[0, 0]
        b = _SQRT_1_2 * val[1, 1]
        c = 0.5 * (val[0, 1] + val[1, 0])
        return wp.vec3(a, b, c)

    @wp.func
    def dof_to_value_3d(dof: vec6):
        a = dof[0] * _SQRT_2 * _SQRT_1_3
        b = dof[1]
        c = dof[2] * _SQRT_1_3
        d = dof[3]
        e = dof[4]
        f = dof[5]
        return wp.mat33(
            a + b - c,
            f,
            e,
            f,
            a - b - c,
            d,
            e,
            d,
            a + 2.0 * c,
        )

    @wp.func
    def value_to_dof_3d(val: wp.mat33):
        a = (val[0, 0] + val[1, 1] + val[2, 2]) * _SQRT_1_3 * _SQRT_1_2
        b = 0.5 * (val[0, 0] - val[1, 1])
        c = 0.5 * (val[2, 2] - (val[0, 0] + val[1, 1] + val[2, 2]) / 3.0) * _SQRT_3

        d = 0.5 * (val[2, 1] + val[1, 2])
        e = 0.5 * (val[0, 2] + val[2, 0])
        f = 0.5 * (val[1, 0] + val[0, 1])

        return vec6(a, b, c, d, e, f)

    @wp.func
    def dof_to_value_3d_voigt(dof: vec6):
        a = _SQRT_2 * dof[0]
        b = _SQRT_2 * dof[1]
        c = _SQRT_2 * dof[2]
        d = dof[3]
        e = dof[4]
        f = dof[5]
        return wp.mat33(
            a,
            f,
            e,
            f,
            b,
            d,
            e,
            d,
            c,
        )

    @wp.func
    def value_to_dof_3d_voigt(val: wp.mat33):
        a = _SQRT_1_2 * val[0, 0]
        b = _SQRT_1_2 * val[1, 1]
        c = _SQRT_1_2 * val[2, 2]

        d = 0.5 * (val[2, 1] + val[1, 2])
        e = 0.5 * (val[0, 2] + val[2, 0])
        f = 0.5 * (val[1, 0] + val[0, 1])

        return vec6(a, b, c, d, e, f)


class SkewSymmetricTensorMapper(DofMapper):
    """Orthonormal isomorphism from R^{n (n-1)} to nxn skew-symmetric tensors,
    using usual L2 norm for vectors and half Frobenius norm, (tau : tau)/2 for tensors.
    """

    def __init__(self, dtype: type):
        self.value_dtype = dtype

        if dtype == wp.mat22:
            self.dof_dtype = float
            self.DOF_SIZE = wp.constant(1)
            self.dof_to_value = SkewSymmetricTensorMapper.dof_to_value_2d
            self.value_to_dof = SkewSymmetricTensorMapper.value_to_dof_2d
        elif dtype == wp.mat33:
            self.dof_dtype = wp.vec3
            self.DOF_SIZE = wp.constant(3)
            self.dof_to_value = SkewSymmetricTensorMapper.dof_to_value_3d
            self.value_to_dof = SkewSymmetricTensorMapper.value_to_dof_3d
        else:
            raise ValueError("Unsupported value dtype: ", dtype)

    def __str__(self):
        return f"{self.__class__.__name__}_{self.DOF_SIZE}"

    @wp.func
    def dof_to_value_2d(dof: float):
        return wp.mat22(0.0, -dof, dof, 0.0)

    @wp.func
    def value_to_dof_2d(val: wp.mat22):
        return 0.5 * (val[1, 0] - val[0, 1])

    @wp.func
    def dof_to_value_3d(dof: wp.vec3):
        a = dof[0]
        b = dof[1]
        c = dof[2]
        return wp.mat33(0.0, -c, b, c, 0.0, -a, -b, a, 0.0)

    @wp.func
    def value_to_dof_3d(val: wp.mat33):
        a = 0.5 * (val[2, 1] - val[1, 2])
        b = 0.5 * (val[0, 2] - val[2, 0])
        c = 0.5 * (val[1, 0] - val[0, 1])
        return wp.vec3(a, b, c)