From 81a90c95746af98d0a77661a1f5f4dce0468157b Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Mon, 6 Apr 2009 14:24:14 +0000
Subject: [PATCH] moved to new module dune-solvers

[[Imported from SVN: r2345]]
---
 .../iterationsteps/projectedblockgsstep.cc    | 87 +++++++++++++++++++
 .../iterationsteps/projectedblockgsstep.hh    | 41 +++++++++
 2 files changed, 128 insertions(+)
 create mode 100644 dune-solvers/iterationsteps/projectedblockgsstep.cc
 create mode 100644 dune-solvers/iterationsteps/projectedblockgsstep.hh

diff --git a/dune-solvers/iterationsteps/projectedblockgsstep.cc b/dune-solvers/iterationsteps/projectedblockgsstep.cc
new file mode 100644
index 00000000..30902ed0
--- /dev/null
+++ b/dune-solvers/iterationsteps/projectedblockgsstep.cc
@@ -0,0 +1,87 @@
+template<class OperatorType, class DiscFuncType>
+inline
+DiscFuncType ProjectedBlockGSStep<OperatorType, DiscFuncType>::getSol()
+{
+    return *(this->x_);
+}
+
+template<class OperatorType, class DiscFuncType>
+inline
+void ProjectedBlockGSStep<OperatorType, DiscFuncType>::iterate()
+{
+    if (hasObstacle_->size()!= (unsigned int)this->x_->size())
+        DUNE_THROW(SolverError, "Size of hasObstacle (" << hasObstacle_->size() 
+                   << ") doesn't match solution vector (" << this->x_->size() << ")");
+
+    const OperatorType& mat = *this->mat_;
+
+    for (int i=0; i<this->x_->size(); i++) {
+
+        /** \todo Handle more general boundary conditions */
+        if ((*this->ignoreNodes_)[i][0])
+            continue;
+
+        bool zeroDiagonal = false;
+        for (int j=0; j<BlockSize; j++) {
+            // When using this solver as part of a truncated multigrid solver,
+            // the diagonal entries of the matrix may get completely truncated
+            // away.  In this case we just do nothing here.
+            zeroDiagonal |= (mat[i][i][j][j] < 1e-10);
+        }
+
+        if (zeroDiagonal)
+            continue;
+
+        VectorBlock r;
+        residual(i, r);
+
+        // Compute x_i += A_{i,i}^{-1} r[i] 
+        VectorBlock v;
+        VectorBlock& x = (*this->x_)[i];
+
+
+        if ((*hasObstacle_)[i] == false) {
+
+            // No obstacle --> solve linear problem
+            mat[i][i].solve(v, r);
+        
+        } else {
+            
+            // Solve the local constraint minimization problem
+            // We use a projected Gauss-Seidel, for lack of anything better
+            BoxConstraint<field_type,BlockSize> defectObstacle = (*obstacles_)[i];
+            defectObstacle -= x;
+
+            // Initial correction
+            v = 0;
+
+            for (int j=0; j<20; j++) {
+
+                for (int k=0; k<BlockSize; k++) {
+
+                    // Compute residual
+                    field_type sr = 0;
+                    for (int l=0; l<BlockSize; l++)
+                        sr += mat[i][i][k][l] * v[l];
+
+                    sr = r[k] - sr;
+                    v[k] += sr / mat[i][i][k][k];
+
+                    // Project
+                    if (v[k] < defectObstacle.lower(k))
+                        v[k] = defectObstacle.lower(k);
+                    else if (v[k] > defectObstacle.upper(k))
+                        v[k] = defectObstacle.upper(k);
+
+                }
+
+            }
+
+        }
+
+        // Add correction
+        x += v;
+
+    }
+
+}
diff --git a/dune-solvers/iterationsteps/projectedblockgsstep.hh b/dune-solvers/iterationsteps/projectedblockgsstep.hh
new file mode 100644
index 00000000..a81e136e
--- /dev/null
+++ b/dune-solvers/iterationsteps/projectedblockgsstep.hh
@@ -0,0 +1,41 @@
+#ifndef DUNE_PROJECTED_BLOCK_GAUSS_SEIDEL_STEP_HH
+#define DUNE_PROJECTED_BLOCK_GAUSS_SEIDEL_STEP_HH
+
+#include <vector>
+
+#include "blockgsstep.hh"
+#include "boxconstraint.hh"
+
+template<class OperatorType, class DiscFuncType>
+class ProjectedBlockGSStep : public BlockGSStep<OperatorType, DiscFuncType>
+{
+    
+    typedef typename DiscFuncType::block_type VectorBlock;
+    
+    typedef typename DiscFuncType::field_type field_type;
+
+    enum {BlockSize = VectorBlock::dimension};
+    
+public:
+    
+    //! Default constructor.  Doesn't init anything
+    ProjectedBlockGSStep() {}
+    
+    //! Constructor with a linear problem
+    ProjectedBlockGSStep(OperatorType& mat, DiscFuncType& x, DiscFuncType& rhs)
+        : LinearIterationStep<OperatorType,DiscFuncType>(mat, x, rhs)
+    {}
+    
+    //! Perform one iteration
+    virtual void iterate();
+    
+    virtual DiscFuncType getSol();
+    
+    Dune::BitSetVector<1>* hasObstacle_;
+    
+    const std::vector<BoxConstraint<field_type,BlockSize> >* obstacles_;
+};
+
+#include "projectedblockgsstep.cc"
+
+#endif
-- 
GitLab