Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
CrossSlipBranch.cpp
Go to the documentation of this file.
1#include <CrossSlipBranch.h>
2
3namespace model
4{
5 std::optional<ThermalCrossSlipEvent> sampleThermalCrossSlip(
6 const std::vector<double>& lengths,
7 const std::vector<std::map<int,double>>& rates,
8 const std::map<int,double>& nucleusLengths,
9 const double dt, const double occurrence, const double targetDraw, const double positionDraw)
10 {
11 if(lengths.size()!=rates.size() || !std::isfinite(dt) || dt<0.0)
12 {
13 throw std::runtime_error("Invalid thermal cross-slip sampling data");
14 }
15 for(const double draw : {occurrence,targetDraw,positionDraw})
16 {
17 if(!std::isfinite(draw) || draw<0.0 || draw>=1.0)
18 {
19 throw std::runtime_error("Thermal cross-slip uniforms must lie in [0,1)");
20 }
21 }
22 double length=0.0;
23 for(const double value : lengths)
24 {
25 if(!std::isfinite(value) || value<0.0)
26 {
27 throw std::runtime_error("Invalid thermal branch length");
28 }
29 length+=value;
30 }
31 std::map<int,double> totals;
32 for(const auto& segment : rates)
33 {
34 for(const auto& [target,rate] : segment)
35 {
36 const double nucleus=nucleusLengths.at(target);
37 if(!std::isfinite(rate) || rate<0.0 || !std::isfinite(nucleus) || nucleus<=0.0)
38 {
39 throw std::runtime_error("Invalid thermal cross-slip rate or nucleation length");
40 }
41 if(length>=nucleus)
42 {
43 totals[target]+=rate;
44 }
45 }
46 }
47 double total=0.0;
48 for(const auto& [target,rate] : totals)
49 {
50 total+=rate;
51 }
52 if(!std::isfinite(total))
53 {
54 throw std::runtime_error("Thermal cross-slip total rate overflow");
55 }
56 if(total<=0.0 || occurrence>=-std::expm1(-total*dt))
57 {
58 return std::nullopt;
59 }
60 double selection=targetDraw*total;
61 for(const auto& [target,rate] : totals)
62 {
63 if(rate>0.0 && selection<rate)
64 {
65 double location=positionDraw*rate;
66 double offset=0.0;
67 for(size_t k=0;k<rates.size();++k)
68 {
69 const auto found=rates[k].find(target);
70 const double local=found==rates[k].end()? 0.0 : found->second;
71 if(local>0.0 && location<local)
72 {
73 const double nucleus=nucleusLengths.at(target);
74 const double center=std::clamp(offset+lengths[k]*location/local,0.5*nucleus,length-0.5*nucleus);
75 return ThermalCrossSlipEvent{target,nucleus,center/length};
76 }
77 location-=local;
78 offset+=lengths[k];
79 }
80 }
81 selection-=rate;
82 }
83 throw std::runtime_error("Thermal cross-slip selection failed");
84 }
85
86 template<int dim>
87 CrossSlipBranch<dim>::CrossSlipBranch(std::deque<std::shared_ptr<LoopNodeType>> nodes,int target) :
88 first(std::move(nodes)),second(target)
89 {
90 }
91
92 template struct CrossSlipBranch<3>;
93}
std::optional< ThermalCrossSlipEvent > sampleThermalCrossSlip(const std::vector< double > &lengths, const std::vector< std::map< int, double > > &rates, const std::map< int, double > &nucleusLengths, const double dt, const double occurrence, const double targetDraw, const double positionDraw)
std::deque< std::shared_ptr< LoopNodeType > > first
CrossSlipBranch(std::deque< std::shared_ptr< LoopNodeType > > nodes, int target)
int k