Johannes Hörmann, 2020
Impose steric radii on a sample point distribution by minizing pseudo-potential. Pseudo-ptential follows formalism described in
L. Martinez, R. Andrade, E. G. Birgin, and J. M. Martínez, “PACKMOL: A package for building initial configurations for molecular dynamics simulations,” J. Comput. Chem., vol. 30, no. 13, pp. 2157–2164, 2009, doi: 10/chm6f7.
# for dynamic module reload during testing, code modifications take immediate effect
%load_ext autoreload
%autoreload 2
# stretching notebook width across whole window
from IPython.core.display import display, HTML
display(HTML("<style>.container { width:100% !important; }</style>"))
# basics & utilities
import itertools # dealing with combinations and permutations
import logging # easy and neat handlin of log outpu
import matplotlib.pyplot as plt # plotting
import numpy as np # basic numerics, in particular lin. alg.
import pandas as pd # display stats neatly
import scipy.constants as sc # fundamental constants
import scipy.spatial.distance # quick methods for computing pairwise distances
import time # timing performance
import timeit # same purpose
# electrochemistry basics
from matscipy.electrochemistry import debye, ionic_strength
# Poisson-Bolzmann distribution
from matscipy.electrochemistry.poisson_boltzmann_distribution import gamma, potential, concentration, charge_density
# sampling
from scipy import interpolate
from matscipy.electrochemistry import continuous2discrete
from matscipy.electrochemistry import get_histogram
from matscipy.electrochemistry.utility import plot_dist
# steric correction
# target functions
from matscipy.electrochemistry.steric_correction import scipy_distance_based_target_function
from matscipy.electrochemistry.steric_correction import numpy_only_target_function
from matscipy.electrochemistry.steric_correction import brute_force_target_function
# closest pair functions
from matscipy.electrochemistry.steric_correction import brute_force_closest_pair
from matscipy.electrochemistry.steric_correction import planar_closest_pair
from matscipy.electrochemistry.steric_correction import scipy_distance_based_closest_pair
from matscipy.electrochemistry.steric_correction import apply_steric_correction
# 3rd party file output
import ase
import ase.io
# matscipy.electrochemistry makes extensive use of Python's logging module
# configure logging: verbosity level and format as desired
standard_loglevel = logging.INFO
# standard_logformat = ''.join(("%(asctime)s",
# "[ %(filename)s:%(lineno)s - %(funcName)s() ]: %(message)s"))
standard_logformat = "[ %(filename)s:%(lineno)s - %(funcName)s() ]: %(message)s"
# reset logger if previously loaded
logging.shutdown()
logging.basicConfig(level=standard_loglevel,
format=standard_logformat,
datefmt='%m-%d %H:%M')
# in Jupyter notebooks, explicitly modifying the root logger necessary
logger = logging.getLogger()
logger.setLevel(standard_loglevel)
# remove all handlers
for h in logger.handlers: logger.removeHandler(h)
# create and append custom handles
ch = logging.StreamHandler()
formatter = logging.Formatter(standard_logformat)
ch.setFormatter(formatter)
ch.setLevel(standard_loglevel)
logger.addHandler(ch)
# Test 1
logging.info("Root logger")
[ <ipython-input-10-adec08aea02d>:2 - <module>() ]: Root logger
# Test 2
logger.info("Root Logger")
[ <ipython-input-11-4335e316391c>:2 - <module>() ]: Root Logger
# Debug Test
logging.debug("Root logger")
See other sample case notebboks for details
# measures of box
xsize = ysize = 5e-9 # nm, SI units
zsize = 20e-9 # nm, SI units
# get continuum distribution, z direction
x = np.linspace(0, zsize, 2000)
c = [1,1]
z = [1,-1]
u = 0.05
phi = potential(x, c, z, u)
C = concentration(x, c, z, u)
rho = charge_density(x, c, z, u)
# potential and concentration distributions analytic solution
# based on Poisson-Boltzmann equation for 0.1 mM NaCl aqueous solution
# at interface
def make_patch_spines_invisible(ax):
ax.set_frame_on(True)
ax.patch.set_visible(False)
for sp in ax.spines.values():
sp.set_visible(False)
deb = debye(c, z)
fig, ax1 = plt.subplots(figsize=[18,5])
ax1.set_xlabel('x (nm)')
ax1.plot(x/sc.nano, phi, marker='', color='red', label='Potential', linewidth=1, linestyle='--')
ax1.set_ylabel('potential (V)')
ax1.axvline(x=deb/sc.nano, label='Debye Length', color='orange')
ax2 = ax1.twinx()
ax2.plot(x/sc.nano, np.ones(x.shape)*c[0], label='Bulk concentration of Na+ ions', color='grey', linewidth=1, linestyle=':')
ax2.plot(x/sc.nano, C[0], marker='', color='green', label='Na+ ions')
ax2.plot(x/sc.nano, C[1], marker='', color='blue', label='Cl- ions')
ax2.set_ylabel('concentration (mM)')
ax3 = ax1.twinx()
# Offset the right spine of par2. The ticks and label have already been
# placed on the right by twinx above.
ax3.spines["right"].set_position(("axes", 1.1))
# Having been created by twinx, par2 has its frame off, so the line of its
# detached spine is invisible. First, activate the frame but make the patch
# and spines invisible.
make_patch_spines_invisible(ax3)
# Second, show the right spine.
ax3.spines["right"].set_visible(True)
ax3.plot(x/sc.nano, rho, label='Charge density', color='grey', linewidth=1, linestyle='--')
ax3.set_ylabel(r'charge density $\rho \> (\mathrm{C}\> \mathrm{m}^{-3})$')
#fig.legend(loc='center')
ax2.legend(loc='upper right', bbox_to_anchor=(-0.1, 1.02),fontsize=15)
ax1.legend(loc='center right', bbox_to_anchor=(-0.1,0.5), fontsize=15)
ax3.legend(loc='lower right', bbox_to_anchor=(-0.1, -0.02), fontsize=15)
fig.tight_layout()
plt.show()
# create distribution functions
distributions = [interpolate.interp1d(x,c) for c in C]
# sample discrete coordinate set
box3 = np.array([xsize, ysize, zsize])
sample_size = 200
samples = [ continuous2discrete(distribution=d, box=box3, count=sample_size) for d in distributions ]
species = ['Na+','Cl-']
for ion,sample,d in zip(species,samples,distributions):
histx, histy, histz = get_histogram(sample, box=box3, n_bins=51)
plot_dist(histx, 'Distribution of {:s} ions in x-direction'.format(ion),
reference_distribution=lambda x: np.ones(x.shape)*1/box3[0])
plot_dist(histy, 'Distribution of {:s} ions in y-direction'.format(ion),
reference_distribution=lambda x: np.ones(x.shape)*1/box3[1])
plot_dist(histz, 'Distribution of {:s} ions in z-direction'.format(ion),
reference_distribution=d)
[ continuous2discrete.py:255 - generate_structure() ]: Using uniform distribution along x and y direction. [ continuous2discrete.py:256 - generate_structure() ]: Using distribution <scipy.interpolate.interpolate.interp1d object at 0x7fae6023d5e0> along z direction. [ continuous2discrete.py:270 - generate_structure() ]: Using [nan nan nan] grid as sampling support. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <function uniform at 0x7fae61a9e0d0> by 2.5e-09. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <function uniform at 0x7fae61a9e0d0> by 2.5e-09. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <scipy.interpolate.interpolate.interp1d object at 0x7fae6023d5e0> by 1.0069226134031856e-08. [ continuous2discrete.py:298 - generate_structure() ]: Drew (200, 3) samples from distributions. [ continuous2discrete.py:255 - generate_structure() ]: Using uniform distribution along x and y direction. [ continuous2discrete.py:256 - generate_structure() ]: Using distribution <scipy.interpolate.interpolate.interp1d object at 0x7fae6023d630> along z direction. [ continuous2discrete.py:270 - generate_structure() ]: Using [nan nan nan] grid as sampling support. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <function uniform at 0x7fae61a9e0d0> by 2.5e-09. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <function uniform at 0x7fae61a9e0d0> by 2.5e-09. [ continuous2discrete.py:289 - generate_structure() ]: Normalizing 'distribution' <scipy.interpolate.interpolate.interp1d object at 0x7fae6023d630> by 4.9443105910395656e-08. [ continuous2discrete.py:298 - generate_structure() ]: Drew (200, 3) samples from distributions.
Initial state of system:
# need all coordinates in one N x 3 array
xstacked = np.vstack(samples)
box6 = np.array([[0.,0.,0],box3]) # needs lower corner
n = xstacked.shape[0]
dim = xstacked.shape[1]
# benchmakr methods
mindsq, (p1,p2) = scipy_distance_based_closest_pair(xstacked)
pmin = np.min(xstacked,axis=0)
pmax = np.max(xstacked,axis=0)
mind = np.sqrt(mindsq)
logger.info("Minimum pair-wise distance in sample: {}".format(mind))
logger.info("First sample point in pair: ({:8.4e},{:8.4e},{:8.4e})".format(*p1))
logger.info("Second sample point in pair ({:8.4e},{:8.4e},{:8.4e})".format(*p2))
logger.info("Box lower boundary: ({:8.4e},{:8.4e},{:8.4e})".format(*box6[0]))
logger.info("Minimum coordinates in sample: ({:8.4e},{:8.4e},{:8.4e})".format(*pmin))
logger.info("Maximum coordinates in sample: ({:8.4e},{:8.4e},{:8.4e})".format(*pmax))
logger.info("Box upper boundary: ({:8.4e},{:8.4e},{:8.4e})".format(*box6[1]))
[ <ipython-input-17-ec5679b8f5f1>:14 - <module>() ]: Minimum pair-wise distance in sample: 1.352188695855715e-10 [ <ipython-input-17-ec5679b8f5f1>:15 - <module>() ]: First sample point in pair: (4.4566e-09,3.7113e-09,1.3501e-08) [ <ipython-input-17-ec5679b8f5f1>:16 - <module>() ]: Second sample point in pair (4.3269e-09,3.6958e-09,1.3537e-08) [ <ipython-input-17-ec5679b8f5f1>:17 - <module>() ]: Box lower boundary: (0.0000e+00,0.0000e+00,0.0000e+00) [ <ipython-input-17-ec5679b8f5f1>:18 - <module>() ]: Minimum coordinates in sample: (2.3292e-12,6.1885e-13,2.2696e-11) [ <ipython-input-17-ec5679b8f5f1>:19 - <module>() ]: Maximum coordinates in sample: (4.9992e-09,4.9942e-09,1.9953e-08) [ <ipython-input-17-ec5679b8f5f1>:20 - <module>() ]: Box upper boundary: (5.0000e-09,5.0000e-09,2.0000e-08)
# apply penalty for steric overlap
# stats: method, x, res, dt, mind, p1, p2 , pmin, pmax
stats = [('initial',xstacked,None,0,mind,p1,p2,pmin,pmax)]
r = 2e-10 # 4 Angstrom steric radius
logger.info("Steric radius: {:8.4e}".format(r))
# see https://scipy-lectures.org/advanced/mathematical_optimization/index.html
methods = [
#'Nelder-Mead', # not suitable
'Powell',
'CG',
'BFGS',
#'Newton-CG', # needs explicit Jacobian
'L-BFGS-B'
]
for m in methods:
try:
logger.info("### {} ###".format(m))
t0 = time.perf_counter()
x1, res = apply_steric_correction(xstacked,box=box6,r=r,method=m)
t1 = time.perf_counter()
dt = t1 - t0
logger.info("{} s runtime".format(dt))
mindsq, (p1,p2) = scipy_distance_based_closest_pair(x1)
mind = np.sqrt(mindsq)
pmin = np.min(x1,axis=0)
pmax = np.max(x1,axis=0)
stats.append([m,x1,res,dt,mind,p1,p2,pmin,pmax])
logger.info("{:s} finished with".format(m))
logger.info(" status = {}, success = {}, #it = {}".format(
res.status, res.success, res.nit))
logger.info(" message = '{}'".format(res.message))
logger.info("Minimum pair-wise distance in final configuration: {:8.4e}".format(mind))
logger.info("First sample point in pair: ({:8.4e},{:8.4e},{:8.4e})".format(*p1))
logger.info("Second sample point in pair ({:8.4e},{:8.4e},{:8.4e})".format(*p2))
logger.info("Box lower boundary: ({:8.4e},{:8.4e},{:8.4e})".format(*box6[0]))
logger.info("Minimum coordinates in sample: ({:8.4e},{:8.4e},{:8.4e})".format(*pmin))
logger.info("Maximum coordinates in sample: ({:8.4e},{:8.4e},{:8.4e})".format(*pmax))
logger.info("Box upper boundary: ({:8.4e},{:8.4e},{:8.4e})".format(*box6[1]))
except:
logger.warning("{} failed.".format(m))
continue
stats_df = pd.DataFrame( [ {
'method': s[0],
'runtime': s[3],
'mind': s[4],
**{'p1{:d}'.format(i): c for i,c in enumerate(s[5]) },
**{'p2{:d}'.format(i): c for i,c in enumerate(s[6]) },
**{'pmin{:d}'.format(i): c for i,c in enumerate(s[7]) },
**{'pmax{:d}'.format(i): c for i,c in enumerate(s[8]) }
} for s in stats] )
print(stats_df.to_string(float_format='%8.6g'))
[ <ipython-input-18-3d6fcc74b808>:7 - <module>() ]: Steric radius: 2.0000e-10 [ <ipython-input-18-3d6fcc74b808>:21 - <module>() ]: ### Powell ### [ steric_correction.py:919 - apply_steric_correction() ]: Normalizing coordinates by reference length [ steric_correction.py:920 - apply_steric_correction() ]: L = V^(1/dim) = (5e-25)^(1/3) = 7.9e-09. [ steric_correction.py:929 - apply_steric_correction() ]: Normalized bounding box: [ steric_correction.py:930 - apply_steric_correction() ]: [0. 0. 0.]. [ steric_correction.py:931 - apply_steric_correction() ]: [0.62996052 0.62996052 2.5198421 ]. [ steric_correction.py:949 - apply_steric_correction() ]: Initial constraint penalty: 1.58368e-02. [ steric_correction.py:950 - apply_steric_correction() ]: Initial total penalty: 1.58786e-02. [ steric_correction.py:951 - apply_steric_correction() ]: Initial constraint gradient norm: 2.51689e-01. [ steric_correction.py:953 - apply_steric_correction() ]: Initial total gradient norm: 2.51661e-01. [ steric_correction.py:975 - apply_steric_correction() ]: Min. dist. 1.35219e-10 between points [ steric_correction.py:976 - apply_steric_correction() ]: [4.45656762e-09 3.71127189e-09 1.35014030e-08] and [ steric_correction.py:977 - apply_steric_correction() ]: [4.32692023e-09 3.69576885e-09 1.35365506e-08]. [ steric_correction.py:978 - apply_steric_correction() ]: Min. dist. 1.70365e-02 between dimensionless points [ steric_correction.py:979 - apply_steric_correction() ]: [0.56149234 0.46759096 1.70107019] and [ steric_correction.py:980 - apply_steric_correction() ]: [0.54515779 0.4656377 1.7054985 ]. [ steric_correction.py:981 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:995 - minimizer_callback() ]: #callback objective gradient min. dist. timing, step timing, tot. [ steric_correction.py:1021 - minimizer_callback() ]: 0 1.58786e-02 2.51661e-01 1.70365e-02 1.18181e-02 1.18181e-02 /home/jotelha/venv/jlh-imtek-nb-python-3.8/lib/python3.8/site-packages/scipy/optimize/_minimize.py:517: RuntimeWarning: Method Powell does not use gradient information (jac). warn('Method %s does not use gradient information (jac).' % method, /home/jotelha/venv/jlh-imtek-nb-python-3.8/lib/python3.8/site-packages/matscipy/electrochemistry/steric_correction.py:1043: OptimizeWarning: Unknown solver options: gtol, eps res = scipy.optimize.minimize(f, x0, method=method, jac=returns_gradient, [ steric_correction.py:1021 - minimizer_callback() ]: 1 1.96849e-08 3.67253e-05 4.91631e-02 1.61874e+02 1.61886e+02 [ steric_correction.py:1021 - minimizer_callback() ]: 2 0.00000e+00 0.00000e+00 5.08633e-02 1.58259e+02 3.20144e+02 [ steric_correction.py:1021 - minimizer_callback() ]: 3 0.00000e+00 0.00000e+00 5.07263e-02 1.70046e+02 4.90191e+02 [ steric_correction.py:1055 - apply_steric_correction() ]: Final constraint penalty: 0.00000e+00. [ steric_correction.py:1056 - apply_steric_correction() ]: Final total penalty: 0.00000e+00. [ steric_correction.py:1057 - apply_steric_correction() ]: Final constraint gradient norm: 0.00000e+00. [ steric_correction.py:1059 - apply_steric_correction() ]: Final total gradient norm: 0.00000e+00. [ steric_correction.py:1074 - apply_steric_correction() ]: Min. dist. 4.02615e-10 between points [ steric_correction.py:1075 - apply_steric_correction() ]: [3.02768041e-09 2.83840652e-09 1.32511960e-08] and [ steric_correction.py:1076 - apply_steric_correction() ]: [3.19153258e-09 2.63912468e-09 1.35602878e-08]. [ steric_correction.py:1077 - apply_steric_correction() ]: Min. dist. 5.07263e-02 between dimensionless points [ steric_correction.py:1078 - apply_steric_correction() ]: [0.38146383 0.35761681 1.66954608] and [ steric_correction.py:1079 - apply_steric_correction() ]: [0.40210791 0.33250887 1.70848921]. [ steric_correction.py:1080 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:1083 - apply_steric_correction() ]: Ellapsed time: 490.24 s. [ <ipython-input-18-3d6fcc74b808>:26 - <module>() ]: 490.3026952969958 s runtime [ <ipython-input-18-3d6fcc74b808>:35 - <module>() ]: Powell finished with [ <ipython-input-18-3d6fcc74b808>:36 - <module>() ]: status = 0, success = True, #it = 3 [ <ipython-input-18-3d6fcc74b808>:38 - <module>() ]: message = 'Optimization terminated successfully.' [ <ipython-input-18-3d6fcc74b808>:39 - <module>() ]: Minimum pair-wise distance in final configuration: 4.0261e-10 [ <ipython-input-18-3d6fcc74b808>:40 - <module>() ]: First sample point in pair: (3.0277e-09,2.8384e-09,1.3251e-08) [ <ipython-input-18-3d6fcc74b808>:41 - <module>() ]: Second sample point in pair (3.1915e-09,2.6391e-09,1.3560e-08) [ <ipython-input-18-3d6fcc74b808>:42 - <module>() ]: Box lower boundary: (0.0000e+00,0.0000e+00,0.0000e+00) [ <ipython-input-18-3d6fcc74b808>:43 - <module>() ]: Minimum coordinates in sample: (2.1189e-10,2.0707e-10,2.7756e-10) [ <ipython-input-18-3d6fcc74b808>:44 - <module>() ]: Maximum coordinates in sample: (4.7925e-09,4.7823e-09,1.9795e-08) [ <ipython-input-18-3d6fcc74b808>:45 - <module>() ]: Box upper boundary: (5.0000e-09,5.0000e-09,2.0000e-08) [ <ipython-input-18-3d6fcc74b808>:21 - <module>() ]: ### CG ### [ steric_correction.py:919 - apply_steric_correction() ]: Normalizing coordinates by reference length [ steric_correction.py:920 - apply_steric_correction() ]: L = V^(1/dim) = (5e-25)^(1/3) = 7.9e-09. [ steric_correction.py:929 - apply_steric_correction() ]: Normalized bounding box: [ steric_correction.py:930 - apply_steric_correction() ]: [0. 0. 0.]. [ steric_correction.py:931 - apply_steric_correction() ]: [0.62996052 0.62996052 2.5198421 ]. [ steric_correction.py:949 - apply_steric_correction() ]: Initial constraint penalty: 1.58368e-02. [ steric_correction.py:950 - apply_steric_correction() ]: Initial total penalty: 1.58786e-02. [ steric_correction.py:951 - apply_steric_correction() ]: Initial constraint gradient norm: 2.51689e-01. [ steric_correction.py:953 - apply_steric_correction() ]: Initial total gradient norm: 2.51661e-01. [ steric_correction.py:975 - apply_steric_correction() ]: Min. dist. 1.35219e-10 between points [ steric_correction.py:976 - apply_steric_correction() ]: [4.45656762e-09 3.71127189e-09 1.35014030e-08] and [ steric_correction.py:977 - apply_steric_correction() ]: [4.32692023e-09 3.69576885e-09 1.35365506e-08]. [ steric_correction.py:978 - apply_steric_correction() ]: Min. dist. 1.70365e-02 between dimensionless points [ steric_correction.py:979 - apply_steric_correction() ]: [0.56149234 0.46759096 1.70107019] and [ steric_correction.py:980 - apply_steric_correction() ]: [0.54515779 0.4656377 1.7054985 ]. [ steric_correction.py:981 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:995 - minimizer_callback() ]: #callback objective gradient min. dist. timing, step timing, tot. [ steric_correction.py:1021 - minimizer_callback() ]: 0 1.58786e-02 2.51661e-01 1.70365e-02 8.65453e-03 8.65453e-03 [ steric_correction.py:1021 - minimizer_callback() ]: 1 5.00628e-05 1.16337e-03 1.71522e-02 2.96741e-02 3.83286e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 2 1.61999e-05 1.30000e-03 2.14091e-02 2.64680e-02 6.47966e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 3 1.21675e-05 5.93159e-04 2.37839e-02 1.66900e-02 8.14866e-02
Optimization terminated successfully. Current function value: 0.000000 Iterations: 3 Function evaluations: 98856
[ steric_correction.py:1021 - minimizer_callback() ]: 4 2.77699e-06 1.59968e-03 3.76265e-02 2.56513e-02 1.07138e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 5 1.60599e-06 2.93886e-04 3.90021e-02 1.10337e-02 1.18172e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 6 5.11949e-08 6.18666e-05 4.82025e-02 1.67713e-02 1.34943e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 7 5.11796e-09 2.01067e-05 4.96827e-02 1.45872e-02 1.49530e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 8 1.40375e-10 3.36985e-06 5.02793e-02 1.47176e-02 1.64248e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 9 3.14756e-12 5.05608e-07 5.03793e-02 1.42127e-02 1.78460e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 10 6.80908e-14 7.43876e-08 5.03943e-02 1.32808e-02 1.91741e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 11 1.46502e-15 1.09118e-08 5.03965e-02 2.16273e-02 2.13369e-01 [ steric_correction.py:1055 - apply_steric_correction() ]: Final constraint penalty: 0.00000e+00. [ steric_correction.py:1056 - apply_steric_correction() ]: Final total penalty: 1.46502e-15. [ steric_correction.py:1057 - apply_steric_correction() ]: Final constraint gradient norm: 0.00000e+00. [ steric_correction.py:1059 - apply_steric_correction() ]: Final total gradient norm: 1.09118e-08. [ steric_correction.py:1074 - apply_steric_correction() ]: Min. dist. 3.99997e-10 between points [ steric_correction.py:1075 - apply_steric_correction() ]: [4.76884633e-09 2.67250974e-10 6.29732571e-10] and [ steric_correction.py:1076 - apply_steric_correction() ]: [4.53299206e-09 5.61438490e-10 4.96225792e-10]. [ steric_correction.py:1077 - apply_steric_correction() ]: Min. dist. 5.03965e-02 between dimensionless points [ steric_correction.py:1078 - apply_steric_correction() ]: [0.60083699 0.03367151 0.07934133] and [ steric_correction.py:1079 - apply_steric_correction() ]: [0.57112121 0.07073682 0.06252053]. [ steric_correction.py:1080 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:1083 - apply_steric_correction() ]: Ellapsed time: 0.24356 s. [ <ipython-input-18-3d6fcc74b808>:26 - <module>() ]: 0.28129917598562315 s runtime [ <ipython-input-18-3d6fcc74b808>:35 - <module>() ]: CG finished with [ <ipython-input-18-3d6fcc74b808>:36 - <module>() ]: status = 0, success = True, #it = 11 [ <ipython-input-18-3d6fcc74b808>:38 - <module>() ]: message = 'Optimization terminated successfully.' [ <ipython-input-18-3d6fcc74b808>:39 - <module>() ]: Minimum pair-wise distance in final configuration: 4.0000e-10 [ <ipython-input-18-3d6fcc74b808>:40 - <module>() ]: First sample point in pair: (4.7688e-09,2.6725e-10,6.2973e-10) [ <ipython-input-18-3d6fcc74b808>:41 - <module>() ]: Second sample point in pair (4.5330e-09,5.6144e-10,4.9623e-10) [ <ipython-input-18-3d6fcc74b808>:42 - <module>() ]: Box lower boundary: (0.0000e+00,0.0000e+00,0.0000e+00) [ <ipython-input-18-3d6fcc74b808>:43 - <module>() ]: Minimum coordinates in sample: (2.0161e-10,2.0354e-10,2.0417e-10) [ <ipython-input-18-3d6fcc74b808>:44 - <module>() ]: Maximum coordinates in sample: (4.7983e-09,4.7956e-09,1.9784e-08) [ <ipython-input-18-3d6fcc74b808>:45 - <module>() ]: Box upper boundary: (5.0000e-09,5.0000e-09,2.0000e-08) [ <ipython-input-18-3d6fcc74b808>:21 - <module>() ]: ### BFGS ### [ steric_correction.py:919 - apply_steric_correction() ]: Normalizing coordinates by reference length [ steric_correction.py:920 - apply_steric_correction() ]: L = V^(1/dim) = (5e-25)^(1/3) = 7.9e-09. [ steric_correction.py:929 - apply_steric_correction() ]: Normalized bounding box: [ steric_correction.py:930 - apply_steric_correction() ]: [0. 0. 0.]. [ steric_correction.py:931 - apply_steric_correction() ]: [0.62996052 0.62996052 2.5198421 ]. [ steric_correction.py:949 - apply_steric_correction() ]: Initial constraint penalty: 1.58368e-02. [ steric_correction.py:950 - apply_steric_correction() ]: Initial total penalty: 1.58786e-02. [ steric_correction.py:951 - apply_steric_correction() ]: Initial constraint gradient norm: 2.51689e-01. [ steric_correction.py:953 - apply_steric_correction() ]: Initial total gradient norm: 2.51661e-01. [ steric_correction.py:975 - apply_steric_correction() ]: Min. dist. 1.35219e-10 between points [ steric_correction.py:976 - apply_steric_correction() ]: [4.45656762e-09 3.71127189e-09 1.35014030e-08] and [ steric_correction.py:977 - apply_steric_correction() ]: [4.32692023e-09 3.69576885e-09 1.35365506e-08]. [ steric_correction.py:978 - apply_steric_correction() ]: Min. dist. 1.70365e-02 between dimensionless points [ steric_correction.py:979 - apply_steric_correction() ]: [0.56149234 0.46759096 1.70107019] and [ steric_correction.py:980 - apply_steric_correction() ]: [0.54515779 0.4656377 1.7054985 ]. [ steric_correction.py:981 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:995 - minimizer_callback() ]: #callback objective gradient min. dist. timing, step timing, tot. [ steric_correction.py:1021 - minimizer_callback() ]: 0 1.58786e-02 2.51661e-01 1.70365e-02 1.31716e-02 1.31716e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 1 5.00628e-05 1.16337e-03 1.71522e-02 5.44155e-02 6.75871e-02
Optimization terminated successfully. Current function value: 0.000000 Iterations: 11 Function evaluations: 34 Gradient evaluations: 34
[ steric_correction.py:1021 - minimizer_callback() ]: 2 2.62839e-05 9.04385e-04 1.96719e-02 2.48219e-01 3.15806e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 3 1.58330e-05 1.69049e-03 2.16104e-02 2.14742e-01 5.30548e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 4 1.12491e-05 1.42037e-03 2.35290e-02 2.89273e-01 8.19821e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 5 1.08856e-05 3.01384e-03 2.58065e-02 2.72914e-01 1.09274e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 6 1.02063e-05 2.57985e-03 2.59236e-02 2.72360e-01 1.36510e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 7 9.03292e-06 1.84478e-03 2.65295e-02 1.96542e-01 1.56164e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 8 7.32511e-06 5.46805e-04 2.81950e-02 3.09872e-01 1.87151e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 9 6.00411e-06 4.93375e-04 3.09887e-02 3.10280e-01 2.18179e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 10 5.80361e-06 3.08226e-03 3.73395e-02 2.95119e-01 2.47691e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 11 3.98286e-06 2.27969e-03 3.89506e-02 3.23676e-01 2.80058e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 12 3.43125e-06 2.28179e-03 4.01860e-02 2.72844e-01 3.07343e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 13 2.47033e-06 1.55492e-03 4.08432e-02 2.09503e-01 3.28293e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 14 1.15311e-06 5.45768e-04 4.32543e-02 1.71850e-01 3.45478e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 15 8.10082e-07 2.04778e-04 4.42466e-02 1.66373e-01 3.62115e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 16 3.34902e-07 1.39397e-04 4.66992e-02 3.06624e-01 3.92778e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 17 1.88939e-07 1.11070e-04 4.71729e-02 2.16427e-01 4.14421e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 18 1.28856e-07 9.44450e-05 4.72048e-02 3.11301e-01 4.45551e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 19 8.42476e-08 7.82579e-05 4.76026e-02 1.80431e-01 4.63594e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 20 5.86521e-08 6.59819e-05 4.82061e-02 1.65517e-01 4.80146e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 21 2.74650e-08 4.46877e-05 4.91870e-02 1.60106e-01 4.96156e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 22 2.40462e-08 4.31590e-05 4.90573e-02 1.93214e-01 5.15478e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 23 2.03885e-08 3.97713e-05 4.91092e-02 1.56141e-01 5.31092e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 24 1.48289e-08 3.32444e-05 4.92683e-02 1.55929e-01 5.46685e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 25 1.10054e-08 2.89149e-05 4.93942e-02 1.63918e-01 5.63076e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 26 4.60784e-09 1.90904e-05 4.97280e-02 1.53624e-01 5.78439e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 27 9.85766e-11 2.82571e-06 5.03044e-02 1.58221e-01 5.94261e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 28 1.60081e-11 1.13974e-06 5.03571e-02 1.53503e-01 6.09611e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 29 1.46493e-14 3.45045e-08 5.03956e-02 1.54335e-01 6.25045e+00 [ steric_correction.py:1021 - minimizer_callback() ]: 30 0.00000e+00 0.00000e+00 5.03968e-02 1.55376e-01 6.40582e+00 [ steric_correction.py:1055 - apply_steric_correction() ]: Final constraint penalty: 0.00000e+00. [ steric_correction.py:1056 - apply_steric_correction() ]: Final total penalty: 0.00000e+00. [ steric_correction.py:1057 - apply_steric_correction() ]: Final constraint gradient norm: 0.00000e+00. [ steric_correction.py:1059 - apply_steric_correction() ]: Final total gradient norm: 0.00000e+00. [ steric_correction.py:1074 - apply_steric_correction() ]: Min. dist. 4.00000e-10 between points [ steric_correction.py:1075 - apply_steric_correction() ]: [4.77216452e-09 2.63374783e-10 6.31226024e-10] and [ steric_correction.py:1076 - apply_steric_correction() ]: [4.53178681e-09 5.56272544e-10 5.03048558e-10]. [ steric_correction.py:1077 - apply_steric_correction() ]: Min. dist. 5.03968e-02 between dimensionless points [ steric_correction.py:1078 - apply_steric_correction() ]: [0.60125505 0.03318314 0.0795295 ] and [ steric_correction.py:1079 - apply_steric_correction() ]: [0.57096936 0.07008595 0.06338015]. [ steric_correction.py:1080 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:1083 - apply_steric_correction() ]: Ellapsed time: 6.4489 s. [ <ipython-input-18-3d6fcc74b808>:26 - <module>() ]: 6.483718997013057 s runtime [ <ipython-input-18-3d6fcc74b808>:35 - <module>() ]: BFGS finished with [ <ipython-input-18-3d6fcc74b808>:36 - <module>() ]: status = 0, success = True, #it = 30 [ <ipython-input-18-3d6fcc74b808>:38 - <module>() ]: message = 'Optimization terminated successfully.' [ <ipython-input-18-3d6fcc74b808>:39 - <module>() ]: Minimum pair-wise distance in final configuration: 4.0000e-10 [ <ipython-input-18-3d6fcc74b808>:40 - <module>() ]: First sample point in pair: (4.7722e-09,2.6337e-10,6.3123e-10) [ <ipython-input-18-3d6fcc74b808>:41 - <module>() ]: Second sample point in pair (4.5318e-09,5.5627e-10,5.0305e-10) [ <ipython-input-18-3d6fcc74b808>:42 - <module>() ]: Box lower boundary: (0.0000e+00,0.0000e+00,0.0000e+00) [ <ipython-input-18-3d6fcc74b808>:43 - <module>() ]: Minimum coordinates in sample: (2.0161e-10,2.0273e-10,2.0944e-10) [ <ipython-input-18-3d6fcc74b808>:44 - <module>() ]: Maximum coordinates in sample: (4.7982e-09,4.7956e-09,1.9784e-08) [ <ipython-input-18-3d6fcc74b808>:45 - <module>() ]: Box upper boundary: (5.0000e-09,5.0000e-09,2.0000e-08) [ <ipython-input-18-3d6fcc74b808>:21 - <module>() ]: ### L-BFGS-B ### [ steric_correction.py:919 - apply_steric_correction() ]: Normalizing coordinates by reference length [ steric_correction.py:920 - apply_steric_correction() ]: L = V^(1/dim) = (5e-25)^(1/3) = 7.9e-09. [ steric_correction.py:929 - apply_steric_correction() ]: Normalized bounding box: [ steric_correction.py:930 - apply_steric_correction() ]: [0. 0. 0.]. [ steric_correction.py:931 - apply_steric_correction() ]: [0.62996052 0.62996052 2.5198421 ]. [ steric_correction.py:949 - apply_steric_correction() ]: Initial constraint penalty: 1.58368e-02. [ steric_correction.py:950 - apply_steric_correction() ]: Initial total penalty: 1.58786e-02. [ steric_correction.py:951 - apply_steric_correction() ]: Initial constraint gradient norm: 2.51689e-01. [ steric_correction.py:953 - apply_steric_correction() ]: Initial total gradient norm: 2.51661e-01. [ steric_correction.py:975 - apply_steric_correction() ]: Min. dist. 1.35219e-10 between points [ steric_correction.py:976 - apply_steric_correction() ]: [4.45656762e-09 3.71127189e-09 1.35014030e-08] and [ steric_correction.py:977 - apply_steric_correction() ]: [4.32692023e-09 3.69576885e-09 1.35365506e-08]. [ steric_correction.py:978 - apply_steric_correction() ]: Min. dist. 1.70365e-02 between dimensionless points [ steric_correction.py:979 - apply_steric_correction() ]: [0.56149234 0.46759096 1.70107019] and [ steric_correction.py:980 - apply_steric_correction() ]: [0.54515779 0.4656377 1.7054985 ]. [ steric_correction.py:981 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:995 - minimizer_callback() ]: #callback objective gradient min. dist. timing, step timing, tot. [ steric_correction.py:1021 - minimizer_callback() ]: 0 1.58786e-02 2.51661e-01 1.70365e-02 9.20630e-03 9.20630e-03 [ steric_correction.py:1021 - minimizer_callback() ]: 1 5.67241e-05 1.21760e-03 1.74713e-02 2.42290e-02 3.34353e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 2 3.12112e-05 9.67402e-04 1.99975e-02 2.11593e-02 5.45947e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 3 5.94990e-06 4.71026e-04 3.08418e-02 1.34996e-02 6.80943e-02
Optimization terminated successfully. Current function value: 0.000000 Iterations: 30 Function evaluations: 36 Gradient evaluations: 36
[ steric_correction.py:1021 - minimizer_callback() ]: 4 2.14738e-06 3.35417e-04 3.85975e-02 1.88098e-02 8.69041e-02 [ steric_correction.py:1021 - minimizer_callback() ]: 5 8.00435e-07 2.25966e-04 4.35191e-02 1.85395e-02 1.05444e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 6 6.44483e-08 7.02902e-05 4.88298e-02 1.82982e-02 1.23742e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 7 2.57235e-08 4.48984e-05 4.94043e-02 1.81208e-02 1.41863e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 8 7.78933e-09 2.49124e-05 4.98521e-02 1.85106e-02 1.60373e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 9 3.06876e-09 1.56952e-05 5.00562e-02 1.80278e-02 1.78401e-01 [ steric_correction.py:1021 - minimizer_callback() ]: 10 1.53545e-09 1.11224e-05 5.01562e-02 1.79609e-02 1.96362e-01 [ steric_correction.py:1055 - apply_steric_correction() ]: Final constraint penalty: 0.00000e+00. [ steric_correction.py:1056 - apply_steric_correction() ]: Final total penalty: 1.53545e-09. [ steric_correction.py:1057 - apply_steric_correction() ]: Final constraint gradient norm: 0.00000e+00. [ steric_correction.py:1059 - apply_steric_correction() ]: Final total gradient norm: 1.11224e-05. [ steric_correction.py:1074 - apply_steric_correction() ]: Min. dist. 3.98090e-10 between points [ steric_correction.py:1075 - apply_steric_correction() ]: [7.22969570e-10 3.71882173e-10 9.28623031e-09] and [ steric_correction.py:1076 - apply_steric_correction() ]: [9.47951998e-10 2.81583628e-10 9.60199089e-09]. [ steric_correction.py:1077 - apply_steric_correction() ]: Min. dist. 5.01562e-02 between dimensionless points [ steric_correction.py:1078 - apply_steric_correction() ]: [0.09108846 0.04685422 1.1699917 ] and [ steric_correction.py:1079 - apply_steric_correction() ]: [0.11943447 0.03547731 1.20977504]. [ steric_correction.py:1080 - apply_steric_correction() ]: normalized by L = 7.9e-09. [ steric_correction.py:1083 - apply_steric_correction() ]: Ellapsed time: 0.22791 s. [ <ipython-input-18-3d6fcc74b808>:26 - <module>() ]: 0.2788100489997305 s runtime [ <ipython-input-18-3d6fcc74b808>:35 - <module>() ]: L-BFGS-B finished with [ <ipython-input-18-3d6fcc74b808>:36 - <module>() ]: status = 0, success = True, #it = 10 [ <ipython-input-18-3d6fcc74b808>:38 - <module>() ]: message = 'b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'' [ <ipython-input-18-3d6fcc74b808>:39 - <module>() ]: Minimum pair-wise distance in final configuration: 3.9809e-10 [ <ipython-input-18-3d6fcc74b808>:40 - <module>() ]: First sample point in pair: (7.2297e-10,3.7188e-10,9.2862e-09) [ <ipython-input-18-3d6fcc74b808>:41 - <module>() ]: Second sample point in pair (9.4795e-10,2.8158e-10,9.6020e-09) [ <ipython-input-18-3d6fcc74b808>:42 - <module>() ]: Box lower boundary: (0.0000e+00,0.0000e+00,0.0000e+00) [ <ipython-input-18-3d6fcc74b808>:43 - <module>() ]: Minimum coordinates in sample: (2.0979e-10,2.0066e-10,2.2803e-10) [ <ipython-input-18-3d6fcc74b808>:44 - <module>() ]: Maximum coordinates in sample: (4.7982e-09,4.7956e-09,1.9780e-08) [ <ipython-input-18-3d6fcc74b808>:45 - <module>() ]: Box upper boundary: (5.0000e-09,5.0000e-09,2.0000e-08)
method runtime mind p10 p11 p12 p20 p21 p22 pmin0 pmin1 pmin2 pmax0 pmax1 pmax2 0 initial 0 1.35219e-10 4.45657e-09 3.71127e-09 1.35014e-08 4.32692e-09 3.69577e-09 1.35366e-08 2.32922e-12 6.18851e-13 2.26956e-11 4.99919e-09 4.9942e-09 1.99532e-08 1 Powell 490.303 4.02615e-10 3.02768e-09 2.83841e-09 1.32512e-08 3.19153e-09 2.63912e-09 1.35603e-08 2.11893e-10 2.0707e-10 2.77557e-10 4.79253e-09 4.78227e-09 1.97952e-08 2 CG 0.281299 3.99997e-10 4.76885e-09 2.67251e-10 6.29733e-10 4.53299e-09 5.61438e-10 4.96226e-10 2.01613e-10 2.03536e-10 2.04167e-10 4.79826e-09 4.79558e-09 1.97842e-08 3 BFGS 6.48372 4e-10 4.77216e-09 2.63375e-10 6.31226e-10 4.53179e-09 5.56273e-10 5.03049e-10 2.01608e-10 2.02733e-10 2.0944e-10 4.79821e-09 4.79558e-09 1.97842e-08 4 L-BFGS-B 0.27881 3.9809e-10 7.2297e-10 3.71882e-10 9.28623e-09 9.47952e-10 2.81584e-10 9.60199e-09 2.09787e-10 2.00663e-10 2.2803e-10 4.79821e-09 4.79558e-09 1.97796e-08
L-BFGS-B fastest.
# Check difference between initial and final configuration, use last result (L-BFGS-B)
np.count_nonzero(xstacked - x1) # that many coordinates modified
353
# Check difference between initial and final configuration, use last result (L-BFGS-B)
np.linalg.norm(xstacked - x1) # euclidean distance between two sets
7.961943476244598e-09
# pick last result and split by species
steric_samples = [ x1[:sample_size,:], x1[sample_size:,:] ]
nbins = 101
for ion,sample,d in zip(species,steric_samples,distributions):
histx, histy, histz = get_histogram(sample, box=box3, n_bins=nbins)
plot_dist(histx, 'Distribution of {:s} ions in x-direction'.format(ion),
reference_distribution=lambda x: np.ones(x.shape)*1/box3[0])
plot_dist(histy, 'Distribution of {:s} ions in y-direction'.format(ion),
reference_distribution=lambda x: np.ones(x.shape)*1/box3[1])
plot_dist(histz, 'Distribution of {:s} ions in z-direction'.format(ion),
reference_distribution=d)
# Distribution of corrections
for ion,sample,steric_sample,d in zip(species,samples,steric_samples,distributions):
hists = get_histogram(sample, box=box3, n_bins=nbins)
steric_hists = get_histogram(steric_sample, box=box3, n_bins=nbins)
# first entry is counts, second entry is bins
diff_hists = [ (h[0] - hs[0], h[1]) for h,hs in zip(hists,steric_hists) ]
for ax, h in zip( ['x','y','z'], diff_hists ):
plot_dist(h, 'Difference from non-steric to steric {:s} ion sample in {:s}-direction'.format(ion, ax))
We utilize ASE to export it to some standard format, i.e. LAMMPS data file. ASE speaks Ångström per default, thus we convert SI units:
symbols = ['Na','Cl']
system = ase.Atoms(
cell=np.diag(box3/sc.angstrom),
pbc=[True,True,False])
for symbol, sample, charge in zip(symbols,samples,z):
system += ase.Atoms(
symbols=symbol*sample_size,
charges=[charge]*sample_size,
positions=sample/sc.angstrom)
system
Atoms(symbols='Cl200Na200', pbc=[True, True, False], cell=[50.0, 50.0, 200.0], initial_charges=...)
ase.io.write('NaCl_200_0.05V_5x5x20nm_at_interface_pb_distributed.lammps',system,format='lammps-data',units="real",atom_style='full')
steric_system = ase.Atoms(
cell=np.diag(box3/sc.angstrom),
pbc=[True,True,False])
for symbol, sample, charge in zip(symbols,steric_samples,z):
steric_system += ase.Atoms(
symbols=symbol*sample_size,
charges=[charge]*sample_size,
positions=sample/sc.angstrom)
steric_system
Atoms(symbols='Cl200Na200', pbc=[True, True, False], cell=[50.0, 50.0, 200.0], initial_charges=...)
ase.io.write('NaCl_200_0.05V_5x5x20nm_at_interface_pb_distributed_steric_correction_2Ang.lammps',steric_system,format='lammps-data',units="real",atom_style='full')
Displacement visualization between non-steric and steric sample with Ovito:
# prepare coordinates and get system dimensions
xstacked = np.vstack(samples)
n = xstacked.shape[0]
dim = xstacked.shape[1]
# normalize volume and coordinates
V = np.product(box6[1]-box6[0])
L = np.power(V,(1./dim))
x0 = xstacked / L
funcs = [
brute_force_target_function,
numpy_only_target_function,
scipy_distance_based_target_function ]
func_names = ['brute','numpy','scipy']
# test for different scalings of coordinate set:
stats = []
K = np.exp(np.log(10)*np.arange(-3,3))
for k in K:
lambdas = [ (lambda x0=xstacked,k=k,f=f: f(x0*k)) for f in funcs ]
vals = [ f() for f in lambdas ]
times = [ timeit.timeit(f,number=1) for f in lambdas ]
diffs = scipy.spatial.distance.pdist(np.atleast_2d(vals).T,metric='euclidean')
stats.append((k,*vals,*diffs,*times))
func_name_tuples = list(itertools.combinations(func_names,2))
diff_names = [ 'd_{:s}_{:s}'.format(f1,f2) for (f1,f2) in func_name_tuples ]
perf_names = [ 't_{:s}'.format(f) for f in func_names ]
fields = ['k',*func_names,*diff_names,*perf_names]
dtypes = [ (field, '>f4') for field in fields ]
labeled_stats = np.array(stats,dtype=dtypes)
stats_df = pd.DataFrame(labeled_stats)
print(stats_df.to_string(float_format='%8.6g'))
k brute numpy scipy d_brute_numpy d_brute_scipy d_numpy_scipy t_brute t_numpy t_scipy 0 0.001 1.2768e+06 1.2768e+06 1.2768e+06 0 0 0 0.0748934 0.0274576 0.00994868 1 0.01 1.2768e+06 1.2768e+06 1.2768e+06 0 0 0 0.0511786 0.00792927 0.00428326 2 0.1 1.2768e+06 1.2768e+06 1.2768e+06 0 0 0 0.0634737 0.0181665 0.00605623 3 1 1.2768e+06 1.2768e+06 1.2768e+06 0 0 0 0.0660553 0.0110747 0.00490169 4 10 1.2768e+06 1.2768e+06 1.2768e+06 4.42378e-09 4.42378e-09 0 0.106502 0.0281443 0.0117425 5 100 1.2768e+06 1.2768e+06 1.2768e+06 0 4.65661e-10 4.65661e-10 0.0585994 0.00632705 0.0116756
Scipy-based target function fastest.
# test minimum distance function implementations on random samples
N = 1000
dim = 3
funcs = [
brute_force_closest_pair,
scipy_distance_based_closest_pair,
planar_closest_pair ]
func_names = ['brute','scipy','planar']
stats = []
for k in range(5):
x = np.random.rand(N,dim)
lambdas = [ (lambda x=x,f=f: f(x)) for f in funcs ]
rets = [ f() for f in lambdas ]
vals = [ v[0] for v in rets ]
coords = [ c for v in rets for p in v[1] for c in p ]
times = [ timeit.timeit(f,number=1) for f in lambdas ]
diffs = scipy.spatial.distance.pdist(
np.atleast_2d(vals).T,metric='euclidean')
stats.append((*vals,*diffs,*times,*coords))
func_name_tuples = list(itertools.combinations(func_names,2))
diff_names = [ 'd_{:s}_{:s}'.format(f1,f2) for (f1,f2) in func_name_tuples ]
perf_names = [ 't_{:s}'.format(f) for f in func_names ]
coord_names = [
'p{:d}{:s}_{:s}'.format(i,a,f) for f in func_names for i in (1,2) for a in ('x','y','z') ]
float_fields = [*func_names,*diff_names,*perf_names,*coord_names]
dtypes = [ (field, 'f4') for field in float_fields ]
labeled_stats = np.array(stats,dtype=dtypes)
stats_df = pd.DataFrame(labeled_stats)
print(stats_df.T.to_string(float_format='%8.6g'))
0 1 2 3 4 brute 8.23034e-05 6.24342e-05 7.73916e-05 0.000105018 6.21209e-06 scipy 8.23034e-05 6.24342e-05 7.73916e-05 0.000105018 6.21209e-06 planar 8.23034e-05 6.24342e-05 7.73916e-05 0.000105018 6.21209e-06 d_brute_scipy 0 0 0 0 0 d_brute_planar 0 0 0 0 0 d_scipy_planar 0 0 0 0 0 t_brute 3.36451 3.34532 3.29159 3.22781 3.56785 t_scipy 0.00688992 0.0072318 0.00715069 0.00668828 0.00780163 t_planar 0.329836 0.385201 0.338101 0.358731 0.328343 p1x_brute 0.718887 0.303597 0.984552 0.527871 0.825703 p1y_brute 0.459294 0.42578 0.844301 0.941305 0.795724 p1z_brute 0.17789 0.760662 0.97241 0.321066 0.684067 p2x_brute 0.717926 0.298073 0.987665 0.535216 0.825263 p2y_brute 0.45134 0.428343 0.847157 0.947524 0.793604 p2z_brute 0.182145 0.765697 0.980127 0.324584 0.682832 p1x_scipy 0.718887 0.303597 0.984552 0.527871 0.825703 p1y_scipy 0.459294 0.42578 0.844301 0.941305 0.795724 p1z_scipy 0.17789 0.760662 0.97241 0.321066 0.684067 p2x_scipy 0.717926 0.298073 0.987665 0.535216 0.825263 p2y_scipy 0.45134 0.428343 0.847157 0.947524 0.793604 p2z_scipy 0.182145 0.765697 0.980127 0.324584 0.682832 p1x_planar 0.718887 0.303597 0.984552 0.527871 0.825263 p1y_planar 0.459294 0.42578 0.844301 0.941305 0.793604 p1z_planar 0.17789 0.760662 0.97241 0.321066 0.682832 p2x_planar 0.717926 0.298073 0.987665 0.535216 0.825703 p2y_planar 0.45134 0.428343 0.847157 0.947524 0.795724 p2z_planar 0.182145 0.765697 0.980127 0.324584 0.684067
Scipy-based implementation fastest.
print('{}'.format(system.symbols))
Na200Cl200
system.cell.array
array([[ 50., 0., 0.], [ 0., 50., 0.], [ 0., 0., 200.]])
np.array(system.get_cell_lengths_and_angles())
array([ 50., 50., 200., 90., 90., 90.])