Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
GalerkinGlideSolver_lumped.cpp
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_GalerkinGlideSolver_cpp_
9#define model_GalerkinGlideSolver_cpp_
10
11#include <GalerkinGlideSolver.h>
13#include <TerminalColors.h>
14
15#include <DislocationNetwork.h>
16
17namespace model
18{
19
20 template <int dim>
22 /* init */ DislocationGlideSolverBase<dim>(DN_in)
23 {
24 std::cout<<greenBoldColor<<"Creating GalerkinGlideSolver"<<defaultColor<<std::endl;
25 }
26
27 template <int dim>
28 Eigen::VectorXd GalerkinGlideSolver<dim>::getNodeVelocities() const
29 {
30 return lumpedSolve();
31 }
32
33
34 template <int dim>
35 size_t GalerkinGlideSolver<dim>::assembleNCtriplets(TripletContainerType& kqqT, Eigen::VectorXd& Fq) const
36 {
37 const size_t Ndof(this->DN.networkNodes().size()*NdofXnode); // the total number of dof in the subnetwork
38 // Rebuild after every topology change; never retain indices on nodes.
39 std::map<size_t,size_t> nodeIndices;
40 for(const auto& entry : this->DN.networkNodes())
41 {
42 nodeIndices.emplace(entry.second.lock()->sID,nodeIndices.size());
43 }
44 kqqT.clear();
45 Fq.setZero(Ndof);
46 for (const auto& networkLink : this->DN.networkLinks())
47 {
48 if (!networkLink.second.lock()->isBoundarySegment())
49 {
50 const auto link=networkLink.second.lock();
51 link->addToGlobalAssembly(kqqT,Fq,nodeIndices.at(link->source->sID),nodeIndices.at(link->sink->sID)); // loop over each segment and add segment contributions to kqqT and Fq
52 }
53 }
54 return Ndof;
55 }
56
57// Shared periodic crossings enforce every participating loop interpolation.
58 template <int dim>
59 size_t GalerkinGlideSolver<dim>::assemblePeriodicConstraints(TripletContainerType &zT) const
60 {
61 return periodicVelocityConstraints<dim>(this->DN,zT);
62 }
63
64 template <int dim>
65 Eigen::VectorXd GalerkinGlideSolver<dim>::lumpedSolve() const
66 {
67 std::cout<<", glideSolver "<<std::flush;
68 TripletContainerType kqqT;
69 Eigen::VectorXd Fq;
70 const size_t Ndof=assembleNCtriplets(kqqT,Fq);
71
72 // Physical boundary nodes keep independent velocities. Only actual
73 // same-grain periodic subdivisions interpolate their source endpoints.
74 // With no subdivisions Z is the identity, including nonperiodic domains.
75 TripletContainerType zT;
76 const size_t nUnconstrained=assemblePeriodicConstraints(zT);
77 SparseMatrixType K(Ndof,Ndof);
78 K.setFromTriplets(kqqT.begin(),kqqT.end());
79 SparseMatrixType Z(Ndof,dim*nUnconstrained);
80 Z.setFromTriplets(zT.begin(),zT.end());
81 const SparseMatrixType reduced(Z.transpose()*K*Z);
82 const Eigen::VectorXd force(Z.transpose()*Fq);
83
84 // Symmetric row-sum lumping after eliminating subdivision velocities.
85 Eigen::VectorXd diagonal=Eigen::VectorXd::Zero(dim*nUnconstrained);
86 for(int k=0;k<reduced.outerSize();++k)
87 {
88 for(typename SparseMatrixType::InnerIterator it(reduced,k);it;++it)
89 {
90 if(it.row()==it.col())
91 {
92 diagonal(it.row())+=it.value();
93 }
94 else
95 {
96 diagonal(it.row())+=0.5*it.value();
97 diagonal(it.col())+=0.5*it.value();
98 }
99 }
100 }
101 Eigen::VectorXd velocity=Eigen::VectorXd::Zero(dim*nUnconstrained);
102 for(Eigen::Index k=0;k<diagonal.size();++k)
103 {
104 if(std::fabs(diagonal(k))>FLT_EPSILON)
105 {
106 velocity(k)=force(k)/diagonal(k);
107 }
108 else if(std::fabs(force(k))>FLT_EPSILON)
109 {
110 throw std::runtime_error("Nonzero glide force on a zero-mass degree of freedom.");
111 }
112 }
113 return Z*velocity;
114 }
115
116 template class GalerkinGlideSolver<3>;
117
118}
119#endif
GalerkinGlideSolver(const DislocationNetwork< dim > &)
int k