Skip to content

Commit 87d75fa

Browse files
Use Symmetric Covariant Axis2Tensor
wip
1 parent 2f82f04 commit 87d75fa

File tree

4 files changed

+93
-9
lines changed

4 files changed

+93
-9
lines changed

src/Geometry/Geometry.jl

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,65 @@ export Contravariant1Vector,
2323
Contravariant123Vector
2424

2525

26+
"""
27+
SimpleSymmetric
28+
29+
A simple Symmetric matrix. `LinearAlgebra.Symmetric` has a field
30+
`uplo::Char`, which results in a failed `check_basetype(T, S)`.
31+
"""
32+
struct SimpleSymmetric{T, S <: AbstractMatrix{<:T}} <: AbstractMatrix{T}
33+
data::S
34+
function SimpleSymmetric{T, S}(data) where {T, S <: AbstractMatrix{<:T}}
35+
new{T, S}(data)
36+
end
37+
end
38+
SimpleSymmetric(A) = cc_symmetric_type(typeof(A))(A)
39+
40+
LinearAlgebra.transpose(A::SimpleSymmetric) = A
41+
42+
"""
43+
cc_symmetric_type(T::Type)
44+
45+
The type of the object returned by `symmetric(::T, ::Symbol)`. For matrices, this is an
46+
appropriately typed `Symmetric`, for `Number`s, it is the original type. If `symmetric` is
47+
implemented for a custom type, so should be `cc_symmetric_type`, and vice versa.
48+
"""
49+
cc_symmetric_type(::Type{T}) where {S, T <: AbstractMatrix{S}} =
50+
SimpleSymmetric{
51+
Union{S, Base.promote_op(transpose, S), cc_symmetric_type(S)},
52+
T,
53+
}
54+
cc_symmetric_type(::Type{T}) where {S <: Number, T <: AbstractMatrix{S}} =
55+
SimpleSymmetric{S, T}
56+
cc_symmetric_type(
57+
::Type{T},
58+
) where {S <: AbstractMatrix, T <: AbstractMatrix{S}} =
59+
SimpleSymmetric{AbstractMatrix, T}
60+
cc_symmetric_type(::Type{T}) where {T <: Number} = T
61+
62+
Base.@propagate_inbounds function Base.getindex(
63+
A::SimpleSymmetric,
64+
i::Integer,
65+
j::Integer,
66+
)
67+
@boundscheck checkbounds(A, i, j)
68+
@inbounds if i == j
69+
data_ij = A.data[i, j]
70+
if data_ij isa AbstractMatrix
71+
return SimpleSymmetric(data_ij)::cc_symmetric_type(eltype(A.data))
72+
elseif data_ij isa Number
73+
return data_ij::cc_symmetric_type(eltype(A.data))
74+
end
75+
elseif (i < j)
76+
return A.data[i, j]
77+
else
78+
return LinearAlgebra.transpose(A.data[j, i])
79+
end
80+
end
81+
82+
Base.@propagate_inbounds Base.getindex(A::SimpleSymmetric, i::Integer) =
83+
A.data[i]
84+
2685

2786
include("coordinates.jl")
2887
include("axistensors.jl")

src/Geometry/axistensors.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,10 @@ struct AxisTensor{
136136
T,
137137
N,
138138
A <: NTuple{N, AbstractAxis},
139-
S <: StaticArray{<:Tuple, T, N},
139+
S <: Union{
140+
SimpleSymmetric{T, <:StaticArray{<:Tuple, T, N}},
141+
StaticArray{<:Tuple, T, N},
142+
},
140143
} <: AbstractArray{T, N}
141144
axes::A
142145
components::S
@@ -147,7 +150,10 @@ AxisTensor(
147150
components::S,
148151
) where {
149152
A <: Tuple{Vararg{AbstractAxis}},
150-
S <: StaticArray{<:Tuple, T, N},
153+
S <: Union{
154+
SimpleSymmetric{T, <:StaticArray{<:Tuple, T, N}},
155+
StaticArray{<:Tuple, T, N},
156+
},
151157
} where {T, N} = AxisTensor{T, N, A, S}(axes, components)
152158

153159
AxisTensor(axes::Tuple{Vararg{AbstractAxis}}, components) =

src/Geometry/localgeometry.jl

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
1+
import LinearAlgebra
2+
import .Geometry: SimpleSymmetric
3+
4+
import InteractiveUtils
15
import LinearAlgebra: issymmetric
26

37
isapproxsymmetric(A::AbstractMatrix{T}; rtol = 10 * eps(T)) where {T} =
48
Base.isapprox(A, A'; rtol)
59

10+
function SimpleSymmetric(x::AxisTensor{FT}) where {FT}
11+
c = SimpleSymmetric(components(x))
12+
A = axes(x)
13+
return AxisTensor{FT, ndims(x), typeof(A), typeof(c)}(A, c)
14+
end
15+
616
"""
717
LocalGeometry
818
@@ -22,9 +32,13 @@ struct LocalGeometry{I, C <: AbstractPoint, FT, S}
2232
"Partial derivatives of the map from `x` to `ξ`: `∂ξ∂x[i,j]` is ∂ξⁱ/∂xʲ"
2333
∂ξ∂x::Axis2Tensor{FT, Tuple{ContravariantAxis{I}, LocalAxis{I}}, S}
2434
"Contravariant metric tensor (inverse of gᵢⱼ), transforms covariant to contravariant vector components"
25-
gⁱʲ::Axis2Tensor{FT, Tuple{ContravariantAxis{I}, ContravariantAxis{I}}, S}
35+
gⁱʲ::Axis2Tensor{FT, Tuple{ContravariantAxis{I}, ContravariantAxis{I}}, SimpleSymmetric{FT, S}}
2636
"Covariant metric tensor (gᵢⱼ), transforms contravariant to covariant vector components"
27-
gᵢⱼ::Axis2Tensor{FT, Tuple{CovariantAxis{I}, CovariantAxis{I}}, S}
37+
gᵢⱼ::Axis2Tensor{
38+
FT,
39+
Tuple{CovariantAxis{I}, CovariantAxis{I}},
40+
SimpleSymmetric{FT, S},
41+
}
2842
@inline function LocalGeometry(
2943
coordinates,
3044
J,
@@ -34,15 +48,16 @@ struct LocalGeometry{I, C <: AbstractPoint, FT, S}
3448
∂ξ∂x = inv(∂x∂ξ)
3549
C = typeof(coordinates)
3650
Jinv = inv(J)
37-
gⁱʲ = ∂ξ∂x * ∂ξ∂x'
38-
gᵢⱼ = ∂x∂ξ' * ∂x∂ξ
39-
isapproxsymmetric(components(gⁱʲ)) || error("gⁱʲ is not symmetric.")
40-
isapproxsymmetric(components(gᵢⱼ)) || error("gᵢⱼ is not symmetric.")
51+
gⁱʲ₀ = ∂ξ∂x * ∂ξ∂x'
52+
gᵢⱼ₀ = ∂x∂ξ' * ∂x∂ξ
53+
isapproxsymmetric(components(gⁱʲ₀)) || error("gⁱʲ is not symmetric.")
54+
isapproxsymmetric(components(gᵢⱼ₀)) || error("gᵢⱼ is not symmetric.")
55+
gⁱʲ = SimpleSymmetric(gⁱʲ₀)
56+
gᵢⱼ = SimpleSymmetric(gᵢⱼ₀)
4157
return new{I, C, FT, S}(coordinates, J, WJ, Jinv, ∂x∂ξ, ∂ξ∂x, gⁱʲ, gᵢⱼ)
4258
end
4359
end
4460

45-
4661
"""
4762
SurfaceGeometry
4863

test/Geometry/axistensor_conversion_benchmarks.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
#=
2+
julia --project
3+
using Revise; include(joinpath("test", "Geometry", "axistensor_conversion_benchmarks.jl"))
4+
=#
15
using Test, StaticArrays
26
#! format: off
37
import Random, BenchmarkTools, StatsBase,

0 commit comments

Comments
 (0)