votca 2026-dev
Loading...
Searching...
No Matches
kmcwaitingtime.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2026 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20// Standard includes
21#include <algorithm>
22#include <limits>
23#include <stdexcept>
24
25// Local VOTCA includes
27
28namespace votca {
29namespace xtp {
30
31double TimeDependentRates::EscapeRate(Index site, double t) const {
32 double sum = 0.0;
33 for (Index e = graph_.EdgeOffset(site); e < graph_.EdgeOffset(site + 1);
34 ++e) {
35 sum += Rate(e, t);
36 }
37 return sum;
38}
39
40namespace {
41// cumulative sums of per-edge values within each site
42std::vector<double> CumulativePerSite(const ToFGraph& graph,
43 const std::vector<double>& value,
44 std::vector<double>& total) {
45 std::vector<double> cumulative(value.size());
46 total.assign(graph.NumberOfSites(), 0.0);
47 for (Index i = 0; i < graph.NumberOfSites(); ++i) {
48 double sum = 0.0;
49 for (Index e = graph.EdgeOffset(i); e < graph.EdgeOffset(i + 1); ++e) {
50 sum += value[e];
51 cumulative[e] = sum;
52 }
53 total[i] = sum;
54 }
55 return cumulative;
56}
57
58// edge of site i with cumulative value reaching target
59Index FindEdge(const ToFGraph& graph, const std::vector<double>& cumulative,
60 Index site, double target) {
61 Index begin = graph.EdgeOffset(site);
62 Index end = graph.EdgeOffset(site + 1);
63 Index e = Index(std::lower_bound(cumulative.begin() + begin,
64 cumulative.begin() + end, target) -
65 cumulative.begin());
66 return std::min(e, end - 1);
67}
68
69double Infinity() { return std::numeric_limits<double>::infinity(); }
70} // namespace
71
72// exponential
73
75 if (!rates.isStatic()) {
76 throw std::runtime_error(
77 "ExponentialWaitingTime needs static rates, use thinning or the "
78 "integrated-rate inversion for time-dependent rates");
79 }
80 graph_ = &rates.Graph();
81 std::vector<double> value(graph_->NumberOfEdges());
82 for (Index e = 0; e < graph_->NumberOfEdges(); ++e) {
83 value[e] = rates.Rate(e, 0.0);
84 }
85 cumulative_ = CumulativePerSite(*graph_, value, escape_);
86}
87
89 KMCRandom& random) const {
90 double escape = escape_[site];
91 return (escape > 0.0) ? t + random.Exponential(escape) : Infinity();
92}
93
95 KMCRandom& random) const {
96 return FindEdge(*graph_, cumulative_, site, random.Uniform() * escape_[site]);
97}
98
99// thinning
100
102 rates_ = &rates;
103 const ToFGraph& graph = rates.Graph();
104 std::vector<double> bound(graph.NumberOfEdges());
105 for (Index e = 0; e < graph.NumberOfEdges(); ++e) {
106 bound[e] = rates.UpperBound(e);
107 if (!(bound[e] >= 0.0)) {
108 throw std::runtime_error("ThinningWaitingTime: invalid upper bound");
109 }
110 }
111 cumulative_ = CumulativePerSite(graph, bound, bound_escape_);
112}
113
115 KMCRandom& random) const {
116 double escape = bound_escape_[site];
117 return (escape > 0.0) ? t + random.Exponential(escape) : Infinity();
118}
119
121 KMCRandom& random) const {
122 const ToFGraph& graph = rates_->Graph();
123 Index e = FindEdge(graph, cumulative_, site,
124 random.Uniform() * bound_escape_[site]);
125 double bound = rates_->UpperBound(e);
126 double rate = rates_->Rate(e, t);
127 if (rate > bound * (1.0 + 1e-12)) {
128 throw std::runtime_error(
129 "ThinningWaitingTime: rate above its upper bound for edge " +
130 std::to_string(e));
131 }
132 return (random.Uniform() * bound <= rate) ? e : -1;
133}
134
135// integrated-rate inversion: template for the implementation
136
138 rates_ = &rates;
139 if (settings_.quadrature_points < 2 || settings_.interpolation_points < 2) {
140 throw std::runtime_error(
141 "IntegratedRateInversion: need at least two quadrature and "
142 "interpolation points");
143 }
144 if (!(rates.Period() > 0.0)) {
145 throw std::runtime_error(
146 "IntegratedRateInversion needs periodic rates (Period() > 0)");
147 }
148 // TODO: per site i, Lambda_i(t) = int_0^t EscapeRate(i, s) ds on [0, T]
149 // (settings_.quadrature_points), I_T = Lambda_i(T), monotone interpolant
150 throw std::logic_error(
151 "IntegratedRateInversion: not implemented yet (template, see "
152 "kmcwaitingtime.h)");
153}
154
156 // TODO: g = -ln(u); split t into periods and phase; m and the remainder
157 // from I_T; monotone root search on [0, 2T) (BEP eqs. 11-18)
158 throw std::logic_error("IntegratedRateInversion: not implemented yet");
159}
160
162 // TODO: edge e with probability Rate(e, t) / EscapeRate(i, t)
163 throw std::logic_error("IntegratedRateInversion: not implemented yet");
164}
165
166std::unique_ptr<WaitingTimeStrategy> MakeWaitingTimeStrategy(
167 const std::string& name) {
168 if (name == "exponential") {
169 return std::make_unique<ExponentialWaitingTime>();
170 } else if (name == "thinning") {
171 return std::make_unique<ThinningWaitingTime>();
172 } else if (name == "inversion") {
173 return std::make_unique<IntegratedRateInversion>(
175 }
176 throw std::runtime_error("unknown waiting-time strategy '" + name +
177 "', use exponential, thinning or inversion");
178}
179
180} // namespace xtp
181} // namespace votca
Index ChooseHop(Index site, double t, KMCRandom &random) const override
std::vector< double > cumulative_
double NextTime(Index site, double t, KMCRandom &random) const override
void Prepare(const TimeDependentRates &rates) override
const TimeDependentRates * rates_
double NextTime(Index site, double t, KMCRandom &random) const override
Index ChooseHop(Index site, double t, KMCRandom &random) const override
void Prepare(const TimeDependentRates &rates) override
Random numbers for kinetic Monte Carlo: one independent stream per (seed, stream) pair....
Definition kmcrandom.h:42
double Uniform()
uniform in (0,1]
Definition kmcrandom.h:46
double Exponential(double rate)
Exp(rate), i.e. -ln(u)/rate.
Definition kmcrandom.h:50
std::vector< double > bound_escape_
const TimeDependentRates * rates_
std::vector< double > cumulative_
double NextTime(Index site, double t, KMCRandom &random) const override
Index ChooseHop(Index site, double t, KMCRandom &random) const override
void Prepare(const TimeDependentRates &rates) override
Hop rates of the edges of a ToFGraph as functions of time.
Definition kmcrates.h:52
virtual double EscapeRate(Index site, double t) const
const ToFGraph & graph_
Definition kmcrates.h:76
const ToFGraph & Graph() const
Definition kmcrates.h:72
virtual double UpperBound(Index edge) const =0
an upper bound of Rate(edge, t) for all t (needed by thinning)
virtual bool isStatic() const
true if no rate depends on time
Definition kmcrates.h:70
virtual double Period() const
common period T of all rates if they are periodic, 0 otherwise
Definition kmcrates.h:67
virtual double Rate(Index edge, double t) const =0
rate of edge e at time t
Hopping graph for time-of-flight (ToF) transport.
Definition tofgraph.h:77
Index NumberOfSites() const
Definition tofgraph.h:149
Index NumberOfEdges() const
Definition tofgraph.h:157
Index EdgeOffset(Index i) const
Definition tofgraph.h:160
Charge transport classes.
Definition ERIs.h:28
std::unique_ptr< WaitingTimeStrategy > MakeWaitingTimeStrategy(const std::string &name)
strategy by name: exponential, thinning, inversion
Provides a means for comparing floating point numbers.
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26