G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsAPALM.h
Go to the documentation of this file.
1 
14 #pragma once
15 
16 #include <gsCore/gsLinearAlgebra.h>
17 #include <gsIO/gsOptionList.h>
20 
21 #include <gsParallel/gsMpi.h>
22 
23 namespace gismo
24 {
25 
26 #define gsMPIInfo(rank) gsInfo<<"[MPI process "<<rank<<"]: "
27 #define gsMPIDebug(rank) gsDebug<<"[MPI process "<<rank<<"]: "
28 
29 /*
30  * IDEA (Hugo Verhelst, 03-03-2023):
31  * The APALM can be extended for adaptive meshes by storing multipatches as solutions.
32  * Starting from a solution (i.e. a mp), one can construct the start point vector internally
33  * and continue with 'normal' arclength methods. The distance function for the ALM
34  * can be re-implemented for multipatches if needed. The major changes will be that the
35  * parts where gsALMBase::step() is called need to be specialized.
36  */
37 
38 template<class T>
39 class gsAPALM
40 {
41 
42 public:
43  typedef typename std::pair<gsVector<T>,T> solution_t;
44 
45  virtual ~gsAPALM()
46  {
47  if (m_comm_dummy)
48  delete m_comm_dummy;
49  }
50 
58 #ifdef GISMO_WITH_MPI
59  gsAPALM( gsALMBase<T> * ALM,
60  const gsAPALMData<T,solution_t> & Data,
61  const gsMpiComm & comm );
62 #else
63  gsAPALM( gsALMBase<T> * ALM,
64  const gsAPALMData<T,solution_t> & Data,
65  const gsSerialComm & comm );
66 #endif
67 
73  gsAPALM( gsALMBase<T> * ALM,
74  const gsAPALMData<T,solution_t> & Data);
75 
79  gsAPALM()
80  :
81 #ifdef GISMO_WITH_MPI
82  m_comm_dummy(new gsMpiComm()),
83 #else
84  m_comm_dummy(new gsSerialComm()),
85 #endif
86  m_comm(*m_comm_dummy)
87  {
88 
89 
90  };
91 
92 private:
93 
94  virtual void _defaultOptions();
95 
96  virtual void _getOptions();
97 
98  void _initStart(const gsVector<T> & Ustart, const T & Lstart, const T & dL);
99  void _initStart(const std::vector<gsVector<T>> & Ustart, const std::vector<T> & Lstart, const std::vector<T> & dLs);
100 
101 public:
105  virtual void initialize();
106 
112  virtual void solve(index_t Nsteps = 10);
118  virtual void serialSolve(index_t Nsteps = 10);
122  virtual void parallelSolve();
123 
131  virtual void serialStepOutput(const std::pair<gsVector<T>,T> & pair, const T & time, index_t step) {};
139  virtual void parallelStepOutput(const std::pair<gsVector<T>,T> & pair, const T & time, index_t step) {};
148  virtual void parallelIntervalOutput(const std::vector<std::pair<gsVector<T>,T>> & stepSolutions, const std::vector<T> & stepTimes, index_t level, index_t ID) {};
149 
155  gsOptionList & options() { return m_options; }
156 
162  const gsAPALMDataContainer<T,solution_t> & getHierarchy() const { return m_data; }
163  gsAPALMDataContainer<T,solution_t> getHierarchy() { return m_data; }
164 
172  const std::vector<solution_t> & getFlatSolutions(index_t branch = 0) const { return m_solutions[branch]; }
173  std::vector<solution_t> getFlatSolutions(index_t branch = 0) { return m_solutions[branch]; }
174 
182  const std::vector<T> & getFlatTimes(index_t branch = 0) const { return m_times[branch]; }
183  std::vector<T> getFlatTimes(index_t branch = 0) { return m_times[branch]; }
184 
192  const std::vector<index_t> & getFlatLevels(index_t branch = 0) const { return m_levels[branch]; }
193  std::vector<index_t> getFlatLevels(index_t branch = 0) { return m_levels[branch]; }
194 
203  const std::vector<solution_t *> & getSolutions(index_t level, index_t branch = 0) const { return m_lvlSolutions[branch][level]; }
204  std::vector<solution_t> getSolutions(index_t level, index_t branch = 0)
205  {
206  std::vector<solution_t> result;
207  for (typename std::vector<solution_t *>::iterator it=m_lvlSolutions[branch][level].begin(); it!=m_lvlSolutions[branch][level].end(); it++)
208  result.push_back(**it);
209  return result;
210  }
211 
219  std::vector<std::vector<solution_t>> getSolutionsPerLevel(index_t branch = 0)
220  {
221  std::vector<std::vector<solution_t>> result(m_lvlSolutions[branch].size());
222  for (size_t l=0; l!=m_lvlSolutions[branch].size(); l++)
223  for (typename std::vector<solution_t *>::iterator it=m_lvlSolutions[branch][l].begin(); it!=m_lvlSolutions[branch][l].end(); it++)
224  result[l].push_back(**it);
225  return result;
226  }
227 
228 
237  const std::vector<T *> & getTimes(index_t level, index_t branch = 0) const { return m_lvlTimes[branch][level]; }
238  std::vector<T> getTimes(index_t level, index_t branch = 0)
239  {
240  std::vector<T> result;
241  for (typename std::vector<T *>::iterator it=m_lvlTimes[branch][level].begin(); it!=m_lvlTimes[branch][level].end(); it++)
242  result.push_back(**it);
243  return result;
244  }
245 
253  std::vector<std::vector<T>> getTimesPerLevel(index_t branch = 0)
254  {
255  std::vector<std::vector<T>> result(m_lvlTimes[branch].size());
256  for (size_t l=0; l!=m_lvlSolutions[branch].size(); l++)
257  for (typename std::vector<T *>::iterator it=m_lvlTimes[branch][l].begin(); it!=m_lvlTimes[branch][l].end(); it++)
258  result[l].push_back(**it);
259  return result;
260  }
261 
262 #ifdef GISMO_WITH_MPI
263 
269  bool isMain() {return (m_rank==0); }
270 
276  index_t rank() {return (m_rank); }
277 
283  index_t size() { return m_proc_count; };
284 
285 #else
286  bool isMain() {return true; }
287  index_t rank() {return 0; }
288  index_t size() {return 1; }
289 #endif
290 
291 protected:
292 
293 #ifdef GISMO_WITH_MPI
294  // For meta-data
295  void _sendMainToWorker( const index_t & workerID,
296  const index_t & branch,
297  const index_t & jobID,
298  const index_t & dataLevel);
299 
300  // For data
301  void _sendMainToWorker( const index_t & workerID,
302  const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
303  const std::pair<T,T> & dataInterval,
304  const solution_t & dataReference );
305 
306  void _sendMainToWorker( const index_t & workerID,
307  const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
308  const T & startTime);
309  // For stop signal
310  void _sendMainToWorker( const index_t & workerID,
311  const bool & stop );
312  void _sendMainToAll( const bool & stop );
313 
314  // For meta-data
315  void _recvMainToWorker( const index_t & sourceID,
316  index_t & branch,
317  index_t & jobID,
318  index_t & dataLevel);
319 
320  // For data
321  void _recvMainToWorker( const index_t & sourceID,
322  std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
323  std::pair<T,T> & dataInterval,
324  solution_t & dataReference);
325 
326  void _recvMainToWorker( const index_t & sourceID,
327  std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
328  T & startTime);
329 
330  // For stop signal
331  void _recvMainToWorker( const index_t & sourceID,
332  bool & stop);
333  // For meta-data
334  void _sendWorkerToMain( const index_t & mainID,
335  const index_t & branch,
336  const index_t & jobID);
337 
338  // For meta-data
339  void _recvWorkerToMain( index_t & sourceID, // source ID will change to MPI
340  index_t & branch,
341  index_t & jobID);
342  // For data
343  void _sendWorkerToMain( const index_t & mainID,
344  const std::vector<T> & distances,
345  const std::vector<solution_t> & stepSolutions,
346  const T & upperDistance,
347  const T & lowerDistance );
348 
349  void _sendWorkerToMain( const index_t & mainID,
350  const T & distance,
351  const std::vector<solution_t> & solutions,
352  const bool & bifurcation);
353 
354  // For data
355  void _recvWorkerToMain( index_t & sourceID, // source ID will change to MPI
356  std::vector<T> & distances,
357  std::vector<solution_t>& stepSolutions,
358  T & upperDistance,
359  T & lowerDistance);
360 
361  void _recvWorkerToMain( index_t & sourceID, // source ID will change to MPI
362  T & distance,
363  std::vector<solution_t> & stepSolutions,
364  bool & bifurcation);
365 
366 #endif
367 
368 #ifdef GISMO_WITH_MPI
369  const gsMpiComm & comm() { return m_comm; }
370 #else
371  const gsSerialComm & comm() { return m_comm; }
372 #endif
373 
374  template <bool _hasWorkers>
375  typename std::enable_if< _hasWorkers, void>::type
376  _solve_impl(index_t Nsteps);
377 
378  template <bool _hasWorkers>
379  typename std::enable_if<!_hasWorkers, void>::type
380  _solve_impl(index_t Nsteps);
381 
382  template <bool _hasWorkers>
383  typename std::enable_if< _hasWorkers, void>::type
384  parallelSolve_impl();
385 
386  template <bool _hasWorkers>
387  typename std::enable_if<!_hasWorkers, void>::type
388  parallelSolve_impl();
389 
390  void _initiation( const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
391  const T & startTime,
392  T & endTime,
393  std::vector<solution_t>&solutions,
394  bool & bifurcation );
395 
396  void _correction( const std::tuple<index_t, T , solution_t, solution_t> & dataEntry,
397  const std::pair<T,T> & dataInterval,
398  const index_t & dataLevel,
399  const solution_t & dataReference,
400  std::vector<T> & distances,
401  std::vector<solution_t>&stepSolutions,
402  T & upperDistance,
403  T & lowerDistance );
404 
405  void _finalize();
406 
407 protected:
408 
409  std::vector<std::vector<solution_t>> m_solutions;
410  std::vector<std::vector<T>> m_times;
411  std::vector<std::vector<index_t>> m_levels;
412 
413  std::queue<std::tuple<solution_t,T,bool>> m_starts; // solution, step length, true if start was a bifurcation
414 
415  std::vector<std::vector<std::vector<solution_t * > > > m_lvlSolutions;
416  std::vector<std::vector<std::vector<T * > > > m_lvlTimes;
417 
418  gsALMBase<T> * m_ALM;
419  gsAPALMData<T,solution_t> m_dataEmpty;
420  gsAPALMDataContainer<T,solution_t> m_data;
421 
422  bool m_verbose;
423  index_t m_subIntervals;
424 
425  gsOptionList m_options;
426 
427  bool m_singularPoint;
428  T m_branchLengthMult;
429  T m_bifLengthMult;
430 
431  index_t m_maxIterations;
432 
433  // Conditional compilation
434 #ifdef GISMO_WITH_MPI
435  const gsMpiComm * m_comm_dummy = nullptr;
436  const gsMpiComm & m_comm;
437  std::queue<index_t> m_workers;
438 #else
439  const gsSerialComm * m_comm_dummy = nullptr;
440  const gsSerialComm & m_comm;
441 #endif
442 
443 
444  index_t m_proc_count, m_rank;
445 };
446 
447 }
448 
449 #ifndef GISMO_BUILD_LIB
450 #include GISMO_HPP_HEADER(gsAPALM.hpp)
451 #endif
Helpers for dealing with MPI codes.
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 &lt;j&gt; in the set ; by def...
#define index_t
Definition: gsConfig.h:32
Provides a list of labeled parameters/options that can be set and accessed easily.
Performs the arc length method to solve a nonlinear equation system.
Base class to perform the arc length method to solve a nonlinear equation system. ...
This is the main header file that collects wrappers of Eigen for linear algebra.