As an example, we solve the curl-curl system arising in electromagnetics
$$ \nabla \times \nabla \times u + \imath w u = 0 $$with natural boundary conditions. To generate the discrete PDE, we use a regular mesh and the mimetic finite volume discretization provided by jInv.Mesh
A good solver for these kinds of problems is BiCGSTAB and we test the implemenation from KrylovMethods for growing mesh sizes. If you have another implementation please add it here and make a PR.
In [ ]:
using jInv.Mesh
using KrylovMethods
using ParSpMatVec
using Base.Test
Ns = 16*[1,2,3,4] # number of grid points
nTrials = 10 # number of repititions
nthreads = 4 # number of threads used to accelerate sparse matvecs
# allocate space for results
timesKM = zeros(length(Ns),nTrials)
timesK = zeros(length(Ns),nTrials)
timesKMOpt = zeros(length(Ns),nTrials)
timesIS = zeros(length(Ns),nTrials);
In [ ]:
relresKM = 0
iterKM = 0
iterKMOpt = 0
relresKMOpt = 0
for k=1:length(Ns)
n = Ns[k]
# build Curl Curl system
M = getRegularMesh([0 1 0 1 0 1],[n,n,n])
CURL = getCurlMatrix(M)
w = 1
A = CURL'*CURL - 1im*w*I(size(CURL,2))
rhs = randn(size(A,2)) + 1im *randn(size(A,2))
if k==1 # warmup
resKM = KrylovMethods.bicgstb(A,rhs,tol=1e-4,maxIter=2,out=-1);
end
for j=1:nTrials
tic()
resKM = KrylovMethods.bicgstb(A,rhs,tol=1e-12,maxIter=100,out=-1)
timesKM[k,j] = toq();
iterKM = resKM[4]
relresKM = resKM[3]
tic()
yt = zeros(Complex128,size(A,1))
Afun(x) = (yt[:]=Complex128(0.0); ParSpMatVec.Ac_mul_B!( Complex128(1.0), A, x, Complex128(0.0), yt, nthreads); return yt)
resKMOpt = KrylovMethods.bicgstb(Afun,rhs,tol=1e-12,maxIter=100,out=-1)
timesKMOpt[k,j] = toq();
iterKMOpt = resKM[4]
relresKMOpt = resKMOpt[3]
@test iterKMOpt==iterKM
# @test abs(relresKMOpt-relresKM)/relresKM < 1e-1
end
println("n=$n, KM.jl: $(mean(timesKM[k,:])) KM.jl+ParSpMat:$(mean(timesKMOpt[k,:]))")
end
In [ ]:
using PyPlot
In [ ]:
loglog(Ns,mean(timesKM,2),"--b",linewidth=3)
hold(true)
loglog(Ns,mean(timesKMOpt,2),"-b",linewidth=3)
xlabel("degrees of freedom")
ylabel("runtime")
title("Comparison of PCG runtimes for 3D CurlCurl")
legend(("KrylovMethods.jl","KrylovMethods+ParSpMatVec"),loc=4)
In [ ]: