El año pasado (2020), en relación con la pandemia, celebramos una conferencia científica en línea sobre química computacional e hicimos un logotipo para ella, que era, por decirlo suavemente, regular. Debajo del corte hay una historia sobre cómo lo bombeamos para la conferencia de este año (2021) utilizando una pequeña cantidad de mecánica cuántica, el método de Monte Carlo, Python y Gnuplot.
Un poco de historia
2020, el coronavirus está ganando impulso, se imponen restricciones y, para mantener el nivel de discusión científica, mejorar la cooperación científica entre los científicos de habla rusa repartidos por todo el mundo, y para todos los demás, organizamos un mini-simposio sobre química computacional en línea .
Pero, ¿qué es una conferencia sin logo? Y habiendo reunido en un puño todas las posibilidades artísticas (de la palabra "mala") del comité organizador de la conferencia, se creó un logo en Inkscape :
. , d- . - Firefly, , , , . , . : ψ, , . , . to Pimp My Ride Logo.
, 2020 , -. . , - ?
. :
,
,
,
, .
- ψ ( ), (x,y,z)=r. . r0, r1, r2, ..., rN, N - . ψn=ψ(rn). , Python :
rn rtrial, (xn,yn,zn) rn -δ +δ, δ — , ,
pacc = |ψtrial|2/|ψn|2, q 0 1, pacc q: pacc<q, (rn+1=rn), , (rn+1=rtrial),
, , -0.1⋅δ +0.1⋅δ.
, , . 10% , , , . .
. d- :
r — r, , . , . , , :
, , .
Python
import numpy as np
import random as rnd
DXYZ = 4.0
dxyz = 0.1*DXYZ
def getWFN(R, a=0.05, b=0.9, R0=1.0):
return (a*(R[1])**3 + b*R[0]*R[1])*np.exp(-np.sqrt(np.dot(R,R))/R0)
Npts = 40000
N2ignore = Npts/10
outf = open("wfn.dat", "w")
outfp = open("wfn_pos.dat", "w")
outfn = open("wfn_neg.dat", "w")
genNewXYZ = lambda xyz, shift: xyz + np.array([rnd.uniform(-shift,shift) for q in range(0,3)])
XYZ = np.array([1.0,1.0,0.0])
Psi = getWFN(XYZ, DXYZ)
for i in range(0,Npts):
trialXYZ = genNewXYZ(XYZ, DXYZ)
trialPsi = getWFN(trialXYZ)
if i % N2ignore == 0:
print("step #%i" % (i))
Ptrial = rnd.random()
Ptest = trialPsi**2/Psi**2
Accepted = False
if Ptrial < Ptest:
Psi = trialPsi
XYZ = trialXYZ
Accepted = True
if i>N2ignore:
r2save = XYZ
if not Accepted:
r2save = genNewXYZ(XYZ, dxyz)
outf.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
if Psi > 0.0:
outfp.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
else:
outfn.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
:
Python
import numpy as np
import random as rnd
DXYZ = 0.5
dxyz = 0.1*DXYZ
def getWFN(R, a=1.0, b=0.5, X0=0.2, Y0=0.5, Z0=0.2):
if R[1]<0.:
return (a*(R[1])**3 + b*R[1])*np.exp(-np.abs(R[0])/X0 - np.abs(R[1])/Y0 - np.abs(R[2])/Z0)
else:
return 0.0
Npts = 20000
N2ignore = Npts/10
outf = open("body.dat", "w")
genNewXYZ = lambda xyz, shift: xyz + np.array([rnd.uniform(-shift,shift) for q in range(0,3)])
XYZ = np.array([0.0,-0.2,0.0])
Psi = getWFN(XYZ, DXYZ)
for i in range(0,Npts):
trialXYZ = genNewXYZ(XYZ, DXYZ)
trialPsi = getWFN(trialXYZ)
if i % N2ignore == 0:
print("step #%i" % (i))
Ptrial = rnd.random()
Ptest = trialPsi**2/Psi**2
Accepted = False
if Ptrial < Ptest:
Psi = trialPsi
XYZ = trialXYZ
Accepted = True
if i>N2ignore:
r2save = XYZ
if not Accepted:
r2save = genNewXYZ(XYZ, dxyz)
outf.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
, s-:
Python
import numpy as np
import random as rnd
DXYZ = 0.9
dxyz = 0.1*DXYZ
def getWFN(R, a=1.0, b=0.5, X0=0.3, Y0=0.5, Z0=0.3):
return np.exp(-np.abs(R[0])/X0 - np.abs(R[1])/Y0 - np.abs(R[2])/Z0)
Npts = 10000
N2ignore = Npts/10
outf = open("head.dat", "w")
genNewXYZ = lambda xyz, shift: xyz + np.array([rnd.uniform(-shift,shift) for q in range(0,3)])
XYZ = np.array([0.0,-0.2,0.0])
Psi = getWFN(XYZ, DXYZ)
for i in range(0,Npts):
trialXYZ = genNewXYZ(XYZ, DXYZ)
trialPsi = getWFN(trialXYZ)
if i % N2ignore == 0:
print("step #%i" % (i))
Ptrial = rnd.random()
Ptest = trialPsi**2/Psi**2
Accepted = False
if Ptrial < Ptest:
Psi = trialPsi
XYZ = trialXYZ
Accepted = True
if i>N2ignore:
r2save = XYZ
if not Accepted:
r2save = genNewXYZ(XYZ, dxyz)
outf.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
, , :
Python
import numpy as np
import random as rnd
DXYZ = 0.9
dxyz = 0.1*DXYZ
def getWFN(R, a=1.0, b=0.5, X0=0.4, Y0=0.68, Z0=0.3):
if R[1]<0.:
return (a*(R[1])**3 + b*R[1])*np.exp(-np.abs(R[0])/X0 - np.abs(R[1])/Y0 - np.abs(R[2])/Z0)
else:
return 0.0
Npts = 1000
N2ignore = Npts/10
outf = open("body_fire.dat", "w")
genNewXYZ = lambda xyz, shift: xyz + np.array([rnd.uniform(-shift,shift) for q in range(0,3)])
XYZ = np.array([0.0,-0.2,0.0])
Psi = getWFN(XYZ, DXYZ)
for i in range(0,Npts):
trialXYZ = genNewXYZ(XYZ, DXYZ)
trialPsi = getWFN(trialXYZ)
if i % N2ignore == 0:
print("step #%i" % (i))
Ptrial = rnd.random()
Ptest = trialPsi**2/Psi**2
Accepted = False
if Ptrial < Ptest:
Psi = trialPsi
XYZ = trialXYZ
Accepted = True
if i>N2ignore:
r2save = XYZ
if not Accepted:
r2save = genNewXYZ(XYZ, dxyz)
outf.write(" %15.10f %15.10f %15.10f %15.5e\n" % tuple(list(r2save)+[Psi]))
(xn, yn, zn, ψn) n=0,1,2,..., . Gnuplot multiplot. (set view map). , : https://github.com/Gnuplotting/gnuplot-palettes.
inferno, — ylrd, . - : plasma, parula, — prgn.
Plasma — , - , . Parula , , ... , , , . prgn, : , , . Inkscape .
Gnuplot
#set terminal pngcairo size 1500,1500 transparent
set terminal pngcairo size 1500,1500 background rgb '#080045'
set output "ff_v2.png"
set multiplot
set view map
set size ratio 1
unset colorbox
unset border
unset key
unset xtics
unset ytics
XMax = 7.
set xrange [-XMax:XMax]
set yrange [-XMax:XMax]
set pm3d depthorder hidden3d 1
set hidden3d
set style fill transparent solid 0.35 noborder
set style circle radius 0.02
load 'prgn.pal'
#load 'plasma.pal'
#load 'parula.pal'
splot 'wfn_pos.dat' u 2:1:3:4 w p pt 7 ps 2 lc palette
splot 'wfn_neg.dat' u 2:1:3:4 w p pt 7 ps 2 lc palette
load 'inferno.pal'
splot 'body.dat' u 1:2:3:4 w l lc palette
splot 'head.dat' u 1:2:3:4 w l lc palette
load 'ylrd.pal'
splot 'body_fire.dat' u 1:2:3:(-$4) w l lw 3 lc palette
P.S.
, - , . , , YouTube .