Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
LoopLink.h
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MoDELib is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_LoopLink_H_
9#define model_LoopLink_H_
10
11#include <algorithm>
12#include <memory>
13#include <string>
14#include <iterator>
15#include <TypeTraits.h>
16
17//#include <NodeObserver.h>
18#include <NetworkBase.h>
19#include <NetworkLink.h>
20
21#ifndef NDEBUG
22#define VerboseLoopLink(N,x) if(verboseLevel>=N){std::cout<<blueColor<<x<<defaultColor;}
23#else
24#define VerboseLoopLink(N,x)
25#endif
26
27namespace model
28{
29 template<typename Derived>
30 class LoopLink : public CRTP<Derived>
31// /* */,public NetworkBase<Derived,std::array<size_t,3>>
32
33 {
34
35 public:
36
38// typedef NetworkBase<Derived,std::array<size_t,3>> NetworkBaseType;
43 typedef std::array<size_t,3> KeyType;
44
45
46 /**********************************************************************/
47 static KeyType loopLinkKey(const std::shared_ptr<LoopType>& loop,
48 const std::shared_ptr<LoopNodeType>& Ni,
49 const std::shared_ptr<LoopNodeType>& Nj)
50 {
51 return KeyType{loop->sID,std::min(Ni->sID,Nj->sID),std::max(Ni->sID,Nj->sID)};
52 // return KeyType{loop->sID,Ni->sID,Nj->sID};
53 }
54
55 static int verboseLevel;
56
57 const KeyType key;
58 const std::shared_ptr<LoopNodeType> source;
59 const std::shared_ptr<LoopNodeType> sink;
60 const std::shared_ptr<LoopType> loop; // THIS SHOULD BE CONST, THAT WAY WE COULD USE A MAP WITH 3 IDs TO STORE LOOPLINKS
61
62 private:
63 std::shared_ptr<NetworkLinkType> _networkLink;
64 bool attached=false;
65
66
67 public:
68
69 Derived* prev;
70 Derived* next;
71
72// friend void LoopNode<LoopNodeType>::addLoopLink(Derived* const);
73// friend void LoopNode<LoopNodeType>::removeLoopLink(Derived* const);
74
75
76 /**********************************************************************/
77 LoopLink(const std::shared_ptr<LoopNodeType>& so,
78 const std::shared_ptr<LoopNodeType>& si,
79 const std::shared_ptr<LoopType>& pL) :
80 /* init */ key(loopLinkKey(pL,so,si))
81// /* init */ NetworkBaseType(pL->p_network(),&pL->p_network()->loopLinks(),loopLinkKey(pL,so,si))
82 /* init */,source(so)
83 /* init */,sink(si)
84 /* init */,loop(pL)
85 /* init */,_networkLink(getNetworkLink())
86 /* init */,prev(nullptr)
87 /* init */,next(nullptr)
88 {
89 VerboseLoopLink(1,"Constructing LoopLink "<<tag()<<std::endl);
91 }
92
94 {
95 if(attached)
96 {
97 return;
98 }
99 bool sourceAdded=false,sinkAdded=false,loopAdded=false;
100 try
101 {
102 source->addLoopLink(this->p_derived());
103 sourceAdded=true;
104 sink->addLoopLink(this->p_derived());
105 sinkAdded=true;
106 loop->addLoopLink(this->p_derived());
107 loopAdded=true;
108 if(_networkLink)
109 {
110 _networkLink->addLoopLink(this->p_derived());
111 }
112 }
113 catch(...)
114 {
115 // A failed constructor does not call ~LoopLink. Undo partial
116 // registration explicitly, including derived segment checks.
117 if(_networkLink && _networkLink->loopLinks().count(this->p_derived()))
118 {
119 _networkLink->removeLoopLink(this->p_derived());
120 }
121 if(loopAdded)
122 {
123 loop->removeLoopLink(this->p_derived());
124 }
125 if(sinkAdded)
126 {
127 sink->removeLoopLink(this->p_derived());
128 }
129 if(sourceAdded)
130 {
131 source->removeLoopLink(this->p_derived());
132 }
133 prev=nullptr;
134 next=nullptr;
135 throw;
136 }
137 attached=true;
138 }
139
140 /**********************************************************************/
142 {
144 }
145
147 {
148 if(!attached)
149 {
150 return;
151 }
152 // Inverse order of attachment, without destroying the link.
153 VerboseLoopLink(1,"Destroying LoopLink "<<tag()<<std::endl);
154 if(_networkLink)
155 {
156 _networkLink->removeLoopLink(this->p_derived());
157 }
158 loop->removeLoopLink(this->p_derived());
159 sink->removeLoopLink(this->p_derived());
160 source->removeLoopLink(this->p_derived());
161 prev=nullptr;
162 next=nullptr;
163 attached=false;
164 }
165
166 const std::shared_ptr<NetworkLinkType>& networkLink() const
167 {
168 return _networkLink;
169 }
170
171 Derived* twin() const
172 {
173 if(networkLink())
174 {
175 for(const auto& link : networkLink()->loopLinks())
176 {
177 if(link->loop==loop && link!=this)
178 {
179 return link;
180 }
181 }
182 }
183 return nullptr;
184 }
185
186 std::shared_ptr<NetworkLinkType> getNetworkLink()
187 {
188 if(this->derived().hasNetworkLink())
189 {
190 auto netLink(loop->network().networkLinks().get(NetworkLinkType::getKey(source->networkNode,sink->networkNode)));
191 return netLink? netLink : loop->network().networkLinks().create(source->networkNode,sink->networkNode);
192 }
193 else
194 {
195 return nullptr;
196 }
197 }
198
200 {
201 if(_networkLink)
202 {
203 _networkLink->removeLoopLink(this->p_derived());
204 }
205 _networkLink=getNetworkLink();
206 if(_networkLink)
207 {
208 _networkLink->addLoopLink(this->p_derived());
209 }
210 }
211
212 /**********************************************************************/
213 const FlowType& flow() const
214 {
216 return loop->flow();
217 }
218
219 /**********************************************************************/
220 std::string tag() const
221 {
223 return source->tag() + "->" + sink->tag() + " ("+std::to_string(loop->sID)+")";
224 }
225
226
227 /**********************************************************************/
228 template <class T>
229 friend T& operator << (T& os, const LoopLink<Derived>& ll)
230 {
231 os << ll.loop->sID<<"\t"
232 /**/<< ll.source->sID<<"\t"
233 /**/<< ll.sink->sID<<"\t";
234
235 return os;
236 }
237
238 };
239
240 template<typename LinkType>
242
243}
244#endif
Derived * p_derived()
A pointer to the derived object.
Definition CRTP.h:27
Derived & derived()
A reference to the derived object.
Definition CRTP.h:24
CRTP()
The default constructor.
Definition CRTP.h:37