21 gsAPALM<T>::gsAPALM( gsALMBase<T> * ALM,
22 const gsAPALMData<T,solution_t> & Data,
23 const gsMpiComm & comm )
25 gsAPALM<T>::gsAPALM( gsALMBase<T> * ALM,
26 const gsAPALMData<T,solution_t> & Data,
27 const gsSerialComm & comm )
34 GISMO_ASSERT(m_dataEmpty.empty(),
"gsAPALMData must be empty; it will be used to define the options!");
35 this->_defaultOptions();
39 m_proc_count = m_comm.size();
40 m_rank = m_comm.rank();
44 gsAPALM<T>::gsAPALM( gsALMBase<T> * ALM,
45 const gsAPALMData<T,solution_t> & Data)
50 m_comm_dummy(new gsMpiComm()),
52 m_comm_dummy(new gsSerialComm()),
56 GISMO_ASSERT(m_dataEmpty.empty(),
"gsAPALMData must be empty; it will be used to define the options!");
57 this->_defaultOptions();
65 void gsAPALM<T>::_defaultOptions()
67 m_options.addInt(
"MaxIt",
"Maximum number of steps",1000);
68 m_options.addSwitch(
"Verbose",
"Verbosity",
false);
69 m_options.addInt(
"SubIntervals",
"Number of subintervals",2);
70 m_options.addSwitch(
"SingularPoint",
"Enable singular point detection",
false);
71 m_options.addReal(
"BranchLengthMultiplier",
"Multiplier for the length of branches after bifurcation",1);
72 m_options.addReal(
"BifLengthMultiplier",
"Multiplier for the length of the first interval after detection of a bifurcation point",0.1);
76 void gsAPALM<T>::_getOptions()
78 m_maxIterations = m_options.getInt(
"MaxIt");
79 m_verbose = m_options.getSwitch(
"Verbose");
80 m_subIntervals = m_options.getInt(
"SubIntervals");
81 m_singularPoint = m_options.getSwitch(
"SingularPoint");
82 m_branchLengthMult = m_options.getReal(
"BranchLengthMultiplier");
83 m_bifLengthMult = m_options.getReal(
"BifLengthMultiplier");
87 void gsAPALM<T>::initialize()
92 if (m_starts.size()==0)
95 gsVector<T> U0(m_ALM->numDofs());
98 this->_initStart(U0,L0,m_ALM->getLength());
103 void gsAPALM<T>::_initStart(
const gsVector<T> & Ustart,
const T & Lstart,
const T & dL)
106 std::vector<gsVector<T>> Ustarts; Ustarts.push_back(Ustart);
107 std::vector<T> Lstarts; Lstarts.push_back(Lstart);
108 std::vector<T> dLs; dLs .push_back(dL);
109 this->_initStart(Ustarts,Lstarts,dLs);
113 void gsAPALM<T>::_initStart(
const std::vector<gsVector<T>> & Ustarts,
const std::vector<T> & Lstarts,
const std::vector<T> & dLs)
115 GISMO_ASSERT(Ustarts.size()==Lstarts.size(),
"Size mismatch in start solutions");
116 GISMO_ASSERT(Ustarts.size()==dLs.size(),
"Size mismatch in start solutions");
118 for (
size_t k=0; k!=Ustarts.size(); k++)
119 m_starts.push(std::make_tuple(std::make_pair(Ustarts[k],Lstarts[k]),dLs[k],
false));
123 void gsAPALM<T>::serialSolve(
index_t Nsteps)
125 #ifdef GISMO_WITH_MPI
131 GISMO_ASSERT(m_starts.size()>0,
"No start point is created. Call initialize first?");
134 gsMatrix<T> Uold, Uprev, U0;
136 bool bisected, finished;
137 std::vector<solution_t> solutions;
138 std::vector<T> times;
139 std::vector<index_t> levels;
140 while (!m_starts.empty())
147 U0 = Uold = Uprev = std::get<0>(m_starts.front()).first;
148 L0 = Lold = Lprev = std::get<0>(m_starts.front()).second;
149 dL = dL0 = std::get<1>(m_starts.front());
150 bisected = std::get<2>(m_starts.front());
156 dL *= m_bifLengthMult;
160 solutions.push_back({U0,L0});
166 std::vector<solution_t> tmpSolutions;
167 while (k<Nsteps && !finished)
169 if (m_verbose) gsMPIInfo(m_rank)<<
"Load step "<< k<<
"\t"<<
"dL = "<<m_ALM->getLength()<<
"; curve time = "<<s<<
"\n";
170 solution_t start = std::make_pair(Uold,Lold);
171 solution_t prev = std::make_pair(Uprev,Lprev);
173 std::tuple<index_t, T, solution_t, solution_t> dataEntry = std::make_tuple(k,dL,start,prev);
175 this->_initiation(dataEntry,s,dL,tmpSolutions,finished);
181 solutions.push_back(tmpSolutions[0]);
188 Uold = tmpSolutions[0].first;
189 Lold = tmpSolutions[0].second;
193 m_starts.push(std::make_tuple(tmpSolutions[1],dL0*m_branchLengthMult,
true));
202 gsAPALMData<T,solution_t> data = m_dataEmpty;
203 data.setData(times,solutions);
208 m_solutions.push_back(solutions);
209 m_times.push_back(times);
210 m_levels.push_back(levels);
214 #ifdef GISMO_WITH_MPI
223 void gsAPALM<T>::parallelSolve()
225 #ifdef GISMO_WITH_MPI
226 if (m_comm.size()==1)
227 this->parallelSolve_impl<false>();
229 this->parallelSolve_impl<true>();
231 this->parallelSolve_impl<false>();
236 void gsAPALM<T>::solve(
index_t Nsteps)
238 #ifdef GISMO_WITH_MPI
239 if (m_comm.size()==1)
240 this->_solve_impl<false>(Nsteps);
242 this->_solve_impl<true>(Nsteps);
244 this->_solve_impl<false>(Nsteps);
249 template <
bool _hasWorkers>
250 typename std::enable_if< _hasWorkers, void>::type
251 gsAPALM<T>::parallelSolve_impl()
253 #ifdef GISMO_WITH_MPI
254 GISMO_ASSERT(m_comm.size()>1,
"Something went wrong. This implementation only works when >1 processes are availbale, but nprocesses = "<<m_comm.size());
257 solution_t reference;
262 std::vector<T> distances;
263 std::vector<solution_t> stepSolutions;
264 T lowerDistance, upperDistance;
265 std::pair<T,T> dataInterval;
269 std::tuple<index_t, T , solution_t, solution_t> dataEntry;
278 gsMPIInfo(m_rank)<<
"Adding workers...\n";
279 for (
index_t w = 1; w!=m_proc_count; w++)
282 while (!m_data.empty() && it < m_maxIterations && !m_workers.empty())
284 gsMPIInfo(m_rank)<<
"Available workers:\t";
285 std::queue<index_t> workers_copy = m_workers;
286 while (!workers_copy.empty())
288 gsMPIInfo(m_rank)<<workers_copy.front()<<
"\t";
291 gsMPIInfo(m_rank)<<
"\n";
294 branch = m_data.getFirstNonEmptyBranch();
295 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
297 dataEntry = m_data.branch(branch).pop();
298 ID = std::get<0>(dataEntry);
299 dataLevel = m_data.branch(branch).jobLevel(ID);
300 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
303 this->_sendMainToWorker(m_workers.front(),stop);
304 this->_sendMainToWorker(m_workers.front(),
308 this->_sendMainToWorker(m_workers.front(),
310 m_data.branch(branch).jobTimes(ID),
321 gsMPIInfo(m_rank)<<njobs<<
" job(s) running\n";
323 index_t source = MPI_ANY_SOURCE;
324 this->_recvWorkerToMain(source,
327 this->_recvWorkerToMain(source,
333 m_data.branch(branch).submit(ID,distances,stepSolutions,upperDistance,lowerDistance);
334 m_data.branch(branch).finishJob(ID);
339 m_workers.push(source);
341 gsMPIInfo(m_rank)<<
"Available workers:\t";
342 std::queue<index_t> workers_copy = m_workers;
343 while (!workers_copy.empty())
345 gsInfo<<workers_copy.front()<<
"\t";
351 while (!m_data.empty() && it < m_maxIterations && !m_workers.empty())
354 branch = m_data.getFirstNonEmptyBranch();
355 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
357 dataEntry = m_data.branch(branch).pop();
358 ID = std::get<0>(dataEntry);
359 dataLevel = m_data.branch(branch).jobLevel(ID);
360 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
362 this->_sendMainToWorker(m_workers.front(),stop);
363 this->_sendMainToWorker(m_workers.front(),
367 this->_sendMainToWorker(m_workers.front(),
369 m_data.branch(branch).jobTimes(ID),
379 this->_sendMainToAll(stop);
387 this->_recvMainToWorker(0,stop);
391 this->_recvMainToWorker(0,
395 this->_recvMainToWorker(0,
401 this->_correction(dataEntry,
410 this->_sendWorkerToMain(0,
413 this->_sendWorkerToMain(0,
431 template <
bool _hasWorkers>
432 typename std::enable_if<!_hasWorkers, void>::type
433 gsAPALM<T>::parallelSolve_impl()
435 solution_t reference;
438 std::vector<T> distances;
439 std::vector<solution_t> stepSolutions;
440 T lowerDistance, upperDistance;
445 std::tuple<index_t, T , solution_t, solution_t> dataEntry;
446 while (!m_data.empty() && it < m_maxIterations)
448 branch = m_data.getFirstNonEmptyBranch();
449 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
451 dataEntry = m_data.branch(branch).pop();
452 ID = std::get<0>(dataEntry);
453 dataLevel = m_data.branch(branch).jobLevel(ID);
454 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
456 this->_correction(dataEntry,
457 m_data.branch(branch).jobTimes(ID),
466 m_data.branch(branch).submit(ID,distances,stepSolutions,upperDistance,lowerDistance);
467 m_data.branch(branch).finishJob(ID);
475 void gsAPALM<T>::_finalize()
477 std::vector<solution_t> solutions;
478 std::vector<T> times;
479 std::vector<index_t> levels;
480 index_t nBranches = m_data.nBranches();
481 m_solutions.resize(nBranches);
482 m_times.resize(nBranches);
483 m_levels.resize(nBranches);
484 m_lvlSolutions.resize(nBranches);
485 m_lvlTimes.resize(nBranches);
486 for (
index_t b=0; b!=nBranches; b++)
488 std::tie(times,solutions,levels) = m_data.branch(b).getFlatSolution();
489 m_times.at(b) = times;
490 m_solutions.at(b) = solutions;
491 m_levels.at(b) = levels;
493 index_t maxLevel = m_data.branch(b).maxLevel();
494 m_lvlSolutions[b].resize(maxLevel+1);
495 m_lvlTimes[b].resize(maxLevel+1);
496 for (
size_t k=0; k!=m_solutions.size(); k++)
498 GISMO_ASSERT(m_lvlSolutions[b].size() > (
size_t)m_levels[b][k],
"level mismatch, maxLevel = " << maxLevel <<
"level = "<<m_levels[b][k]);
499 GISMO_ASSERT(m_lvlTimes[b].size() > (
size_t)m_levels[b][k],
"level mismatch, maxLevel = " << maxLevel <<
"level = "<<m_levels[b][k]);
500 m_lvlSolutions[b][m_levels[b][k]].push_back(&(m_solutions[b][k]));
501 m_lvlTimes[b][m_levels[b][k]].push_back(&(m_times[b][k]));
507 template <
bool _hasWorkers>
508 typename std::enable_if< _hasWorkers, void>::type
509 gsAPALM<T>::_solve_impl(
index_t Nsteps)
511 #ifdef GISMO_WITH_MPI
512 GISMO_ASSERT(m_comm.size()>1,
"Something went wrong. This implementation only works when >1 processes are availbale, but nprocesses = "<<m_comm.size());
515 solution_t reference;
520 std::tuple<index_t, T , solution_t, solution_t> dataEntry;
523 std::pair<T,T> dataInterval;
524 std::vector<T> distances;
525 std::vector<solution_t> stepSolutions;
526 T lowerDistance, upperDistance;
531 std::vector<solution_t> solutions;
543 std::vector<index_t> K(1);
550 while (!m_starts.empty())
553 U0 = std::get<0>(m_starts.front()).first;
554 L0 = std::get<0>(m_starts.front()).second;
555 dL = std::get<1>(m_starts.front());
558 gsAPALMData<T,solution_t> data = m_dataEmpty;
559 branch = m_data.add(data);
560 m_data.branch(branch).addStartPoint(T(0),std::make_pair(U0,L0));
561 m_data.branch(branch).setLength(dL);
564 gsMPIInfo(m_rank)<<
"Adding workers...\n";
565 for (
index_t w = 1; w!=m_proc_count; w++)
568 while (!m_data.empty() && it < m_maxIterations && !m_workers.empty())
570 gsMPIInfo(m_rank)<<
"Available workers:\t";
571 std::queue<index_t> workers_copy = m_workers;
572 while (!workers_copy.empty())
574 gsMPIInfo(m_rank)<<workers_copy.front()<<
"\t";
577 gsMPIInfo(m_rank)<<
"\n";
580 branch = m_data.getFirstNonEmptyBranch();
581 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
583 dataEntry = m_data.branch(branch).pop();
584 ID = std::get<0>(dataEntry);
585 dataLevel = m_data.branch(branch).jobLevel(ID);
589 this->_sendMainToWorker(m_workers.front(),stop);
590 this->_sendMainToWorker(m_workers.front(),
594 this->_sendMainToWorker(m_workers.front(),
596 m_data.branch(branch).jobStartTime(ID)
602 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
605 this->_sendMainToWorker(m_workers.front(),stop);
606 this->_sendMainToWorker(m_workers.front(),
610 this->_sendMainToWorker(m_workers.front(),
612 m_data.branch(branch).jobTimes(ID),
623 gsMPIInfo(m_rank)<<njobs<<
" job(s) running\n";
624 index_t source = MPI_ANY_SOURCE;
626 this->_recvWorkerToMain(source,
631 dataLevel = m_data.branch(branch).jobLevel(ID);
634 this->_recvWorkerToMain(source,
639 T tstart = m_data.branch(branch).jobStartTime(ID);
640 m_data.branch(branch).appendData(tstart+distance,solutions[0],
false);
641 m_data.branch(branch).finishJob(ID);
643 if (K[branch]++ < Nsteps-1)
647 GISMO_ASSERT(solutions.size()==1,
"There must be one solution, but solutions.size() = "<<solutions.size());
648 m_data.branch(branch).appendPoint(
true);
651 if (branch!=0 && ID==0)
652 m_data.branch(branch).setLength(m_data.branch(branch).getLength()/m_bifLengthMult);
656 GISMO_ASSERT(solutions.size()==2,
"There must be two solutions!");
657 gsAPALMData<T,solution_t> data = m_dataEmpty;
658 branch = m_data.add(data);
660 m_data.branch(branch).addStartPoint(T(0),solutions[1],
true);
663 m_data.branch(branch).setLength(m_ALM->getLength()*m_branchLengthMult*m_bifLengthMult);
670 this->_recvWorkerToMain(source,
676 m_data.branch(branch).submit(ID,distances,stepSolutions,upperDistance,lowerDistance);
677 m_data.branch(branch).finishJob(ID);
683 m_workers.push(source);
685 gsMPIInfo(m_rank)<<
"Available workers:\t";
686 std::queue<index_t> workers_copy = m_workers;
687 while (!workers_copy.empty())
689 gsInfo<<workers_copy.front()<<
"\t";
695 while (!m_data.empty() && it < m_maxIterations && !m_workers.empty())
698 branch = m_data.getFirstNonEmptyBranch();
699 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
701 dataEntry = m_data.branch(branch).pop();
702 ID = std::get<0>(dataEntry);
705 dataLevel = m_data.branch(branch).jobLevel(ID);
708 this->_sendMainToWorker(m_workers.front(),stop);
709 this->_sendMainToWorker(m_workers.front(),
714 this->_sendMainToWorker(m_workers.front(),
716 m_data.branch(branch).jobStartTime(ID)
722 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
725 this->_sendMainToWorker(m_workers.front(),stop);
726 this->_sendMainToWorker(m_workers.front(),
730 this->_sendMainToWorker(m_workers.front(),
732 m_data.branch(branch).jobTimes(ID),
742 this->_sendMainToAll(stop);
750 this->_recvMainToWorker(0,stop);
755 this->_recvMainToWorker(0,
763 this->_recvMainToWorker(0,
768 this->_initiation(dataEntry,
775 this->_sendWorkerToMain(0,
778 this->_sendWorkerToMain(0,
786 this->_recvMainToWorker(0,
792 this->_correction(dataEntry,
801 this->_sendWorkerToMain(0,
804 this->_sendWorkerToMain(0,
823 template <
bool _hasWorkers>
824 typename std::enable_if<!_hasWorkers, void>::type
825 gsAPALM<T>::_solve_impl(
index_t Nsteps)
829 std::vector<index_t> K(1);
838 while (!m_starts.empty())
841 U0 = std::get<0>(m_starts.front()).first;
842 L0 = std::get<0>(m_starts.front()).second;
843 dL = std::get<1>(m_starts.front());
846 gsAPALMData<T,solution_t> data = m_dataEmpty;
847 branch = m_data.add(data);
848 m_data.branch(branch).addStartPoint(T(0),std::make_pair(U0,L0));
849 m_data.branch(branch).setLength(dL);
853 std::tuple<index_t, T , solution_t, solution_t> dataEntry;
854 while (!m_data.empty() && it < m_maxIterations)
856 branch = m_data.getFirstNonEmptyBranch();
857 gsMPIInfo(m_rank)<<
"There are "<<m_data.branch(branch).nActive()<<
" active jobs and "<<m_data.branch(branch).nWaiting()<<
" jobs in the queue of branch "<<branch<<
"\n";
859 dataEntry = m_data.branch(branch).pop();
860 ID = std::get<0>(dataEntry);
862 dataLevel = m_data.branch(branch).jobLevel(ID);
865 if (m_verbose) gsMPIInfo(m_rank)<<
"Initialization\n";
866 T startTime = m_data.branch(branch).jobStartTime(ID);
868 std::vector<solution_t> solutions;
870 this->_initiation(dataEntry,
877 m_data.branch(branch).appendData(startTime+distance,solutions[0],
false);
878 m_data.branch(branch).finishJob(ID);
881 if (K[branch]++ < Nsteps - 1)
885 GISMO_ASSERT(solutions.size()==1,
"There must be one solution!");
886 m_data.branch(branch).appendPoint(
true);
889 if (branch!=0 && ID==0)
890 m_data.branch(branch).setLength(m_data.branch(branch).getLength()/m_bifLengthMult);
894 GISMO_ASSERT(solutions.size()==2,
"There must be two solutions!");
895 gsAPALMData<T,solution_t> data = m_dataEmpty;
896 branch = m_data.add(data);
898 m_data.branch(branch).addStartPoint(T(0),solutions[1],
true);
901 m_data.branch(branch).setLength(m_ALM->getLength()*m_branchLengthMult*m_bifLengthMult);
907 if (m_verbose) gsMPIInfo(m_rank)<<
"Correction\n";
908 solution_t reference;
909 std::vector<T> distances;
910 std::vector<solution_t> stepSolutions;
911 T lowerDistance, upperDistance;
912 bool success = m_data.branch(branch).getReferenceByID(ID,reference);
914 this->_correction(dataEntry,
915 m_data.branch(branch).jobTimes(ID),
924 m_data.branch(branch).submit(ID,distances,stepSolutions,upperDistance,lowerDistance);
925 m_data.branch(branch).finishJob(ID);
935 void gsAPALM<T>::_initiation(
const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
938 std::vector<solution_t>&solutions,
941 solution_t start, prev;
943 T tstart = startTime;
949 gsMatrix<T> Uprev, Uold;
953 std::tie(ID,dL,start,prev) = dataEntry;
954 std::tie(Uold,Lold) = start;
955 std::tie(Uprev,Lprev) = prev;
958 m_ALM->setLength(dL);
959 m_ALM->setSolution(Uold,Lold);
961 m_ALM->setPrevious(Uprev,Lprev);
962 gsMPIDebug(m_rank)<<
"Start - ||u|| = "<<Uold.norm()<<
", L = "<<Lold<<
"\n";
963 gsMPIDebug(m_rank)<<
"Prev - ||u|| = "<<Uprev.norm()<<
", L = "<<Lprev<<
"\n";
965 bool diverged =
true;
969 gsMPIInfo(m_rank)<<
"Starting with ID "<<ID<<
" from (|U|,L) = ("<<Uold.norm()<<
","<<Lold<<
"), curve time = "<<tstart<<
", arc-length = "<<dL<<
"\n";
975 if (m_verbose) gsMPIInfo(m_rank)<<
"Error: Loop terminated, arc length method did not converge.\n";
977 m_ALM->setLength(dL);
978 m_ALM->setSolution(Uold,Lold);
985 m_ALM->computeStability(m_ALM->options().getSwitch(
"Quasi"));
986 if (m_ALM->stabilityChange())
988 gsMPIInfo(m_rank)<<
"Bifurcation spotted!"<<
"\n";
989 if (m_ALM->isBifurcation(
false))
991 m_ALM->computeSingularPoint(Uold,Lold,
false,
false,
false);
997 DeltaU = m_ALM->solutionU() - Uold;
998 DeltaL = m_ALM->solutionL() - Lold;
999 distance = m_ALM->distance(DeltaU,DeltaL);
1000 solutions.push_back(std::make_pair(m_ALM->solutionU(),m_ALM->solutionL()));
1002 this->serialStepOutput(solutions[0],tstart,ID);
1006 m_ALM->switchBranch();
1008 solutions.push_back(std::make_pair(m_ALM->solutionU(),m_ALM->solutionL()));
1014 void gsAPALM<T>::_correction(
const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
1015 const std::pair<T,T> & dataInterval,
1017 const solution_t & dataReference,
1018 std::vector<T> & distances,
1019 std::vector<solution_t>&stepSolutions,
1023 solution_t start, prev, reference;
1030 index_t Nintervals = m_subIntervals;
1031 bool bisected =
false;
1035 gsMatrix<T> Uprev, Uold;
1038 stepSolutions.resize(Nintervals);
1039 std::vector<T> stepTimes(Nintervals);
1040 distances.resize(Nintervals+1);
1042 std::tie(ID,dL0,start,prev) = dataEntry;
1043 std::tie(Uold,Lold) = start;
1044 std::tie(Uprev,Lprev) = prev;
1045 std::tie(tstart,tend) = dataInterval;
1047 gsMPIDebug(m_rank)<<
"tstart = "<<tstart<<
" , "<<
"tend = "<<tend<<
"\n";
1049 gsMatrix<T> Uori = Uold;
1052 dL0 = dL0 / Nintervals;
1055 m_ALM->setLength(dL);
1056 m_ALM->setSolution(Uold,Lold);
1058 m_ALM->setPrevious(Uprev,Lprev);
1059 gsMPIDebug(m_rank)<<
"Start - ||u|| = "<<Uold.norm()<<
", L = "<<Lold<<
"\n";
1060 gsMPIDebug(m_rank)<<
"Prev - ||u|| = "<<Uprev.norm()<<
", L = "<<Lprev<<
"\n";
1065 gsMPIInfo(m_rank)<<
"Starting with ID "<<ID<<
" from (|U|,L) = ("<<Uold.norm()<<
","<<Lold<<
"), curve time = "<<time<<
"\n";
1066 for (
index_t k = 0; k!=Nintervals; k++)
1068 gsMPIDebug(m_rank)<<
"Interval "<<k+1<<
" of "<<Nintervals<<
"\n";
1069 gsMPIDebug(m_rank)<<
"Start - ||u|| = "<<Uold.norm()<<
", L = "<<Lold<<
"\n";
1074 gsMPIInfo(m_rank)<<
"Error: Loop terminated, arc length method did not converge.\n";
1077 m_ALM->setLength(dL);
1078 m_ALM->setSolution(Uold,Lold);
1084 std::pair<gsVector<T>,T> pair = std::make_pair(m_ALM->solutionU(),m_ALM->solutionL());
1085 stepSolutions.at(k) = pair;
1086 DeltaU = m_ALM->solutionU() - Uold;
1087 DeltaL = m_ALM->solutionL() - Lold;
1089 distances.at(k) = m_ALM->distance(DeltaU,DeltaL);
1091 s += distances.at(k);
1092 time += distances.at(k);
1093 stepTimes.at(k) = time;
1095 Uold = m_ALM->solutionU();
1096 Lold = m_ALM->solutionL();
1108 stepSolutions.resize(Nintervals);
1109 stepTimes.resize(Nintervals);
1110 distances.resize(Nintervals+1);
1113 this->parallelStepOutput(pair,time,k);
1115 m_ALM->setLength(dL);
1120 gsMPIDebug(m_rank)<<
"Ref - ||u|| = "<<dataReference.first.norm()<<
", L = "<<dataReference.second<<
"\n";
1122 GISMO_ASSERT(dataReference.first.normalized().size()==m_ALM->solutionU().normalized().size(),
"Reference solution and current solution have different size! ref.size() = "<<dataReference.first.normalized().size()<<
"; sol.size() = "<<m_ALM->solutionU().normalized().size());
1123 GISMO_ASSERT((dataReference.first.normalized()).dot(m_ALM->solutionU().normalized())>-0.8,
1124 "Reference is almost in the opposite direction of the solution. Are branches mirrored? result:" << (reference.first.normalized()).dot(m_ALM->solutionU().normalized()));
1126 DeltaU = dataReference.first - m_ALM->solutionU();
1127 DeltaL = dataReference.second - m_ALM->solutionL();
1128 distances.back() = m_ALM->distance(DeltaU,DeltaL);
1130 DeltaU = dataReference.first - Uori;
1131 DeltaL = dataReference.second - Lori;
1132 upperDistance = m_ALM->distance(DeltaU,DeltaL);
1134 DeltaU = stepSolutions.back().first - Uori;
1135 DeltaL = stepSolutions.back().second - Lori;
1136 lowerDistance = m_ALM->distance(DeltaU,DeltaL);
1138 std::vector<solution_t> stepSolutionsExport(Nintervals+2);
1139 std::vector<T> stepTimesExport(Nintervals+2);
1142 std::pair<gsVector<T>,T> front = std::make_pair(start.first,start.second);
1143 stepSolutionsExport.front() = front;
1144 std::pair<gsVector<T>,T> back = std::make_pair(dataReference.first,dataReference.second);
1145 stepSolutionsExport.back() = back;
1147 stepTimesExport.front() = tstart;
1148 stepTimesExport.back() = tend;
1151 for (
index_t k=0; k!=Nintervals; k++)
1153 std::swap(stepSolutions.at(k),stepSolutionsExport.at(k+1));
1154 std::swap(stepTimes.at(k),stepTimesExport.at(k+1));
1157 this->parallelIntervalOutput(stepSolutionsExport,stepTimesExport,dataLevel,ID);
1160 for (
index_t k=0; k!=Nintervals; k++)
1162 std::swap(stepSolutionsExport.at(k+1),stepSolutions.at(k));
1163 std::swap(stepTimesExport.at(k+1),stepTimes.at(k));
1170 #ifdef GISMO_WITH_MPI
1173 void gsAPALM<T>::_sendMainToWorker(
const index_t & workerID,
1178 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<workerID<<
"\n";
1180 m_comm.isend(&branch ,1,workerID,&req[0] ,0 );
1181 m_comm.isend(&jobID ,1,workerID,&req[1] ,1 );
1182 m_comm.isend(&dataLevel ,1,workerID,&req[2] ,2 );
1183 MPI_Waitall( 3, req, MPI_STATUSES_IGNORE );
1187 void gsAPALM<T>::_sendMainToWorker(
const index_t & workerID,
1188 const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
1189 const std::pair<T,T> & dataInterval,
1190 const solution_t & dataReference )
1192 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<workerID<<
"\n";
1196 solution_t start, prev;
1197 gsVector<T> startU, prevU, refU;
1198 index_t startSize,prevSize, refSize;
1199 T startL, prevL, refL;
1203 std::tie(ID,dL0,start,prev) = dataEntry;
1204 std::tie(tstart,tend) = dataInterval;
1206 std::tie(startU,startL) = start;
1207 startSize = startU.size();
1208 std::tie(prevU,prevL) = prev;
1209 prevSize = prevU.size();
1210 std::tie(refU,refL) = dataReference;
1211 refSize = refU.size();
1214 MPI_Request req[10];
1215 m_comm.isend(&ID ,1,workerID,&req[0] ,0 );
1216 m_comm.isend(&dL0 ,1,workerID,&req[1] ,1 );
1217 m_comm.isend(&tstart ,1,workerID,&req[2] ,2 );
1218 m_comm.isend(&tend ,1,workerID,&req[3] ,3 );
1220 m_comm.isend(&startSize ,1,workerID,&req[4] ,4 );
1221 m_comm.isend(&startL ,1,workerID,&req[5] ,5 );
1223 m_comm.isend(&prevSize ,1,workerID,&req[6] ,6 );
1224 m_comm.isend(&prevL ,1,workerID,&req[7] ,7 );
1226 m_comm.isend(&refSize ,1,workerID,&req[8] ,8 );
1227 m_comm.isend(&refL ,1,workerID,&req[9] ,9 );
1229 MPI_Waitall( 10, req , MPI_STATUSES_IGNORE );
1230 MPI_Request req_data[3];
1231 m_comm.isend(startU.data(), startSize,workerID,&req_data[0],10);
1232 m_comm.isend(prevU.data(), prevSize, workerID,&req_data[1],11);
1233 m_comm.isend(refU.data(), refSize, workerID,&req_data[2],12);
1235 MPI_Waitall( 3 , req_data, MPI_STATUSES_IGNORE );
1239 void gsAPALM<T>::_sendMainToWorker(
const index_t & workerID,
1240 const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
1241 const T & startTime)
1243 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<workerID<<
"\n";
1247 solution_t start, prev;
1248 gsVector<T> startU, prevU;
1254 std::tie(ID,dL0,start,prev) = dataEntry;
1257 std::tie(startU,startL) = start;
1258 startSize = startU.size();
1259 std::tie(prevU,prevL) = prev;
1260 prevSize = prevU.size();
1264 m_comm.isend(&ID ,1,workerID,&req[0] ,0 );
1265 m_comm.isend(&dL0 ,1,workerID,&req[1] ,1 );
1266 m_comm.isend(&tstart ,1,workerID,&req[2] ,2 );
1268 m_comm.isend(&startSize ,1,workerID,&req[3] ,3 );
1269 m_comm.isend(&startL ,1,workerID,&req[4] ,4 );
1271 m_comm.isend(&prevSize ,1,workerID,&req[5] ,5 );
1272 m_comm.isend(&prevL ,1,workerID,&req[6] ,6 );
1273 MPI_Waitall( 7, req , MPI_STATUSES_IGNORE );
1275 MPI_Request req_data[2];
1276 m_comm.isend(startU.data(), startSize,workerID,&req_data[0],7);
1277 m_comm.isend(prevU.data(), prevSize, workerID,&req_data[1],8);
1279 MPI_Waitall( 2, req_data, MPI_STATUSES_IGNORE );
1283 void gsAPALM<T>::_sendMainToWorker(
const index_t & workerID,
1288 gsMPIInfo(m_rank)<<
"Sending stop signal from "<<m_rank<<
" to "<<workerID<<
"\n";
1289 m_comm.send(&stop,1,workerID,99);
1293 void gsAPALM<T>::_sendMainToAll(
const bool & stop )
1295 for (
index_t w = 1; w!=m_proc_count; w++)
1296 this->_sendMainToWorker(w,stop);
1300 void gsAPALM<T>::_recvMainToWorker(
const index_t & sourceID,
1305 gsMPIInfo(m_rank)<<
"Receiving data on "<<m_rank<<
" from "<<sourceID<<
"\n";
1307 m_comm.irecv(&branch ,1,sourceID,&req[0] ,0 );
1308 m_comm.irecv(&jobID ,1,sourceID,&req[1] ,1 );
1309 m_comm.irecv(&dataLevel ,1,sourceID,&req[2] ,2 );
1310 MPI_Waitall( 3, req, MPI_STATUSES_IGNORE );
1315 void gsAPALM<T>::_recvMainToWorker(
const index_t & sourceID,
1316 std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
1317 std::pair<T,T> & dataInterval,
1318 solution_t & dataReference)
1320 gsMPIInfo(m_rank)<<
"Receiving data on "<<m_rank<<
" from "<<sourceID<<
"\n";
1324 solution_t start, prev;
1325 gsVector<T> startU, prevU, refU;
1326 index_t startSize,prevSize, refSize;
1327 T startL, prevL, refL;
1332 MPI_Request req[10];
1333 m_comm.irecv(&ID ,1,sourceID,&req[0] ,0 );
1334 m_comm.irecv(&dL0 ,1,sourceID,&req[1] ,1 );
1335 m_comm.irecv(&tstart ,1,sourceID,&req[2] ,2 );
1336 m_comm.irecv(&tend ,1,sourceID,&req[3] ,3 );
1338 m_comm.irecv(&startSize ,1,sourceID,&req[4] ,4 );
1339 m_comm.irecv(&startL ,1,sourceID,&req[5] ,5 );
1341 m_comm.irecv(&prevSize ,1,sourceID,&req[6] ,6 );
1342 m_comm.irecv(&prevL ,1,sourceID,&req[7] ,7 );
1344 m_comm.irecv(&refSize ,1,sourceID,&req[8] ,8 );
1345 m_comm.irecv(&refL ,1,sourceID,&req[9] ,9 );
1347 MPI_Waitall( 10, req, MPI_STATUSES_IGNORE );
1348 dataInterval = std::make_pair(tstart,tend);
1350 startU.resize(startSize);
1351 prevU .resize(prevSize);
1352 refU .resize(refSize);
1354 MPI_Request req_data[3];
1355 m_comm.irecv(startU.data(), startSize,sourceID,&req_data[0],10);
1356 m_comm.irecv(prevU.data(), prevSize, sourceID,&req_data[1],11);
1357 m_comm.irecv(refU.data(), refSize, sourceID,&req_data[2],12);
1359 MPI_Waitall( 3, req_data, MPI_STATUSES_IGNORE );
1361 start = std::make_pair(startU,startL);
1362 prev = std::make_pair(prevU ,prevL);
1363 dataReference = std::make_pair(refU ,refL);
1365 dataEntry = std::make_tuple(ID,dL0,start,prev);
1369 void gsAPALM<T>::_recvMainToWorker(
const index_t & sourceID,
1370 std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
1373 gsMPIInfo(m_rank)<<
"Receiving data on "<<m_rank<<
" from "<<sourceID<<
"\n";
1377 solution_t start, prev;
1378 gsVector<T> startU, prevU;
1384 m_comm.irecv(&ID ,1,sourceID,&req[0] ,0 );
1385 m_comm.irecv(&dL0 ,1,sourceID,&req[1] ,1 );
1386 m_comm.irecv(&startTime ,1,sourceID,&req[2] ,2 );
1388 m_comm.irecv(&startSize ,1,sourceID,&req[3] ,3 );
1389 m_comm.irecv(&startL ,1,sourceID,&req[4] ,4 );
1391 m_comm.irecv(&prevSize ,1,sourceID,&req[5] ,5 );
1392 m_comm.irecv(&prevL ,1,sourceID,&req[6] ,6 );
1394 MPI_Waitall( 7, req, MPI_STATUSES_IGNORE );
1396 startU.resize(startSize);
1397 prevU .resize(prevSize);
1399 MPI_Request req_data[2];
1400 m_comm.irecv(startU.data(), startU.size(),sourceID,&req_data[0],7);
1401 m_comm.irecv(prevU.data(), prevU.size(), sourceID,&req_data[1],8);
1403 MPI_Waitall( 2, req_data, MPI_STATUSES_IGNORE );
1405 start = std::make_pair(startU,startL);
1406 prev = std::make_pair(prevU ,prevL);
1408 dataEntry = std::make_tuple(ID,dL0,start,prev);
1412 void gsAPALM<T>::_recvMainToWorker(
const index_t & sourceID,
1416 m_comm.recv(&stop,1,sourceID,99);
1421 void gsAPALM<T>::_sendWorkerToMain(
const index_t & mainID,
1425 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<mainID<<
"\n";
1429 MPI_Request req_meta[2];
1430 m_comm.isend(&branch ,1, mainID, &req_meta[0], tag++);
1431 m_comm.isend(&jobID ,1, mainID, &req_meta[1], tag++);
1432 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
1437 void gsAPALM<T>::_recvWorkerToMain(
index_t & sourceID,
1445 MPI_Request req_meta[2];
1446 m_comm.irecv(&branch ,1, sourceID, &req_meta[0], tag++);
1447 MPI_Wait ( &req_meta[0], &status );
1448 if (sourceID==MPI_ANY_SOURCE) sourceID = status.MPI_SOURCE;
1451 m_comm.irecv(&jobID ,1, sourceID, &req_meta[1], tag++);
1452 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
1456 void gsAPALM<T>::_sendWorkerToMain(
const index_t & mainID,
1457 const std::vector<T> & distances,
1458 const std::vector<solution_t> & stepSolutions,
1459 const T & upperDistance,
1460 const T & lowerDistance )
1462 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<mainID<<
"\n";
1465 index_t size = stepSolutions.size();
1469 MPI_Request req_meta[2];
1470 m_comm.isend(&upperDistance ,1, mainID, &req_meta[0], tag++);
1471 m_comm.isend(&lowerDistance ,1, mainID, &req_meta[1], tag++);
1473 MPI_Request req_solSize;
1474 m_comm.isend(&size ,1, mainID, &req_solSize, tag++);
1476 MPI_Request req_vecSizes[size];
1477 MPI_Request req_loads[size];
1478 MPI_Request req_distances[size+1];
1479 for (
index_t k=0; k!=size; k++)
1481 m_comm.isend(&distances.at(k) ,1, mainID, &req_distances[k] , tag++);
1482 load = stepSolutions.at(k).second;
1483 m_comm.isend(&load ,1, mainID, &req_loads[k] , tag++);
1484 vectorSize= stepSolutions.at(k).first.size();
1485 m_comm.isend(&vectorSize ,1, mainID, &req_vecSizes[k] , tag++);
1487 m_comm.isend(&(distances.at(size)),1, mainID, &req_distances[size], tag++);
1489 MPI_Request req_data[size];
1490 for (
index_t k=0; k!=size; k++)
1491 m_comm.isend( stepSolutions.at(k).first.data(),
1492 stepSolutions.at(k).first.size(), mainID, &req_data[k], tag++);
1494 MPI_Wait(&req_solSize,MPI_STATUS_IGNORE);
1495 MPI_Waitall( size, req_vecSizes, MPI_STATUSES_IGNORE );
1496 MPI_Waitall( size, req_data, MPI_STATUSES_IGNORE );
1497 MPI_Waitall( size, req_loads, MPI_STATUSES_IGNORE );
1498 MPI_Waitall( size+1, req_distances, MPI_STATUSES_IGNORE );
1499 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
1503 void gsAPALM<T>::_sendWorkerToMain(
const index_t & mainID,
1505 const std::vector<solution_t> & solutions,
1506 const bool & bifurcation)
1508 gsMPIInfo(m_rank)<<
"Sending data from "<<m_rank<<
" to "<<mainID<<
"\n";
1511 index_t size = solutions.size();
1515 MPI_Request req_meta[2];
1516 m_comm.isend(&distance ,1, mainID, &req_meta[0], tag++);
1517 m_comm.isend(&bifurcation ,1, mainID, &req_meta[1], tag++);
1519 MPI_Request req_solSize;
1520 m_comm.isend(&size ,1, mainID, &req_solSize, tag++);
1522 MPI_Request req_vecSizes[size];
1523 MPI_Request req_loads[size];
1524 for (
index_t k=0; k!=size; k++)
1526 load = solutions.at(k).second;
1527 m_comm.isend(&load ,1, mainID, &req_loads[k] , tag++);
1528 vectorSize= solutions.at(k).first.size();
1529 m_comm.isend(&vectorSize ,1, mainID, &req_vecSizes[k] , tag++);
1532 MPI_Request req_data[size];
1533 for (
index_t k=0; k!=size; k++)
1534 m_comm.isend( solutions.at(k).first.data(),
1535 solutions.at(k).first.size(), mainID, &req_data[k], tag++);
1537 MPI_Wait(&req_solSize,MPI_STATUS_IGNORE);
1538 MPI_Waitall( size, req_vecSizes, MPI_STATUSES_IGNORE );
1539 MPI_Waitall( size, req_data, MPI_STATUSES_IGNORE );
1540 MPI_Waitall( size, req_loads, MPI_STATUSES_IGNORE );
1541 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
1545 void gsAPALM<T>::_recvWorkerToMain(
index_t & sourceID,
1546 std::vector<T> & distances,
1547 std::vector<solution_t> & stepSolutions,
1556 MPI_Request req_meta[2];
1557 m_comm.irecv(&upperDistance ,1, sourceID, &req_meta[0], tag++);
1558 MPI_Wait ( &req_meta[0], &status );
1559 if (sourceID==MPI_ANY_SOURCE) sourceID = status.MPI_SOURCE;
1560 gsMPIInfo(m_rank)<<
"Receiving data on "<<m_rank<<
" from "<<sourceID<<
"\n";
1563 m_comm.irecv(&lowerDistance ,1, sourceID, &req_meta[1], tag++);
1566 MPI_Request req_solSize;
1567 m_comm.irecv(&size ,1, sourceID, &req_solSize, tag++);
1569 MPI_Wait(&req_solSize,MPI_STATUS_IGNORE);
1572 std::vector<gsVector<T>> Us(size);
1573 std::vector<T > Ls(size);
1574 std::vector<index_t > vectorSizes(size);
1576 distances.resize(size+1);
1577 stepSolutions.resize(size);
1580 MPI_Request req_vecSizes[size];
1581 MPI_Request req_loads[size];
1582 MPI_Request req_distances[size+1];
1583 for (
index_t k=0; k!=size; k++)
1585 m_comm.irecv(&distances.at(k) ,1, sourceID, &req_distances[k] , tag++);
1586 m_comm.irecv(&Ls.at(k) ,1, sourceID, &req_loads[k] , tag++);
1587 m_comm.irecv(&vectorSizes.at(k) ,1, sourceID, &req_vecSizes[k] , tag++);
1589 m_comm.irecv(&(distances.at(size)),1, sourceID, &req_distances[size], tag++);
1592 MPI_Waitall( size, req_vecSizes, MPI_STATUSES_IGNORE );
1593 for (
index_t k=0; k!=size; k++)
1594 Us[k].resize(vectorSizes.at(k));
1597 MPI_Request req_data[size];
1598 for (
index_t k=0; k!=size; k++)
1599 m_comm.irecv(Us.at(k).data() ,vectorSizes.at(k) , sourceID, &req_data[k], tag++);
1602 MPI_Waitall( size, req_data, MPI_STATUSES_IGNORE );
1603 MPI_Waitall( size, req_loads, MPI_STATUSES_IGNORE );
1604 for (
index_t k=0; k!=size; k++)
1605 stepSolutions.at(k) = std::make_pair(Us.at(k),Ls.at(k));
1608 MPI_Waitall( size+1, req_distances, MPI_STATUSES_IGNORE );
1610 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
1614 void gsAPALM<T>::_recvWorkerToMain(
index_t & sourceID,
1616 std::vector<solution_t> & solutions,
1623 MPI_Request req_meta[2];
1624 m_comm.irecv(&distance ,1, sourceID, &req_meta[0], tag++);
1625 MPI_Wait ( &req_meta[0], &status );
1626 if (sourceID==MPI_ANY_SOURCE) sourceID = status.MPI_SOURCE;
1627 gsMPIInfo(m_rank)<<
"Receiving data on "<<m_rank<<
" from "<<sourceID<<
"\n";
1630 m_comm.irecv(&bifurcation ,1, sourceID, &req_meta[1], tag++);
1633 MPI_Request req_solSize;
1634 m_comm.irecv(&size ,1, sourceID, &req_solSize, tag++);
1636 MPI_Wait(&req_solSize,MPI_STATUS_IGNORE);
1639 std::vector<gsVector<T>> Us(size);
1640 std::vector<T > Ls(size);
1641 std::vector<index_t > vectorSizes(size);
1643 solutions.resize(size);
1646 MPI_Request req_vecSizes[size];
1647 MPI_Request req_loads[size];
1648 for (
index_t k=0; k!=size; k++)
1650 m_comm.irecv(&Ls.at(k) ,1, sourceID, &req_loads[k] , tag++);
1651 m_comm.irecv(&vectorSizes.at(k) ,1, sourceID, &req_vecSizes[k] , tag++);
1655 MPI_Waitall( size, req_vecSizes, MPI_STATUSES_IGNORE );
1656 for (
index_t k=0; k!=size; k++)
1657 Us[k].resize(vectorSizes.at(k));
1660 MPI_Request req_data[size];
1661 for (
index_t k=0; k!=size; k++)
1662 m_comm.irecv(Us.at(k).data() ,vectorSizes.at(k) , sourceID, &req_data[k], tag++);
1665 MPI_Waitall( size, req_data, MPI_STATUSES_IGNORE );
1666 MPI_Waitall( size, req_loads, MPI_STATUSES_IGNORE );
1667 for (
index_t k=0; k!=size; k++)
1668 solutions.at(k) = std::make_pair(Us.at(k),Ls.at(k));
1671 MPI_Waitall( 2, req_meta, MPI_STATUSES_IGNORE );
#define GISMO_NO_IMPLEMENTATION
Definition: gsDebug.h:129
T distance(gsMatrix< T > const &A, gsMatrix< T > const &B, index_t i=0, index_t j=0, bool cols=false)
compute a distance between the point number in the set and the point number <j> in the set ; by def...
Assembly failed due to an error in the expression (e.g. overflow)
#define index_t
Definition: gsConfig.h:32
gsStatus
Definition: gsStructuralAnalysisTypes.h:20
#define GISMO_ENSURE(cond, message)
Definition: gsDebug.h:102
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
#define gsInfo
Definition: gsDebug.h:43