You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
4.7 KiB
147 lines
4.7 KiB
# Created: 20150528
|
|
# Test module for stochastic fitting
|
|
|
|
import numpy
|
|
from wpylib.params import struct
|
|
from wpylib.math.fitting.stochastic import StochasticFitting
|
|
|
|
def setup_MC_TZ():
|
|
"""
|
|
Internal identifier: Cr2_TZ_data_20140728uhf
|
|
Binding energy of Cr2, phaseless QMC/UHF, cc-pwCVTZ-DK, dt=0.01
|
|
"""
|
|
global Cr2_TZ_data_20140728uhf
|
|
from numpy import asarray, matrix
|
|
Cr2_TZ_data_20140728uhf = asarray(matrix("""
|
|
1.550 -1.613 0.025 ;
|
|
1.600 -1.897 0.036 ;
|
|
1.6788 -2.141 0.016 ;
|
|
1.720 -2.143 0.025 ;
|
|
1.800 -2.190 0.022 ;
|
|
1.900 -2.064 0.020 ;
|
|
2.000 -2.038 0.023 ;
|
|
2.400 -1.611 0.019 ;
|
|
3.000 -1.037 0.018
|
|
"""))
|
|
|
|
|
|
|
|
def test_fit_PEC_MC_TZ(show_samples=True, save_fig=False, rng=None, num_iter=200):
|
|
"""20150528
|
|
PEC fitting, using `morse2` functional form.
|
|
|
|
Options:
|
|
- show_samples : prints the sample data (recommended)
|
|
- save_fig : dumps the fit result for each stochastic snapshot
|
|
(not recommended unless you are debugging/diagnosing)
|
|
|
|
Modeled after do_morse2_sfit routine in Cr2 analysis script.
|
|
|
|
Example output:
|
|
|
|
test_MC_TZ_PEC_fit::
|
|
ansatz=morse2_fit_func
|
|
Raw data: (x, y, dy)
|
|
1.550 -1.613 0.025
|
|
1.600 -1.897 0.036
|
|
1.679 -2.141 0.016
|
|
1.720 -2.143 0.025
|
|
1.800 -2.190 0.022
|
|
1.900 -2.064 0.020
|
|
2.000 -2.038 0.023
|
|
2.400 -1.611 0.019
|
|
3.000 -1.037 0.018
|
|
Using guess param from NLF: [-2.18625505 9.82497657 1.80455072 1.86192922]
|
|
Final parameters : -2.187(10) 9.85(61) 1.8044(66) 1.864(83)
|
|
Total execution time = 0.55 secs
|
|
All testings passed.
|
|
|
|
Where the input variables are:
|
|
x = bond length (angstrom)
|
|
y, dy = binding energy (eV)
|
|
and the final (output) parameters are (in the same order as above):
|
|
Ebind = binding energy minimum (eV)
|
|
k = spring constant (eV/angstrom**2)
|
|
r0 = equilibrium bond length (angstrom)
|
|
a = morse2 nonlinear constant (angstrom**-1)
|
|
|
|
The guess params from NLF above are the same as what gnuplot fitting
|
|
routine gives, which are:
|
|
|
|
Final set of parameters Asymptotic Standard Error
|
|
======================= ==========================
|
|
|
|
E0 = -2.18626 +/- 0.03193 (1.46%)
|
|
k = 9.82591 +/- 1.59 (16.19%)
|
|
re = 1.80454 +/- 0.01763 (0.9771%)
|
|
a = 1.86206 +/- 0.2172 (11.66%)
|
|
|
|
Nonlinear-fitting.pl (perl script) gives the stochastic fit result:
|
|
|
|
-2.183(11) 9.97(65) 1.8046(69) 1.886(90)
|
|
|
|
Excellent agreement!
|
|
|
|
"""
|
|
from numpy import array
|
|
from wpylib.text_tools import matrix_str, str_indent
|
|
from wpylib.timer import block_timer as Timer
|
|
from wpylib.math.fitting.funcs_pec import morse2_fit_func
|
|
from wpylib.py import function_name
|
|
|
|
global MC_TZ_PEC_fit
|
|
global Cr2_TZ_data_20140728uhf
|
|
|
|
print("test_MC_TZ_PEC_fit::")
|
|
setup_MC_TZ()
|
|
|
|
# parameters etc
|
|
ansatz = morse2_fit_func()
|
|
if rng is None:
|
|
rng = dict(seed=378711, rng_class=numpy.random.RandomState)
|
|
rawdata = Cr2_TZ_data_20140728uhf
|
|
sfit = MC_TZ_PEC_fit = StochasticFitting()
|
|
|
|
print("ansatz=%s" \
|
|
% (function_name(ansatz),))
|
|
|
|
# This corresponds to fit_variant==1 in the subroutine
|
|
ansatz.fit_method = "leastsq"
|
|
ansatz.fit_opts['leastsq'] = dict(xtol=1e-8, epsfcn=1e-6)
|
|
|
|
sfit.init_func(ansatz)
|
|
sfit.init_samples(x=rawdata[:,0], y=rawdata[:,1], dy=rawdata[:,2])
|
|
sfit.init_rng(**rng)
|
|
if show_samples:
|
|
print("Raw data: (x, y, dy)")
|
|
print(str_indent(matrix_str(rawdata, fmt="%8.3f")))
|
|
|
|
with Timer() as tmr:
|
|
sfit.mcfit_loop_begin_()
|
|
sfit.mcfit_loop1_(num_iter=num_iter, save_fig=save_fig)
|
|
sfit.mcfit_loop_end_()
|
|
sfit.mcfit_analysis_()
|
|
sfit.mcfit_report_final_params()
|
|
|
|
nlf_fit_result = sfit.nlf_rec['xopt']
|
|
|
|
# Verify the results:
|
|
# * deterministic fit (only precise to these digits; more digits are discarded)
|
|
nlf_fit_ref = numpy.array([-2.18625505, 9.82497657, 1.80455072, 1.86192922])
|
|
|
|
assert numpy.allclose(nlf_fit_result, nlf_fit_ref, atol=0.6e-8, rtol=0)
|
|
|
|
def match_mc_param(name, val_ref, err_ref, atol):
|
|
vv = sfit.final_mc_params[name]
|
|
assert numpy.allclose(vv.value(), val_ref, atol=atol, rtol=0)
|
|
assert numpy.allclose(vv.error(), err_ref, atol=atol, rtol=0)
|
|
|
|
match_mc_param('E0', -2.187, 0.010, 0.6e-3)
|
|
match_mc_param('k', 9.85, 0.61, 0.6e-2)
|
|
match_mc_param('r0', 1.8044, 0.0066, 0.6e-4)
|
|
match_mc_param('a', 1.864, 0.083, 0.6e-3)
|
|
print("All testings passed.")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
test_fit_PEC_MC_TZ()
|
|
|