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());
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) -
66 return std::min(
e, end - 1);
69double Infinity() {
return std::numeric_limits<double>::infinity(); }
76 throw std::runtime_error(
77 "ExponentialWaitingTime needs static rates, use thinning or the "
78 "integrated-rate inversion for time-dependent rates");
81 std::vector<double> value(
graph_->NumberOfEdges());
83 value[
e] = rates.
Rate(
e, 0.0);
91 return (escape > 0.0) ? t + random.
Exponential(escape) : Infinity();
107 if (!(bound[
e] >= 0.0)) {
108 throw std::runtime_error(
"ThinningWaitingTime: invalid upper bound");
117 return (escape > 0.0) ? t + random.
Exponential(escape) : Infinity();
125 double bound =
rates_->UpperBound(
e);
126 double rate =
rates_->Rate(
e, t);
127 if (rate > bound * (1.0 + 1
e-12)) {
128 throw std::runtime_error(
129 "ThinningWaitingTime: rate above its upper bound for edge " +
132 return (random.
Uniform() * bound <= rate) ?
e : -1;
140 throw std::runtime_error(
141 "IntegratedRateInversion: need at least two quadrature and "
142 "interpolation points");
144 if (!(rates.
Period() > 0.0)) {
145 throw std::runtime_error(
146 "IntegratedRateInversion needs periodic rates (Period() > 0)");
150 throw std::logic_error(
151 "IntegratedRateInversion: not implemented yet (template, see "
152 "kmcwaitingtime.h)");
158 throw std::logic_error(
"IntegratedRateInversion: not implemented yet");
163 throw std::logic_error(
"IntegratedRateInversion: not implemented yet");
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>(
176 throw std::runtime_error(
"unknown waiting-time strategy '" + name +
177 "', use exponential, thinning or inversion");
Index ChooseHop(Index site, double t, KMCRandom &random) const override
std::vector< double > escape_
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....
double Uniform()
uniform in (0,1]
double Exponential(double rate)
Exp(rate), i.e. -ln(u)/rate.
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.
virtual double EscapeRate(Index site, double t) const
const ToFGraph & Graph() const
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
virtual double Period() const
common period T of all rates if they are periodic, 0 otherwise
virtual double Rate(Index edge, double t) const =0
rate of edge e at time t
Hopping graph for time-of-flight (ToF) transport.
Index NumberOfSites() const
Index NumberOfEdges() const
Index EdgeOffset(Index i) const
Charge transport classes.
std::unique_ptr< WaitingTimeStrategy > MakeWaitingTimeStrategy(const std::string &name)
strategy by name: exponential, thinning, inversion
Provides a means for comparing floating point numbers.