From 67ecd248591e16b16c5ddd31ceda2a3cdd9dffce Mon Sep 17 00:00:00 2001
From: Markus Blatt <mblatt@dune-project.org>
Date: Thu, 27 Sep 2007 06:23:49 +0000
Subject: [PATCH] Added and improved multiplicative Schwarz methods.

[[Imported from SVN: r820]]
---
 istl/overlappingschwarz.hh          | 51 +++++++++++++++++---
 istl/test/laplacian.hh              | 53 +++++++++++++++++----
 istl/test/overlappingschwarztest.cc | 73 ++++++++++++++++++++++-------
 3 files changed, 144 insertions(+), 33 deletions(-)

diff --git a/istl/overlappingschwarz.hh b/istl/overlappingschwarz.hh
index e1233ae9e..f35ff60b8 100644
--- a/istl/overlappingschwarz.hh
+++ b/istl/overlappingschwarz.hh
@@ -24,7 +24,7 @@ namespace Dune
   /**
    * @file
    * @author Markus Blatt
-   * @brief Contains an additive overlapping Schwarz preconditioner
+   * @brief Contains one level overlapping Schwarz preconditioners
    */
 #ifdef HAVE_SUPERLU
 
@@ -104,6 +104,9 @@ namespace Dune
   struct MultiplicativeSchwarzMode
   {};
 
+  struct SymmetricMultiplicativeSchwarzMode
+  {};
+
   namespace
   {
     template<typename T>
@@ -161,6 +164,12 @@ namespace Dune
       typedef MultiplicativeAdder<X> Adder;
     };
 
+    template<class X>
+    struct AdderSelector<SymmetricMultiplicativeSchwarzMode,X>
+    {
+      typedef MultiplicativeAdder<X> Adder;
+    };
+
     template<typename T1, typename T2, bool forward>
     struct ApplyHelper
     {
@@ -217,10 +226,34 @@ namespace Dune
       }
     };
 
+    template<class T>
+    struct Applier
+    {
+      typedef T smoother;
+      typedef typename smoother::range_type range_type;
+
+      static void apply(smoother& sm, range_type& v, const range_type& b)
+      {
+        sm.template apply<true>(v, b);
+      }
+    };
+
+    template<class M, class X, class TA>
+    struct Applier<SeqOverlappingSchwarz<M,X,SymmetricMultiplicativeSchwarzMode, TA> >
+    {
+      typedef SeqOverlappingSchwarz<M,X,SymmetricMultiplicativeSchwarzMode, TA> smoother;
+      typedef typename smoother::range_type range_type;
+
+      static void apply(smoother& sm, range_type& v, const range_type& b)
+      {
+        sm.template apply<true>(v, b);
+        sm.template apply<false>(v, b);
+      }
+    };
   }
 
   /**
-   * @brief Sequential additive overlapping Schwarz preconditioner
+   * @brief Sequential overlapping Schwarz preconditioner
    */
   template<class M, class X, class TM=AdditiveSchwarzMode, class TA=std::allocator<X> >
   class SeqOverlappingSchwarz
@@ -246,7 +279,7 @@ namespace Dune
      * @brief The mode (additive or multiplicative) of the Schwarz
      * method.
      *
-     * Either Schwarz::Additive or Schwarz::Multiplicative
+     * Either AdditiveSchwarzMode or MultiplicativeSchwarzMode
      */
     typedef TM Mode;
 
@@ -342,6 +375,7 @@ namespace Dune
       const BlockVector<FieldVector<T,n>,A>* x;
       int i;
     };
+
   };
 
 
@@ -481,6 +515,7 @@ namespace Dune
       for(DomainIterator d=iter->begin(); d != iter->end(); ++d)
         subDomains[*d].insert(row);
 
+#ifdef DUNE_ISTL_WITH_CHECKING
     int i=0;
     typedef typename std::vector<std::set<size_type> >::const_iterator iterator;
     for(iterator iter=subDomains.begin(); iter != subDomains.end(); ++iter) {
@@ -491,6 +526,7 @@ namespace Dune
       }
       std::cout<<std::endl;
     }
+#endif
     initialize(rowToDomain, mat);
   }
 
@@ -502,14 +538,14 @@ namespace Dune
   {
     typedef typename subdomain_vector::const_iterator DomainIterator;
 
-#ifndef NDEBUG
+#ifdef DUNE_ISTL_WITH_CHECKING
     int i=0;
 
     for(DomainIterator d=sd.begin(); d != sd.end(); ++d,++i) {
       //std::cout<<i<<": "<<d->size()<<std::endl;
       assert(d->size()>0);
       typedef typename DomainIterator::value_type::const_iterator entry_iterator;
-      std::cout<<"domain "<<i++<<":";
+      std::cout<<"domain "<<i<<":";
       for(entry_iterator entry = d->begin(); entry != d->end(); ++entry) {
         std::cout<<" "<<*entry;
       }
@@ -549,6 +585,7 @@ namespace Dune
         ++initializer, ++solver, ++domain) {
       solver->mat.N_=domain->size();
       solver->mat.M_=domain->size();
+      //solver->setVerbosity(true);
       *initializer=SuperMatrixInitializer<matrix_type>(solver->mat);
     }
 
@@ -578,8 +615,9 @@ namespace Dune
   template<class M, class X, class TM, class TA>
   void SeqOverlappingSchwarz<M,X,TM,TA>::apply(X& x, const X& b)
   {
-    this->template apply<true>(x, b);
+    Applier<SeqOverlappingSchwarz>::apply(*this, x, b);
   }
+
   template<class M, class X, class TM, class TA>
   template<bool forward>
   void SeqOverlappingSchwarz<M,X,TM,TA>::apply(X& x, const X& b)
@@ -600,7 +638,6 @@ namespace Dune
 
     X v(x); // temporary for the update
     v=0;
-    //x=1;
 
     typedef typename AdderSelector<TM,X>::Adder Adder;
     for(iterator solver=ApplyHelper<solver_vector,subdomain_vector,forward>::begin(solvers);
diff --git a/istl/test/laplacian.hh b/istl/test/laplacian.hh
index ca2d5ebe3..270f2cf1a 100644
--- a/istl/test/laplacian.hh
+++ b/istl/test/laplacian.hh
@@ -53,19 +53,54 @@ void setupLaplacian(Dune::BCRSMatrix<B>& A, int N)
     int x = i.index()%N; // x coordinate in the 2d field
     int y = i.index()/N;  // y coordinate in the 2d field
 
-    i->operator[](i.index())=diagonal;
+    /*    if(x==0 || x==N-1 || y==0||y==N-1){
 
-    if(y>0)
-      i->operator[](i.index()-N)=bone;
+       i->operator[](i.index())=1.0;
 
-    if(y<N-1)
-      i->operator[](i.index()+N)=bone;
+       if(y>0)
+       i->operator[](i.index()-N)=0;
 
-    if(x>0)
-      i->operator[](i.index()-1)=bone;
+       if(y<N-1)
+       i->operator[](i.index()+N)=0.0;
+
+       if(x>0)
+       i->operator[](i.index()-1)=0.0;
+
+       if(x < N-1)
+       i->operator[](i.index()+1)=0.0;
+
+       }else*/
+    {
+
+      i->operator[](i.index())=diagonal;
 
-    if(x < N-1)
-      i->operator[](i.index()+1)=bone;
+      if(y>0)
+        i->operator[](i.index()-N)=bone;
+
+      if(y<N-1)
+        i->operator[](i.index()+N)=bone;
+
+      if(x>0)
+        i->operator[](i.index()-1)=bone;
+
+      if(x < N-1)
+        i->operator[](i.index()+1)=bone;
+    }
+  }
+}
+template<int BS>
+void setBoundary(Dune::BlockVector<Dune::FieldVector<double,BS> >& lhs,
+                 Dune::BlockVector<Dune::FieldVector<double,BS> >& rhs,
+                 int N)
+{
+  for(int i=0; i < lhs.size(); ++i) {
+    int x = i/N;
+    int y = i%N;
+
+    if(x==0 || y ==0 || x==N-1 || y==N-1) {
+      double h = 1.0 / ((double) (N-1));
+      lhs[i]=rhs[i]=0; //((double)x)*((double)y)*h*h;
+    }
   }
 }
 #endif
diff --git a/istl/test/overlappingschwarztest.cc b/istl/test/overlappingschwarztest.cc
index c662e4b51..107079aa9 100644
--- a/istl/test/overlappingschwarztest.cc
+++ b/istl/test/overlappingschwarztest.cc
@@ -1,18 +1,20 @@
 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 // vi: set et ts=4 sw=2 sts=2:
 #include "config.h"
+#include <dune/istl/io.hh>
 #include <dune/istl/bvector.hh>
 #include <dune/istl/operators.hh>
 #include <dune/common/fmatrix.hh>
 #include <dune/common/fvector.hh>
 #include <laplacian.hh>
 #include <dune/common/timer.hh>
+#include <dune/common/sllist.hh>
 #include <dune/istl/overlappingschwarz.hh>
 int main(int argc, char** argv)
 {
 
   const int BS=1;
-  int N=100;
+  int N=4;
 
   if(argc>1)
     N = atoi(argv[1]);
@@ -30,17 +32,26 @@ int main(int argc, char** argv)
   Vector b(N*N), x(N*N);
 
   setupLaplacian(mat,N);
-  b=1;
-  x=0;
-
+  b=0;
+  x=100;
+  //setBoundary(x,b,N);
+  /*
+     for (BCRSMat::RowIterator row = mat.begin(); row != mat.end(); ++row)
+     (*row)[row.index()]+=row.index();
+   */
   // create the subdomains
-  int domainSize=4;
-  int overlap = 1;
+  int domainSize=2;
+  if(argc>2)
+    domainSize = atoi(argv[2]);
+  int overlap = 0;
 
   int domainsPerDim=(N+domainSize-1)/domainSize;
 
   // set up the overlapping domains
-  std::vector<std::set<BCRSMat::size_type> > domains(domainsPerDim*domainsPerDim);
+  typedef Dune::SeqOverlappingSchwarz<BCRSMat,Vector> Schwarz;
+  typedef Schwarz::subdomain_vector subdomain_vector;
+
+  subdomain_vector domains(domainsPerDim*domainsPerDim);
 
 
   for(int j=0; j < N; ++j)
@@ -72,27 +83,55 @@ int main(int argc, char** argv)
         domains[domain*domainsPerDim+xdomain].insert(j*N+i);
     }
 
-  typedef std::vector<std::set<BCRSMat::size_type> >::const_iterator iterator;
-  int i=0;
-  for(iterator iter=domains.begin(); iter != domains.end(); ++iter) {
-    typedef std::set<BCRSMat::size_type>::const_iterator entry_iterator;
-    std::cout<<"domain "<<i++<<":";
-    for(entry_iterator entry = iter->begin(); entry != iter->end(); ++entry) {
-      std::cout<<" "<<*entry;
+  typedef subdomain_vector::const_iterator iterator;
+
+  if(N<10) {
+    int i=0;
+    for(iterator iter=domains.begin(); iter != domains.end(); ++iter) {
+      typedef iterator::value_type::const_iterator entry_iterator;
+      std::cout<<"domain "<<i++<<":";
+      for(entry_iterator entry = iter->begin(); entry != iter->end(); ++entry) {
+        std::cout<<" "<<*entry;
+      }
+      std::cout<<std::endl;
     }
-    std::cout<<std::endl;
+    Dune::printmatrix(std::cout, mat, std::string("A"), std::string("A"));
+    Dune::printvector(std::cout, b, std::string("B"), std::string("B"));
+    Dune::printvector(std::cout, x, std::string("X"), std::string("X"));
   }
 
-  Dune::SeqOverlappingSchwarz<BCRSMat,Vector> prec(mat, domains);
+  Dune::SeqOverlappingSchwarz<BCRSMat,Vector> prec(mat, domains, 1);
 
 
   Dune::Timer watch;
 
   watch.reset();
 
-  Dune::LoopSolver<Vector> solver(fop, prec, 10e-8,80,2);
+  Dune::LoopSolver<Vector> solver(fop, prec, 1e-2,100,2);
   Dune::InverseOperatorResult res;
 
+
+  //  b=0;
+  //  x=100;
+  //  setBoundary(x,b,N);
+  std::cout<<"Additive Schwarz"<<std::endl;
   solver.apply(x,b, res);
 
+  Dune::SeqOverlappingSchwarz<BCRSMat,Vector,Dune::MultiplicativeSchwarzMode> prec1(mat,domains, 1);
+  Dune::LoopSolver<Vector> solver1(fop, prec1, 1e-2,100,2);
+
+  b=0;
+  x=100;
+  //setBoundary(x,b,N);
+  std::cout << "Multiplicative Schwarz"<<std::endl;
+
+  solver1.apply(x,b, res);
+
+  Dune::SeqSOR<BCRSMat,Vector,Vector> sor(mat, 1,1);
+  Dune::LoopSolver<Vector> solver2(fop, sor, 1e-2,100,2);
+  b=0;
+  x=100;
+  //setBoundary(x,b,N);
+  std::cout << "SOR"<<std::endl;
+  solver2.apply(x,b, res);
 }
-- 
GitLab