Loading...
Searching...
No Matches
Tunneling.h
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12#pragma once
13
14// One-dimensional tunnelling along a mass-weighted minimum energy path.
15//
16// A two-level system in a glass is a pair of adjacent minima that the system
17// tunnels between at about one kelvin. Its splitting follows from a WKB
18// integral along the mass-weighted path joining the minima (Damart and
19// Rodney; Khomenko et al.; Mocanu et al.). Energies are in eV, lengths in
20// Angstrom and masses in amu, so mass-weighted lengths are in
21// amu^0.5 Angstrom and hbar is kHbar.
22
23#include "Matter.h"
24
25#include <array>
26#include <functional>
27#include <limits>
28#include <memory>
29#include <string>
30#include <vector>
31
32namespace eonc::tunneling {
33
37inline constexpr double kHbar = 0.06465415129579072;
38
41inline constexpr double kBoltzmann = 8.617333262145177e-5;
42
44double massWeightedDistance(const Matter &a, const Matter &b);
45
47std::vector<double>
48massWeightedPath(const std::vector<std::shared_ptr<Matter>> &band);
49
54class Profile {
55public:
56 Profile(std::vector<double> s, std::vector<double> v);
57 double operator()(double x) const;
58 const std::vector<double> &s() const { return s_; }
59 const std::vector<double> &v() const { return v_; }
60
61private:
62 std::vector<double> s_, v_, m_;
63};
64
69double wellCurvature(const Profile &p, bool leftEnd);
70
72double hbarOmega(double curvature);
73
75double wkbAction(const Profile &p, double energy, int points = 4001);
76
77struct Splitting {
78 double delta = 0.0;
79 double barrier = 0.0;
80 double hwReactant = 0.0;
81 double hwProduct = 0.0;
82 double referenceEnergy = 0.0;
83 double action = 0.0;
84 double delta0 = 0.0;
87 bool deepWells = false;
88 double tlsEnergy() const;
89};
90
95Splitting wkbSplitting(const Profile &p, double hwReactant, double hwProduct);
96
99Splitting bandSplitting(const std::vector<std::shared_ptr<Matter>> &band,
100 double referenceEnergy);
101
106std::vector<VectorXd> ringFromPath(const std::vector<VectorXd> &path,
107 const std::vector<double> &energies,
108 double betaHbar, long beads);
109
113double wkbLogRateAlongPath(const Profile &profile, double beta,
114 double hwReactant);
115
116// Ring-polymer instanton for the splitting between two minima.
117//
118// A path of P + 1 beads in mass-weighted coordinates q runs from one minimum
119// to the other in imaginary time beta hbar, the ends fixed at the minima. The
120// instanton is the path that minimises the discretised Euclidean action
121//
122// S = sum_j |q_{j+1} - q_j|^2 / (2 dtau) + dtau sum_j' V(q_j),
123//
124// dtau = beta hbar / P, with half weight on the two ends (trapezoid). The
125// splitting follows from the ratio of the off-diagonal to the diagonal
126// imaginary-time propagator, both in the same steepest-descent
127// approximation:
128//
129// delta0 = 2 hbar sqrt(S0 / (2 pi hbar dtau))
130// sqrt(det J_well / det' J) exp(-(S - S_well) / hbar),
131//
132// with J the Hessian of S over the interior beads, det' leaving out its
133// zero mode (the kink's position in imaginary time), S0 the integral of
134// |dq/dtau|^2 and J_well the same Hessian with every bead at a minimum.
135// Time runs in amu^0.5 Angstrom eV^-0.5, so hbar is kHbar. Where the minimum
136// energy path curves, the instanton cuts the corner and follows the
137// transverse zero-point energy, which a one-dimensional WKB integral along
138// the path cannot.
139
141 long beads = 256;
142 double betaHbarOmega = 30.0;
144 long maxIterations = 5000;
145 double forceTolerance = 1e-4;
147 long memory = 20;
148};
149
153 std::function<void(const std::vector<VectorXd> &q, std::vector<double> &v,
154 std::vector<VectorXd> &grad)>;
155
157using BeadHessian = std::function<MatrixXd(long j, const VectorXd &q)>;
158
159struct Instanton {
160 std::vector<VectorXd> path;
161 std::vector<double> energies;
162 double betaHbar = 0.0;
163 double dtau = 0.0;
164 double action = 0.0;
165 double s0 = 0.0;
166 double zeroMode = 0.0;
167 double delta0 = 0.0;
168 double asymmetry = 0.0;
169 long iterations = 0;
170 bool converged = false;
173 bool symmetricEnough = false;
176 double modeSeparation = 0.0;
177};
178
181double pathOmega(const MatrixXd &hessStart, const MatrixXd &hessEnd,
182 const VectorXd &start, const VectorXd &end);
183
187Instanton optimizeInstanton(const VectorXd &start, const VectorXd &end,
188 double betaHbar, std::vector<VectorXd> guess,
189 const BatchPotential &potential,
190 const InstantonOptions &options);
191
194void instantonSplitting(Instanton &inst, const BeadHessian &hessian,
195 const MatrixXd &hessStart, const MatrixXd &hessEnd);
196
197// Ring-polymer instanton for the thermal rate below the crossover
198// temperature (Richardson and Althorpe, J. Chem. Phys. 131, 214106 (2009)).
199//
200// A closed ring of N beads in mass-weighted coordinates q, beta_N = beta / N,
201// has the potential
202//
203// U_N = sum_j V(q_j) + sum_j |q_{j+1} - q_j|^2 / (2 beta_N^2 hbar^2),
204//
205// q_N = q_0. Below T_c = hbar omega_b / (2 pi kB), omega_b the imaginary
206// frequency at the saddle, the instanton is a first-order saddle of U_N:
207// one negative mode, and one zero mode that cycles the beads. The rate is
208//
209// k Z_r = (1 / (beta_N hbar)) sqrt(B_N / (2 pi beta_N hbar^2))
210// prod'_k 1 / (beta_N hbar |omega_k|) exp(-beta_N U_N),
211//
212// B_N = sum_j |q_{j+1} - q_j|^2, omega_k^2 the eigenvalues of the
213// mass-weighted Hessian of U_N with the zero mode left out, and Z_r the
214// ring-polymer partition function of the harmonic reactant,
215//
216// Z_r = exp(-beta V_r) prod_{k=0}^{N-1} prod_m
217// 1 / (beta_N hbar sqrt(lambda_m + 4 sin^2(pi k / N) / (beta_N
218// hbar)^2)),
219//
220// lambda_m the eigenvalues of the reactant's mass-weighted Hessian. Above
221// T_c the ring collapses onto the saddle and the formula no longer applies.
222
224inline constexpr double kTimeUnitSeconds = 1.0180505717871193e-14;
225
228double crossoverTemperature(const MatrixXd &hessSaddle);
229
232double parabolicFactor(double temperature, double crossover);
233
238double harmonicTstLogRate(const MatrixXd &hessReactant,
239 const MatrixXd &hessSaddle, double beta,
240 double barrier, long rigidModes);
241
250double quantumHarmonicTstLogRate(const MatrixXd &hessReactant,
251 const MatrixXd &hessSaddle, double beta,
252 double barrier, long rigidModes);
253
255 long beads = 32;
256 long maxIterations = 1000;
257 double forceTolerance = 1e-3;
259 long lanczosFirst = 30;
260 long lanczosRestart = 6;
261 double lanczosStep = 1e-4;
262 double maxStep = 0.05;
264 long memory = 10;
268 bool halfRing = true;
274 bool checkOddSector = true;
275 double energyShift = 0.0;
279 long newtonLimit = std::numeric_limits<long>::max();
283 std::string initialHessians = "saddle";
292 std::vector<double> rigidSqrtMasses;
294 std::array<bool, 3> rigidRotations{{false, false, false}};
295};
296
300 double logDetPrime = 0.0;
305 double zeroEigenvalue = 0.0;
306};
307
313RingSpectrum ringSpectrum(const std::vector<MatrixXd> &beadHessians, double c,
314 const std::vector<VectorXd> &tau);
315
317 std::vector<VectorXd> beads;
318 std::vector<double> energies;
319 double beta = 0.0;
320 double betaN = 0.0;
321 double temperature = 0.0;
322 double crossover = 0.0;
323 double ringPotential = 0.0;
324 double bN = 0.0;
325 double negativeEigenvalue = 0.0;
326 double zeroEigenvalue = 0.0;
327 long negativeModes = 0;
328 long iterations = 0;
329 bool converged = false;
330 double logRateTimesZr = 0.0;
331 double logZr = 0.0;
332 double logRate = 0.0;
333 double rate = 0.0;
335 double effectiveBarrier = 0.0;
339 double classicalRate = 0.0;
340 double classicalLogRate = 0.0;
341};
342
352RateInstanton optimizeRateInstanton(const VectorXd &saddle,
353 const MatrixXd &hessSaddle, double beta,
354 std::vector<VectorXd> guess,
355 const BatchPotential &potential,
356 const RateInstantonOptions &options);
357
359using RingBeadHessian = std::function<MatrixXd(long j, const VectorXd &q)>;
360
373void instantonRate(RateInstanton &inst, const RingBeadHessian &hessian,
374 const MatrixXd &hessReactant, double vReactant,
375 const MatrixXd &hessSaddle = MatrixXd(),
376 double vSaddle = 0.0, long rigidModes = 0,
377 long denseLimit = 4096);
378
383double cyclicRingLogAbsDet(double c, const std::vector<MatrixXd> &diag);
384
387std::vector<VectorXd> cyclicRingSolve(double c,
388 const std::vector<MatrixXd> &diag,
389 const std::vector<VectorXd> &rhs);
390
391} // namespace eonc::tunneling
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic, eOnStorageOrder > MatrixXd
Definition Eigen.h:33
Energy along the path, interpolated as a monotone cubic (Fritsch and Carlson), flat at both ends beca...
Definition Tunneling.h:54
std::vector< double > m_
Definition Tunneling.h:62
std::vector< double > s_
Definition Tunneling.h:62
std::vector< double > v_
Definition Tunneling.h:62
Profile(std::vector< double > s, std::vector< double > v)
Definition Tunneling.cpp:61
const std::vector< double > & v() const
Definition Tunneling.h:59
double operator()(double x) const
Definition Tunneling.cpp:91
const std::vector< double > & s() const
Definition Tunneling.h:58
std::function< MatrixXd(long j, const VectorXd &q)> BeadHessian
The mass-weighted Hessian d2V/dq2 at interior bead j (1..P-1).
Definition Tunneling.h:157
RingSpectrum ringSpectrum(const std::vector< MatrixXd > &beadHessians, double c, const std::vector< VectorXd > &tau)
The ring Hessian of bead Hessians beadHessians (d2V/dq2 at each of the N beads) and spring constant c...
double cyclicRingLogAbsDet(double c, const std::vector< MatrixXd > &diag)
log|det| of the cyclic block-tridiagonal ring Hessian.
Splitting bandSplitting(const std::vector< std::shared_ptr< Matter > > &band, double referenceEnergy)
The splitting of a converged band, with the well frequencies from the band's curvature at each end.
std::vector< VectorXd > cyclicRingSolve(double c, const std::vector< MatrixXd > &diag, const std::vector< VectorXd > &rhs)
Solves that same cyclic ring Hessian.
double wkbAction(const Profile &p, double energy, int points)
(1/hbar) integral sqrt(2 (V(s) - E)) ds over the path where V > E.
double parabolicFactor(double temperature, double crossover)
(pi T_c / T) / sin(pi T_c / T).
void instantonSplitting(Instanton &inst, const BeadHessian &hessian, const MatrixXd &hessStart, const MatrixXd &hessEnd)
Fills delta0, zeroMode and modeSeparation from the bead Hessians and the Hessians of the two minima.
constexpr double kTimeUnitSeconds
One unit of time, sqrt(amu Angstrom^2 / eV), in seconds.
Definition Tunneling.h:224
void instantonRate(RateInstanton &inst, const RingBeadHessian &hessian, const MatrixXd &hessReactant, double vReactant, const MatrixXd &hessSaddle, double vSaddle, long rigidModes, long denseLimit)
Fills the rate from the bead Hessians, the reactant minimum's Hessian and energy, and optionally the ...
double pathOmega(const MatrixXd &hessStart, const MatrixXd &hessEnd, const VectorXd &start, const VectorXd &end)
omega along the straight line between the minima from the curvature of each well there,...
std::function< MatrixXd(long j, const VectorXd &q)> RingBeadHessian
The mass-weighted Hessian d2V/dq2 at ring bead j (0..N-1).
Definition Tunneling.h:359
std::vector< VectorXd > ringFromPath(const std::vector< VectorXd > &path, const std::vector< double > &energies, double betaHbar, long beads)
Closed ring of beads samples of path whose imaginary-time period is betaHbar.
RateInstanton optimizeRateInstanton(const VectorXd &saddle, const MatrixXd &hessSaddle, double beta, std::vector< VectorXd > guess, const BatchPotential &potential, const RateInstantonOptions &options)
Finds the rate instanton at inverse temperature beta (1 / eV).
constexpr double kHbar
hbar in eV^0.5 amu^0.5 Angstrom, correctly rounded from the exact SI values (h = 6....
Definition Tunneling.h:37
Splitting wkbSplitting(const Profile &p, double hwReactant, double hwProduct)
delta0 = (hbar omega / pi) exp(-S) with the Landau and Lifshitz prefactor.
double harmonicTstLogRate(const MatrixXd &hessReactant, const MatrixXd &hessSaddle, double beta, double barrier, long rigidModes)
ln(k) for classical harmonic transition-state theory, k in 1/time.
double wellCurvature(const Profile &p, bool leftEnd)
d2V/ds2 at one end of the path, in eV / (amu Angstrom^2), from a least squares fit of a s^2 + b s^3 t...
double massWeightedDistance(const Matter &a, const Matter &b)
sqrt(sum_i m_i |b_i - a_i|^2) under the minimum image of a's cell.
Definition Tunneling.cpp:34
std::function< void(const std::vector< VectorXd > &q, std::vector< double > &v, std::vector< VectorXd > &grad)> BatchPotential
V (eV) and dV/dq (eV / (amu^0.5 Angstrom)) at every point of q, all in one call so a potential can sp...
Definition Tunneling.h:152
double quantumHarmonicTstLogRate(const MatrixXd &hessReactant, const MatrixXd &hessSaddle, double beta, double barrier, long rigidModes)
ln(k) for quantum harmonic transition-state theory, k in 1/time: (1 / (2 pi beta hbar)) prod_r 2 sinh...
double crossoverTemperature(const MatrixXd &hessSaddle)
T_c = hbar omega_b / (2 pi kB) from the mass-weighted Hessian at the saddle, in K; throws when the He...
double wkbLogRateAlongPath(const Profile &profile, double beta, double hwReactant)
ln(k), k in 1/time, for the one-dimensional thermal rate along profile.
double hbarOmega(double curvature)
hbar omega in eV for a mass-weighted curvature.
std::vector< double > massWeightedPath(const std::vector< std::shared_ptr< Matter > > &band)
Cumulative mass-weighted arc length at each image of a band.
Definition Tunneling.cpp:52
Instanton optimizeInstanton(const VectorXd &start, const VectorXd &end, double betaHbar, std::vector< VectorXd > guess, const BatchPotential &potential, const InstantonOptions &options)
Minimises the action from guess (P + 1 beads, ends at the minima, or empty for a tanh kink along the ...
constexpr double kBoltzmann
Boltzmann constant in eV / K, correctly rounded from the exact 1.380649e-23 J / K.
Definition Tunneling.h:41
long maxIterations
L-BFGS iterations.
Definition Tunneling.h:144
double forceTolerance
largest per-bead |dS/dq| / dtau, eV / (amu^0.5 Angstrom)
Definition Tunneling.h:145
long beads
P: segments from one minimum to the other.
Definition Tunneling.h:141
long memory
L-BFGS correction pairs.
Definition Tunneling.h:147
double betaHbarOmega
beta hbar omega of the stiffer end along the path; sets the imaginary time
Definition Tunneling.h:142
double asymmetry
V(end) - V(start), eV.
Definition Tunneling.h:168
std::vector< double > energies
V at every bead, eV.
Definition Tunneling.h:161
double zeroMode
the eigenvalue det' leaves out
Definition Tunneling.h:166
double action
(S - S_well) / hbar
Definition Tunneling.h:164
double s0
integral of |dq/dtau|^2 dtau
Definition Tunneling.h:165
bool symmetricEnough
beta |asymmetry| < 0.1: the propagator ratio reads delta0 only when the wells lie within a small frac...
Definition Tunneling.h:173
double modeSeparation
The second smallest eigenvalue of J over the zero mode's: small means the kink is not isolated in ima...
Definition Tunneling.h:176
double betaHbar
imaginary time the path spans
Definition Tunneling.h:162
double dtau
betaHbar / P
Definition Tunneling.h:163
double delta0
tunnelling splitting, eV
Definition Tunneling.h:167
std::vector< VectorXd > path
P + 1 beads, ends at the minima.
Definition Tunneling.h:160
long memory
L-BFGS correction pairs.
Definition Tunneling.h:264
std::vector< double > rigidSqrtMasses
Rigid motions of the ring: a translation, or one rotation about the ring's centre of mass,...
Definition Tunneling.h:292
std::array< bool, 3 > rigidRotations
Definition Tunneling.h:294
double maxStep
largest bead move per step, amu^0.5 Angstrom
Definition Tunneling.h:262
double energyShift
subtracted from every bead potential, eV
Definition Tunneling.h:275
long beads
N, beads on the ring.
Definition Tunneling.h:255
long lanczosRestart
Lanczos steps from the previous mode.
Definition Tunneling.h:260
double forceTolerance
largest per-bead |dU_N/dq|, eV / (amu^0.5 Angstrom)
Definition Tunneling.h:257
bool halfRing
Even N, when the guess already matches under j -> N - j: evaluate the potential from one turning poin...
Definition Tunneling.h:268
double lanczosStep
finite-difference step, amu^0.5 Angstrom
Definition Tunneling.h:261
std::string initialHessians
Where the bead Hessian blocks start: "saddle" copies the saddle's Hessian to every bead and lets the ...
Definition Tunneling.h:283
long newtonLimit
Active coordinates at or below this take the Newton step.
Definition Tunneling.h:279
long lanczosFirst
Lanczos steps for the first minimum mode.
Definition Tunneling.h:259
bool checkOddSector
A half ring that has converged, or that is stationary at the wrong index, is probed for an unstable m...
Definition Tunneling.h:274
long maxIterations
translation steps
Definition Tunneling.h:256
long negativeModes
eigenvalues below the zero mode
Definition Tunneling.h:327
double zeroEigenvalue
the eigenvalue left out
Definition Tunneling.h:326
double beta
1 / (kB T), 1 / eV
Definition Tunneling.h:319
std::vector< double > energies
V at every bead, eV.
Definition Tunneling.h:318
double bN
sum_j |q_{j+1} - q_j|^2, amu Angstrom^2
Definition Tunneling.h:324
double logRate
ln k, k in 1 / time
Definition Tunneling.h:332
std::vector< VectorXd > beads
N beads, q_N = q_0 implied.
Definition Tunneling.h:317
double classicalRate
Classical harmonic transition-state theory at the same T, 1 / s, when the saddle Hessian was given; i...
Definition Tunneling.h:339
double logRateTimesZr
ln(k Z_r), k in 1 / time
Definition Tunneling.h:330
double negativeEigenvalue
of the ring Hessian, 1 / time^2
Definition Tunneling.h:325
double effectiveBarrier
-kB T ln(2 pi hbar beta k): the barrier an Eyring rate would need, eV.
Definition Tunneling.h:335
Spectrum of a closed ring's Hessian without forming it.
Definition Tunneling.h:298
double logDetPrime
ln |det' J|: the product over every eigenvalue but the one along tau.
Definition Tunneling.h:300
long negativeModes
Eigenvalues below zero, the one along tau left out.
Definition Tunneling.h:302
bool deepWells
Both barriers stand above hbar omega; below that WKB is not the right tool and the number is reported...
Definition Tunneling.h:87
double hwReactant
hbar omega of the reactant well, eV
Definition Tunneling.h:80
double delta0
tunnelling splitting, eV
Definition Tunneling.h:84
double barrier
path maximum above the reactant, eV
Definition Tunneling.h:79
double referenceEnergy
the level tunnelling happens at, eV
Definition Tunneling.h:82
double action
the WKB exponent, dimensionless
Definition Tunneling.h:83
double tlsEnergy() const
sqrt(delta^2 + delta0^2), eV
double hwProduct
hbar omega of the product well, eV
Definition Tunneling.h:81
double delta
product minus reactant, eV
Definition Tunneling.h:78