Skip to content

Commit b67eed0

Browse files
committed
upgraded from TensorFields to Cartan
1 parent d368fac commit b67eed0

File tree

5 files changed

+88
-61
lines changed

5 files changed

+88
-61
lines changed

Project.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
name = "Adapode"
22
uuid = "0750cfb5-909a-49d7-927e-29b6595444bf"
33
authors = ["Michael Reed"]
4-
version = "0.2.9"
4+
version = "0.3"
55

66
[deps]
77
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
8+
Cartan = "e24af43f-9fd5-4672-9264-a75f3ae40eb2"
89
Grassmann = "4df31cd9-4c27-5bea-88d0-e6a7146666d8"
9-
TensorFields = "86e2b4fd-d9c8-44dc-a03f-e0a387f3b4e6"
1010
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1111
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1212

1313
[compat]
1414
julia = "1"
1515
Requires = "1"
16-
TensorFields = "0.1"
17-
Grassmann = "0.8"
16+
Grassmann = "0.8,0.9"
17+
Cartan = "0.3"
1818

1919
[extras]
2020
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

README.md

+21-20
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
[![Gitter](https://badges.gitter.im/Grassmann-jl/community.svg)](https://gitter.im/Grassmann-jl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
1313
[![Build Status](https://travis-ci.org/chakravala/Adapode.jl.svg?branch=master)](https://travis-ci.org/chakravala/Adapode.jl)
1414

15-
This Julia project originally started as a FORTRAN 95 project called [adapode](https://github.com/chakravala/adapode).
15+
This Julia project originally started as a FORTRAN 95 project called [adapode](https://github.com/chakravala/adapode) and evolved with [Grassmann.jl](https://github.com/chakravala/Grassmann.jl) and [Cartan.jl](https://github.com/chakravala/Cartan.jl).
1616

1717
```julia
1818
using Grassmann, Adapode, Makie
@@ -46,61 +46,62 @@ L2Projector(initmesh(0:1/5:1)[3],x->2x[2]*sin(2π*x[2])+3)
4646

4747
Partial differential equations can also be assembled with various additional methods:
4848
```julia
49-
PoissonSolver(p,e,t,c,f,κ,gD=1,gN=0) = mesh(t,color=solvepoisson(t,e,c,f,κ,gD,gN))
5049
function solvepoisson(t,e,c,f,κ,gD=0,gN=0)
5150
m = volumes(t)
5251
b = assemblefunction(t,f,m)
5352
A = assemblestiffness(t,c,m)
5453
R,r = assemblerobin(e,κ,gD,gN)
55-
return (A+R)\(b+r)
54+
return TensorField(t,(A+R)\(b+r))
5655
end
57-
function solveSD(t,e,c,f,δ,κ,gD=0,gN=0)
56+
function solvetransportdiffusion(tf,eκ,c,δ,gD=0,gN=0)
57+
t,f,e,κ = base(tf),fiber(tf),base(eκ),fiber(eκ)
5858
m = volumes(t)
5959
g = gradienthat(t,m)
6060
A = assemblestiffness(t,c,m,g)
61-
b = means(t,f)
61+
b = means(immersion(t),f)
6262
C = assembleconvection(t,b,m,g)
6363
Sd = assembleSD(t,sqrt(δ)*b,m,g)
6464
R,r = assemblerobin(e,κ,gD,gN)
65-
return (A+R-C'+Sd)\r
65+
return TensorField(t,(A+R-C'+Sd)\r)
6666
end
6767
function solvetransport(t,e,c,ϵ=0.1)
6868
m = volumes(t)
6969
g = gradienthat(t,m)
7070
A = assemblestiffness(t,ϵ,m,g)
7171
b = assembleload(t,m)
7272
C = assembleconvection(t,c,m,g)
73-
return solvedirichlet(A+C,b,e)
73+
return TensorField(t,solvedirichlet(A+C,b,e))
7474
end
7575
```
76-
Such modular methods can work on input meshes of any dimension.
76+
Such modular methods can work with a `TensorField` of any dimension.
7777
The following examples are based on trivially generated 1 dimensional domains:
7878
```Julia
7979
function BackwardEulerHeat1D()
8080
x,m = 0:0.01:1,100; p,e,t = initmesh(x)
8181
T = range(0,0.5,length=m+1) # time grid
8282
ξ = 0.5.-abs.(0.5.-x) # initial condition
83-
A = assemblestiffness(t) # assemble(t,1,2x)
84-
M,b = assemblemassfunction(t,2x).+assemblerobin(e,1e6,0,0)
83+
A = assemblestiffness(p(t)) # assemble(p(t),1,2x)
84+
M,b = assemblemassfunction(p(t),2x).+assemblerobin(p(e),1e6,0,0)
8585
h = Float64(T.step); LHS = M+h*A # time step
8686
for l 1:m
8787
ξ = LHS\(M*ξ+h*b); l%10==0 && println(l*h)
8888
end
89-
mesh(t,color=ξ)
89+
lines(TensorField(p(t),ξ))
9090
end
9191
function PoissonAdaptive(g,p,e,t,c=1,a=0,f=1)
9292
ϵ = 1.0
93+
pt,pe = p(t),p(e)
9394
while ϵ > 5e-5 && length(t) < 10000
94-
m = volumes(t)
95-
h = gradienthat(t,m)
96-
A,M,b = assemble(t,c,a,f,m,h)
97-
ξ = solvedirichlet(A+M,b,e)
98-
η = jumps(t,c,a,f,ξ,m,h)
99-
display(mesh(t,color=ξ,shading=false))
95+
m = volumes(pt)
96+
h = gradienthat(pt,m)
97+
A,M,b = assemble(pt,c,a,f,m,h)
98+
ξ = solvedirichlet(A+M,b,pe)
99+
η = jumps(pt,c,a,f,ξ,m,h)
100+
display(lines(TensorField(pt,ξ)))
100101
if typeof(g)<:AbstractRange
101-
scatter!(p,ξ,markersize=0.01)
102+
#scatter!(p,ξ,markersize=0.01)
102103
else
103-
wireframe!(t,color=(:red,0.6),linewidth=3)
104+
#wireframe!(t,color=(:red,0.6),linewidth=3)
104105
end
105106
ϵ = sqrt(norm(η)^2/length(η))
106107
println(t,", ϵ=, α=$(ϵ/maximum(η))"); sleep(0.5)
@@ -110,5 +111,5 @@ function PoissonAdaptive(g,p,e,t,c=1,a=0,f=1)
110111
end
111112
PoissonAdaptive(refinemesh(0:0.25:1)...,1,0,x->exp(-100abs2(x[2]-0.5)))
112113
```
113-
More general problems for finite element boundary value problems are also enabled by mesh representations imported from external sources.
114+
More general problems for finite element boundary value problems are also enabled by mesh representations imported from external sources and managed by `Cartan` via `Grassmann` algebra.
114115
These methods can automatically generalize to higher dimensional manifolds and are compatible with discrete differential geometry.

src/Adapode.jl

+15-15
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module Adapode
1818
# |___|___||_____||___._|| __||_____||_____||_____|
1919
# |__|
2020

21-
using SparseArrays, LinearAlgebra, Grassmann, TensorFields, Requires
21+
using SparseArrays, LinearAlgebra, Grassmann, Cartan, Requires
2222
import Grassmann: value, vector, valuetype, tangent, list
2323
import Grassmann: Values, Variables, FixedVector
2424
import Grassmann: Scalar, GradedVector, Bivector, Trivector
@@ -78,12 +78,12 @@ function explicit(x,h,c,fx,i)
7878
end
7979
function heun(x,f::Function,h)
8080
hfx = h*f(x)
81-
fiber(x)+(hfx+h*f((base(x)+h)(fiber(x)+hfx)))/2
81+
fiber(x)+(hfx+h*f((point(x)+h)(fiber(x)+hfx)))/2
8282
end
8383
function heun(x,f::TensorField,t)
8484
fx = f[t.i]
8585
hfx = t.h*fx
86-
fiber(x)+(hfx+t.h*f(base(fx)(fiber(x)+hfx)))/2
86+
fiber(x)+(hfx+t.h*f(point(fx)(fiber(x)+hfx)))/2
8787
end
8888

8989
@pure butcher(::Val{N},::Val{A}=Val(false)) where {N,A} = A ? CBA[N] : CB[N]
@@ -94,7 +94,7 @@ function butcher(x::Section{B,F},f,h,v::Val{N}=Val(4),a::Val{A}=Val(false)) wher
9494
fx = F<:Vector ? FixedVector{n,F}(undef) : Variables{n,F}(undef)
9595
@inbounds fx[1] = f(x)
9696
for k 2:n
97-
@inbounds fx[k] = f((base(x)+h*sum(b[k-1]))explicit(x,h,b[k-1],fx))
97+
@inbounds fx[k] = f((point(x)+h*sum(b[k-1]))explicit(x,h,b[k-1],fx))
9898
end
9999
return fx
100100
end
@@ -108,7 +108,7 @@ end # more accurate compared with CAB[k] methods
108108
function predictcorrect(x,f,fx,t,k::Val{m}=Val(4)) where m
109109
iszero(t.s) && initsteps!(x,f,fx,t)
110110
@inbounds xti = x[t.i]
111-
xi,tn = fiber(xti),base(xti)+t.h
111+
xi,tn = fiber(xti),point(xti)+t.h
112112
xn = multistep!(xti,f,fx,t,k)
113113
t.s = (t.s%(m+1))+1; t.i += 1
114114
xn = multistep!(tn(xi+xn),f,fx,t,k,Val(true))
@@ -117,7 +117,7 @@ end
117117
function predictcorrect(x,f,fx,t,::Val{1})
118118
@inbounds xti = x[t.i]
119119
t.i += 1
120-
fiber(xti)+t.h*f((base(xti)+t.h)(fiber(xti)+t.h*f(xti)))
120+
fiber(xti)+t.h*f((point(xti)+t.h)(fiber(xti)+t.h*f(xti)))
121121
end
122122

123123
initsteps(x0,t,tmax,m) = initsteps(init(x0),t,tmax,m)
@@ -142,7 +142,7 @@ end
142142
function predictcorrect2(x,f,fx,t,k::Val{m}=Val(4)) where m
143143
iszero(t.s) && initsteps!(x,f,fx,t)
144144
@inbounds xti = x[t.i]
145-
xi,tn = fiber(xti),base(xti)+t.h
145+
xi,tn = fiber(xti),point(xti)+t.h
146146
xn = multistep2!(xti,f,fx,t,k)
147147
t.s = (t.s%m)+1; t.i += 1
148148
xn = multistep2!(tn(xi+xn),f,fx,t,k,Val(true))
@@ -152,7 +152,7 @@ end
152152
function predictcorrect2(x,f,fx,t,::Val{1})
153153
@inbounds xti = x[t.i]
154154
t.i += 1
155-
fiber(xti)+t.h*f((base(xti)+t.h)xti)
155+
fiber(xti)+t.h*f((point(xti)+t.h)xti)
156156
end
157157

158158
initsteps2(x0,t,tmax,f,m,B) = initsteps2(init(x0),t,tmax,f,m,B)
@@ -165,7 +165,7 @@ function initsteps!(x,f,fx,t,B=Val(4))
165165
@inbounds xi = x[t.i]
166166
for j 1:m
167167
@inbounds fx[j] = f(xi)
168-
xi = (base(xi)+t.h) explicit(xi,f,t.h,B)
168+
xi = (point(xi)+t.h) explicit(xi,f,t.h,B)
169169
x[t.i+j] = xi
170170
end
171171
t.s = 1+m
@@ -175,18 +175,18 @@ end
175175
function explicit!(x,f,t,B=Val(5))
176176
resize!(x,t.i,10000)
177177
@inbounds xti = x[t.i]
178-
xi,tn = fiber(xti)
178+
xi = fiber(xti)
179179
fx,b = butcher(xti,f,t.h,B,Val(true)),butcher(B,Val(true))
180180
t.i += 1
181-
@inbounds x[t.i] = (base(xti)+t.h) explicit(xti,t.h,b[end-1],fx)
181+
@inbounds x[t.i] = (point(xti)+t.h) explicit(xti,t.h,b[end-1],fx)
182182
@inbounds t.e = maximum(abs.(t.h*value(b[end]fx)))
183183
end
184184

185185
function predictcorrect!(x,f,fx,t,B::Val{m}=Val(4)) where m
186186
resize!(x,t.i+m,10000)
187187
iszero(t.s) && initsteps!(x,f,fx,t)
188188
@inbounds xti = x[t.i]
189-
xi,tn = fiber(xti),base(xti)+t.h
189+
xi,tn = fiber(xti),point(xti)+t.h
190190
p = xi + multistep!(xti,f,fx,t,B)
191191
t.s = (t.s%(m+1))+1
192192
c = xi + multistep!(tnp,f,fx,t,B,Val(true))
@@ -196,7 +196,7 @@ function predictcorrect!(x,f,fx,t,B::Val{m}=Val(4)) where m
196196
end
197197
function predictcorrect!(x,f,fx,t,::Val{1})
198198
@inbounds xti = x[t.i]
199-
xi,tn = fiber(xti),base(xti)+t.h
199+
xi,tn = fiber(xti),point(xti)+t.h
200200
p = xi + t.h*f(xti)
201201
c = xi + t.h*f(tnp)
202202
t.i += 1
@@ -298,7 +298,7 @@ function timeloop!(x,t,tmax,::Val{m}=Val(1)) where m
298298
t.s = 0
299299
end
300300
iszero(t.s) && checkstep!(t)
301-
d = tmax-time(x[t.i])
301+
d = tmax-point(x[t.i])
302302
d t.h && (t.h = d)
303303
done = d t.hmax
304304
done && truncate!(x,t.i-1)
@@ -310,6 +310,6 @@ time(x) = x[1]
310310
Base.resize!(x,i,h) = length(x)<i+1 && resize!(x,i+h)
311311
truncate!(x,i) = length(x)>i+1 && resize!(x,i)
312312

313-
show_progress(x,t,b) = t.i%75000 == 11 && println(time(x[t.i])," out of ",b)
313+
show_progress(x,t,b) = t.i%75000 == 11 && println(point(x[t.i])," out of ",b)
314314

315315
end # module

src/element.jl

+40-15
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ export assemble, assembleglobal, assemblestiffness, assembleconvection, assemble
1616
export assemblemass, assemblefunction, assemblemassfunction, assembledivergence
1717
export assemblemassincidence, asssemblemassnodes, assemblenodes
1818
export assembleload, assemblemassload, assemblerobin, edges, edgesindices, neighbors
19-
export solvepoisson, solveSD, solvetransport, solvedirichlet, adaptpoisson
19+
export solvepoisson, solvetransport, solvetransportdiffusion, solvedirichlet, adaptpoisson
2020
export gradienthat, gradientCR, gradient, interp, nedelec, nedelecmean, jumps
2121
export submesh, detsimplex, iterable, callable, value, edgelengths, laplacian
2222
export boundary, interior, trilength, trinormals, incidence, degrees
23-
import Grassmann: norm, column, columns, points, pointset, edges
23+
import Grassmann: norm, column, columns
2424
using Base.Threads
2525

26-
import TensorFields: iterpts, iterable, callable, revrot
27-
import TensorFields: gradienthat, laplacian, gradient, assemblelocal!
26+
import Cartan: points, pointset, edges, iterpts, iterable, callable, revrot
27+
import Cartan: gradienthat, laplacian, gradient, assemblelocal!
2828

2929
trilength(rc) = value.(abs.(value(rc)))
3030
function trinormals(t)
@@ -52,8 +52,15 @@ function assembleglobal(M,t,m::T,c::C,g::F) where {T<:AbstractVector,C<:Abstract
5252
end
5353
return A
5454
end
55+
function assembleglobal(M,X::SimplexFrameBundle,m::T,c::C,g::F) where {T<:AbstractVector,C<:AbstractVector,F<:AbstractVector}
56+
np = length(points(X)); A = spzeros(np,np); t = immersion(X)
57+
for k 1:length(t)
58+
assemblelocal!(A,M(c[k],g[k],Val(mdims(Manifold(X)))),m[k],value(t[k]))
59+
end
60+
return A
61+
end
5562

56-
import TensorFields: weights, degrees, assembleincidence, incidence
63+
import Cartan: weights, degrees, assembleincidence, incidence
5764

5865
assemblemassincidence(t,f,m=volumes(t),l=m) = assemblemassincidence(t,iterpts(t,f),iterable(t,m),iterable(t,l))
5966
function assemblemassincidence(t,f::F,m::V,l::T) where {F<:AbstractVector,V<:AbstractVector,T<:AbstractVector}
@@ -66,14 +73,25 @@ function assemblemassincidence(t,f::F,m::V,l::T) where {F<:AbstractVector,V<:Abs
6673
end
6774
return M,b
6875
end
76+
function assemblemassincidence(X::SimplexFrameBundle,f::F,m::V,l::T) where {F<:AbstractVector,V<:AbstractVector,T<:AbstractVector}
77+
np,n,t = length(points(X)),Val(mdims(Manifold(X))),immersion(X)
78+
M,b,v = spzeros(np,np), zeros(np), f
79+
for k 1:length(t)
80+
tk = value(t[k])
81+
assemblelocal!(M,mass(nothing,nothing,n),m[k],tk)
82+
b[tk] .+= v[tk]*l[k]
83+
end
84+
return M,b
85+
end
6986

7087
assemblefunction(t,f,m=volumes(t),d=degrees(t,m)) = assembleincidence(t,iterpts(t,f)/mdims(t),m)
7188
assemblenodes(t,f,m=volumes(t),d=degrees(t,m)) = assembleincidence(t,iterpts(t,f)./d,m)
7289
assemblemassload(t,m=volumes(t),l=m,d=degrees(t)) = assemblemassincidence(t,inv.(d),m,l)
7390
assemblemassfunction(t,f,m=volumes(t),l=m) = assemblemassincidence(t,iterpts(t,f)/mdims(t),iterable(t,m),iterable(t,l))
91+
assemblemassfunction(tf::TensorField,m=volumes(base(tf)),l=m) = assemblemassfunction(base(tf),fiber(tf),m,l)
7492
assemblemassnodes(t,f,m=volumes(t),l=m,d=degrees(t)) = assemblemassincidence(t,iterpts(t,f)./d,iterable(t,m),iterable(t,l))
7593

76-
import TensorFields: assembleload, interp, pretni
94+
import Cartan: assembleload, interp, pretni
7795

7896
#mass(a,b,::Val{N}) where N = (ones(SMatrix{N,N,Int})+I)/Int(factorial(N+1)/factorial(N-1))
7997
mass(a,b,::Val{N}) where N = (x=Submanifold(N)(∇);outer(x,x)+I)/Int(factorial(N+1)/factorial(N-1))
@@ -82,6 +100,8 @@ assemblemass(t,m=volumes(t)) = assembleglobal(mass,t,iterpts(t,m))
82100
stiffness(c,g::Float64,::Val{2}) = (cg = c*g^2; Chain(Chain(cg,-cg),Chain(-cg,cg)))
83101
stiffness(c,g,::Val{N}) where N = Chain{Submanifold(N),1}(map.(*,c,value(g).⋅Ref(g)))
84102
assemblestiffness(t,c=1,m=volumes(t),g=gradienthat(t,m)) = assembleglobal(stiffness,t,m,iterable(c isa Real ? t : means(t),c),g)
103+
assemblestiffness(t::SimplexFrameBundle,c=1,m=volumes(t),g=gradienthat(t,m)) = assembleglobal(stiffness,t,m,iterable(c isa Real ? immersion(t) : means(t),c),g)
104+
85105
# iterable(means(t),c) # mapping of c.(means(t))
86106

87107
#=function sonicstiffness(c,g,::Val{N}) where N
@@ -133,18 +153,19 @@ function solvepoisson(t,e,c,f,κ,gD=0,gN=0)
133153
b = assemblenodes(t,f,m)
134154
A = assemblestiffness(t,c,m)
135155
R,r = assemblerobin(e,κ,gD,gN)
136-
return (A+R)\(b+r)
156+
return TensorField(t,(A+R)\(b+r))
137157
end
138158

139-
function solveSD(t,e,c,f,δ,κ,gD=0,gN=0)
159+
function solvetransportdiffusion(tf,eκ,c,δ,gD=0,gN=0)
160+
t,f,e,κ = base(tf),fiber(tf),base(eκ),fiber(eκ)
140161
m = volumes(t)
141162
g = gradienthat(t,m)
142163
A = assemblestiffness(t,c,m,g)
143-
b = means(t,f)
164+
b = means(immersion(t),f)
144165
C = assembleconvection(t,b,m,g)
145166
Sd = assembleSD(t,sqrt(δ)*b,m,g)
146167
R,r = assemblerobin(e,κ,gD,gN)
147-
return (A+R-C'+Sd)\r
168+
return TensorField(t,(A+R-C'+Sd)\r)
148169
end
149170

150171
function solvetransport(t,e,c,ϵ=0.1)
@@ -153,7 +174,7 @@ function solvetransport(t,e,c,ϵ=0.1)
153174
A = assemblestiffness(t,ϵ,m,g)
154175
b = assembleload(t,m)
155176
C = assembleconvection(t,c,m,g)
156-
return solvedirichlet(A+C,b,e)
177+
TensorField(t,solvedirichlet(A+C,b,e))
157178
end
158179

159180
function adaptpoisson(g,p,e,t,c=1,a=0,f=1=1e6,gD=0,gN=0)
@@ -171,8 +192,12 @@ function adaptpoisson(g,p,e,t,c=1,a=0,f=1,κ=1e6,gD=0,gN=0)
171192
return g,p,e,t
172193
end
173194

174-
solvedirichlet(M,b,e::ChainBundle) = solvedirichlet(M,b,pointset(e))
175-
solvedirichlet(M,b,e::ChainBundle,u) = solvedirichlet(M,b,pointset(e),u)
195+
#solvedirichlet(M,b,e::ChainBundle) = solvedirichlet(M,b,pointset(e))
196+
#solvedirichlet(M,b,e::ChainBundle,u) = solvedirichlet(M,b,pointset(e),u)
197+
solvedirichlet(M,b,e::SimplexFrameBundle) = solvedirichlet(M,b,vertices(e))
198+
solvedirichlet(M,b,e::SimplexManifold) = solvedirichlet(M,b,vertices(e))
199+
solvedirichlet(M,b,e::SimplexFrameBundle,u) = solvedirichlet(M,b,vertices(e),u)
200+
solvedirichlet(M,b,e::SimplexManifold,u) = solvedirichlet(M,b,vertices(e),u)
176201
function solvedirichlet(A,b,fixed,boundary)
177202
neq = length(b)
178203
free,ξ = interior(fixed,neq),zeros(eltype(b),neq)
@@ -187,15 +212,15 @@ function solvedirichlet(M,b,fixed)
187212
return ξ
188213
end
189214

190-
import TensorFields: interior
215+
import Cartan: interior
191216

192217
solvehomogenous(e,M,b) = solvedirichlet(M,b,e)
193218
export solvehomogenous, solveboundary
194219
const solveboundary = solvedirichlet # deprecate
195220
const edgelengths = volumes # deprecate
196221
const boundary = pointset # deprecate
197222

198-
import TensorFields: facesindices, edgesindices, neighbor, neighbors, centroidvectors
223+
import Cartan: facesindices, edgesindices, neighbor, neighbors, centroidvectors
199224

200225
#=
201226
facesindices(t,cols=columns(t)) = mdims(t) == 3 ? edgesindices(t,cols) : throw(error())

0 commit comments

Comments
 (0)