]> https://gitweb.dealii.org/ - dealii.git/commitdiff
gauss elimination argument for linear operator
authorESeNonFossiIo <esenonfossiio@gmail.com>
Mon, 15 Jun 2015 22:04:39 +0000 (00:04 +0200)
committerESeNonFossiIo <esenonfossiio@gmail.com>
Thu, 25 Jun 2015 13:48:07 +0000 (15:48 +0200)
include/deal.II/lac/block_linear_operator.h

index 4d0e274fb42044b14f4fcdf883799c03073db957..3ed5833ab2677e18a052ddd3514357e9df2bf99c 100644 (file)
@@ -662,6 +662,177 @@ block_triangular_inverse(const BlockMatrix &block_matrix,
   return result * inverse_diagonal;
 }
 
+/**
+ * @relates LinearOperator
+ *
+ * This function implement a gauss elimination argument to invert a lower
+ * block triangular matrix.
+ * It takes as argement a block matrix @p block_matrix and an array of LinearOperators
+ * @p inverse_diagonal representing inverses of digonal blocks of @p block_matrix.
+ *
+ * Caveat: Tvmult and Tvmult_add have not been implemented, yet. This may lead to mistakes.
+ * @ingroup LAOperators
+ */
+
+template <unsigned int n, typename Range, typename Domain, typename BlockMatrix>
+LinearOperator<Range, Domain>
+gauss_lower_block_inverse(const BlockMatrix &block_matrix,
+                          const std::array<LinearOperator<typename Range::BlockType, typename Domain::BlockType>, n> &inverse_diagonal)
+{
+  LinearOperator<Range, Domain> return_op;
+
+  return_op.reinit_range_vector = [inverse_diagonal](Range &v, bool fast)
+  {
+    // Reinitialize the block vector to m blocks:
+    v.reinit(n);
+
+    // And reinitialize every individual block with reinit_range_vectors:
+    for (unsigned int i = 0; i < n; ++i)
+      inverse_diagonal[i].reinit_range_vector(v.block(i), fast);
+
+    v.collect_sizes();
+  };
+
+  return_op.reinit_domain_vector = [inverse_diagonal](Domain &v, bool fast)
+  {
+    // Reinitialize the block vector to m blocks:
+    v.reinit(n);
+
+    // And reinitialize every individual block with reinit_domain_vectors:
+    for (unsigned int i = 0; i < n; ++i)
+      inverse_diagonal[i].reinit_domain_vector(v.block(i), fast);
+
+    v.collect_sizes();
+  };
+
+  return_op.vmult = [&block_matrix, inverse_diagonal](Range &v, const Domain &u)
+  {
+    static GrowingVectorMemory<typename  Range::BlockType> vector_memory;
+    typename  Range::BlockType *tmp = vector_memory.alloc();
+
+    inverse_diagonal[0].vmult(v.block(0), u.block(0));
+    for (unsigned int i=1; i<n; ++i)
+      {
+        inverse_diagonal[i].reinit_range_vector(*tmp, /*bool fast=*/ true);
+        *tmp = u.block(i);
+        *tmp *= -1.;
+        for (unsigned int j=0; j<i; ++j)
+          block_matrix.block(i,j).vmult_add(*tmp, v.block(j));
+        *tmp *= -1.;
+        inverse_diagonal[i].vmult(v.block(i),*tmp);
+      }
+
+    vector_memory.free(tmp);
+  };
+
+  return_op.vmult_add = [&block_matrix, inverse_diagonal](Range &v, const Domain &u)
+  {
+    static GrowingVectorMemory<typename  Range::BlockType> vector_memory;
+    typename  Range::BlockType *tmp = vector_memory.alloc();
+
+    inverse_diagonal[0].vmult_add(v.block(0), u.block(0));
+    for (unsigned int i=1; i<n; ++i)
+      {
+        inverse_diagonal[i].reinit_range_vector(*tmp, /*bool fast=*/ true);
+        *tmp = u.block(i);
+        *tmp *= -1.;
+        for (unsigned int j=0; j<i; ++j)
+          block_matrix.block(i,j).vmult_add(*tmp, v.block(j));
+        *tmp *= -1.;
+        inverse_diagonal[i].vmult_add(v.block(i),*tmp);
+      }
+
+    vector_memory.free(tmp);
+  };
+
+  return return_op;
+}
+
+/**
+ * @relates LinearOperator
+ *
+ * This function implement a gauss elimination argument to invert an upper
+ * block triangular matrix.
+ * It takes as argement a block matrix @p block_matrix and an array of LinearOperators
+ * @p inverse_diagonal representing inverses of digonal blocks of @p block_matrix.
+ *
+ * Caveat: Tvmult and Tvmult_add have not been implemented, yet. This may lead to mistakes.
+ * @ingroup LAOperators
+ */
+
+template <unsigned int n, typename Range, typename Domain, typename BlockMatrix>
+LinearOperator<Range, Domain>
+gauss_upper_block_inverse(const BlockMatrix &block_matrix,
+                          const std::array<LinearOperator<typename Range::BlockType, typename Domain::BlockType>, n> &inverse_diagonal)
+{
+  LinearOperator<Range, Domain> return_op;
+
+  return_op.reinit_range_vector = [inverse_diagonal](Range &v, bool fast)
+  {
+    // Reinitialize the block vector to m blocks:
+    v.reinit(n);
+
+    // And reinitialize every individual block with reinit_range_vectors:
+    for (unsigned int i = 0; i < n; ++i)
+      inverse_diagonal[i].reinit_range_vector(v.block(i), fast);
+
+    v.collect_sizes();
+  };
+
+  return_op.reinit_domain_vector = [inverse_diagonal](Domain &v, bool fast)
+  {
+    // Reinitialize the block vector to m blocks:
+    v.reinit(n);
+
+    // And reinitialize every individual block with reinit_domain_vectors:
+    for (unsigned int i = 0; i < n; ++i)
+      inverse_diagonal[i].reinit_domain_vector(v.block(i), fast);
+
+    v.collect_sizes();
+  };
+
+  return_op.vmult = [&block_matrix, inverse_diagonal](Range &v, const Domain &u)
+  {
+    static GrowingVectorMemory<typename  Range::BlockType> vector_memory;
+    typename  Range::BlockType *tmp = vector_memory.alloc();
+
+    inverse_diagonal[n-1].vmult(v.block(n-1),u.block(n-1));
+    for (int i=n-2; i>=0; --i)
+      {
+        inverse_diagonal[i].reinit_range_vector(*tmp, /*bool fast=*/ true);
+        *tmp = u.block(i);
+        *tmp *= -1.;
+        for (int j=i+1; j<n; ++j)
+          block_matrix.block(i,j).vmult_add(*tmp,v.block(j));
+        *tmp *= -1.;
+        inverse_diagonal[i].vmult(v.block(i),*tmp);
+      }
+
+    vector_memory.free(tmp);
+  };
+
+  return_op.vmult_add = [&block_matrix, inverse_diagonal](Range &v, const Domain &u)
+  {
+    static GrowingVectorMemory<typename  Range::BlockType> vector_memory;
+    typename  Range::BlockType *tmp = vector_memory.alloc();
+
+    inverse_diagonal[n-1].vmult_add(v.block(n-1),u.block(n-1));
+    for (int i=n-2; i>=0; --i)
+      {
+        inverse_diagonal[i].reinit_range_vector(*tmp, /*bool fast=*/ true);
+        *tmp = u.block(i);
+        *tmp *= -1.;
+        for (int j=i+1; j<n; ++j)
+          block_matrix.block(i,j).vmult_add(*tmp,v.block(j));
+        *tmp *= -1.;
+        inverse_diagonal[i].vmult_add(v.block(i),*tmp);
+      }
+
+    vector_memory.free(tmp);
+  };
+
+  return return_op;
+}
 
 //@}
 

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.