xref: /libCEED/julia/LibCEED.jl/src/Misc.jl (revision ded9b81dfe1c5b0a720aeaeab78a4be02eef9bb5)
1import LinearAlgebra: det
2
3"""
4    CeedDim(dim)
5
6The singleton object of type `CeedDim{dim}`, used for dispatch to linear algebra operations
7specialized for small matrices (1, 2, or 3 dimensions).
8"""
9struct CeedDim{dim} end
10@inline CeedDim(dim) = CeedDim{Int(dim)}()
11
12"""
13    det(J, ::CeedDim{dim})
14
15Specialized determinant calculations for matrices of size 1, 2, or 3.
16"""
17@inline det(J, ::CeedDim{1}) = @inbounds J[1]
18@inline det(J, ::CeedDim{2}) = @inbounds J[1]*J[4] - J[3]*J[2]
19#! format: off
20@inline det(J, ::CeedDim{3}) = @inbounds (
21    J[1]*(J[5]*J[9] - J[6]*J[8]) -
22    J[2]*(J[4]*J[9] - J[6]*J[7]) +
23    J[3]*(J[4]*J[8] - J[5]*J[7])
24)
25#! format: on
26
27"""
28    setvoigt(J::StaticArray{Tuple{D,D},T,2})
29    setvoigt(J, ::CeedDim{dim})
30
31Given a symmetric matrix `J`, return a `SVector` that encodes `J` using the [Voigt
32convention](https://en.wikipedia.org/wiki/Voigt_notation).
33
34The size of the symmetric matrix `J` must be known statically, either specified using
35[`CeedDim`](@ref) or `StaticArray`.
36"""
37@inline setvoigt(J::StaticArray{Tuple{D,D}}) where {D} = setvoigt(J, CeedDim(D))
38@inline setvoigt(J, ::CeedDim{1}) = @inbounds @SVector [J[1]]
39@inline setvoigt(J, ::CeedDim{2}) = @inbounds @SVector [J[1], J[4], J[2]]
40@inline setvoigt(J, ::CeedDim{3}) = @inbounds @SVector [J[1], J[5], J[9], J[6], J[3], J[2]]
41
42@inline function setvoigt!(V, J, ::CeedDim{1})
43    @inbounds V[1] = J[1]
44end
45
46@inline function setvoigt!(V, J, ::CeedDim{2})
47    @inbounds begin
48        V[1] = J[1]
49        V[2] = J[4]
50        V[3] = J[2]
51    end
52end
53
54@inline function setvoigt!(V, J, ::CeedDim{3})
55    @inbounds begin
56        V[1] = J[1]
57        V[2] = J[5]
58        V[3] = J[9]
59        V[4] = J[6]
60        V[5] = J[3]
61        V[6] = J[2]
62    end
63end
64
65"""
66    getvoigt(V, ::CeedDim{dim})
67
68Given a vector `V` that encodes a symmetric matrix using the [Voigt
69convention](https://en.wikipedia.org/wiki/Voigt_notation), return the corresponding
70`SMatrix`.
71"""
72@inline getvoigt(V, ::CeedDim{1}) = @inbounds @SMatrix [V[1]]
73@inline getvoigt(V, ::CeedDim{2}) = @inbounds @SMatrix [V[1] V[3]; V[3] V[2]]
74@inline getvoigt(V, ::CeedDim{3}) = @inbounds @SMatrix [
75    V[1] V[6] V[5]
76    V[6] V[2] V[4]
77    V[5] V[4] V[3]
78]
79@inline getvoigt(V::StaticArray{Tuple{1}}) = getvoigt(V, CeedDim(1))
80@inline getvoigt(V::StaticArray{Tuple{3}}) = getvoigt(V, CeedDim(2))
81@inline getvoigt(V::StaticArray{Tuple{6}}) = getvoigt(V, CeedDim(3))
82
83@inline function getvoigt!(J, V, ::CeedDim{1})
84    @inbounds J[1, 1] = V[1]
85end
86
87@inline function getvoigt!(J, V, ::CeedDim{2})
88    @inbounds begin
89        #! format: off
90        J[1,1] = V[1] ; J[1,2] = V[3]
91        J[2,1] = V[3] ; J[2,2] = V[2]
92        #! format: on
93    end
94end
95
96@inline function getvoigt!(J, V, ::CeedDim{3})
97    @inbounds begin
98        #! format: off
99        J[1,1] = V[1] ; J[1,2] = V[6] ; J[1,3] = V[5]
100        J[2,1] = V[6] ; J[2,2] = V[2] ; J[2,3] = V[4]
101        J[3,1] = V[5] ; J[3,2] = V[4] ; J[3,3] = V[3]
102        #! format: on
103    end
104end
105
106function tmp_view(obj, view_fn)
107    str = mktemp() do fname, f
108        cf = Libc.FILE(f)
109        er = view_fn(obj, cf.ptr)
110        ccall(:fflush, Cint, (Ptr{Cvoid},), cf)
111        seek(f, 0)
112        read(f, String)
113    end
114    chomp(str)
115end
116
117function ceed_show(io::IO, obj, view_fn)
118    print(io, tmp_view(obj[], view_fn))
119end
120