From 8ec7621faa610f647f599739905d23f3254b74b0 Mon Sep 17 00:00:00 2001
From: Nicolas Marsic <marsic@temf.tu-darmstadt.de>
Date: Mon, 3 Jul 2017 16:28:10 +0200
Subject: [PATCH] Start to reuse LU in a GetDP way... WARNING: change in the
 GetDP .pro file interface!

---
 bin/beyn.py                        | 19 +++++-------
 bin/solver.py                      | 49 +++++++++++++++++++-----------
 example/maxwell_linear/maxwell.pro | 35 +++++++++++++++------
 3 files changed, 64 insertions(+), 39 deletions(-)

diff --git a/bin/beyn.py b/bin/beyn.py
index c2729a2..ffe0426 100644
--- a/bin/beyn.py
+++ b/bin/beyn.py
@@ -101,7 +101,7 @@ def simple(operator, origin, radius,
     norm   = np.empty((nFound))
     for i in range(nFound):
         operator.apply(Q[:, i], myLambda[i]) # Apply eigenpair
-        r = operator.solution()              # Get residual
+        r = operator.solution(0)             # Get residual
         norm[i] = np.linalg.norm(r)          # Save the norm
 
     # Done
@@ -174,18 +174,15 @@ def multiSolve(solver, B, w):
     w -- the complex frequency to use
     """
 
-    # Number of solve
-    nSolve = B.shape[1]
-
-    # Initialise X
-    size = solver.size()
-    X    = np.matlib.empty((size, nSolve), dtype=complex)
+    # Solve
+    solver.solve(B, w)
 
-    # Loop and solve
+    # Get solutions
+    nSolve = B.shape[1]
+    size   = solver.size()
+    X      = np.matlib.empty((size, nSolve), dtype=complex)
     for i in range(nSolve):
-        b = B[:, i]
-        solver.solve(b, w)
-        X[:, i] = solver.solution()
+        X[:, i] = solver.solution(i)
 
     # Done
     return X
diff --git a/bin/solver.py b/bin/solver.py
index ed8e82d..e890314 100644
--- a/bin/solver.py
+++ b/bin/solver.py
@@ -18,11 +18,13 @@ class GetDPWave:
     The .pro file should use the following variables:
     angularFreqRe -- the real part of the angular frequency to use
     angularFreqIm -- the imaginary part of the angular frequency to use
-    b -- the right hand side (RHS) to use
-    x -- the solution vector computed by GetDP
-    imposeRHS -- should the imposed RHS be taken into account?
-    doPostpro -- should only a view be created for x?
-    doApply -- should only the application of x be computed?
+    nRHS -- the number of right hand side that should be considered (default: 1)
+    b_i / b~{i} -- the ith right hand side to use (first index is 0)
+    x_i / x~{i} -- the ith solution vector computed by GetDP (first index is 0)
+    doInit -- should some initialization be done (default: 0)?
+    doSolve -- should Ax_i = b_i be solved for all i (default: 0)?
+    doPostpro -- should only a view be created for x (default: 0)?
+    doApply -- should only the application of x be computed (default: 0)?
     fileName -- post-processing file name
     """
 
@@ -44,19 +46,20 @@ class GetDPWave:
         self.__resolution = resolution
         self.__optional   = optional
 
-        # Generate DoFs and initialise RHS and solution vectors in GetDP
+        # Generate DoFs and assemble a first system
+        GetDP.GetDPSetNumber("doInit", 1);
         GetDP.GetDP(["getdp",     self.__pro,
                      "-msh",      self.__mesh,
                      "-solve",    self.__resolution,
                      "-v", "2"] + self.__optional)
 
-    def solution(self):
-        """Returns the solution"""
-        return self.__toNumpy(GetDP.GetDPGetNumber("x"))
+    def solution(self, i):
+        """Returns the solution for the ith RHS (first index is 0)"""
+        return self.__toNumpy(GetDP.GetDPGetNumber("x_" + str(i)))
 
     def size(self):
         """Returns the number of degrees of freedom"""
-        return self.solution().shape[0]
+        return self.solution(0).shape[0]
 
     def apply(self, x, w):
         """Applies x to the operator with a pulsation of w
@@ -65,23 +68,34 @@ class GetDPWave:
         """
         GetDP.GetDPSetNumber("angularFreqRe", np.real(w).tolist())
         GetDP.GetDPSetNumber("angularFreqIm", np.imag(w).tolist())
-        GetDP.GetDPSetNumber("x", self.__toGetDP(x))
+        GetDP.GetDPSetNumber("x_0", self.__toGetDP(x))
         GetDP.GetDPSetNumber("doApply", 1)
         GetDP.GetDP(["getdp",  self.__pro,
                      "-msh",   self.__mesh,
                      "-cal"] + self.__optional)
-        GetDP.GetDPSetNumber("doApply", 0)
 
     def solve(self, b, w):
-        """Solves with b as RHS and w as complex angular frequency"""
+        """Solves with b as RHS and w as complex angular frequency
+
+        b is a matrix and each column is a different RHS
+        """
+        # Number of RHS
+        nRHS = b.shape[1]
+
+        # Set variables
+        GetDP.GetDPSetNumber("nRHS", nRHS)
         GetDP.GetDPSetNumber("angularFreqRe", np.real(w).tolist())
         GetDP.GetDPSetNumber("angularFreqIm", np.imag(w).tolist())
-        GetDP.GetDPSetNumber("b", self.__toGetDP(b))
-        GetDP.GetDPSetNumber("imposeRHS", 1)
+
+        # Set RHS
+        for i in range(nRHS):
+            GetDP.GetDPSetNumber("b_" + str(i), self.__toGetDP(b[:, i]))
+
+        # Solve
+        GetDP.GetDPSetNumber("doSolve", 1)
         GetDP.GetDP(["getdp",  self.__pro,
                      "-msh",   self.__mesh,
                      "-cal"] + self.__optional)
-        GetDP.GetDPSetNumber("imposeRHS", 0)
 
     def view(self, x, fileName):
         """Generates a post-processing view
@@ -92,13 +106,12 @@ class GetDPWave:
 
         This method generates a linear system
         """
-        GetDP.GetDPSetNumber("x", self.__toGetDP(x))
+        GetDP.GetDPSetNumber("x_0", self.__toGetDP(x))
         GetDP.GetDPSetNumber("doPostpro", 1)
         GetDP.GetDPSetString("fileName", fileName)
         GetDP.GetDP(["getdp",  self.__pro,
                      "-msh",   self.__mesh,
                      "-cal"] + self.__optional)
-        GetDP.GetDPSetNumber("doPostpro", 0)
 
     @staticmethod
     def __toNumpy(vGetDP):
diff --git a/example/maxwell_linear/maxwell.pro b/example/maxwell_linear/maxwell.pro
index 0b7a0f2..1e219c8 100644
--- a/example/maxwell_linear/maxwell.pro
+++ b/example/maxwell_linear/maxwell.pro
@@ -16,11 +16,15 @@ Function{
          angularFreqRe, angularFreqIm];
 
   // Algebraic data //
-  DefineConstant[x() = {},  // Solution
-                 b() = {}]; // Right hand side
+  DefineConstant[nRHS = 1];       // Number of RHS for this run
+  For i In {0:nRHS-1}
+    DefineConstant[x~{i}() = {},  // Solution
+                   b~{i}() = {}]; // Right hand side
+  EndFor
 
   // Control data //
-  DefineConstant[imposeRHS = 0,          // Should I use an imposed RHS?
+  DefineConstant[doInit    = 0,          // Should I initialize some stuff?
+                 doSolve   = 0,          // Should I solve Ax = b?
                  doPostpro = 0,          // Should I only create a view for x()?
                  doApply   = 0,          // Should I only apply x(): x <- Ax?
                  fileName  = "eig.pos"]; // Postpro file name
@@ -91,21 +95,32 @@ Resolution{
     Operation{
       Generate[A];
 
-      If(imposeRHS)
-        CopyRightHandSide[b(), A];
+      If(doInit)
+        CopySolution[A, x~{0}()];
       EndIf
 
-      If(!doPostpro && !doApply)
+      If(doSolve)
+        // Full solve for first RHS
+        CopyRightHandSide[b~{0}(), A];
         Solve[A];
-        CopySolution[A, x()];
+        CopySolution[A, x~{0}()];
+
+        // SolveAgain for other RHSs
+        For i In {1:nRHS-1}
+          CopyRightHandSide[b~{i}(), A];
+          SolveAgain[A];
+          CopySolution[A, x~{i}()];
+        EndFor
       EndIf
+
       If(doApply)
-        CopySolution[x(), A];
+        CopySolution[x~{0}(), A];
         Apply[A];
-        CopySolution[A, x()];
+        CopySolution[A, x~{0}()];
       EndIf
+
       If(doPostpro)
-        CopySolution[x(), A];
+        CopySolution[x~{0}(), A];
         PostOperation[Maxwell];
       EndIf
     }
-- 
GitLab