8#ifndef model_GalerkinClimbSolver_cpp_
9#define model_GalerkinClimbSolver_cpp_
29 std::cout<<greenBoldColor<<
"Creating GalerkinClimbSolver"<<defaultColor<<std::endl;
33 typename GalerkinClimbSolver<dim>::ForceVectorMatrixType GalerkinClimbSolver<dim>::clusterForceKernel(
const int&
k,
const NetworkLinkType& fieldSegment)
const
35 const Eigen::Matrix<double,1,mSize> deltaC(fieldSegment.quadraturePoint(
k).cDD-fieldSegment.quadraturePoint(
k).cCD);
36 const double u(fieldSegment.quadraturePoint(
k).abscissa);
37 return (ForceVectorMatrixType()<<(1.0-
u)*deltaC,
u*deltaC).finished();
41 typename GalerkinClimbSolver<dim>::ForceVectorMatrixType GalerkinClimbSolver<dim>::clusterForceVector(
const NetworkLinkType& fieldSegment)
const
43 ForceVectorMatrixType
F(ForceVectorMatrixType::Zero());
44 const auto bxt(fieldSegment.burgers().cross(fieldSegment.chord()));
45 NetworkLinkType::QuadratureDynamicType::integrate(fieldSegment.quadraturePoints().size(),
this,F,&GalerkinClimbSolver<dim>::clusterForceKernel,fieldSegment);
46 F.row(0)*=bxt.dot(fieldSegment.source->climbDirection());
47 F.row(1)*=bxt.dot(fieldSegment.sink->climbDirection());
52 typename GalerkinClimbSolver<dim>::StiffnessMatrixType GalerkinClimbSolver<dim>::clusterStiffnessKernel(
const int&
k,
const NetworkLinkType& fieldSegment,
const NetworkLinkType& sourceSegment)
const
54 StiffnessMatrixType
temp(StiffnessMatrixType::Zero());
55 if(sourceSegment.grains().size() == 1)
57 const auto bxt(fieldSegment.burgers().cross(fieldSegment.chord()));
58 const double u(fieldSegment.quadraturePoint(
k).abscissa);
59 const Eigen::Matrix<double,2,1>
m(( Eigen::Matrix<double,2,1>()<<(1.0-
u)*bxt.dot(fieldSegment.source->climbDirection()),
60 u*bxt.dot(fieldSegment.sink->climbDirection())).finished());
61 const auto sourceConcentratoinMatrices(sourceSegment.concentrationMatrices(fieldSegment.quadraturePoint(
k).r,this->CD->cdp));
62 for(
int kc=0; kc < mSize; kc++)
64 temp.template block<2,2>(kc*2,0)+=
m*sourceConcentratoinMatrices.row(kc);
71 typename GalerkinClimbSolver<dim>::StiffnessMatrixType GalerkinClimbSolver<dim>::clusterStiffnessMatrix(
const NetworkLinkType& fieldSegment,
const NetworkLinkType& sourceSegment)
const
73 StiffnessMatrixType K(StiffnessMatrixType::Zero());
74 NetworkLinkType::QuadratureDynamicType::integrate(fieldSegment.quadraturePoints().size(),
this,K,&GalerkinClimbSolver<dim>::clusterStiffnessKernel,fieldSegment,sourceSegment);
79 Eigen::VectorXd GalerkinClimbSolver<dim>::getNodeVelocitiesPipe()
const
81 Eigen::VectorXd nodeVelocities(Eigen::VectorXd::Zero(this->
DN.networkNodes().size()*dim));
82 return nodeVelocities;
86 void GalerkinClimbSolver<dim>::computeClimbScalarVelocities(
const bool& updateStiffness)
88 std::cout<<
", climbSolver "<<std::flush;
89 computeClimbScalarVelocitiesBulk(updateStiffness);
97 void GalerkinClimbSolver<dim>::computeClimbScalarVelocitiesBulk(
const bool& updateStiffness)
100 std::vector<Eigen::VectorXd> Fc(mSize,Eigen::VectorXd::Zero(this->
DN.networkNodes().size()));
101 std::vector<Eigen::VectorXd> KKc(mSize,Eigen::VectorXd::Zero(this->
DN.networkNodes().size()));
105 const size_t nThreads(omp_get_max_threads());
107 std::vector<std::vector<Eigen::VectorXd>> KKcT(nThreads,KKc);
108 std::vector<std::vector<Eigen::VectorXd>> FcT(nThreads,Fc);
109 const EqualIteratorRange<typename DislocationNetwork<dim>::NetworkLinkContainerType::const_iterator> eir(this->
DN.networkLinks().begin(),this->DN.networkLinks().end(),nThreads);
110#pragma omp parallel for
111 for(
size_t thread=0;thread<eir.size();++thread)
113 auto& Fc_ref(FcT[thread]);
114 auto& KKc_ref(KKcT[thread]);
115 for(
auto fieldLinkIter=eir[thread].
first;fieldLinkIter!=eir[thread].second;++fieldLinkIter)
118 const auto& fieldLink(*fieldLinkIter);
122 for(
const auto& fieldLink : this->
DN.networkLinks())
132 if( !fieldLink.second.lock()->hasZeroBurgers()
133 && fieldLink.second.lock()->isSessile()
134 && !fieldLink.second.lock()->isBoundarySegment()
135 && !fieldLink.second.lock()->isGrainBoundarySegment()
136 && fieldLink.second.lock()->chordLength()>FLT_EPSILON
139 const size_t i0(fieldLink.second.lock()->source->gID());
140 const size_t i1(fieldLink.second.lock()-> sink->gID());
142 const ForceVectorMatrixType fc(clusterForceVector(*fieldLink.second.lock()));
143 for(
int kc=0; kc<mSize; ++kc)
149 Fc_ref[kc](i0)+=fc(0,kc);
150 Fc_ref[kc](i1)+=fc(1,kc);
154 for(
const auto& sourceLink : this->
DN.networkLinks())
156 if( !sourceLink.second.lock()->hasZeroBurgers()
157 && !sourceLink.second.lock()->isBoundarySegment()
158 && !sourceLink.second.lock()->isGrainBoundarySegment()
159 && sourceLink.second.lock()->chordLength()>FLT_EPSILON
162 const size_t j0(sourceLink.second.lock()->source->gID());
163 const size_t j1(sourceLink.second.lock()-> sink->gID());
164 const StiffnessMatrixType kcc(clusterStiffnessMatrix(*fieldLink.second.lock(),*sourceLink.second.lock()));
166 for(
int kc=0; kc<mSize; ++kc)
168 const Eigen::Matrix<double,2,2> kccs(kcc.template block<2,2>(2*kc,0));
176 KKc_ref[kc](i0)+=0.5*kccs(0,0)+0.5*kccs(0,1);
177 KKc_ref[kc](j0)+=0.5*kccs(0,0)+0.5*kccs(1,0);
178 KKc_ref[kc](i1)+=0.5*kccs(1,0)+0.5*kccs(1,1);
179 KKc_ref[kc](j1)+=0.5*kccs(0,1)+0.5*kccs(1,1);
235 for(
size_t thread=0;thread< eir.size();++thread)
237 for(
int kc=0; kc<mSize; ++kc)
239 Fc[kc]+=FcT[thread][kc];
240 KKc[kc]+=KKcT[thread][kc];
247 std::vector<Eigen::Array<double,1,mSize>> nodeV(this->
DN.networkNodes().size(),Eigen::Array<double,1,mSize>::Zero());
249 for(
int kc=0; kc<mSize; ++kc)
261 for (
size_t n=0;
n<this->
DN.networkNodes().size();
n++)
263 if(std::fabs(KKc[kc](n))>FLT_EPSILON)
265 nodeV[
n](kc)=Fc[kc](n)/KKc[kc](
n);
275 this->scalarVelocities().resize(this->
DN.networkNodes().size(),Eigen::Array<double,1,mSize>::Zero());
276 for(
size_t k=0;
k<this->
DN.networkNodes().size();++
k)
278 this->scalarVelocities()[
k]=nodeV[
k];
285 void GalerkinClimbSolver<dim>::computeClimbScalarVelocitiesBulk(
const bool& updateStiffness)
287 const size_t nodeCount(this->
DN.networkNodes().size());
288 Fc.assign(mSize,Eigen::VectorXd::Zero(nodeCount));
291 KKc.assign(mSize,Eigen::VectorXd::Zero(nodeCount));
294 using NetworkLinkPtrType=std::shared_ptr<NetworkLinkType>;
297 NetworkLinkPtrType link;
301 struct FieldQuadratureData
303 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
308 using FieldQuadratureContainer=std::vector<FieldQuadratureData,Eigen::aligned_allocator<FieldQuadratureData>>;
311 NetworkLinkPtrType link;
314 ForceVectorMatrixType force;
315 FieldQuadratureContainer quadrature;
319 std::vector<SourceData> sources;
320 std::vector<FieldData>
fields;
321 sources.reserve(this->
DN.networkLinks().size());
322 fields.reserve(this->
DN.networkLinks().size());
323 for(
const auto& networkLink : this->
DN.networkLinks())
325 const auto link(networkLink.second.lock());
331 const bool isActive(!link->hasZeroBurgers()
332 && !link->isBoundarySegment()
333 && !link->isGrainBoundarySegment()
334 && link->chordLength()>FLT_EPSILON);
336 if(isActive && link->grains().size()==1)
338 sources.push_back({link,link->source->gID(),link->sink->gID()});
341 if(isActive && link->isSessile())
343 FieldData
field{link,link->source->gID(),link->sink->gID(),clusterForceVector(*link),{}};
344 field.quadrature.reserve(link->quadraturePoints().size());
348 const auto bxt(link->burgers().cross(link->chord()));
349 const double sourceProjection(bxt.dot(link->source->climbDirection()));
350 const double sinkProjection(bxt.dot(link->sink->climbDirection()));
351 for(
const auto& qp : link->quadraturePoints())
353 field.quadrature.push_back({qp.r,
354 qp.weight*(1.0-qp.abscissa)*sourceProjection,
355 qp.weight*qp.abscissa*sinkProjection});
357 fields.emplace_back(std::move(field));
362 const size_t nThreads(omp_get_max_threads());
363 std::vector<std::vector<Eigen::VectorXd>> KKcT(nThreads,KKc);
364 std::vector<std::vector<Eigen::VectorXd>> FcT(nThreads,Fc);
365#pragma omp parallel for schedule(guided)
366 for(
size_t fieldIndex=0;fieldIndex<
fields.size();++fieldIndex)
368 const size_t thread(omp_get_thread_num());
369 auto& Fc_ref(FcT[thread]);
370 auto& KKc_ref(KKcT[thread]);
371 const auto&
field(fields[fieldIndex]);
375 for(
const auto& field : fields)
378 for(
int kc=0;kc<mSize;++kc)
386 for(
const auto& source : sources)
388 Eigen::Array<double,mSize,1> i0Term(Eigen::Array<double,mSize,1>::Zero());
389 Eigen::Array<double,mSize,1> j0Term(Eigen::Array<double,mSize,1>::Zero());
390 Eigen::Array<double,mSize,1> i1Term(Eigen::Array<double,mSize,1>::Zero());
391 Eigen::Array<double,mSize,1> j1Term(Eigen::Array<double,mSize,1>::Zero());
395 for(
const auto& qp :
field.quadrature)
397 const auto concentration(
source.link->concentrationMatrices(qp.r,this->CD->cdp));
398 const auto c0(concentration.col(0).array());
399 const auto c1(concentration.col(1).array());
400 i0Term+=0.5*qp.weightedM0*(c0+c1);
401 j0Term+=0.5*(qp.weightedM0+qp.weightedM1)*c0;
402 i1Term+=0.5*qp.weightedM1*(c0+c1);
403 j1Term+=0.5*(qp.weightedM0+qp.weightedM1)*c1;
406 for(
int kc=0;kc<mSize;++kc)
408 KKc_ref[kc](
field.i0)+=i0Term(kc);
409 KKc_ref[kc](
source.j0)+=j0Term(kc);
410 KKc_ref[kc](
field.i1)+=i1Term(kc);
411 KKc_ref[kc](
source.j1)+=j1Term(kc);
418 for(
size_t thread=0;thread<nThreads;++thread)
420 for(
int kc=0;kc<mSize;++kc)
422 Fc[kc]+=FcT[thread][kc];
425 KKc[kc]+=KKcT[thread][kc];
431 const auto Z=periodicClimbVelocityMap<dim>(this->DN);
432 std::vector<Eigen::Array<double,1,mSize>> nodeV(nodeCount,Eigen::Array<double,1,mSize>::Zero());
433 for(
int kc=0;kc<mSize;++kc)
436 for(
size_t n=0;
n<nodeCount;++
n)
438 nodeV[
n](kc)=constrained(n);
442 this->scalarVelocities().resize(nodeCount,Eigen::Array<double,1,mSize>::Zero());
443 for(
size_t k=0;
k<nodeCount;++
k)
445 this->scalarVelocities()[
k]=nodeV[
k];
450 Eigen::VectorXd GalerkinClimbSolver<dim>::getNodeVelocitiesBulk()
const
452 Eigen::VectorXd nodeVelocities(Eigen::VectorXd::Zero(this->
DN.networkNodes().size()*dim));
454 for(
auto& node: this->
DN.networkNodes())
456 const double vScalarTotal(-1.0*(this->scalarVelocities()[
k]*this->CD->cdp.msVector/this->CD->cdp.msVector.abs()).matrix().sum());
457 nodeVelocities.template segment<dim>(
k*dim)= vScalarTotal*node.second.lock()->climbDirection();
460 return interpolateClimbSubdivisionVelocities<dim>(this->DN,nodeVelocities);
464 Eigen::VectorXd GalerkinClimbSolver<dim>::getNodeVelocities()
const
466 return getNodeVelocitiesBulk()+getNodeVelocitiesPipe();
469 template class GalerkinClimbSolver<3>;
GalerkinClimbSolver(const DislocationNetwork< dim > &, const ClusterDynamics< dim > *const)
void field(QGridLayout *layout, int row, const QString &title, QWidget *input, const QString &description)
Eigen::VectorXd solveConstrainedVelocityDiagonal(const Eigen::VectorXd &diagonal, const Eigen::VectorXd &force, const VelocityMatrix &Z)
Eigen::Matrix< double, 3, 1 > VectorDim