Parameter Optimization
Selectively optimizing parameters
In the Basis Sets section, we have briefly introduced ParamBox
as the parameters embedded in containers such as BasisFunc
and BasisFuncs
. This means how we construct the basis set using the parameters will determine the parameter space for the basis set optimization. (For more information please refer to Constructing basis sets based on ParamBox.) Sometimes, we can select parameters for optimization to achieve higher efficiency.
Here is an example of using GaussFunc
and GridBox
to quickly generate a grid-based basis set with only 3 independent parameters. One is the spacing $L$ of the grid points that determines all the center coordinates of the basis functions; the other two are the exponent coefficient $\alpha$ and the contraction coefficient $d$.
julia> nuc = ["H", "H"];
julia> nucCoords = [[-0.7,0.0,0.0], [0.7,0.0,0.0]];
julia> grid = GridBox(1, 3.0)
GridBox{Float64, 3, 8, โฆ}(spacing, nPoint, point, param)
julia> gf1 = GaussFunc(0.7, 1.0);
julia> bs = genBasisFunc.(grid.point, Ref(gf1)) |> collect;
After building the basis set, we need to use markParams!
to mark all the unique parameters that can also be optimized later:
julia> pars = markParams!(bs, true)
3-element Vector{ParamBox{Float64}}: ParamBox{Float64, :X, โฆ}{2}[๐][Lโ]โฆโโง[-1.5] ParamBox{Float64, :ฮฑ, โฆ}{0}[โ][ฮฑโ]โฆ=โง[0.7] ParamBox{Float64, :d, โฆ}{0}[โ][dโ]โฆ=โง[1.0]
When markParams!
's second argument is set to true
, it will return only the ParamBox
es that have unique independent variables. Thus, the length of pars
is 3 for the aforementioned three independent parameters, despite the basis set having eight basis functions with a total of 40 parameters. However, if we take a step further, we can remove the ParamBox
representing $d$ since each basis function here is just one same Gaussian function. Thus, input the rest parameters (along with other necessary arguments) into optimizeParams!
and we will have a more efficient optimization iteration:
julia> parsPartial = pars[1:2];
julia> isConverged, Es = optimizeParams!(parsPartial, bs, nuc, nucCoords, POconfig(maxStep=10));
Step 0: ๐ = 0.33268816 โฅvec(โ๐)โฅโ = 4.24093968 Step duration: 24.959378 seconds. Step 1: ๐ = -0.12730324 โฅvec(โ๐)โฅโ = 3.96879286 Step duration: 0.769129 second. Step 2: ๐ = -0.85913818 โฅvec(โ๐)โฅโ = 2.86813146 Step duration: 8.636303 seconds. Step 4: ๐ = -1.61878993 โฅvec(โ๐)โฅโ = 0.62882932 Step duration: 1.099411 seconds. Step 6: ๐ = -1.65687612 โฅvec(โ๐)โฅโ = 0.06863309 Step duration: 1.097882 seconds. The optimization of parameters ๐ := [:Lโ, :ฮฑโ] with respect to ๐(๐) from the profile :HFenergy just ended at Step 10: ๐ = -1.6625356874 ๐ = [1.0085804, 0.4097516] after 49.451672 seconds. The iteration has not converged: โฅฮ๐โฅโ โ 0.00085395, โฅvec(โ๐)โฅโ โ 0.03748260.
After the optimization, you can check the original bs
and find that the inside parameters are changed as well. This is because the !
in the function name indicates that optimizeParams!
is a function that modifies its arguments.
julia> getParams(bs)
40-element Vector{ParamBox{Float64}}: ParamBox{Float64, :X, โฆ}{2}[๐][Lโ]โฆโโง[-0.5042902069] ParamBox{Float64, :Y, โฆ}{2}[๐][Lโ]โฆโโง[-0.5042902069] ParamBox{Float64, :Z, โฆ}{2}[๐][Lโ]โฆโโง[-0.5042902069] ParamBox{Float64, :ฮฑ, โฆ}{0}[โ][ฮฑโ]โฆ=โง[0.4097516014] ParamBox{Float64, :d, โฆ}{0}[โ][dโ]โฆ=โง[1.0] ParamBox{Float64, :X, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :Y, โฆ}{2}[๐][Lโ]โฆโโง[-0.5042902069] ParamBox{Float64, :Z, โฆ}{2}[๐][Lโ]โฆโโง[-0.5042902069] ParamBox{Float64, :ฮฑ, โฆ}{0}[โ][ฮฑโ]โฆ=โง[0.4097516014] ParamBox{Float64, :d, โฆ}{0}[โ][dโ]โฆ=โง[1.0] โฎ ParamBox{Float64, :Y, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :Z, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :ฮฑ, โฆ}{0}[โ][ฮฑโ]โฆ=โง[0.4097516014] ParamBox{Float64, :d, โฆ}{0}[โ][dโ]โฆ=โง[1.0] ParamBox{Float64, :X, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :Y, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :Z, โฆ}{2}[๐][Lโ]โฆโโง[0.5042902069] ParamBox{Float64, :ฮฑ, โฆ}{0}[โ][ฮฑโ]โฆ=โง[0.4097516014] ParamBox{Float64, :d, โฆ}{0}[โ][dโ]โฆ=โง[1.0]
If you want to go through the above example by yourself, you can find the script here.