From 013757f05e5f9d4810039254c45b7005e4bbe580 Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Fri, 22 Mar 2024 06:10:36 +0100
Subject: [PATCH] Allow to use MixedRiemannianPNSolver, where applicable

---
 problems/cosserat-continuum-cantilever.parset |  3 +
 problems/film-on-substrate.parset             |  2 +-
 src/cosserat-continuum.cc                     | 83 ++++++++++++++-----
 src/film-on-substrate.cc                      | 14 +++-
 test/filmonsubstratetest.cc                   | 14 +++-
 5 files changed, 90 insertions(+), 26 deletions(-)

diff --git a/problems/cosserat-continuum-cantilever.parset b/problems/cosserat-continuum-cantilever.parset
index bfa21a84..ac1a0765 100644
--- a/problems/cosserat-continuum-cantilever.parset
+++ b/problems/cosserat-continuum-cantilever.parset
@@ -20,6 +20,9 @@ numLevels = 1
 # Number of homotopy steps for the Dirichlet boundary conditions
 numHomotopySteps = 1
 
+# Solver type: trustRegion or proximalNewton
+solvertype = trustRegion
+
 # Tolerance of the trust region solver
 tolerance = 1e-3
 
diff --git a/problems/film-on-substrate.parset b/problems/film-on-substrate.parset
index 1ce5db4b..8bfd2012 100644
--- a/problems/film-on-substrate.parset
+++ b/problems/film-on-substrate.parset
@@ -61,7 +61,7 @@ initialDeformation = "x"
 #  Solver parameters
 #############################################
 
-# Inner solver, cholmod or multigrid
+# Solver type: trustRegion or proximalNewton
 solvertype = trustRegion
 
 # Number of homotopy steps for the Dirichlet boundary conditions
diff --git a/src/cosserat-continuum.cc b/src/cosserat-continuum.cc
index ee4f3bd2..be9c9288 100644
--- a/src/cosserat-continuum.cc
+++ b/src/cosserat-continuum.cc
@@ -43,6 +43,8 @@
 #include <dune/foamgrid/foamgrid.hh>
 #endif
 
+#include <dune/istl/multitypeblockvector.hh>
+
 #include <dune/functions/functionspacebases/lagrangebasis.hh>
 #include <dune/functions/functionspacebases/compositebasis.hh>
 #include <dune/functions/functionspacebases/powerbasis.hh>
@@ -66,6 +68,7 @@
 #include <dune/gfe/assemblers/mixedgfeassembler.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -504,31 +507,65 @@ int main (int argc, char *argv[]) try
           RealTuple<double,3>,
           Rotation<double,3> > mixedAssembler(compositeBasis, &localGFEADOLCStiffness);
 #if MIXED_SPACE
-      MixedRiemannianTrustRegionSolver<GridType,
-          CompositeBasis,
-          DeformationFEBasis, RealTuple<double,3>,
-          OrientationFEBasis, Rotation<double,3> > solver;
-      solver.setup(*grid,
-                   &mixedAssembler,
-                   deformationFEBasis,
-                   orientationFEBasis,
-                   x,
-                   deformationDirichletDofs,
-                   orientationDirichletDofs, tolerance,
-                   maxSolverSteps,
-                   initialTrustRegionRadius,
-                   multigridIterations,
-                   mgTolerance,
-                   mu, nu1, nu2,
-                   baseIterations,
-                   baseTolerance,
-                   instrumented);
+      if (parameterSet.get<std::string>("solvertype", "trustRegion") == "trustRegion")
+      {
 
-      solver.setScaling(parameterSet.get<FieldVector<double,6> >("solverScaling"));
+        MixedRiemannianTrustRegionSolver<GridType,
+            CompositeBasis,
+            DeformationFEBasis, RealTuple<double,3>,
+            OrientationFEBasis, Rotation<double,3> > solver;
+        solver.setup(*grid,
+                     &mixedAssembler,
+                     deformationFEBasis,
+                     orientationFEBasis,
+                     x,
+                     deformationDirichletDofs,
+                     orientationDirichletDofs, tolerance,
+                     maxSolverSteps,
+                     initialTrustRegionRadius,
+                     multigridIterations,
+                     mgTolerance,
+                     mu, nu1, nu2,
+                     baseIterations,
+                     baseTolerance,
+                     instrumented);
 
-      solver.setInitialIterate(x);
-      solver.solve();
-      x = solver.getSol();
+        solver.setScaling(parameterSet.get<FieldVector<double,6> >("solverScaling"));
+
+        solver.setInitialIterate(x);
+        solver.solve();
+        x = solver.getSol();
+      }
+      else
+      {
+        //Create BitVector matching the tangential space
+        const int dimRotationTangent = Rotation<double,3>::TangentVector::dimension;
+        using VectorForBit = MultiTypeBlockVector<std::vector<FieldVector<double,3> >, std::vector<FieldVector<double,dimRotationTangent> > >;
+        using BitVector = Solvers::DefaultBitVector_t<VectorForBit>;
+        BitVector dirichletDofs;
+        dirichletDofs[_0].resize(compositeBasis.size({0}));
+        dirichletDofs[_1].resize(compositeBasis.size({1}));
+        for (size_t i = 0; i < compositeBasis.size({0}); i++) {
+          for (size_t j = 0; j < 3; j++)
+            dirichletDofs[_0][i][j] = deformationDirichletDofs[i][j];
+        }
+        for (size_t i = 0; i < compositeBasis.size({1}); i++) {
+          for (int j = 0; j < dimRotationTangent; j++)
+            dirichletDofs[_1][i][j] = orientationDirichletDofs[i][j];
+        }
+        GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,3>, OrientationFEBasis, Rotation<double,3>, BitVector> solver;
+        solver.setup(*grid,
+                     &mixedAssembler,
+                     x,
+                     dirichletDofs,
+                     tolerance,
+                     maxSolverSteps,
+                     initialRegularization,
+                     instrumented);
+        solver.setInitialIterate(x);
+        solver.solve();
+        x = solver.getSol();
+      }
 #else
       //The MixedRiemannianTrustRegionSolver can treat the Displacement and Orientation Space as separate ones
       //The RiemannianTrustRegionSolver can only treat the Displacement and Rotation together in a ProductManifold.
diff --git a/src/film-on-substrate.cc b/src/film-on-substrate.cc
index 0630bf58..97fc8ef8 100644
--- a/src/film-on-substrate.cc
+++ b/src/film-on-substrate.cc
@@ -64,6 +64,7 @@
 #include <dune/gfe/assemblers/sumenergy.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -650,7 +651,18 @@ int main (int argc, char *argv[]) try
     } else { //parameterSet.get<std::string>("solvertype") == "proximalNewton"
 
 #if MIXED_SPACE
-      DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
+      GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>, BitVector> solver;
+      solver.setup(*grid,
+                   &mixedAssembler,
+                   x,
+                   dirichletDofs,
+                   tolerance,
+                   maxSolverSteps,
+                   initialRegularization,
+                   instrumented);
+      solver.setInitialIterate(x);
+      solver.solve();
+      x = solver.getSol();
 #else
       RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
       solver.setup(*grid,
diff --git a/test/filmonsubstratetest.cc b/test/filmonsubstratetest.cc
index 876871df..c9b40dda 100644
--- a/test/filmonsubstratetest.cc
+++ b/test/filmonsubstratetest.cc
@@ -47,6 +47,7 @@
 #include <dune/gfe/assemblers/sumenergy.hh>
 
 #if MIXED_SPACE
+#include <dune/gfe/mixedriemannianpnsolver.hh>
 #include <dune/gfe/mixedriemanniantrsolver.hh>
 #else
 #include <dune/gfe/assemblers/geodesicfeassemblerwrapper.hh>
@@ -458,7 +459,18 @@ int main (int argc, char *argv[])
   } else {    // solverType == "proximalNewton"
 
 #if MIXED_SPACE
-    DUNE_THROW(Exception, "Error: There is no MixedRiemannianProximalNewtonSolver!");
+    GFE::MixedRiemannianProximalNewtonSolver<CompositeBasis, DeformationFEBasis, RealTuple<double,dim>, OrientationFEBasis, Rotation<double,dim>, BitVector> solver;
+    solver.setup(*grid,
+                 &mixedAssembler,
+                 x,
+                 dirichletDofs,
+                 tolerance,
+                 maxSolverSteps,
+                 1.0 /* initialRegularization */,
+                 false /* instrumented */);
+    solver.setInitialIterate(x);
+    solver.solve();
+    x = solver.getSol();
 #else
     RiemannianProximalNewtonSolver<DeformationFEBasis, RBM, GFEAssemblerWrapper> solver;
     solver.setup(*grid,
-- 
GitLab