ug4
feti.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3  * Authors: Ingo Heppner, Andreas Vogel
4  *
5  * This file is part of UG4.
6  *
7  * UG4 is free software: you can redistribute it and/or modify it under the
8  * terms of the GNU Lesser General Public License version 3 (as published by the
9  * Free Software Foundation) with the following additional attribution
10  * requirements (according to LGPL/GPL v3 §7):
11  *
12  * (1) The following notice must be displayed in the Appropriate Legal Notices
13  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14  *
15  * (2) The following notice must be displayed at a prominent place in the
16  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17  *
18  * (3) The following bibliography is recommended for citation and must be
19  * preserved in all covered files:
20  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21  * parallel geometric multigrid solver on hierarchically distributed grids.
22  * Computing and visualization in science 16, 4 (2013), 151-164"
23  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24  * flexible software system for simulating pde based models on high performance
25  * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  */
32 
33 /* TODO:
34  * If finished: Check for unnecessary "set zero" operations!
35  *
36  */
37 
38 #ifndef __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__FETI__
39 #define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__FETI__
40 
41 
42 #ifdef UG_PARALLEL
43 
44 #include <iostream>
45 #include <sstream>
46 #include <string>
53 #include "pcl/pcl.h"
54 
55 /*
56  * Outline of FETI-DP algorithm (after Klawonn, A., Widlund, O., Dryja, M.:
57  * "Dual-Primal FETI methods for three-dimensional elliptic problems with
58  * heterogeneous coefficients", SIAM J. Numer. Anal., 40/2002a, 159--179.):
59  *
60  * 1. eliminate the primal variables associated with the interior nodes,
61  * the vertex nodes designated as primal (as well as the Lagrange
62  * multipliers related to the optional constraints - if any)
63  * ==> reduced system with Schur complement \tilde{S} related to the subspace
64  * \tilde{W}_{\Delta}, and a reduced right hand side \tilde{f}_{\Delta}.
65  *
66  * 2. Reformulate as a variational problem, with a vector of Lagrange multipliers
67  * ==> saddle point problem.
68  *
69  * 3. Eliminate subvectors u_{\Delta}
70  * ==> system for the dual variables: F \lambda = d
71  *
72  * 4. Instead of solving ... action of the inverse of the Schur complement can be
73  * obtained by solving the entire linear system from which it originates after
74  * augmenting the given right hand side with zeros.
75  * Group all the interior and dual variables of each subdomain together
76  * and factor the resulting blocks in parallel across the subdomains using a
77  * good ordering algorithm.
78  *
79  * The contributions of the remaining Schur complement, of the primal variables,
80  * can also be computed locally prior to subassembly and factorization of this
81  * final, global part of the linear system of equations.
82  */
83 
84 namespace ug{
85 
87 
91 template <typename TAlgebra>
93 {
94  public:
95  // Algebra type
96  typedef TAlgebra algebra_type;
97 
98  // Vector type
99  typedef typename TAlgebra::vector_type vector_type;
100 
101  // Matrix type
102  typedef typename TAlgebra::matrix_type matrix_type;
103 
104  public:
106 
107  // assigns standard layouts, creates the feti layouts
109  size_t numIndices,
111  bool bDebug = false)
112  {
113  // if no indices, nothing to do
114  if(numIndices == 0) return;
115 
116  m_spStdLayouts = stdLayouts;
118 
119  // create FETI Layouts:
120  // \todo: For some documentation info see mail by S. Reiter, 30. Januar 2011 16:10:52 MEZ
121 // (if the information therein is not already outdated ...)
124  m_spInnerLayouts->master(), m_spInnerLayouts->slave(),
127  stdLayouts->master(), stdLayouts->slave(),
128  (int)(numIndices - 1), DDInfo);
129  UG_LOG("[BuildDomainDecompositionLayouts done]");
130 
131  // create intra feti subdomain communicator
132  int localSubdomID = DDInfo.map_proc_id_to_subdomain_id(pcl::ProcRank());
133  pcl::ProcessCommunicator worldComm;
134  for(int i = 0; i < DDInfo.get_num_subdomains(); ++i){
135  if(localSubdomID == i)
136  m_spInnerLayouts->proc_comm() = worldComm.create_sub_communicator(true);
137  else
138  worldComm.create_sub_communicator(false);
139  }
140  UG_LOG("[intra feti sd comms created]");
141 
142  // create set of unique indices (to avoid doubles due to several interfaces)
143  // collect from dual layouts
146 
149 
152 
155  UG_LOG("[CollectElements for duals done]");
156 
157  // create union of all dual unknowns
162  UG_LOG("[union of duals created]");
163 
164  // collect from primal layouts
167 
170 
171  // create union of all primal unknowns
174  UG_LOG("[CollectElements for primals done] ");
175 
176  // test output
177  if(bDebug && false)
178  {
180  UG_LOG("STANDARD LAYOUTS:\n");
181  PrintLayout(m_spStdLayouts->proc_comm(), comTmp, m_spStdLayouts->master(), m_spStdLayouts->slave());
182  UG_LOG("INNER LAYOUTS:\n");
183  PrintLayout(m_spStdLayouts->proc_comm(), comTmp, m_spInnerLayouts->master(), m_spInnerLayouts->slave());
184  UG_LOG("PRIMAL LAYOUTS:\n");
186  UG_LOG("DUAL LAYOUTS:\n");
188  UG_LOG("DUAL NBR LAYOUTS:\n");
190  }
191  }
192 
193  // tests the previously created layouts:
194  void test_layouts(bool bPrint)
195  {
196  if (m_spInnerLayouts.invalid() || m_spInnerLayouts.invalid()) {
197  UG_LOG("LAYOUTS not yet created!\n");
198  return;
199  }
201 
202  UG_LOG("TEST STANDARD LAYOUTS:\n");
203  if (TestLayout(m_spStdLayouts->proc_comm(), comTmp, m_spStdLayouts->master(), m_spStdLayouts->slave(), bPrint) != true) {
204  UG_LOG("STANDARD LAYOUTS inconsistent!\n");
205  } else {
206  UG_LOG("STANDARD LAYOUTS are consistent!\n");
207  }
208 
209  UG_LOG("TEST INNER LAYOUTS:\n");
210  if (TestLayout(m_spStdLayouts->proc_comm(), comTmp, m_spInnerLayouts->master(), m_spInnerLayouts->slave(), bPrint) != true) {
211  UG_LOG("INNER LAYOUTS inconsistent!\n");
212  } else {
213  UG_LOG("INNER LAYOUTS are consistent!\n");
214  }
215 
216  UG_LOG("TEST PRIMAL LAYOUTS:\n");
217  if (TestLayout(m_spStdLayouts->proc_comm(), comTmp, m_masterPrimalLayout, m_slavePrimalLayout, bPrint) != true) {
218  UG_LOG("PRIMAL LAYOUTS inconsistent!\n");
219  } else {
220  UG_LOG("PRIMAL LAYOUTS are consistent!\n");
221  }
222 
223  UG_LOG("TEST DUAL LAYOUTS:\n");
224  if (TestLayout(m_spStdLayouts->proc_comm(), comTmp, m_masterDualLayout, m_slaveDualLayout, bPrint) != true) {
225  UG_LOG("DUAL LAYOUTS inconsistent!\n");
226  } else {
227  UG_LOG("DUAL LAYOUTS are consistent!\n");
228  }
229 
230  UG_LOG("TEST DUAL NBR LAYOUTS:\n");
231  if (TestLayout(m_spStdLayouts->proc_comm(), comTmp, m_masterDualNbrLayout, m_slaveDualNbrLayout, bPrint) != true) {
232  UG_LOG("DUAL NBR LAYOUTS inconsistent!\n");
233  } else {
234  UG_LOG("DUAL NBR LAYOUTS are consistent!\n");
235  }
236  }
237 
238  // standard layouts
239  const IndexLayout& get_std_master_layout() {return m_spStdLayouts->master();}
240  const IndexLayout& get_std_slave_layout() {return m_spStdLayouts->slave();}
242 
243  // intra subdomain layouts
247 
248  // dual layouts
251  const std::vector<IndexLayout::Element>& get_dual_master_indices() const {return m_vUniqueMasterDualIndex;}
252  const std::vector<IndexLayout::Element>& get_dual_slave_indices() const {return m_vUniqueSlaveDualIndex;}
253 
254  // dual nbr layouts
257  const std::vector<IndexLayout::Element>& get_dual_nbr_master_indices() const {return m_vUniqueMasterDualNbrIndex;}
258  const std::vector<IndexLayout::Element>& get_dual_nbr_slave_indices() const {return m_vUniqueSlaveDualNbrIndex;}
259 
260  // primal layouts
263  const std::vector<IndexLayout::Element>& get_primal_master_indices() const {return m_vUniquePrimalMasterIndex;}
264  const std::vector<IndexLayout::Element>& get_primal_slave_indices() const {return m_vUniquePrimalSlaveIndex;}
265 
266  // union of indices
267  const std::vector<IndexLayout::Element>& get_primal_indices() const {return m_vUniquePrimalIndex;}
268  const std::vector<IndexLayout::Element>& get_dual_indices() const {return m_vUniqueDualIndex;}
269 
270  public:
271 
272  // sets standard communication layouts and communicators
274  {
275  vec.set_layouts(m_spStdLayouts);
276  }
277 
278  // sets intra subdomain communication layouts and communicators
280  {
281  vec.set_layouts(m_spInnerLayouts);
282  }
283 
284  public:
287  number alpha1, const vector_type& vecSrc1,
288  number alpha2, const vector_type& vecSrc2)
289  {
290  VecScaleAdd(vecDest, alpha1, vecSrc1, alpha2, vecSrc2, m_vUniqueDualIndex);
291  }
292 
295  number alpha1, const vector_type& vecSrc1,
296  number alpha2, const vector_type& vecSrc2)
297  {
298  VecScaleAdd(vecDest, alpha1, vecSrc1, alpha2, vecSrc2, m_vUniquePrimalIndex);
299  }
300 
303  const vector_type& vecSrc1, number alpha1)
304  {
305  VecScaleAdd(vecInOut, alpha1, vecSrc1, 1.0, vecInOut, m_vUniqueDualIndex);
306  }
307 
310  const vector_type& vecSrc1, number alpha1)
311  {
312  VecScaleAdd(vecInOut, alpha1, vecSrc1, 1.0, vecInOut, m_vUniquePrimalIndex);
313  }
314 
317  {
318  VecSet(vecDest, alpha, m_vUniqueDualIndex);
319  }
320 
323  {
324  VecSet(vecDest, alpha, m_vUniquePrimalIndex);
325  }
326 
329  {
330  VecScaleAssign(vecDest, alpha, vecSrc, m_vUniqueDualIndex);
331  }
332 
335  {
336  VecScaleAssign(vecDest, alpha, vecSrc, m_vUniquePrimalIndex);
337  }
338 
341  {
342  // forward to VecProc
343  return sqrt(vec_prod_on_identified_dual(vec, vec));
344  }
345 
347  {
348  // compute norm on dual master indices
349  double tProdLocal = VecProd(vecSrc1, vecSrc2, m_vUniqueMasterDualIndex);
350 
351  // global value
352  double tProdGlobal;
353 
354  // sum up values
355  m_spStdLayouts->proc_comm().allreduce(&tProdLocal, &tProdGlobal, 1,
357 
358  // return result
359  return tProdGlobal;
360  }
361 
362  public:
364  {
366  }
367 
369  {
371  }
372 
373  // sets standard communication layouts and communicators
375  {
376  mat.set_slave_layout(get_std_slave_layout());
377  mat.set_master_layout(get_std_master_layout());
378  mat.set_process_communicator(get_std_process_communicator());
379  }
380 
381  // sets intra subdomain communication layouts and communicators
383  {
384  mat.set_layouts(m_spInnerLayouts);
385  }
386 
387  protected:
388  void sort_and_remove_doubles(std::vector<IndexLayout::Element>& vIndex)
389  {
390  // sort vector
391  std::sort(vIndex.begin(), vIndex.end());
392 
393  // remove doubles
394  vIndex.erase(std::unique(vIndex.begin(), vIndex.end()),
395  vIndex.end());
396  }
397 
398  void add_merge_sort_remove_doubles(std::vector<IndexLayout::Element>& vOut,
399  const std::vector<IndexLayout::Element>& v)
400  {
401  // on entry, vOut and v are supposed to be sorted
402 
403  // original size of vOut
404  size_t mid = vOut.size();
405 
406  // add second vector
407  vOut.insert(vOut.end(), v.begin(), v.end() );
408 
409  // merge both
410  std::inplace_merge(vOut.begin(), vOut.begin()+mid, vOut.end());
411 
412  // remove doubles
413  vOut.erase(std::unique(vOut.begin(), vOut.end()),
414  vOut.end());
415  }
416 
417  protected:
418  // Standard Layouts
420 
421  // Layouts and Communicator for Inner variables
423 
424  // Layouts for Dual variables
427  std::vector<IndexLayout::Element> m_vUniqueMasterDualIndex;
428  std::vector<IndexLayout::Element> m_vUniqueSlaveDualIndex;
429 
430  // Layouts for Dual Neighbour variables
433  std::vector<IndexLayout::Element> m_vUniqueMasterDualNbrIndex;
434  std::vector<IndexLayout::Element> m_vUniqueSlaveDualNbrIndex;
435 
436  // Layouts for Primal variables
439  std::vector<IndexLayout::Element> m_vUniquePrimalMasterIndex;
440  std::vector<IndexLayout::Element> m_vUniquePrimalSlaveIndex;
441 
442  // unique indices for layouts
443  std::vector<IndexLayout::Element> m_vUniqueDualIndex;
444  std::vector<IndexLayout::Element> m_vUniquePrimalIndex;
445 
446 }; /* end class 'FetiLayouts' */
447 
449 
466 template <typename TVector>
467 void ComputeDifferenceOnDelta(TVector& diff, const TVector& u,
468  IndexLayout& dualMasterLayoutIn,
469  IndexLayout& dualSlaveLayoutIn,
470  IndexLayout& dualNbrMasterLayoutIn,
471  IndexLayout& dualNbrSlaveLayoutIn)
472 {
473  // Copy all values
474  diff = u;
475 
476  // Communicate values:
477  // (a) Slaves send their u values, every master subtracts the value of only
478  // one of his slaves ...
479  VecSubtractOneSlaveFromMaster(&diff, dualMasterLayoutIn, dualSlaveLayoutIn);
480 
481  // (b) masters send their diff values to all slaves (but not vice versa)
482  VecCopy(&diff, dualMasterLayoutIn, dualSlaveLayoutIn);
483 
484  // (c) and also to the additional slaves living in "Dual neighbour layout"
485  VecCopy(&diff, dualNbrMasterLayoutIn, dualNbrSlaveLayoutIn);
486 
487  // now the vector 'diff' should be consistent!
488  return;
489 };
490 
492 
506 template <typename TVector>
507 void ComputeDifferenceOnDeltaTransposed(TVector& f, const TVector& diff,
508  const std::vector<IndexLayout::Element>& vDualMasterIndex,
509  const std::vector<IndexLayout::Element>& vDualSlaveIndex,
510  const std::vector<IndexLayout::Element>& vDualNbrSlaveIndex)
511 {
512  // Copy values (no communication is performed):
513  // (a) set f = +1 * d on masters ...
514  VecScaleAssign(f, 1.0, diff, vDualMasterIndex);
515 
516  // (b) set f = -1 * d on slaves
517  VecScaleAssign(f, -1.0, diff, vDualSlaveIndex);
518 
519  // (c) set f = +1 * d on slaves living in "Dual neighbour layout"
520  // ("+1" since in this context these dofs play the role of masters!)
521  VecScaleAssign(f, +1.0, diff, vDualNbrSlaveIndex);
522  return;
523 
524 };
525 
527 
536 template <typename TAlgebra>
538  : public ILinearOperator< typename TAlgebra::vector_type,
539  typename TAlgebra::vector_type>,
540  public DebugWritingObject<TAlgebra>
541 {
542  public:
543  // Algebra type
544  typedef TAlgebra algebra_type;
545 
546  // Vector type
547  typedef typename TAlgebra::vector_type vector_type;
548 
549  // Matrix type
550  typedef typename TAlgebra::matrix_type matrix_type;
551 
552  protected:
555 
556  public:
559 
561  virtual const char* name() const {return "Local Schur Complement Solver";}
562 
564 
587  {
588  // save current operator
589  m_spOperator = A;
590  }
591 
593 
598  {
599  // remember the Dirichlet Solver
600  m_spDirichletSolver = dirichletSolver;
601  }
602 
605  {
606  m_pFetiLayouts = &fetiLayouts;
607  }
608 
610  void init(const vector_type& u) {init();}
611 
613 
620  virtual void init();
621 
624  virtual void apply(vector_type& f, const vector_type& u);
625 
627  virtual void apply_sub(vector_type& f, const vector_type& u);
628 
630  void set_statistic_type(std::string type) {m_statType = type;}
631 
633  void print_statistic_of_inner_solver(bool bPrintOnlyAverages); // const;
634 
637 
638  // destructor
639  virtual ~LocalSchurComplement() {};
640 
641  protected:
642  // Operator that is inverted by this Inverse Operator
644 
645  // Parallel Matrix
647 
648  // Feti Layouts
650 
651  // Copy of matrix
653 
654  // Parallel Dirichlet Matrix
656 
657  // Linear Solver to invert the local Dirichlet problems
659 
660  // Convergence history
661  std::string m_statType;
662 
663  struct StepConv
664  {
667  };
668 
669  std::map<std::string, std::vector<StepConv> > m_mvStepConv;
670 
672 
674 
675 }; /* end class 'LocalSchurComplement' */
676 
677 /* 1.7 Application of \f${\tilde{S}_{\Delta \Delta}}^{-1}\f$ */
679 
683 template <typename TAlgebra>
685  : public ILinearOperatorInverse< typename TAlgebra::vector_type,
686  typename TAlgebra::vector_type>,
687  public DebugWritingObject<TAlgebra>
688 {
689  public:
690  // Algebra type
691  typedef TAlgebra algebra_type;
692 
693  // Vector type
694  typedef typename TAlgebra::vector_type vector_type;
695 
696  // Matrix type
697  typedef typename TAlgebra::matrix_type matrix_type;
698 
701 
702  protected:
706 
707  public:
710 
712  virtual const char* name() const {return "Schur Complement Inverse";}
713 
715  virtual bool supports_parallel() const
716  {
717  bool bRet = true;
718  if(m_spNeumannSolver.valid() || !m_spNeumannSolver->supports_parallel())
719  bRet = false;
720  if(m_spCoarseProblemSolver.valid() || !m_spCoarseProblemSolver->supports_parallel())
721  bRet = false;
722  return bRet;
723  }
724 
727  {
728  // remember the Dirichlet Solver
729  m_spNeumannSolver = neumannSolver;
730  }
731 
734  {
735  // remember the coarse problem Solver
736  m_spCoarseProblemSolver = coarseProblemSolver;
737  }
738 
741  {
742  m_pFetiLayouts = &fetiLayouts;
743  }
744 
745  // Init for Linear Operator L
746  virtual bool init(SmartPtr<ILinearOperator<vector_type> > L);
747 
748 
749  // Init for Linear Operator J and Linearization point (current solution)
751  {
752  return init(J);
753  }
754 
755  // Solve A*u = f, such that u = A^{-1} f
756  virtual bool apply(vector_type& u, const vector_type& f);
757 
758  // Solve A*u = f, such that u = A^{-1} f
759  // This is done by iterating: u := u + B(f - A*u)
760  // In f the last defect f := f - A*u is returned
761  virtual bool apply_return_defect(vector_type& u, vector_type& f);
762 
764  void set_statistic_type(std::string type) {m_statType = type;}
765 
767  void print_statistic_of_inner_solver(bool bPrintOnlyAverages); // const;
768 
771 
774 
775  // destructor
777 
778  protected:
779  // Operator that is inverted by this Inverse Operator ==> from which SC is built (05022011)
781 
782  // Parallel Matrix to invert ==> from which SC is built (05022011)
784 
785  // Feti Layouts
787 
788  // Copy of matrix
790 
791  // Parallel Neumann Matrix
793 
794  // Neumann Solver
796 
797  // Coarse problem Solver on root.
799 
800  // Process gathering the Schur Complement w.r.t. Primal unknowns
802 
803  // Layouts for all to one communication
807 
808  // Schur Complement operator for gathered matrix
810 
811  // Matrix for one proc Schur complement
813 
814  // Convergence history
815  std::string m_statType;
816 
817  struct StepConv
818  {
820  int numIter7;
825  };
826 
827  std::map<std::string, std::vector<StepConv> > m_mvStepConv;
828 
829  // testing of 'one-to-many layouts'
831 
833 
834 }; /* end class 'PrimalSubassembledMatrixInverse' */
835 
837 
842 template <typename TAlgebra>
843 class FETISolver : public IMatrixOperatorInverse< typename TAlgebra::matrix_type,
844  typename TAlgebra::vector_type>,
845  public DebugWritingObject<TAlgebra>
846 {
847  public:
848  // Algebra type
849  typedef TAlgebra algebra_type;
850 
851  // Vector type
852  typedef typename TAlgebra::vector_type vector_type;
853 
854  // Matrix type
855  typedef typename TAlgebra::matrix_type matrix_type;
856 
859 
860  protected:
864 
865  public:
867  FETISolver();
868 
870  virtual const char* name() const {return "FETI Solver";}
871 
873  virtual bool supports_parallel() const
874  {
875  if(m_spDirichletSolver.valid())
876  if(!m_spDirichletSolver->supports_parallel())
877  return false;
878  if(m_spNeumannSolver.valid())
879  if(!m_spNeumannSolver->supports_parallel())
880  return false;
881  if(m_spCoarseProblemSolver.valid())
882  if(!m_spCoarseProblemSolver->supports_parallel())
883  return false;
884  return true;
885  }
886 
889  {
890  // remember the Dirichlet Solver
891  m_spDirichletSolver = dirichletSolver;
892  }
893 
896  {
897  // remember the Dirichlet Solver
898  m_spNeumannSolver = neumannSolver;
899  }
900 
903  {
904  // remember the coarse problem Solver
905  m_spCoarseProblemSolver = coarseProblemSolver;
906  }
907 
908  // set debug output
910  {
911  m_LocalSchurComplement.set_debug(spDebugWriter);
914  }
915 
918 
920 
929  bool apply_F(vector_type& f, const vector_type& v);
930 
932 
941  bool compute_d(vector_type& d, const vector_type& f);
942 
944  bool apply_scaling_matrix(vector_type& s, const vector_type& v) // maybe restrict to layout
945  {
946  // copy values
947  s = v;
948 
949  // scale by 1/2
950  s *= 1./2.;
951 
952  // \todo: more general: m_Ddelta.apply(s,v), with additional member 'matrix_type m_Ddelta;'
953 
954  // we're done
955  return true;
956  }
957 
959 
966  bool apply_M_inverse(vector_type& z, const vector_type& r);
967 
968  // tests layouts:
969  void test_layouts(bool bPrint);
970 
971  // set member 'm_bTestOneToManyLayouts' of class 'PrimalSubassembledMatrixInverse':
973  {
975  }
976 
977 
981  virtual bool apply_return_defect(vector_type& lambda, vector_type& d);
982 
984  virtual bool apply(vector_type& x, const vector_type& b)
985  {
986  // copy defect
987  vector_type d; d.resize(b.size());
988  d = b;
989 
990  // solve on copy of defect
991  return apply_return_defect(x, d);
992  }
993 
995  void print_statistic_of_inner_solver(bool bPrintOnlyAverages) //const
996  {
997  // sum over all calls of inner solvers is done in the following print functions!
1000  UG_LOG("\n");
1001 
1004 
1005  int totalIterCntOfInnerSolvers = m_PrimalSubassembledMatrixInverse.get_total_itercnt_of_inner_solvers();
1006  totalIterCntOfInnerSolvers += m_LocalSchurComplement.get_total_itercnt_of_inner_solvers();
1007 
1008  UG_LOG("Total number of calls of sub problem solvers: " << totalIterCntOfInnerSolvers);
1009  UG_LOG(" in " << std::setw(5) << m_iterCnt << " FETI iterations ");
1010  UG_LOG(" on " << std::setw(5) << m_pDDInfo->get_num_subdomains() << " FETI subdomains, "
1011  << std::fixed << (double)totalIterCntOfInnerSolvers/m_iterCnt
1012  << std::scientific << " per FETI iteration, "
1013  << std::fixed << (double)totalIterCntOfInnerSolvers/m_pDDInfo->get_num_subdomains()
1014  << std::scientific << " per FETI subdomain.\n");
1015 
1016  }
1017 
1018  // destructor
1019  virtual ~FETISolver() {};
1020 
1021  protected:
1022  // Prepare the convergence check
1024  {
1025  convergence_check()->set_name(name());
1026  convergence_check()->set_symbol('%');
1027 
1028  // set preconditioner string
1029  std::stringstream ss;
1030  ss << " (Inherent Preconditioner) ";
1031  convergence_check()->set_info(ss.str());
1032  }
1033 
1034  protected:
1035  virtual void write_debug(const vector_type& vec, const char* filename)
1036  {
1037  // add iter count to name
1038  std::string name(filename);
1039  char ext[20]; snprintf(ext, 20, "_iter%03d.vec", m_iterCnt);
1040  name.append(ext);
1041 
1042  // if no debug writer set, we're done
1043  if(debug_writer() == SPNULL) return;
1044 
1045  // write
1046  debug_writer()->write_vector(vec, name.c_str());
1047  }
1048 
1050 
1051  protected:
1052  // Operator that is inverted by this Inverse Operator
1054 
1055  // Parallel Matrix to invert
1057 
1058  // Feti Layouts
1060 
1061  // Local Schur complement for each feti subdomain
1063 
1064  // Dirichlet solver for inverse of \f$A_{II}\f$ in local Schur complement
1066 
1067  // PrimalSubassembledMatrixInverse
1069 
1070  // Neumann solver for inverse of \f$A_{\{I,\Delta\}, \{I,\Delta\}}\f$ in the
1071  // creation of the S_{\Pi \Pi} Schur complement in PrimalSubassembledMatrixInverse
1073 
1074  // Solver used in solving coarse problem on root.
1075  // It solves \f$S_{\Pi \Pi} u_{\Pi} = \tilde{f}_{\Pi}\f$
1077 
1078  public:
1080  {
1081  m_pDDInfo = &ddInfo;
1082  }
1083 
1084  private:
1085  // pointer to Domain decomposition info object
1087 
1088 }; /* end class 'FETISolver' */
1089 
1090 } // end namespace ug
1091 
1092 #endif /* UG_PARALLEL */
1093 
1094 #endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__FETI__ */
parameterString s
Definition: smart_pointer.h:296
Definition: smart_pointer.h:108
Definition: pcl_domain_decomposition.h:43
virtual int get_num_subdomains() const =0
virtual int map_proc_id_to_subdomain_id(int procID) const =0
mapping method "proc-id" ==> "subdomain-id"
Performs communication between interfaces on different processes.
Definition: pcl_interface_communicator.h:68
Definition: pcl_process_communicator.h:70
ProcessCommunicator create_sub_communicator(bool participate) const
creates a new communicator containing a subset of the current communicator
Definition: pcl_process_communicator.cpp:122
Extends the HorizontalAlgebraLayouts by vertical layouts.
Definition: algebra_layouts.h:121
Definition: debug_writer.h:354
virtual void set_debug(SmartPtr< IDebugWriter< algebra_type > > spDebugWriter)
set debug writer
Definition: debug_writer.h:384
TAlgebra::vector_type vector_type
type of vector
Definition: debug_writer.h:360
SmartPtr< IDebugWriter< algebra_type > > debug_writer()
returns the debug writer
Definition: debug_writer.h:391
operator implementation of the FETI-DP solver
Definition: feti.h:846
ConstSmartPtr< IConvergenceCheck< X > > convergence_check() const
returns the convergence check
Definition: linear_operator_inverse.h:202
virtual ~FETISolver()
Definition: feti.h:1019
ILinearOperatorInverse< vector_type > base_type
Base type.
Definition: feti.h:858
virtual const char * name() const
name of solver
Definition: feti.h:870
virtual bool apply(vector_type &x, const vector_type &b)
solves the system
Definition: feti.h:984
virtual bool init(SmartPtr< MatrixOperator< matrix_type, vector_type > > A)
initializes the solver for operator A
Definition: feti.cpp:1374
TAlgebra::vector_type vector_type
Definition: feti.h:852
virtual bool apply_return_defect(vector_type &lambda, vector_type &d)
Definition: feti.cpp:1501
void prepare_conv_check()
Definition: feti.h:1023
LocalSchurComplement< algebra_type > m_LocalSchurComplement
Definition: feti.h:1062
bool apply_scaling_matrix(vector_type &s, const vector_type &v)
function which applies diagonal scaling matrix to a vector
Definition: feti.h:944
FETISolver()
constructor
Definition: feti.cpp:1363
virtual void write_debug(const vector_type &vec, const char *filename)
Definition: feti.h:1035
SmartPtr< ILinearOperatorInverse< vector_type > > m_spCoarseProblemSolver
Definition: feti.h:1076
void set_dirichlet_solver(SmartPtr< ILinearOperatorInverse< vector_type > > dirichletSolver)
sets the Dirichlet solver
Definition: feti.h:888
void set_debug(SmartPtr< IDebugWriter< algebra_type > > spDebugWriter)
set debug writer
Definition: feti.h:909
int m_iterCnt
Definition: feti.h:1049
PrimalSubassembledMatrixInverse< algebra_type > m_PrimalSubassembledMatrixInverse
Definition: feti.h:1068
void print_statistic_of_inner_solver(bool bPrintOnlyAverages)
prints some convergence statistic of inner solvers
Definition: feti.h:995
void set_domain_decomp_info(pcl::IDomainDecompositionInfo &ddInfo)
Definition: feti.h:1079
void set_test_one_to_many_layouts(bool bTest)
Definition: feti.h:972
bool apply_M_inverse(vector_type &z, const vector_type &r)
function which applies matrix to a vector
Definition: feti.cpp:1820
TAlgebra::matrix_type matrix_type
Definition: feti.h:855
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition: feti.h:873
bool apply_F(vector_type &f, const vector_type &v)
function which applies matrix of the reduced system ("Delta system") to a vector
Definition: feti.cpp:1742
SmartPtr< ILinearOperatorInverse< vector_type > > m_spDirichletSolver
Definition: feti.h:1065
SmartPtr< ILinearOperatorInverse< vector_type > > m_spNeumannSolver
Definition: feti.h:1072
void test_layouts(bool bPrint)
Definition: feti.cpp:1874
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spOperator
Definition: feti.h:1053
void set_neumann_solver(SmartPtr< ILinearOperatorInverse< vector_type > > neumannSolver)
sets the Neumann solver
Definition: feti.h:895
bool compute_d(vector_type &d, const vector_type &f)
function which computes right hand side vector 'd' of the dual unknowns
Definition: feti.cpp:1783
FetiLayouts< algebra_type > m_fetiLayouts
Definition: feti.h:1059
TAlgebra algebra_type
Definition: feti.h:849
pcl::IDomainDecompositionInfo * m_pDDInfo
Definition: feti.h:1086
void set_coarse_problem_solver(SmartPtr< ILinearOperatorInverse< vector_type > > coarseProblemSolver)
sets the coarse problem solver
Definition: feti.h:902
matrix_type * m_pMatrix
Definition: feti.h:1056
Auxiliary class for handling of "FETI layouts".
Definition: feti.h:93
void vec_use_intra_sd_communication(vector_type &vec)
Definition: feti.h:279
void vec_set_on_dual(vector_type &vecDest, number alpha)
sets vecDest = alpha on dual
Definition: feti.h:316
IndexLayout & get_intra_sd_master_layout()
Definition: feti.h:244
void vec_scale_assign_on_primal(vector_type &vecDest, const vector_type &vecSrc, number alpha)
calculates vecDest = alpha*vecSrc on primal
Definition: feti.h:334
IndexLayout & get_dual_master_layout()
Definition: feti.h:249
IndexLayout & get_intra_sd_slave_layout()
Definition: feti.h:245
IndexLayout & get_primal_slave_layout()
Definition: feti.h:262
IndexLayout m_masterDualNbrLayout
Definition: feti.h:431
void mat_use_intra_sd_communication(matrix_type &mat)
Definition: feti.h:382
void vec_scale_add_on_primal(vector_type &vecDest, number alpha1, const vector_type &vecSrc1, number alpha2, const vector_type &vecSrc2)
calculates vecDest = alpha1*vecSource1 + alpha2*vecSource2 on primal
Definition: feti.h:294
void mat_set_dirichlet_on_dual(matrix_type &mat)
Definition: feti.h:363
std::vector< IndexLayout::Element > m_vUniqueSlaveDualIndex
Definition: feti.h:428
void vec_set_on_primal(vector_type &vecDest, number alpha)
sets vecDest = alpha on primal
Definition: feti.h:322
void test_layouts(bool bPrint)
Definition: feti.h:194
IndexLayout & get_dual_slave_layout()
Definition: feti.h:250
IndexLayout & get_dual_nbr_slave_layout()
Definition: feti.h:256
void mat_use_std_communication(matrix_type &mat)
Definition: feti.h:374
ConstSmartPtr< AlgebraLayouts > m_spStdLayouts
Definition: feti.h:419
TAlgebra::matrix_type matrix_type
Definition: feti.h:102
const std::vector< IndexLayout::Element > & get_dual_master_indices() const
Definition: feti.h:251
number vec_prod_on_identified_dual(const vector_type &vecSrc1, const vector_type &vecSrc2)
Definition: feti.h:346
const IndexLayout & get_std_slave_layout()
Definition: feti.h:240
std::vector< IndexLayout::Element > m_vUniquePrimalSlaveIndex
Definition: feti.h:440
void mat_set_dirichlet_on_primal(matrix_type &mat)
Definition: feti.h:368
const std::vector< IndexLayout::Element > & get_dual_slave_indices() const
Definition: feti.h:252
IndexLayout m_slaveDualNbrLayout
Definition: feti.h:432
void create_layouts(ConstSmartPtr< AlgebraLayouts > stdLayouts, size_t numIndices, pcl::IDomainDecompositionInfo &DDInfo, bool bDebug=false)
Definition: feti.h:108
pcl::ProcessCommunicator & get_intra_sd_process_communicator()
Definition: feti.h:246
std::vector< IndexLayout::Element > m_vUniqueMasterDualIndex
Definition: feti.h:427
const pcl::ProcessCommunicator & get_std_process_communicator()
Definition: feti.h:241
number vec_norm_on_identified_dual(vector_type &vec)
calculates norm on dual
Definition: feti.h:340
std::vector< IndexLayout::Element > m_vUniquePrimalMasterIndex
Definition: feti.h:439
void vec_scale_add_on_dual(vector_type &vecDest, number alpha1, const vector_type &vecSrc1, number alpha2, const vector_type &vecSrc2)
calculates vecDest = alpha1*vecSource1 + alpha2*vecSource2 on dual
Definition: feti.h:286
const std::vector< IndexLayout::Element > & get_primal_master_indices() const
Definition: feti.h:263
std::vector< IndexLayout::Element > m_vUniquePrimalIndex
Definition: feti.h:444
const IndexLayout & get_std_master_layout()
Definition: feti.h:239
FetiLayouts()
Definition: feti.h:105
SmartPtr< AlgebraLayouts > m_spInnerLayouts
Definition: feti.h:422
void vec_scale_append_on_primal(vector_type &vecInOut, const vector_type &vecSrc1, number alpha1)
calculates vecInOut += alpha1*vecSrc1 on primal
Definition: feti.h:309
const std::vector< IndexLayout::Element > & get_dual_indices() const
Definition: feti.h:268
IndexLayout m_masterDualLayout
Definition: feti.h:425
void vec_use_std_communication(vector_type &vec)
Definition: feti.h:273
const std::vector< IndexLayout::Element > & get_dual_nbr_master_indices() const
Definition: feti.h:257
IndexLayout & get_dual_nbr_master_layout()
Definition: feti.h:255
IndexLayout m_slaveDualLayout
Definition: feti.h:426
IndexLayout m_slavePrimalLayout
Definition: feti.h:438
void vec_scale_assign_on_dual(vector_type &vecDest, const vector_type &vecSrc, number alpha)
calculates vecDest = alpha*vecSrc on dual
Definition: feti.h:328
const std::vector< IndexLayout::Element > & get_primal_slave_indices() const
Definition: feti.h:264
const std::vector< IndexLayout::Element > & get_primal_indices() const
Definition: feti.h:267
std::vector< IndexLayout::Element > m_vUniqueMasterDualNbrIndex
Definition: feti.h:433
std::vector< IndexLayout::Element > m_vUniqueDualIndex
Definition: feti.h:443
IndexLayout & get_primal_master_layout()
Definition: feti.h:261
const std::vector< IndexLayout::Element > & get_dual_nbr_slave_indices() const
Definition: feti.h:258
IndexLayout m_masterPrimalLayout
Definition: feti.h:437
TAlgebra algebra_type
Definition: feti.h:96
std::vector< IndexLayout::Element > m_vUniqueSlaveDualNbrIndex
Definition: feti.h:434
void add_merge_sort_remove_doubles(std::vector< IndexLayout::Element > &vOut, const std::vector< IndexLayout::Element > &v)
Definition: feti.h:398
void vec_scale_append_on_dual(vector_type &vecInOut, const vector_type &vecSrc1, number alpha1)
calculates vecInOut += alpha1*vecSrc1 on dual
Definition: feti.h:302
TAlgebra::vector_type vector_type
Definition: feti.h:99
void sort_and_remove_doubles(std::vector< IndexLayout::Element > &vIndex)
Definition: feti.h:388
base class for all debug writer
Definition: debug_writer.h:244
describes a linear mapping X->Y
Definition: linear_operator.h:80
describes an inverse linear mapping X->Y
Definition: linear_operator_inverse.h:80
ConstSmartPtr< IConvergenceCheck< X > > convergence_check() const
returns the convergence check
Definition: linear_operator_inverse.h:202
describes an inverse linear mapping X->Y based on a matrix
Definition: matrix_operator_inverse.h:64
operator implementation of the local Schur complement
Definition: feti.h:541
SmartPtr< ILinearOperatorInverse< vector_type > > m_spDirichletSolver
Definition: feti.h:658
void init(const vector_type &u)
implementation of the operator for the solution dependent initialization.
Definition: feti.h:610
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spOperator
Definition: feti.h:639
void set_statistic_type(std::string type)
sets statistic slot where next iterate should be counted
Definition: feti.h:630
matrix_type * m_pMatrix
Definition: feti.h:646
int get_total_itercnt_of_inner_solvers()
Definition: feti.h:636
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spDirichletOperator
Definition: feti.h:652
LocalSchurComplement()
constructor
Definition: feti.cpp:98
void print_statistic_of_inner_solver(bool bPrintOnlyAverages)
prints some convergence statistic of inner solvers
Definition: feti.cpp:283
std::string m_statType
Definition: feti.h:661
virtual const char * name() const
name of solver
Definition: feti.h:561
virtual void apply_sub(vector_type &f, const vector_type &u)
solves the system
Definition: feti.cpp:268
std::map< std::string, std::vector< StepConv > > m_mvStepConv
Definition: feti.h:669
matrix_type * m_pDirichletMatrix
Definition: feti.h:655
virtual void apply(vector_type &f, const vector_type &u)
Definition: feti.cpp:154
int m_totalIterCntOfInnerSolvers
Definition: feti.h:673
FetiLayouts< algebra_type > * m_pFetiLayouts
Definition: feti.h:649
int m_applyCnt
Definition: feti.h:671
TAlgebra algebra_type
Definition: feti.h:544
void set_feti_layouts(FetiLayouts< algebra_type > &fetiLayouts)
sets the primal layouts
Definition: feti.h:604
virtual void init()
initializes the solver for operator A
Definition: feti.cpp:109
void set_matrix(SmartPtr< MatrixOperator< matrix_type, vector_type > > A)
set original matrix from which the local Schur complement is constructed
Definition: feti.h:586
TAlgebra::vector_type vector_type
Definition: feti.h:547
void set_dirichlet_solver(SmartPtr< ILinearOperatorInverse< vector_type > > dirichletSolver)
sets a sequential Dirichlet solver
Definition: feti.h:597
void clear_total_itercnt_of_inner_solvers()
Definition: feti.h:635
virtual ~LocalSchurComplement()
Definition: feti.h:639
TAlgebra::matrix_type matrix_type
Definition: feti.h:550
Definition: matrix_operator.h:49
operator implementation of the inverse of the Schur complement w.r.t. the "Delta unknowns"
Definition: feti.h:688
SmartPtr< ILinearOperatorInverse< vector_type > > m_spNeumannSolver
Definition: feti.h:795
std::map< std::string, std::vector< StepConv > > m_mvStepConv
Definition: feti.h:827
void set_coarse_problem_solver(SmartPtr< ILinearOperatorInverse< vector_type > > coarseProblemSolver)
sets the coarse problem solver
Definition: feti.h:733
SmartPtr< ILinearOperatorInverse< vector_type > > m_spCoarseProblemSolver
Definition: feti.h:798
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spOperator
Definition: feti.h:776
int m_primalRootProc
Definition: feti.h:801
virtual bool init(SmartPtr< ILinearOperator< vector_type > > J, const vector_type &u)
Definition: feti.h:750
std::string m_statType
Definition: feti.h:815
IndexLayout m_masterAllToOneLayout
Definition: feti.h:804
bool m_bTestOneToManyLayouts
Definition: feti.h:830
FetiLayouts< algebra_type > * m_pFetiLayouts
Definition: feti.h:786
void clear_total_itercnt_of_inner_solvers()
Definition: feti.h:769
virtual ~PrimalSubassembledMatrixInverse()
Definition: feti.h:776
void print_statistic_of_inner_solver(bool bPrintOnlyAverages)
prints some convergence statistic of inner solvers
Definition: feti.cpp:1151
pcl::ProcessCommunicator m_allToOneProcessComm
Definition: feti.h:806
int get_total_itercnt_of_inner_solvers()
Definition: feti.h:770
matrix_type * m_pNeumannMatrix
Definition: feti.h:792
ILinearOperatorInverse< vector_type > base_type
Base type.
Definition: feti.h:700
void set_test_one_to_many_layouts(bool bTest)
set 'm_bTestOneToManyLayouts'
Definition: feti.h:773
IndexLayout m_slaveAllToOneLayout
Definition: feti.h:805
void set_statistic_type(std::string type)
sets statistic slot where next iterate should be counted
Definition: feti.h:764
PrimalSubassembledMatrixInverse()
constructor
Definition: feti.cpp:367
virtual bool init(SmartPtr< ILinearOperator< vector_type > > L)
Definition: feti.cpp:385
TAlgebra::vector_type vector_type
Definition: feti.h:694
virtual bool supports_parallel() const
returns if parallel solving is supported
Definition: feti.h:715
void set_neumann_solver(SmartPtr< ILinearOperatorInverse< vector_type > > neumannSolver)
sets the Neumann solver
Definition: feti.h:726
void set_feti_layouts(FetiLayouts< algebra_type > &fetiLayouts)
sets the primal layouts
Definition: feti.h:740
virtual const char * name() const
name of class
Definition: feti.h:712
int m_totalIterCntOfInnerSolvers
Definition: feti.h:832
virtual bool apply_return_defect(vector_type &u, vector_type &f)
applies inverse operator, i.e. returns u = A^{-1} f and returns defect d := f - A*u
Definition: feti.cpp:906
TAlgebra algebra_type
Definition: feti.h:691
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spRootSchurComplementOp
Definition: feti.h:809
SmartPtr< MatrixOperator< matrix_type, vector_type > > m_spNeumannOperator
Definition: feti.h:789
TAlgebra::matrix_type matrix_type
Definition: feti.h:697
virtual bool apply(vector_type &u, const vector_type &f)
applies inverse operator, i.e. returns u = A^{-1} f
Definition: feti.cpp:1137
matrix_type * m_pMatrix
Definition: feti.h:783
matrix_type * m_pRootSchurComplementMatrix
Definition: feti.h:812
virtual void set_debug(SmartPtr< IVectorDebugWriter< vector_type > > spDebugWriter)
set debug writer
Definition: debug_writer.h:280
void VecSubtractOneSlaveFromMaster(TVector *pVec, const IndexLayout &masterLayout, const IndexLayout &slaveLayout, pcl::InterfaceCommunicator< IndexLayout > *pCom=NULL)
subtracts values of only one slave dof per master on layout
Definition: parallelization_util.h:445
void SetDirichletRow(TSparseMatrix &A, size_t i, size_t alpha)
Definition: sparsematrix_util.h:796
void CollectElements(std::vector< typename TLayout::Element > &elemsOut, TLayout &layout, bool clearContainer=true)
writes all elements in the interfaces into the vector.
Definition: pcl_layout_util.h:114
#define PCL_RO_SUM
Definition: pcl_methods.h:63
int ProcRank()
returns the rank of the process
Definition: pcl_base.cpp:83
bool TestLayout(const pcl::ProcessCommunicator &processCommunicator, pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout, bool bPrint=false, boost::function< TValue(typename TLayout::Element)> cbToValue=TrivialToValue< typename TLayout::Element >, bool compareValues=false)
Checks whether the given layouts are consistent.
Definition: pcl_layout_tests.h:300
#define PCL_DT_DOUBLE
Definition: pcl_datatype.h:57
bool PrintLayout(const pcl::ProcessCommunicator &processCommunicator, pcl::InterfaceCommunicator< TLayout > &com, const TLayout &masterLayout, const TLayout &slaveLayout, boost::function< TValue(typename TLayout::Element)> cbToValue=TrivialToValue< typename TLayout::Element >)
Definition: pcl_layout_tests.h:344
number alpha
const NullSmartPtr SPNULL
The equivalent to NULL for smart pointers.
Definition: smart_pointer.h:90
#define UG_LOG(msg)
Definition: log.h:367
double number
Definition: types.h:124
void VecCopy(vector_target_t &target, const vector_source_t &source, typename vector_target_t::value_type fill)
Copy contents between vectors of possibly different types.
Definition: math_vector_functions_common_impl.hpp:56
void VecSet(vector_t &vInOut, typename vector_t::value_type s)
Set each vector component to scalar (componentwise)
Definition: math_vector_functions_common_impl.hpp:539
void VecScaleAdd(vector_t &vOut, typename vector_t::value_type s1, const vector_t &v1, typename vector_t::value_type s2, const vector_t &v2)
Scales two Vectors, adds them and returns the sum in a third vector.
Definition: math_vector_functions_common_impl.hpp:265
CPUAlgebra::vector_type vector_type
the ug namespace
void ComputeDifferenceOnDeltaTransposed(TVector &f, const TVector &diff, const std::vector< IndexLayout::Element > &vDualMasterIndex, const std::vector< IndexLayout::Element > &vDualSlaveIndex, const std::vector< IndexLayout::Element > &vDualNbrSlaveIndex)
'ComputeDifferenceOnDeltaTransposed()': Apply
Definition: feti.h:507
void BuildDomainDecompositionLayouts(IndexLayout &subdomMastersOut, IndexLayout &subdomSlavesOut, IndexLayout &processMastersOut, IndexLayout &processSlavesOut, IndexLayout &deltaNbrMastersOut, IndexLayout &deltaNbrSlavesOut, IndexLayout &crossPointMastersOut, IndexLayout &crossPointSlavesOut, const IndexLayout &standardMasters, const IndexLayout &standardSlaves, int highestReferencedIndex, IDomainDecompositionInfo &ddinfo)
Definition: parallelization_util.cpp:497
double VecProd(const double &a, const double &b)
returns scal<a, b>
Definition: operations_vec.h:84
void ComputeDifferenceOnDelta(TVector &diff, const TVector &u, IndexLayout &dualMasterLayoutIn, IndexLayout &dualSlaveLayoutIn, IndexLayout &dualNbrMasterLayoutIn, IndexLayout &dualNbrSlaveLayoutIn)
Application of the "jump operator" .
Definition: feti.h:467
void VecScaleAssign(double &dest, double alpha1, const double &v1)
calculates dest = alpha1*v1. for doubles
Definition: operations_vec.h:49
number lastDef3b
Definition: feti.h:666
int numIter3b
Definition: feti.h:665
number lastDef2a
Definition: feti.h:822
number lastDef7
Definition: feti.h:823
number lastDefSC
Definition: feti.h:824