Skip to content

Commit a679662

Browse files
committed
Fix the basis optimization file
1 parent 22bdc47 commit a679662

File tree

3 files changed

+77
-64
lines changed

3 files changed

+77
-64
lines changed

src/basis-forge.jl

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
###############################################################################
22
# basis_forge.jl #
3-
# --------- #
3+
# ------------------------------------------------------------------------ #
44
# Build custom Gaussian‑format basis sets via automatic least‑squares fits #
55
# to Slater targets. #
66
# #
@@ -9,63 +9,61 @@
99
###############################################################################
1010

1111
using LinearAlgebra
12-
using QuadGK # ∫₀^∞ … r² dr integrals
13-
using Optim # derivative‑free optimisation
12+
using QuadGK # ∫₀^∞ … r² dr integrals
13+
using Optim # derivative‑free optimisation
1414

1515
# ---------- numerical settings ----------------------------------------------
16-
const ATOL = 1e-12 # quadrature accuracy
16+
const ATOL = 1e-12 # quadrature accuracy
1717

1818
# ---------- Slater target ----------------------------------------------------
1919
χ_STO(r, ζ; n, l) = r^(n - 1) * exp(-ζ * r) * r^l
20-
2120
sto_norm(ζ; n, l) = sqrt((2ζ)^(2n + 2l + 1) / factorial(2n + 2l))
2221

2322
# ---------- primitive Gaussian ----------------------------------------------
2423
χ_G(r, α; l) = r^l * exp(-α * r^2)
25-
2624
radial_integral(f) = QuadGK.quadgk(r -> f(r) * r^2, 0.0, Inf; atol = ATOL)[1]
2725

2826
# ---------- build A, B, C matrices ------------------------------------------
2927
function build_matrices(alphas, ζ; n, l)
3028
k = length(alphas)
31-
Nsto = sto_norm(ζ; n, l)
32-
sto(r) = Nsto * χ_STO(r, ζ; n, l)
29+
Nsto = sto_norm(ζ; n = n, l = l)
30+
sto(r) = Nsto * χ_STO(r, ζ; n = n, l = l)
3331

34-
A = 1.0 # <STO|STO>
35-
B = [ radial_integral(r -> χ_G(r, α; l) * sto(r)) for α in alphas ]
36-
C = [ radial_integral(r -> χ_G(r, αi; l) * χ_G(r, αj; l))
37-
for αi in alphas, αj in alphas ]
32+
A = 1.0 # STO|STO
33+
B = [radial_integral(r -> χ_G(r, α; l) * sto(r)) for α in alphas]
34+
C = [radial_integral(r -> χ_G(r, αi; l) * χ_G(r, αj; l))
35+
for αi in alphas, αj in alphas]
3836
return A, B, Symmetric(reshape(C, k, k))
3937
end
4038

4139
# ---------- inner LSQ for coefficients + RMS --------------------------------
4240
function inner_fit(alphas, ζ; n, l)
43-
A, B, C = build_matrices(alphas, ζ; n, l)
41+
A, B, C = build_matrices(alphas, ζ; n = n, l = l)
4442
coeffs = C \ B
4543
coeffs ./= sqrt(dot(coeffs, C * coeffs)) # renormalise
46-
RMS² = A - 2dot(coeffs, B) + dot(coeffs, C * coeffs)
47-
return coeffs, sqrt(RMS²)
44+
rms² = A - 2dot(coeffs, B) + dot(coeffs, C * coeffs)
45+
return coeffs, sqrt(rms²)
4846
end
4947

5048
# ---------- outer optimisation of β, γ, ζ (even‑tempered αᵢ) ---------------
51-
function optimise_basis(k; n, l; β0 = 0.15, γ0 = 3.2, ζ0 = 1.0)
49+
function optimise_basis(k, n, l, β0 = 0.15, γ0 = 3.2, ζ0 = 1.0)
5250
obj(p) = begin
5351
β, γ, ζ = p
54-
αs =* γ^(i - 1) for i = 1:k]
55-
_, rms = inner_fit(αs, ζ; n, l)
52+
alphas =* γ^(i - 1) for i = 1:k]
53+
_, rms = inner_fit(alphas, ζ; n = n, l = l)
5654
rms
5755
end
5856

59-
p0 = [β0, γ0, ζ0]
60-
lower = [1e-4, 1.01, 0.1] # β>0, γ>1, ζ>0
61-
upper = [1e2, 10.0, 5.0]
57+
p0 = [β0, γ0, ζ0]
58+
lower = [1e-4, 1.01, 0.1] # β>0, γ>1, ζ>0
59+
upper = [1e2, 10.0, 5.0]
6260

63-
res = optimize(obj, lower, upper, p0,
64-
Fminbox{NelderMead}(); x_tol = 1e-10, f_tol = 1e-12)
61+
opts = Optim.Options(x_tol = 1e-10, f_tol = 1e-12)
62+
res = optimize(obj, lower, upper, p0, Fminbox(NelderMead()), opts)
6563

66-
β, γ, ζ = Optim.minimizer(res)
67-
αs =* γ^(i - 1) for i = 1:k]
68-
coeffs, rms = inner_fit(αs, ζ; n, l)
64+
β, γ, ζ = Optim.minimizer(res)
65+
alphas =* γ^(i - 1) for i = 1:k]
66+
coeffs, rms = inner_fit(alphas, ζ; n = n, l = l)
6967
return β, γ, ζ, coeffs, rms
7068
end
7169

@@ -76,7 +74,7 @@ function print_gaussian94(io, element, n, l, β, γ, coeffs)
7674
println(io, " $element $lchar $k")
7775
for (i, c) in enumerate(coeffs)
7876
α = β * γ^(i - 1)
79-
@printf(io, " %14.8f %14.8f\n", α, c)
77+
print(io, " $c\n")
8078
end
8179
end
8280

@@ -88,22 +86,22 @@ shell_table = Dict(
8886
"H" => [(1, 0, 3)], # 1s STO‑3G
8987
"C" => [(1, 0, 3), # 1s
9088
(2, 0, 3), # 2s
91-
(2, 1, 3), # 2p (shares β,γ with 2s manually)
92-
(0, 2, 1)] # 3d polarisation (single prim.)
89+
(2, 1, 3), # 2p (shares β,γ with 2s)
90+
(0, 2, 1)] # 3d polarisation
9391
)
9492

9593
open("my-basis.gbs", "w") do io
9694
for el in elements
9795
for (idx, (n, l, k)) in enumerate(shell_table[el])
9896
# share β, γ between 2s and 2p (SP trick) if consecutive in list
9997
if el == "C" && n == 2 && l == 1 && idx > 1
100-
β, γ, _, _, _ = optimise_basis(k; n = 2, l = 0)
101-
ζ = 1.0 # ζ irrelevant for pure Gaussian fit
98+
β, γ, _, _, _ = optimise_basis(k, 2, 0)
99+
ζ = 1.0 # ζ irrelevant for pure Gaussian fit
102100
coeffs, _ = inner_fit([β * γ^(i - 1) for i = 1:k],
103101
ζ; n = 2, l = 1)
104102
print_gaussian94(io, el, n, l, β, γ, coeffs)
105103
else
106-
β, γ, ζ, coeffs, _ = optimise_basis(k; n, l)
104+
β, γ, ζ, coeffs, _ = optimise_basis(k, n, l)
107105
print_gaussian94(io, el, n, l, β, γ, coeffs)
108106
end
109107
end

src/my-basis.gbs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
H s 3
2+
0.24965746218505253 0.4768772962297831
3+
0.9884344390703059 1.138167295631296
4+
3.913372473585632 0.9768881958678963
5+
C s 3
6+
0.24965746218505253 0.4768772962297831
7+
0.9884344390703059 1.138167295631296
8+
3.913372473585632 0.9768881958678963
9+
C s 3
10+
0.15 0.3508367526991321
11+
0.48 0.8230658425364937
12+
1.5360000000000003 -0.45283881485029753
13+
C p 3
14+
0.15 0.31802869255359717
15+
0.48 -0.3594329396282634
16+
1.5360000000000003 0.4658671835361496
17+
C d 1
18+
0.2536263833250992 0.23652096181090168

src/sto3g-test-2.jl

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,40 @@ import Optim: converged
1616
const atol = 1e-12 # absolute accuracy for quadgk
1717

1818
# ---------- STO target ------------------------------------------------------
19-
χ_STO(r, ζ; n=1, l=0) = r^(n-1) * exp(-ζ*r) * r^l # radial × angular factor
19+
χ_STO(r, ζ, n=1, l=0) = r^(n-1) * exp(-ζ*r) * r^l # radial × angular factor
2020

2121
# analytic normalisation N = √[(2ζ)^{2n+2l+1}/(2n+2l)!]
22-
function sto_norm; n, l)
22+
function sto_norm, n, l)
2323
return sqrt( (2ζ)^(2n+2l+1) / factorial(2n+2l) )
2424
end
2525

2626
# ---------- primitive Gaussian ---------------------------------------------
27-
χ_G(r, α; l=0) = r^l * exp(-α * r^2)
27+
χ_G(r, α, l=0) = r^l * exp(-α * r^2)
2828

2929
# ---------- helper: radial integral ----------------------------------------
3030
radial_integral(f) = QuadGK.quadgk(r -> f(r) * r^2, 0.0, Inf; atol)[1]
3131

3232
# ---------- build matrices for given αs and ζ ------------------------------
33-
function build_matrices(alphas, ζ; n=1, l=0)
33+
function build_matrices(alphas, ζ, n=1, l=0)
3434
k = length(alphas)
35-
Nsto = sto_norm; n, l)
36-
sto = r -> Nsto * χ_STO(r, ζ; n, l)
35+
Nsto = sto_norm, n, l)
36+
sto = r -> Nsto * χ_STO(r, ζ, n, l)
3737

3838
# A = <STO|STO> = 1 (normalised), but keep it explicit for completeness
3939
A = 1.0
4040

4141
# Bᵢ = <PGFᵢ|STO>
42-
B = [ radial_integral(r -> χ_G(r, α; l) * sto(r)) for α in alphas ]
42+
B = [ radial_integral(r -> χ_G(r, α, l) * sto(r)) for α in alphas ]
4343

4444
# Cᵢⱼ = <PGFᵢ|PGFⱼ>
45-
C = [ radial_integral(r -> χ_G(r, αi; l) * χ_G(r, αj; l))
45+
C = [ radial_integral(r -> χ_G(r, αi, l) * χ_G(r, αj, l))
4646
for αi in alphas, αj in alphas ]
4747
return A, B, Symmetric(reshape(C, k, k))
4848
end
4949

5050
# ---------- inner LSQ: coeffs + RMS ----------------------------------------
51-
function inner_fit(alphas, ζ; n=1, l=0)
52-
A, B, C = build_matrices(alphas, ζ; n, l)
51+
function inner_fit(alphas, ζ, n=1, l=0)
52+
A, B, C = build_matrices(alphas, ζ, n, l)
5353
coeffs = C \ B # normal equations
5454
coeffs ./= sqrt(dot(coeffs, C * coeffs)) # renormalise contracted AO
5555
RMS² = A - 2dot(coeffs,B) + dot(coeffs, C * coeffs)
@@ -62,10 +62,10 @@ end
6262
6363
`p = [β, γ, ζ]` → returns RMS radial error for k primitives.
6464
"""
65-
function rms_objective(p, k; n=1, l=0)
65+
function rms_objective(p, k, n=1, l=0)
6666
β, γ, ζ = p
6767
αs = [ β * γ^(i-1) for i = 1:k ]
68-
_, rms = inner_fit(αs, ζ; n, l)
68+
_, rms = inner_fit(αs, ζ, n, l)
6969
return rms
7070
end
7171

@@ -75,32 +75,29 @@ end
7575
7676
Returns (β★, γ★, ζ★, coeffs, RMS★).
7777
"""
78-
function optimise_basis(k; n=1, l=0, β0=0.15, γ0=3.2, ζ0=1.0)
79-
# initial parameter vector
80-
p0 = [β0, γ0, ζ0]
81-
82-
# parameter bounds (β>0, γ>1, ζ>0) – feel free to widen
83-
lower = [1e-4, 1.01, 0.1]
84-
upper = [1e2 , 10.0, 5.0]
85-
86-
obj(p) = rms_objective(p, k; n, l)
78+
function optimise_basis(k, n, l, β0 = 0.15, γ0 = 3.2, ζ0 = 1.0)
79+
obj(p) = begin
80+
β, γ, ζ = p
81+
αs =* γ^(i - 1) for i = 1:k]
82+
_, rms = inner_fit(αs, ζ, n, l)
83+
rms
84+
end
8785

88-
res = optimize(obj, lower, upper, p0,
89-
Fminbox{NelderMead}();
90-
x_tol = 1e-10, f_tol = 1e-12)
86+
p0 = [β0, γ0, ζ0]
87+
lower = [1e-4, 1.01, 0.1] # β>0, γ>1, ζ>0
88+
upper = [1e2, 10.0, 5.0]
9189

92-
if !converged(res)
93-
error("Optimisation failed!")
94-
end
90+
opts = Optim.Options(x_tol = 1e-10, f_tol = 1e-12)
91+
res = optimize(obj, lower, upper, p0, Fminbox(NelderMead()), opts)
9592

96-
β, γ, ζ = Optim.minimizer(res)
97-
αs = [ β★ * γ^(i-1) for i = 1:k ]
98-
coeffs, RMS★ = inner_fit(αs, ζ★; n, l)
99-
return β, γ, ζ, coeffs, RMS★, res
93+
β, γ, ζ = Optim.minimizer(res)
94+
αs = [β * γ^(i - 1) for i = 1:k]
95+
coeffs, rms = inner_fit(αs, ζ, n, l)
96+
return β, γ, ζ, coeffs, rms
10097
end
10198

10299
# ---------- example: H 1s STO‑3G (k=3, n=1, l=0) ---------------------------
103-
β, γ, ζ, c, rms, res = optimise_basis(3; n=1, l=0)
100+
β, γ, ζ, c, rms, res = optimise_basis(3, 1, 0)
104101

105102
println("=== STO‑3G automatic fit (H 1s) ===")
106103
println("β = ", round(β, 8))

0 commit comments

Comments
 (0)