Here is a run of the Julia code
conjulia -- Energy Conserving IRK Scheme
y(0)=[1.0, 1.0, 1.0]
p n h E(100) dE(100) error
7 128 7.8125000e-01 3.0000000e+00 0.0000000e+00 3.8059634e-02
8 256 3.9062500e-01 3.0000000e+00 -3.5527137e-15 7.3773381e-03
9 512 1.9531250e-01 3.0000000e+00 -2.2204460e-15 4.9289848e-04
10 1024 9.7656250e-02 3.0000000e+00 5.3290705e-15 3.2058762e-05
11 2048 4.8828125e-02 3.0000000e+00 4.4408921e-16 2.0240981e-06
12 4096 2.4414062e-02 3.0000000e+00 7.1054274e-15 1.2682855e-07
13 8192 1.2207031e-02 3.0000000e+00 -1.6431301e-14 7.9318318e-09
14 16384 6.1035156e-03 3.0000000e+00 6.4837025e-14 4.9582805e-10
15 32768 3.0517578e-03 3.0000000e+00 2.0428104e-14 3.0986253e-11
16 65536 1.5258789e-03 3.0000000e+00 -1.0658141e-14 1.9332709e-12
y(100)=[-0.11882343279003697, 0.20699682299721942, -1.7155271222248394]
Total execution time 1166.090384056 seconds.
real 21m38.138s
user 20m51.230s
sys 0m15.350s
and here is a run of the Go program
congo -- Energy Conserving IRK Scheme
y(0)=[1, 1, 1]
p n h E(100) dE(100) error
7 128 7.8125000e-01 3.0000000e+00 0.0000000e+00 3.8059634e-02
8 256 3.9062500e-01 3.0000000e+00 -3.5527137e-15 7.3773381e-03
9 512 1.9531250e-01 3.0000000e+00 -4.4408921e-16 4.9289848e-04
10 1024 9.7656250e-02 3.0000000e+00 8.4376950e-15 3.2058762e-05
11 2048 4.8828125e-02 3.0000000e+00 3.9968029e-15 2.0240981e-06
12 4096 2.4414062e-02 3.0000000e+00 5.7731597e-15 1.2682855e-07
13 8192 1.2207031e-02 3.0000000e+00 -1.6431301e-14 7.9318324e-09
14 16384 6.1035156e-03 3.0000000e+00 5.9063865e-14 4.9582719e-10
15 32768 3.0517578e-03 3.0000000e+00 1.8651747e-14 3.0986469e-11
16 65536 1.5258789e-03 3.0000000e+00 -1.0658141e-14 1.9335909e-12
y(100)=[-0.11882343279003703, 0.20699682299721947, -1.7155271222248394]
Total execution time 148.85671734809875 seconds.
real 2m29.261s
user 2m26.410s
sys 0m1.820s
For reference the source codes for the two programs are
# conserve.jl -- Energy Conserving IRK Scheme
using Printf, LinearAlgebra
s3o6=sqrt(3)/6
a=[1/4 1/4-s3o6; 1/4+s3o6 1/4]
b=[1/2,1/2]
c=[1/2-s3o6,1/2+s3o6]
function euler(t,y,h)
return y+h*fF(t,y)
end
function rk2(t,y,h)
k1=fF(t,y)
k2=fF(t,y+h*2/3*k1)
return y+h*(1/4*k1+3/4*k2)
end
function fF(t,y)
F=zeros(3)
F[1] = sin(t)*y[2]*y[3] - y[1]*y[2]*y[3]
F[2] = (y[1]*y[3])/20 - sin(t)*y[1]*y[3]
F[3] = -(y[1]*y[2])/20 + y[1]^2*y[2]
return F
end
function fG(t,y,h,k)
G=zeros(6)
G[1] = k[1] - sin(t + h*c[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3]) + (h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
G[2] = k[2] - sin(t + h*c[1])*(-(h*(a[1, 1]*k[1] + a[1, 2]*k[4])) - y[1])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3]) - ((h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3]))/20
G[3] = k[3] + ((h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2]))/20 - (h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])^2*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])
G[4] = k[4] - sin(t + h*c[2])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3]) + (h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
G[5] = k[5] - sin(t + h*c[2])*(-(h*(a[2, 1]*k[1] + a[2, 2]*k[4])) - y[1])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3]) - ((h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3]))/20
G[6] = k[6] + ((h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2]))/20 - (h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])^2*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])
return G
end
function fDG(t,y,h,k)
DG=zeros(6,6)
DG[1, 1] = 1 + h*a[1, 1]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[1, 2] = -(sin(t + h*c[1])*h*a[1, 1]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])) + h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[1, 3] = -(sin(t + h*c[1])*h*a[1, 1]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])) + h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])
DG[1, 4] = h*a[1, 2]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[1, 5] = -(sin(t + h*c[1])*h*a[1, 2]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])) + h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[1, 6] = -(sin(t + h*c[1])*h*a[1, 2]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])) + h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])
DG[2, 1] = -(h*a[1, 1]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3]))/20 + sin(t + h*c[1])*h*a[1, 1]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[2, 2] = 1
DG[2, 3] = -(sin(t + h*c[1])*h*a[1, 1]*(-(h*(a[1, 1]*k[1] + a[1, 2]*k[4])) - y[1])) - (h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1]))/20
DG[2, 4] = -(h*a[1, 2]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3]))/20 + sin(t + h*c[1])*h*a[1, 2]*(h*(a[1, 1]*k[3] + a[1, 2]*k[6]) + y[3])
DG[2, 5] = 0
DG[2, 6] = -(sin(t + h*c[1])*h*a[1, 2]*(-(h*(a[1, 1]*k[1] + a[1, 2]*k[4])) - y[1])) - (h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1]))/20
DG[3, 1] = (h*a[1, 1]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2]))/20 - 2*h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])
DG[3, 2] = (h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1]))/20 - h*a[1, 1]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])^2
DG[3, 3] = 1
DG[3, 4] = (h*a[1, 2]*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2]))/20 - 2*h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])*(h*(a[1, 1]*k[2] + a[1, 2]*k[5]) + y[2])
DG[3, 5] = (h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1]))/20 - h*a[1, 2]*(h*(a[1, 1]*k[1] + a[1, 2]*k[4]) + y[1])^2
DG[3, 6] = 0
DG[4, 1] = h*a[2, 1]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[4, 2] = -(sin(t + h*c[2])*h*a[2, 1]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])) + h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[4, 3] = -(sin(t + h*c[2])*h*a[2, 1]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])) + h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])
DG[4, 4] = 1 + h*a[2, 2]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[4, 5] = -(sin(t + h*c[2])*h*a[2, 2]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])) + h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[4, 6] = -(sin(t + h*c[2])*h*a[2, 2]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])) + h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])
DG[5, 1] = -(h*a[2, 1]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3]))/20 + sin(t + h*c[2])*h*a[2, 1]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[5, 2] = 0
DG[5, 3] = -(sin(t + h*c[2])*h*a[2, 1]*(-(h*(a[2, 1]*k[1] + a[2, 2]*k[4])) - y[1])) - (h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1]))/20
DG[5, 4] = -(h*a[2, 2]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3]))/20 + sin(t + h*c[2])*h*a[2, 2]*(h*(a[2, 1]*k[3] + a[2, 2]*k[6]) + y[3])
DG[5, 5] = 1
DG[5, 6] = -(sin(t + h*c[2])*h*a[2, 2]*(-(h*(a[2, 1]*k[1] + a[2, 2]*k[4])) - y[1])) - (h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1]))/20
DG[6, 1] = (h*a[2, 1]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2]))/20 - 2*h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])
DG[6, 2] = (h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1]))/20 - h*a[2, 1]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])^2
DG[6, 3] = 0
DG[6, 4] = (h*a[2, 2]*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2]))/20 - 2*h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])*(h*(a[2, 1]*k[2] + a[2, 2]*k[5]) + y[2])
DG[6, 5] = (h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1]))/20 - h*a[2, 2]*(h*(a[2, 1]*k[1] + a[2, 2]*k[4]) + y[1])^2
DG[6, 6] = 1
return DG
end
function irk(t,y,h)
k1=fF(t+h*c[1],rk2(t,y,h*c[1]))
k2=fF(t+h*c[2],rk2(t,y,h*c[2]))
Ki=[k1;k2]
lastone=false
for i=1:10
Gi=fG(t,y,h,Ki)
DGi=fDG(t,y,h,Ki)
DK=-DGi\Gi
Ki+=DK
if lastone
break
end
if norm(DK)<=norm(Ki)*10e-10
lastone=true
end
end
k1=Ki[1:3]
k2=Ki[4:6]
return y+h*(b[1]*k1+b[2]*k2)
end
function solve(t0,y0,h,n)
yn=copy(y0)
for j=1:n
tn=t0+(j-1)*h
yn=irk(tn,yn,h)
end
return yn
end
function main(args)
@printf("conjulia -- Energy Conserving IRK Scheme\n\n")
t0=0; T=100
y0=[1.0,1,1]
if length(args)==3
for j=1:3
y0[j]=parse(Float64,args[j])
end
end
println("y($t0)=$y0\n")
einit=y0'*y0
yold=zeros(3)
@printf("%5s %7s %14s %14s %14s %14s\n",
"p","n","h","E(100)","dE(100)","error")
yn=copy(y0)
n=64
for p=6:16
h=T/n
yn=solve(t0,y0,h,n)
if p>6
@printf("%5d %7d %14.7e %14.7e %14.7e %14.7e\n",
p,n,h,yn'*yn,yn'*yn-einit,norm(yold-yn))
end
flush(stdout)
yold=copy(yn)
n*=2
end
println("\ny($T)=$yn")
end
tsec=@elapsed main(ARGS)
println("\nTotal execution time ",tsec," seconds.")
and
/* congo.go -- Energy Conserving IRK Scheme */
package main
import ("fmt"; "os"; "time"; "math"; "strconv";
"unsafe"; . "gonum.org/v1/gonum/mat")
var (s3o6 float64; a [2][2]float64; b,c [2]float64)
func doinit(){
s3o6=math.Sqrt(3.)/6
a=[2][2]float64{{1./4, 1./4-s3o6}, {1./4+s3o6, 1./4}}
b=[2]float64{1./2,1./2}
c=[2]float64{1./2-s3o6,1./2+s3o6}
}
var tictime float64
func tic() {
now:=time.Now()
tictime=float64(now.Unix())+1.0E-9*float64(now.Nanosecond())
}
func toc() float64 {
now:=time.Now()
return float64(now.Unix())+1.0E-9*float64(now.Nanosecond())-tictime
}
func sin(t float64) float64 {
return math.Sin(t)
}
func prvec(yn *VecDense) {
y:=(*yn).RawVector().Data
fmt.Printf("[")
for j:=0;j<len(y);j++ {
fmt.Printf("%g%s",y[j],
func() string{if j<len(y)-1 { return ", "
} else { return "]" }}())
}
}
func fF(t float64,yv *VecDense) *VecDense {
var F [3]float64
y:=(*yv).RawVector().Data
F[0] = sin(t)*y[1]*y[2] - y[0]*y[1]*y[2]
F[1] = (y[0]*y[2])/20 - sin(t)*y[0]*y[2]
F[2] = -(y[0]*y[1])/20 + math.Pow(y[0],2)*y[1]
return NewVecDense(3,F[:])
}
func fG(t float64,yv *VecDense,h float64,kv *VecDense) *VecDense {
var G [6]float64
y:=(*yv).RawVector().Data
k:=(*kv).RawVector().Data
G[0] = k[0] - sin(t + h*c[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2]) + (h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
G[1] = k[1] - sin(t + h*c[0])*(-(h*(a[0][0]*k[0] + a[0][1]*k[3])) - y[0])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2]) - ((h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2]))/20
G[2] = k[2] + ((h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1]))/20 - math.Pow(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0],2)*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])
G[3] = k[3] - sin(t + h*c[1])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2]) + (h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
G[4] = k[4] - sin(t + h*c[1])*(-(h*(a[1][0]*k[0] + a[1][1]*k[3])) - y[0])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2]) - ((h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2]))/20
G[5] = k[5] + ((h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1]))/20 - math.Pow(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0],2)*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])
return NewVecDense(6,G[:])
}
func fDG(t float64,yv *VecDense,h float64,kv *VecDense) *Dense {
var DG [6][6]float64
y:=(*yv).RawVector().Data
k:=(*kv).RawVector().Data
DG[0][0] = 1 + h*a[0][0]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[0][1] = -(sin(t + h*c[0])*h*a[0][0]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])) + h*a[0][0]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[0][2] = -(sin(t + h*c[0])*h*a[0][0]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])) + h*a[0][0]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])
DG[0][3] = h*a[0][1]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[0][4] = -(sin(t + h*c[0])*h*a[0][1]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])) + h*a[0][1]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[0][5] = -(sin(t + h*c[0])*h*a[0][1]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])) + h*a[0][1]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])
DG[1][0] = -(h*a[0][0]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2]))/20 + sin(t + h*c[0])*h*a[0][0]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[1][1] = 1
DG[1][2] = -(sin(t + h*c[0])*h*a[0][0]*(-(h*(a[0][0]*k[0] + a[0][1]*k[3])) - y[0])) - (h*a[0][0]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0]))/20
DG[1][3] = -(h*a[0][1]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2]))/20 + sin(t + h*c[0])*h*a[0][1]*(h*(a[0][0]*k[2] + a[0][1]*k[5]) + y[2])
DG[1][4] = 0
DG[1][5] = -(sin(t + h*c[0])*h*a[0][1]*(-(h*(a[0][0]*k[0] + a[0][1]*k[3])) - y[0])) - (h*a[0][1]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0]))/20
DG[2][0] = (h*a[0][0]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1]))/20 - 2*h*a[0][0]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])
DG[2][1] = (h*a[0][0]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0]))/20 - h*a[0][0]*math.Pow(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0],2)
DG[2][2] = 1
DG[2][3] = (h*a[0][1]*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1]))/20 - 2*h*a[0][1]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0])*(h*(a[0][0]*k[1] + a[0][1]*k[4]) + y[1])
DG[2][4] = (h*a[0][1]*(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0]))/20 - h*a[0][1]*math.Pow(h*(a[0][0]*k[0] + a[0][1]*k[3]) + y[0],2)
DG[2][5] = 0
DG[3][0] = h*a[1][0]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[3][1] = -(sin(t + h*c[1])*h*a[1][0]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])) + h*a[1][0]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[3][2] = -(sin(t + h*c[1])*h*a[1][0]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])) + h*a[1][0]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])
DG[3][3] = 1 + h*a[1][1]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[3][4] = -(sin(t + h*c[1])*h*a[1][1]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])) + h*a[1][1]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[3][5] = -(sin(t + h*c[1])*h*a[1][1]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])) + h*a[1][1]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])
DG[4][0] = -(h*a[1][0]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2]))/20 + sin(t + h*c[1])*h*a[1][0]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[4][1] = 0
DG[4][2] = -(sin(t + h*c[1])*h*a[1][0]*(-(h*(a[1][0]*k[0] + a[1][1]*k[3])) - y[0])) - (h*a[1][0]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0]))/20
DG[4][3] = -(h*a[1][1]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2]))/20 + sin(t + h*c[1])*h*a[1][1]*(h*(a[1][0]*k[2] + a[1][1]*k[5]) + y[2])
DG[4][4] = 1
DG[4][5] = -(sin(t + h*c[1])*h*a[1][1]*(-(h*(a[1][0]*k[0] + a[1][1]*k[3])) - y[0])) - (h*a[1][1]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0]))/20
DG[5][0] = (h*a[1][0]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1]))/20 - 2*h*a[1][0]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])
DG[5][1] = (h*a[1][0]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0]))/20 - h*a[1][0]*math.Pow(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0],2)
DG[5][2] = 0
DG[5][3] = (h*a[1][1]*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1]))/20 - 2*h*a[1][1]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0])*(h*(a[1][0]*k[1] + a[1][1]*k[4]) + y[1])
DG[5][4] = (h*a[1][1]*(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0]))/20 - h*a[1][1]*math.Pow(h*(a[1][0]*k[0] + a[1][1]*k[3]) + y[0],2)
DG[5][5] = 1
return NewDense(6,6,(*[36]float64)(unsafe.Pointer(&DG[0][0]))[:])
}
func euler(t float64,y *VecDense,h float64) *VecDense {
var w VecDense
w.AddScaledVec(y,h,fF(t,y))
return &w
}
func rk2(t float64,y *VecDense,h float64) *VecDense {
k1:=fF(t,y)
var xi1,xi2 VecDense
xi1.AddScaledVec(y,h*2/3,k1)
k2:=fF(t,&xi1)
xi1.AddScaledVec(k1,3.0,k2)
xi2.AddScaledVec(y,h/4,&xi1)
return &xi2
}
func irk(t float64,y *VecDense,h float64) *VecDense {
k1:=fF(t+h*c[0],rk2(t,y,h*c[0]))
k2:=fF(t+h*c[1],rk2(t,y,h*c[1]))
Ki:=NewVecDense(6,nil)
copy((*Ki).RawVector().Data[0:3],(*k1).RawVector().Data)
copy((*Ki).RawVector().Data[3:6],(*k2).RawVector().Data)
lastone:=false
for i:=0;i<10;i++ {
Gi:=fG(t,y,h,Ki)
DGi:=fDG(t,y,h,Ki)
var DK VecDense
DK.SolveVec(DGi,Gi)
Ki.SubVec(Ki,&DK)
if lastone {
break
}
if Norm(&DK,2)<=Norm(Ki,2)*10e-10 {
lastone=true
}
}
copy((*k1).RawVector().Data,(*Ki).RawVector().Data[0:3])
copy((*k2).RawVector().Data,(*Ki).RawVector().Data[3:6])
var xi1,xi2 VecDense
xi1.AddScaledVec(k1,b[1]/b[0],k2)
xi2.AddScaledVec(y,h*b[0],&xi1)
return &xi2
}
func solve(t0 float64,y0 *VecDense,h float64,n int) *VecDense{
ycopy:=*y0; yn:=&ycopy
for j:=0;j<n;j++ {
tn:=t0+float64(j)*h
yn=irk(tn,yn,h)
}
return yn
}
func main() {
tic()
doinit()
fmt.Printf("congo -- Energy Conserving IRK Scheme\n\n")
t0:=0.0; T:=100.0
y0v:=[]float64{1,1,1}
if len(os.Args)==4 {
for j:=0;j<3;j++ {
y0v[j],_=strconv.ParseFloat(os.Args[j+1],64)
}
}
y0:=NewVecDense(3,y0v)
fmt.Printf("y(%g)=",0.0); prvec(y0); fmt.Printf("\n\n")
einit:=Dot(y0,y0)
yold:=NewVecDense(3,nil)
fmt.Printf("%5s %7s %14s %14s %14s %14s\n",
"p","n","h","E(100)","dE(100)","error")
var yn *VecDense
n:=64
for p:=6;p<=16;p++ {
h:=T/float64(n)
yn=solve(t0,y0,h,n)
var er VecDense
er.SubVec(yold,yn)
ner:=Norm(&er,2)
if p>6 {
fmt.Printf("%5d %7d %14.7e %14.7e %14.7e %14.7e\n",
p,n,h,Dot(yn,yn),Dot(yn,yn)-einit,ner)
}
*yold=*yn
n*=2
}
fmt.Printf("\ny(%g)=",T); prvec(yn); fmt.Printf("\n")
fmt.Printf("\nTotal execution time %g seconds.\n",toc())
os.Exit(0)
}
I had expected the run times to be similar or even that Julia would be faster than Go. However, Julia is eight times slower.
The above timings were made with 32-bit ARM and Julia 1.6.0. A similar performance differential appears on 64-bit ARM and 64-bit AMD architectures.
Does anyone know what’s going on?