23#include <boost/format.hpp>
24#include <boost/timer/progress_display.hpp>
48 ".decayprobfile",
"");
53 alpha_ = carrier_options.get(
".alpha").as<
double>();
54 outputsteps_ = carrier_options.get(
".outputsteps").as<
unsigned long>();
62 field_ = Eigen::Vector3d::Zero();
67 Eigen::VectorXd outrates = Eigen::VectorXd::Zero(
nodes_.size());
68 Eigen::VectorXd inrates = Eigen::VectorXd::Zero(
nodes_.size());
69 Eigen::VectorXd decayrates = Eigen::VectorXd::Ones(
nodes_.size());
71 for (
unsigned i = 0; i <
nodes_.size(); i++) {
75 if (event.isDecayEvent()) {
76 decayrates[i] =
event.getRate();
78 inrates[
event.getDestination()->getId()] +=
event.getRate();
79 outrates[i] +=
event.getRate();
84 outrates = decayrates.cwiseQuotient(outrates + decayrates);
85 inrates = decayrates.cwiseQuotient(inrates + decayrates);
88 probs.open(filename, std::fstream::out);
89 if (!probs.is_open()) {
90 std::string error_msg =
"Unable to write to file " + filename;
91 throw std::runtime_error(error_msg);
93 probs <<
"#SiteID, Relative Prob outgoing, Relative Prob ingoing\n";
94 for (
unsigned i = 0; i <
nodes_.size(); i++) {
95 probs <<
nodes_[i].getId() <<
" " << outrates[i] <<
" " << inrates[i]
105 std::vector<tools::Property*> jobProps = xml.
Select(
"lifetimes.site");
106 if (jobProps.size() !=
nodes_.size()) {
107 throw std::runtime_error(
108 (boost::format(
"The number of sites in the topology: %i does not match "
109 "the number in the lifetimefile: %i") %
110 nodes_.size() % jobProps.size())
115 Index site_id = prop->getAttribute<
Index>(
"id");
116 double lifetime = boost::lexical_cast<double>(prop->value());
118 for (
auto& node :
nodes_) {
119 if (node.getId() == site_id && !(node.canDecay())) {
120 node.AddDecayEvent(1.0 / lifetime);
123 }
else if (node.getId() == site_id && node.canDecay()) {
124 throw std::runtime_error(
125 (boost::format(
"Node %i appears twice in your list") % site_id)
130 throw std::runtime_error(
131 (boost::format(
"Site from file with id: %i not found in state file") %
136 for (
auto& node :
nodes_) {
137 node.InitEscapeRate();
146 const Eigen::Vector3d& dr_travelled = affectedcarrier.
get_dRtravelled();
147 traj << simtime <<
"\t" << insertioncount <<
"\t" << affectedcarrier.
getId()
149 << affectedcarrier.
getSteps() <<
"\t"
158 std::chrono::time_point<std::chrono::system_clock> realtime_start =
159 std::chrono::system_clock::now();
161 <<
"\nAlgorithm: VSSM for Multiple Charges with finite Lifetime\n"
162 "number of charges: "
167 throw std::runtime_error(
168 "ERROR in kmclifetime: specified number of charges is greater than the "
169 "number of nodes. This conflicts with single occupation.");
173 std::fstream energyfile;
179 if (!traj.is_open()) {
181 throw std::runtime_error(error_msg);
184 traj <<
"#Simtime [s]\t Insertion\t Carrier ID\t Lifetime[s]\tSteps\t Last "
185 "Segment\t x_travelled[nm]\t y_travelled[nm]\t z_travelled[nm]\n";
190 <<
"Tracking the energy of one charge carrier and exponential average "
194 if (!energyfile.is_open()) {
196 throw std::runtime_error(error_msg);
199 energyfile <<
"Simtime [s]\tSteps\tCarrier ID\tEnergy_a=" <<
alpha_
209 unsigned long insertioncount = 0;
210 unsigned long step = 0;
211 double simtime = 0.0;
213 std::vector<GNode*> forbiddennodes;
214 std::vector<GNode*> forbiddendests;
216 time_t now = time(
nullptr);
217 tm* localtm = localtime(&now);
219 <<
"Run started at " << asctime(localtm) << std::flush;
221 double avlifetime = 0.0;
222 double meanfreepath = 0.0;
223 Eigen::Vector3d difflength_squared = Eigen::Vector3d::Zero();
225 double avgenergy =
carriers_[0].getCurrentEnergy();
229 std::chrono::duration<double> elapsed_time =
230 std::chrono::system_clock::now() - realtime_start;
231 if (elapsed_time.count() > (
maxrealtime_ * 60. * 60.)) {
233 <<
"\nReal time limit of " <<
maxrealtime_ <<
" hours ("
235 <<
" seconds) has been reached. Stopping here.\n"
240 double cumulated_rate = 0;
243 cumulated_rate += carrier.getCurrentEscapeRate();
245 if (cumulated_rate == 0) {
247 throw std::runtime_error(
248 "ERROR in kmclifetime: Incorrect rates in the database file. All the "
249 "escape rates for the current setting are 0.");
256 if (
carriers_[0].getId() > carrieridold) {
257 avgenergy =
carriers_[0].getCurrentEnergy();
266 energyfile << simtime <<
"\t" << step <<
"\t" <<
carriers_[0].getId()
274 carrier.updateLifetime(dt);
275 carrier.updateSteps(1);
276 carrier.updateOccupationtime(dt);
280 bool secondlevel =
true;
281 while (secondlevel) {
284 GNode* newnode =
nullptr;
293 boost::timer::progress_display progress(
insertions_);
302 if (event.isDecayEvent()) {
303 const Eigen::Vector3d& dr_travelled =
306 meanfreepath += dr_travelled.norm();
307 difflength_squared += dr_travelled.cwiseAbs2();
308 WriteToTraj(traj, insertioncount, simtime, *affectedcarrier);
317 newnode =
event.getDestination();
352 <<
"\nTotal runtime:\t\t\t\t\t" << simtime
354 "Total KMC steps:\t\t\t\t"
355 << step <<
"\nAverage lifetime:\t\t\t\t"
356 << avlifetime / double(insertioncount) <<
" s\n"
357 <<
"Mean freepath\t l=<|r_x-r_o|> :\t\t"
360 <<
"Average diffusionlength\t d=sqrt(<(r_x-r_o)^2>)\t"
361 << std::sqrt(difflength_squared.norm() /
double(insertioncount)) *
376 "\n KMCLIFETIME started"
377 "\n-----------------------------------\n"
392 time_t now = time(
nullptr);
393 tm* localtm = localtime(&now);
Index getCurrentNodeId() const
GNode & getCurrentNode() const
void jumpAccordingEvent(const GLink &event)
const Eigen::Vector3d & get_dRtravelled() const
double getLifetime() const
const std::vector< GLink > & Events() const
void ResetForbiddenlist(std::vector< GNode * > &forbiddenid) const
void LoadGraph(Topology &top)
std::vector< Chargecarrier > carriers_
double Promotetime(double cumulated_rate)
Chargecarrier * ChooseAffectedCarrier(double cumulated_rate)
const GLink & ChooseHoppingDest(const GNode &node)
void AddtoForbiddenlist(GNode &node, std::vector< GNode * > &forbiddenid) const
void RandomlyAssignCarriertoSite(Chargecarrier &Charge)
void RandomlyCreateCharges()
std::string trajectoryfile_
bool CheckSurrounded(const GNode &node, const std::vector< GNode * > &forbiddendests) const
std::string injectionmethod_
tools::Random RandomVariable_
std::vector< GNode > nodes_
void WriteOccupationtoFile(double simtime, std::string filename)
bool CheckForbidden(const GNode &node, const std::vector< GNode * > &forbiddenlist) const
void WriteToTraj(std::fstream &traj, unsigned long insertioncount, double simtime, const Chargecarrier &affectedcarrier) const
void WriteDecayProbability(std::string filename)
void ReadLifetimeFile(std::string filename)
std::string lifetimefile_
unsigned long outputsteps_
void ParseSpecificOptions(const tools::Property &user_options)
std::string energy_outputfile_
unsigned long insertions_
bool Evaluate(Topology &top)
void setReportLevel(Log::Level ReportLevel)
void setCommonPreface(const std::string &preface)
std::string ToLongString() const
Container for segments and box and atoms.
#define XTP_LOG(level, log)
base class for all analysis tools
static Level current_level