From 606ee8ed91a4c45dd1688a166eccd84785945947 Mon Sep 17 00:00:00 2001 From: Martin Kronbichler Date: Sat, 15 Mar 2008 16:41:19 +0000 Subject: [PATCH] Some more changes of signs in introductions. git-svn-id: https://svn.dealii.org/trunk@15891 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/examples/step-20/doc/intro.dox | 18 ++++++++++++++++++ deal.II/examples/step-21/doc/intro.dox | 12 ++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/deal.II/examples/step-20/doc/intro.dox b/deal.II/examples/step-20/doc/intro.dox index 7fa21d7a1f..595fa6a884 100644 --- a/deal.II/examples/step-20/doc/intro.dox +++ b/deal.II/examples/step-20/doc/intro.dox @@ -178,6 +178,7 @@ components. For example, in 2d, the first term could be rewritten like this \left((x_h^i)_1, K^{-1}_{11} (x_h^j)_1\right). @f} If we implemented this, we would get code like this: + @code for (unsigned int q=0; qFEValues. To compute the boundary term we then simply have to loop over all boundary faces and integrate there. The mechanism works in the same way as above, i.e. the extractor classes also work on FEFaceValues objects: + @code for (unsigned int face_no=0; face_no::faces_per_cell; @@ -390,6 +396,7 @@ need, which in fact includes only the ability to perform matrix-vector products; we form them by using a CG solve (this of course requires that the matrix passed to this class satisfies the requirements of the CG solvers). Here are the relevant parts of the code that implements this: + @code class InverseMatrix { @@ -414,6 +421,7 @@ void InverseMatrix::vmult (Vector &dst, cg.solve (*matrix, dst, src, PreconditionIdentity()); } @endcode + Once created, objects of this class can act as matrices: they perform matrix-vector multiplications. How this is actually done is irrelevant to the outside world. @@ -422,6 +430,7 @@ Using this class, we can then write a class that implements the Schur complement in much the same way: to act as a matrix, it only needs to offer a function to perform a matrix-vector multiplication, using the algorithm above. Here are again the relevant parts of the code: + @code class SchurComplement { @@ -466,6 +475,7 @@ With all this, we can go ahead and write down the solver we are going to use. Essentially, all we need to do is form the right hand sides of the two equations defining $P$ and $U$, and then solve them with the Schur complement matrix and the mass matrix, respectively: + @code template void MixedLaplaceProblem::solve () @@ -545,6 +555,7 @@ the inverse of its diagonal, which is cheap. To implement something like this, let us first generalize the InverseMatrix class so that it can work not only with SparseMatrix objects, but with any matrix type. This looks like so: + @code template class InverseMatrix @@ -574,12 +585,14 @@ void InverseMatrix::vmult (Vector &dst, cg.solve (*matrix, dst, src, PreconditionIdentity()); } @endcode + Essentially, the only change we have made is the introduction of a template argument that generalizes the use of SparseMatrix. The next step is to define a class that represents the approximate Schur complement. This should look very much like the Schur complement class itself, except that it doesn't need the object representing $M^{-1}$ any more: + @code class ApproximateSchurComplement : public Subscriptor { @@ -604,12 +617,14 @@ void ApproximateSchurComplement::vmult (Vector &dst, system_matrix->block(1,0).vmult (dst, tmp2); } @endcode + Note how the vmult function differs in simply doing one Jacobi sweep (i.e. multiplying with the inverses of the diagonal) instead of multiplying with the full $M^{-1}$. With all this, we already have the preconditioner: it should be the inverse of the approximate Schur complement, i.e. we need code like this: + @code ApproximateSchurComplement approximate_schur_complement (system_matrix); @@ -617,10 +632,12 @@ the approximate Schur complement, i.e. we need code like this: InverseMatrix preconditioner (approximate_schur_complement) @endcode + That's all! Taken together, the first block of our solve() function will then look like this: + @code Vector schur_rhs (solution.block(1).size()); @@ -644,6 +661,7 @@ look like this: cg.solve (schur_complement, solution.block(1), schur_rhs, preconditioner); @endcode + Note how we pass the so-defined preconditioner to the solver working on the Schur complement matrix. diff --git a/deal.II/examples/step-21/doc/intro.dox b/deal.II/examples/step-21/doc/intro.dox index ea09ee7345..43a928a54a 100644 --- a/deal.II/examples/step-21/doc/intro.dox +++ b/deal.II/examples/step-21/doc/intro.dox @@ -79,7 +79,7 @@ of course is going to change as the fluids move around. The second part of the equations is a therefore description of the dynamics of the saturation. We model this as an advected quantity: @f{eqnarray*} - S_{t} + \mathbf{u} \cdot \nabla F(S) = 0. + S_{t} + \mathbf{u} \cdot \nabla F(S) = 0, @f} where $\mathbf u$ is the total velocity @f[ @@ -145,7 +145,7 @@ derived above by going back to the first order, mixed formulation. To this end, we re-introduce the total velocity $\mathbf u$ and write the equations in the following form: @f{eqnarray*} - \mathbf{u}-\mathbf{K}\lambda(S) \nabla p&=&0 \\ + \mathbf{u}+\mathbf{K}\lambda(S) \nabla p&=&0 \\ \nabla \cdot\mathbf{u} &=& q \\ S_{t} + \mathbf{u} \cdot \nabla F(S) &=& 0. @f} @@ -215,7 +215,7 @@ cell term to get an equation as follows: \right\} &=& (S^n,\sigma)_\Omega + - \triangle t \sum_K \left(F(S^n), q^{n+1} \sigma\right). + \triangle t \sum_K \left(F(S^n) q^{n+1}, \sigma\right)_K. @f} @@ -288,7 +288,7 @@ M^u(S^n)_{ij} &=& v_j\right)_\Omega, \\ B_{ij} &=& -(\nabla \cdot \mathbf v_i, \phi_j)_\Omega, +-(\nabla \cdot \mathbf v_j, \phi_i)_\Omega, \\ H_{ij} &=& - @@ -305,10 +305,10 @@ M^S_{ij} &=& (\phi_i, \phi_j)_\Omega, \\ (F_2)_i &=& -(q,\phi_i)_\Omega, +-(q^{n+1},\phi_i)_\Omega, \\ (F_3)_i &=& -(S^n,\phi_i)_\Omega. +(S^n,\phi_i)_\Omega +\triangle t \sum_K \left(F(S^n) q^{n+1}, \phi_i\right)_K. @f} Note the following complication, however: Since the matrix $H_{ij}$ -- 2.39.5