Last year (2020), in connection with the pandemic, we held an online scientific conference on computational chemistry , and we made a logo for it, which was, to put it mildly, so-so. Below the cut is a story about how we pumped it for this (2021) conference using a small amount of quantum mechanics, the Monte Carlo method, Python and Gnuplot.
A bit of background
2020, the coronavirus is gaining momentum, restrictions are imposed, and to maintain the level of scientific discussion, improve scientific cooperation among Russian-speaking scientists scattered around the world, and for all the rest of the good, we organized a mini-symposium on computational chemistry online .
But what is a conference without a logo? And having gathered into a fist all the artistic (from the word "bad") possibilities of the organizing committee of the conference, a logo was created in 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 .