{"action":"created","comment":{"url":"https://api.github.com/repos/tjhei/dealii/pulls/comments/52118673","id":52118673,"diff_hunk":"@@ -0,0 +1,1212 @@\n+/* ---------------------------------------------------------------------\n+ *\n+ * Copyright (C) 1999 - 2016 by the deal.II authors\n+ *\n+ * This file is part of the deal.II library.\n+ *\n+ * The deal.II library is free software; you can use it, redistribute\n+ * it, and/or modify it under the terms of the GNU Lesser General\n+ * Public License as published by the Free Software Foundation; either\n+ * version 2.1 of the License, or (at your option) any later version.\n+ * The full text of the license can be found in the file LICENSE at\n+ * the top level of the deal.II distribution.\n+ *\n+ * ---------------------------------------------------------------------\n+\n+ */\n+\n+// @sect3{Include files}\n+\n+#include <deal.II/base/quadrature_lib.h>\n+#include <deal.II/base/logstream.h>\n+#include <deal.II/base/function.h>\n+#include <deal.II/base/utilities.h>\n+\n+#include <deal.II/lac/block_vector.h>\n+#include <deal.II/lac/full_matrix.h>\n+#include <deal.II/lac/block_sparse_matrix.h>\n+#include <deal.II/lac/block_sparsity_pattern.h>\n+#include <deal.II/lac/solver_cg.h>\n+#include <deal.II/lac/precondition.h>\n+#include <deal.II/lac/constraint_matrix.h>\n+#include <deal.II/lac/dynamic_sparsity_pattern.h>\n+#include <deal.II/lac/solver_gmres.h>\n+\n+#include <deal.II/grid/tria.h>\n+#include <deal.II/grid/grid_generator.h>\n+#include <deal.II/grid/tria_accessor.h>\n+#include <deal.II/grid/tria_iterator.h>\n+#include <deal.II/grid/tria_boundary_lib.h>\n+#include <deal.II/grid/grid_tools.h>\n+#include <deal.II/grid/grid_refinement.h>\n+\n+#include <deal.II/dofs/dof_handler.h>\n+#include <deal.II/dofs/dof_renumbering.h>\n+#include <deal.II/dofs/dof_accessor.h>\n+#include <deal.II/dofs/dof_tools.h>\n+\n+#include <deal.II/fe/fe_q.h>\n+#include <deal.II/fe/fe_system.h>\n+#include <deal.II/fe/fe_values.h>\n+\n+#include <deal.II/numerics/vector_tools.h>\n+#include <deal.II/numerics/matrix_tools.h>\n+#include <deal.II/numerics/data_out.h>\n+#include <deal.II/numerics/error_estimator.h>\n+\n+#include <deal.II/lac/sparse_direct.h>\n+\n+#include <deal.II/lac/sparse_ilu.h>\n+#include <deal.II/grid/grid_out.h>\n+\n+#include <fstream>\n+#include <sstream>\n+\n+// We need to include this class for all of the timings between ILU and Multigrid\n+#include <deal.II/base/timer.h>\n+\n+// This includes the files necessary for us to use Multigrid\n+#include <deal.II/multigrid/multigrid.h>\n+#include <deal.II/multigrid/mg_transfer.h>\n+#include <deal.II/multigrid/mg_tools.h>\n+#include <deal.II/multigrid/mg_coarse.h>\n+#include <deal.II/multigrid/mg_smoother.h>\n+#include <deal.II/multigrid/mg_matrix.h>\n+\n+int count_mm = 0;\n+bool use_multigrid = false;\n+\n+namespace Step22\n+{\n+  using namespace dealii;\n+\n+  // @sect3{ASPECT BlockSchurPreconditioner}\n+\n+  // Implement the block Schur preconditioner for the Stokes system.\n+  template <class PreconditionerA, class PreconditionerMp>\n+  class BlockSchurPreconditioner : public Subscriptor\n+  {\n+  public:\n+    // Constructor of the BlockSchurPreconditioner.\n+    //\n+    // S is The entire Stokes matrix.\n+    //\n+    // Spre is the matrix whose blocks are used in the definition of\n+    // the preconditioning of the Stokes matrix, i.e. containing approximations\n+    // of the A and S blocks.\n+    //\n+    // Mppreconditioner is the Preconditioner object for the Schur complement,\n+    //     typically chosen as the mass matrix.\n+    //\n+    // Apreconditioner is the Preconditioner object for the matrix A.\n+    //\n+    // do_solve_A is a flag indicating whether we should actually solve with\n+    //     the matrix $A$, or only apply one preconditioner step with it.\n+    BlockSchurPreconditioner (const BlockSparseMatrix<double>                 &S,\n+                              const SparseMatrix<double>                 &P,\n+                              const PreconditionerMp                     &Mppreconditioner,\n+                              const PreconditionerA                      &Apreconditioner,\n+                              const bool                                do_solve_A);\n+\n+\n+    // Matrix vector product with this preconditioner object.\n+    void vmult (BlockVector<double>       &dst,\n+                const BlockVector<double> &src) const;\n+\n+    unsigned int n_iterations_A() const;\n+    unsigned int n_iterations_S() const;\n+\n+  private:\n+\n+    // References to the various matrix object this preconditioner works on.\n+    const BlockSparseMatrix<double> &stokes_matrix;\n+    const SparseMatrix<double> &pressure_mass_matrix;\n+    const PreconditionerMp                    &mp_preconditioner;\n+    const PreconditionerA                     &a_preconditioner;\n+\n+\n+    // Whether to actually invert the $\\tilde A$ part of the preconditioner matrix\n+    // or to just apply a single preconditioner step with it.\n+    const bool do_solve_A;\n+    mutable unsigned int n_iterations_A_;\n+    mutable unsigned int n_iterations_S_;\n+  };\n+\n+  template <class PreconditionerA, class PreconditionerMp>\n+  BlockSchurPreconditioner<PreconditionerA, PreconditionerMp>::\n+  BlockSchurPreconditioner (const BlockSparseMatrix<double>  &S,\n+                            const SparseMatrix<double>                &P,\n+                            const PreconditionerMp                     &Mppreconditioner,\n+                            const PreconditionerA                      &Apreconditioner,\n+                            const bool                                  do_solve_A)\n+    :\n+    stokes_matrix     (S),\n+    pressure_mass_matrix (P),\n+    mp_preconditioner (Mppreconditioner),\n+    a_preconditioner  (Apreconditioner),\n+    do_solve_A        (do_solve_A),\n+    n_iterations_A_(0),\n+    n_iterations_S_(0)\n+  {}\n+\n+  template <class PreconditionerA, class PreconditionerMp>\n+  unsigned int\n+  BlockSchurPreconditioner<PreconditionerA, PreconditionerMp>::\n+  n_iterations_A() const\n+  {\n+    return n_iterations_A_;\n+  }\n+  template <class PreconditionerA, class PreconditionerMp>\n+  unsigned int\n+  BlockSchurPreconditioner<PreconditionerA, PreconditionerMp>::\n+  n_iterations_S() const\n+  {\n+    return n_iterations_S_;\n+  }\n+\n+\n+  template <class PreconditionerA, class PreconditionerMp>\n+  void\n+  BlockSchurPreconditioner<PreconditionerA, PreconditionerMp>::\n+  vmult (BlockVector<double>       &dst,\n+         const BlockVector<double> &src) const\n+  {\n+    Vector<double> utmp(src.block(0));\n+\n+    // First solve with the bottom left block, which we have built\n+    // as a mass matrix with the inverse of the viscosity\n+    {\n+      SolverControl solver_control(1000, 1e-6 * src.block(1).l2_norm());\n+      SolverCG<>    cg (solver_control);\n+\n+\n+      // This takes care of the mass matrix\n+      dst.block(1) = 0.0;\n+      cg.solve(pressure_mass_matrix,\n+               dst.block(1), src.block(1),\n+               mp_preconditioner);\n+      n_iterations_S_ += solver_control.last_step();\n+\n+\n+      dst.block(1) *= -1.0;\n+    }\n+\n+    // Apply the top right block\n+    {\n+      stokes_matrix.block(0,1).vmult(utmp, dst.block(1)); //B^T\n+      utmp*=-1.0;\n+      utmp.add(src.block(0));\n+    }\n+\n+    // Now either solve with the top left block (if do_solve_A==true)\n+    // or just apply one preconditioner sweep (for the first few\n+    // iterations of our two-stage outer GMRES iteration)\n+    if (do_solve_A == true)\n+      {\n+        SolverControl solver_control(10000, utmp.l2_norm()*1e-2);\n+        SolverCG<>    cg (solver_control);\n+\n+        dst.block(0) = 0.0;\n+        cg.solve(stokes_matrix.block(0,0), dst.block(0), utmp,\n+                 a_preconditioner);\n+        n_iterations_A_ += solver_control.last_step();\n+      }\n+    else\n+      {\n+        a_preconditioner.vmult (dst.block(0), utmp);\n+        n_iterations_A_ += 1;\n+      }\n+  }\n+\n+  // This structure is similar to Step-22 except the 2D and 3D case both use ILU\n+  template <int dim>\n+  struct InnerPreconditioner;\n+\n+  template <>\n+  struct InnerPreconditioner<2>\n+  {\n+    typedef SparseILU<double> type;\n+  };\n+\n+  template <>\n+  struct InnerPreconditioner<3>\n+  {\n+    typedef SparseILU<double> type;\n+  };\n+\n+  template <int dim>\n+  class StokesProblem\n+  {\n+  public:\n+    StokesProblem (const unsigned int degree);\n+    void run ();\n+\n+  private:\n+    void setup_dofs ();\n+    void assemble_system ();\n+    void assemble_multigrid ();\n+    void solve ();\n+    void output_results (const unsigned int refinement_cycle) const;\n+    void refine_mesh ();\n+\n+    const unsigned int   degree;\n+\n+    Triangulation<dim>   triangulation;\n+    FESystem<dim>        fe;\n+    FESystem<dim>        velocity_fe;\n+    DoFHandler<dim>      dof_handler;\n+    DoFHandler<dim>      velocity_dof_handler;\n+\n+    ConstraintMatrix     constraints;\n+    ConstraintMatrix     velocity_constraints;\n+\n+    ConstraintMatrix     hanging_node_constraints;\n+    ConstraintMatrix     velocity_hanging_node_constraints;\n+\n+    BlockSparsityPattern      sparsity_pattern;\n+    BlockSparsityPattern      sparsity_pattern_velocity;\n+    BlockSparseMatrix<double> system_matrix;\n+\n+    BlockVector<double> solution;\n+    BlockVector<double> system_rhs;\n+\n+    std::vector<double> dof_indices;\n+    std::vector<double> vel_dof_indices;\n+\n+    MGLevelObject<SparsityPattern>        mg_sparsity_patterns;\n+    MGLevelObject<SparseMatrix<double> > mg_matrices;\n+    MGLevelObject<SparseMatrix<double> > mg_interface_matrices;\n+    MGConstrainedDoFs                     mg_constrained_dofs;\n+\n+    TimerOutput computing_timer;\n+  };\n+\n+  template <int dim>\n+  class BoundaryValues : public Function<dim>\n+  {\n+  public:\n+    BoundaryValues () : Function<dim>(dim+1) {}\n+\n+    virtual double value (const Point<dim>   &p,\n+                          const unsigned int  component = 0) const;\n+\n+    virtual void vector_value (const Point<dim> &p,\n+                               Vector<double>   &value) const;\n+  };\n+\n+  template <int dim>\n+  double\n+  BoundaryValues<dim>::value (const Point<dim>  &p,\n+                              const unsigned int component) const\n+  {\n+    Assert (component < this->n_components,\n+            ExcIndexRange (component, 0, this->n_components));\n+\n+    if (component == 0)\n+      return (p[0] < 0 ? -1 : (p[0] > 0 ? 1 : 0));\n+    return 0;\n+  }\n+\n+  template <int dim>\n+  void\n+  BoundaryValues<dim>::vector_value (const Point<dim> &p,\n+                                     Vector<double>   &values) const\n+  {\n+    for (unsigned int c=0; c<this->n_components; ++c)\n+      values(c) = BoundaryValues<dim>::value (p, c);\n+  }\n+\n+  template <int dim>\n+  class BoundaryValuesForVelocity : public Function<dim>\n+  {\n+  public:\n+    BoundaryValuesForVelocity () : Function<dim>(dim) {}\n+\n+    virtual double value (const Point<dim>   &p,\n+                          const unsigned int  component = 0) const;\n+\n+    virtual void vector_value (const Point<dim> &p,\n+                               Vector<double>   &value) const;\n+  };\n+\n+\n+  template <int dim>\n+  double\n+  BoundaryValuesForVelocity<dim>::value (const Point<dim>  &p,\n+                                         const unsigned int component) const\n+  {\n+    Assert (component < this->n_components,\n+            ExcIndexRange (component, 0, this->n_components));\n+\n+    if (component == 0)\n+      return (p[0] < 0 ? -1 : (p[0] > 0 ? 1 : 0));\n+    return 0;\n+  }\n+\n+\n+  template <int dim>\n+  void\n+  BoundaryValuesForVelocity<dim>::vector_value (const Point<dim> &p,\n+                                                Vector<double>   &values) const\n+  {\n+    for (unsigned int c=0; c<this->n_components; ++c)\n+      values(c) = BoundaryValuesForVelocity<dim>::value (p, c);\n+  }\n+\n+\n+\n+  template <int dim>\n+  class RightHandSide : public Function<dim>\n+  {\n+  public:\n+    RightHandSide () : Function<dim>(dim+1) {}\n+\n+    virtual double value (const Point<dim>   &p,\n+                          const unsigned int  component = 0) const;\n+\n+    virtual void vector_value (const Point<dim> &p,\n+                               Vector<double>   &value) const;\n+\n+  };\n+\n+\n+  template <int dim>\n+  double\n+  RightHandSide<dim>::value (const Point<dim>  &/*p*/,\n+                             const unsigned int /*component*/) const\n+  {\n+    return 0;\n+  }\n+\n+\n+  template <int dim>\n+  void\n+  RightHandSide<dim>::vector_value (const Point<dim> &p,\n+                                    Vector<double>   &values) const\n+  {\n+    for (unsigned int c=0; c<this->n_components; ++c)\n+      values(c) = RightHandSide<dim>::value (p, c);\n+  }\n+\n+\n+\n+\n+\n+  template <class Matrix, class Preconditioner>\n+  class InverseMatrix : public Subscriptor\n+  {\n+  public:\n+    InverseMatrix (const Matrix         &m,\n+                   const Preconditioner &preconditioner);\n+\n+    void vmult (Vector<double>       &dst,\n+                const Vector<double> &src) const;\n+\n+  private:\n+    const SmartPointer<const Matrix> matrix;\n+    const SmartPointer<const Preconditioner> preconditioner;\n+  };\n+\n+\n+  template <class Matrix, class Preconditioner>\n+  InverseMatrix<Matrix,Preconditioner>::InverseMatrix (const Matrix &m,\n+                                                       const Preconditioner &preconditioner)\n+    :\n+    matrix (&m),\n+    preconditioner (&preconditioner)\n+  {}\n+\n+\n+  // In Schur complement it is important that A^(-1) is accurate which is why we do it this way\n+  template <class Matrix, class Preconditioner>\n+  void InverseMatrix<Matrix,Preconditioner>::vmult (Vector<double>       &dst,\n+                                                    const Vector<double> &src) const\n+  {\n+    SolverControl solver_control (src.size(), 1e-6*src.l2_norm());\n+    SolverCG<>    cg (solver_control);\n+\n+    dst = 0;\n+\n+    cg.solve (*matrix, dst, src, *preconditioner);\n+    count_mm = count_mm + solver_control.last_step();\n+  }\n+\n+\n+\n+  template <class Preconditioner>\n+  class SchurComplement : public Subscriptor\n+  {\n+  public:\n+    SchurComplement (const BlockSparseMatrix<double> &system_matrix,\n+                     const InverseMatrix<SparseMatrix<double>, Preconditioner> &A_inverse);\n+\n+    void vmult (Vector<double>       &dst,\n+                const Vector<double> &src) const;\n+\n+  private:\n+    const SmartPointer<const BlockSparseMatrix<double> > system_matrix;\n+    const SmartPointer<const InverseMatrix<SparseMatrix<double>, Preconditioner> > A_inverse;\n+\n+    mutable Vector<double> tmp1, tmp2;\n+  };\n+\n+\n+\n+  template <class Preconditioner>\n+  SchurComplement<Preconditioner>::\n+  SchurComplement (const BlockSparseMatrix<double> &system_matrix,\n+                   const InverseMatrix<SparseMatrix<double>,Preconditioner> &A_inverse)\n+    :\n+    system_matrix (&system_matrix),\n+    A_inverse (&A_inverse),\n+    tmp1 (system_matrix.block(0,0).m()),\n+    tmp2 (system_matrix.block(0,0).m())\n+  {}\n+\n+\n+  template <class Preconditioner>\n+  void SchurComplement<Preconditioner>::vmult (Vector<double>       &dst,\n+                                               const Vector<double> &src) const\n+  {\n+    // This is the transfer (understand)\n+    system_matrix->block(0,1).vmult (tmp1, src);    // multiply with the top right block: B\n+    A_inverse->vmult (tmp2, tmp1);                  // multiply with A^-1\n+    system_matrix->block(1,0).vmult (dst, tmp2);    // multiply with the bottom left block: B^T\n+  }\n+\n+  template <int dim>\n+  StokesProblem<dim>::StokesProblem (const unsigned int degree)\n+    :\n+    degree (degree),\n+    triangulation (Triangulation<dim>::maximum_smoothing),\n+    fe (FE_Q<dim>(degree+1), dim, // Finite element for whole system\n+        FE_Q<dim>(degree), 1),\n+    velocity_fe (FE_Q<dim>(degree+1), dim), // Finite element for velocity-only\n+    dof_handler (triangulation),\n+    velocity_dof_handler (triangulation),\n+    computing_timer (std::cout, TimerOutput::summary,\n+                     TimerOutput::wall_times)\n+  {}\n+\n+// @sect4{StokesProblem::setup_dofs}\n+\n+// This function sets up things differently based on if you want to use ILU or GMG as a preconditioner.\n+  template <int dim>\n+  void StokesProblem<dim>::setup_dofs ()\n+  {\n+    if (use_multigrid==false)\n+      {\n+        system_matrix.clear ();\n+\n+        dof_handler.distribute_dofs (fe);\n+        DoFRenumbering::Cuthill_McKee (dof_handler);\n+\n+        std::vector<unsigned int> block_component (dim+1,0);\n+        block_component[dim] = 1;\n+        DoFRenumbering::component_wise (dof_handler, block_component);\n+\n+        {\n+          constraints.clear ();\n+\n+          FEValuesExtractors::Vector velocities(0);\n+          DoFTools::make_hanging_node_constraints (dof_handler,\n+                                                   constraints);\n+          VectorTools::interpolate_boundary_values (dof_handler,\n+                                                    1,\n+                                                    BoundaryValues<dim>(),\n+                                                    constraints,\n+                                                    fe.component_mask(velocities));\n+        }\n+\n+        constraints.close ();\n+\n+        std::vector<types::global_dof_index> dofs_per_block (2);\n+        DoFTools::count_dofs_per_block (dof_handler, dofs_per_block, block_component);\n+        const unsigned int n_u = dofs_per_block[0],\n+                           n_p = dofs_per_block[1];\n+\n+        std::cout << \"   Number of active cells: \"\n+                  << triangulation.n_active_cells()\n+                  << std::endl\n+                  << \"   Number of degrees of freedom: \"\n+                  << dof_handler.n_dofs()\n+                  << \" (\" << n_u << '+' << n_p << ')'\n+                  << std::endl;\n+\n+        {\n+          BlockDynamicSparsityPattern dsp (2,2);\n+\n+          dsp.block(0,0).reinit (n_u, n_u);\n+          dsp.block(1,0).reinit (n_p, n_u);\n+          dsp.block(0,1).reinit (n_u, n_p);\n+          dsp.block(1,1).reinit (n_p, n_p);\n+\n+          dsp.collect_sizes();\n+\n+          DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints, false);\n+          sparsity_pattern.copy_from (dsp);\n+        }\n+\n+        system_matrix.reinit (sparsity_pattern);\n+\n+        solution.reinit (2);\n+        solution.block(0).reinit (n_u);\n+        solution.block(1).reinit (n_p);\n+        solution.collect_sizes ();\n+\n+        system_rhs.reinit (2);\n+        system_rhs.block(0).reinit (n_u);\n+        system_rhs.block(1).reinit (n_p);\n+        system_rhs.collect_sizes ();\n+      }\n+    else\n+      {\n+        system_matrix.clear ();\n+\n+        // We don't need the multigrid dofs for whole problem finite element\n+        dof_handler.distribute_dofs(fe);\n+\n+        // Distribute only the dofs for velocity finite element\n+        velocity_dof_handler.distribute_dofs(velocity_fe);\n+\n+        // Multigrid only needs the dofs for velocity\n+        velocity_dof_handler.distribute_mg_dofs(velocity_fe);\n+\n+        // This first creates and array (0,0,1) which means that it first does everything with index 0 and then 1\n+        std::vector<unsigned int> block_component (dim+1,0);\n+\n+        block_component[dim] = 1;\n+\n+        DoFRenumbering::component_wise (dof_handler, block_component);\n+\n+        constraints.clear ();\n+        velocity_constraints.clear ();\n+        hanging_node_constraints.clear ();\n+        velocity_hanging_node_constraints.clear ();\n+\n+        // This always knows how to use the dim (start at 0 one)\n+        FEValuesExtractors::Vector velocities(0);\n+\n+        // This is further explained in vector valued dealii step-20\n+        DoFTools::make_hanging_node_constraints (dof_handler, constraints);\n+        DoFTools::make_hanging_node_constraints (dof_handler, hanging_node_constraints);\n+\n+        // For adaptivity, these must be taken care of (correctly)\n+        DoFTools::make_hanging_node_constraints (velocity_dof_handler, velocity_constraints);\n+        DoFTools::make_hanging_node_constraints (velocity_dof_handler, velocity_hanging_node_constraints);\n+\n+        VectorTools::interpolate_boundary_values (dof_handler,\n+                                                  1,\n+                                                  BoundaryValues<dim>(),\n+                                                  constraints,\n+                                                  fe.component_mask(velocities));\n+        VectorTools::interpolate_boundary_values (velocity_dof_handler,\n+                                                  1,\n+                                                  BoundaryValuesForVelocity<dim>(),\n+                                                  velocity_constraints);\n+\n+        constraints.close ();\n+        velocity_constraints.close ();\n+        hanging_node_constraints.close ();\n+        velocity_hanging_node_constraints.close ();\n+\n+        typename FunctionMap<dim>::type      boundary_condition_function_map;\n+        BoundaryValuesForVelocity<dim>                velocity_boundary_condition;\n+        boundary_condition_function_map[1] = &velocity_boundary_condition;\n+\n+        mg_constrained_dofs.clear();\n+        mg_constrained_dofs.initialize(velocity_dof_handler, boundary_condition_function_map);\n+        const unsigned int n_levels = triangulation.n_levels();\n+\n+        mg_interface_matrices.resize(0, n_levels-1);\n+        mg_interface_matrices.clear ();\n+        mg_matrices.resize(0, n_levels-1);\n+        mg_matrices.clear ();\n+        mg_sparsity_patterns.resize(0, n_levels-1);\n+\n+        for (unsigned int level=0; level<n_levels; ++level)\n+          {\n+            DynamicSparsityPattern csp;\n+            csp.reinit(velocity_dof_handler.n_dofs(level), // Generates sparsity pattern, matrices, interface matrices for each matrix on each level\n+                       velocity_dof_handler.n_dofs(level));\n+            MGTools::make_sparsity_pattern(velocity_dof_handler, csp, level);\n+\n+            mg_sparsity_patterns[level].copy_from (csp);\n+\n+            mg_matrices[level].reinit(mg_sparsity_patterns[level]);\n+            //std::cout << \"mg_matrices[\" << level << \"] has size \" <<  mg_matrices[level].m() << \" by \" << mg_matrices[level].n() << std::endl;\n+            mg_interface_matrices[level].reinit(mg_sparsity_patterns[level]);\n+          }\n+\n+        std::vector<types::global_dof_index> dofs_per_block (2); //if you did 012 then you'd have three answers\n+        DoFTools::count_dofs_per_block (dof_handler, dofs_per_block, block_component);\n+        const unsigned int n_u = dofs_per_block[0],\n+                           n_p = dofs_per_block[1];\n+\n+        std::cout << \"   Number of active cells: \"\n+                  << triangulation.n_active_cells()\n+                  << std::endl\n+                  << \"   Number of degrees of freedom: \"\n+                  << dof_handler.n_dofs()\n+                  << \" (\" << n_u << '+' << n_p << ')'\n+                  << std::endl\n+                  << \"   Number of velocity degrees of freedom: \"\n+                  << velocity_dof_handler.n_dofs()\n+                  << std::endl;\n+\n+        Assert (n_u == velocity_dof_handler.n_dofs(), ExcMessage (\"Numbers of degrees of freedom must match for the velocity part of the main dof handler and the whole velocity dof handler.\"));\n+\n+        {\n+          BlockDynamicSparsityPattern csp (2,2);\n+\n+          csp.block(0,0).reinit (n_u, n_u);\n+          csp.block(1,0).reinit (n_p, n_u);\n+          csp.block(0,1).reinit (n_u, n_p);\n+          csp.block(1,1).reinit (n_p, n_p);\n+\n+          csp.collect_sizes();\n+\n+          DoFTools::make_sparsity_pattern (dof_handler, csp, constraints, false);\n+          sparsity_pattern.copy_from (csp);\n+\n+        }\n+        system_matrix.reinit (sparsity_pattern);\n+\n+        solution.reinit (2);\n+        solution.block(0).reinit (n_u);\n+        solution.block(1).reinit (n_p);\n+        solution.collect_sizes ();\n+\n+        system_rhs.reinit (2);\n+        system_rhs.block(0).reinit (n_u);\n+        system_rhs.block(1).reinit (n_p);\n+        system_rhs.collect_sizes ();\n+      }\n+  }\n+\n+\n+// @sect4{StokesProblem::assemble_system}\n+\n+// In this function, the system matrix is assembled the same regardless of using ILU and GMG\n+  template <int dim>\n+  void StokesProblem<dim>::assemble_system ()\n+  {\n+    system_matrix=0;\n+    system_rhs=0;\n+\n+    QGauss<dim>   quadrature_formula(degree+2);\n+\n+    FEValues<dim> fe_values (fe, quadrature_formula,\n+                             update_values    |\n+                             update_quadrature_points  |\n+                             update_JxW_values |\n+                             update_gradients);\n+\n+    const unsigned int   dofs_per_cell   = fe.dofs_per_cell;\n+\n+    const unsigned int   n_q_points      = quadrature_formula.size();\n+\n+    FullMatrix<double>   local_matrix (dofs_per_cell, dofs_per_cell);\n+    Vector<double>       local_rhs (dofs_per_cell);\n+\n+    std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);\n+\n+    const RightHandSide<dim>          right_hand_side;\n+    std::vector<Vector<double> >      rhs_values (n_q_points,\n+                                                  Vector<double>(dim+1));\n+\n+    const FEValuesExtractors::Vector velocities (0);\n+    const FEValuesExtractors::Scalar pressure (dim);\n+\n+    std::vector<SymmetricTensor<2,dim> > symgrad_phi_u (dofs_per_cell);\n+    std::vector<double>                  div_phi_u   (dofs_per_cell);\n+    std::vector<double>                  phi_p       (dofs_per_cell);\n+\n+    typename DoFHandler<dim>::active_cell_iterator\n+    cell = dof_handler.begin_active(),\n+    endc = dof_handler.end();\n+    for (; cell!=endc; ++cell)\n+      {\n+        fe_values.reinit (cell);\n+        local_matrix = 0;\n+        local_rhs = 0;\n+\n+        right_hand_side.vector_value_list(fe_values.get_quadrature_points(),\n+                                          rhs_values);\n+\n+        for (unsigned int q=0; q<n_q_points; ++q)\n+          {\n+            for (unsigned int k=0; k<dofs_per_cell; ++k)\n+              {\n+                symgrad_phi_u[k] = fe_values[velocities].symmetric_gradient (k, q);\n+                div_phi_u[k]     = fe_values[velocities].divergence (k, q);\n+                phi_p[k]         = fe_values[pressure].value (k, q);\n+              }\n+\n+            for (unsigned int i=0; i<dofs_per_cell; ++i)\n+              {\n+                for (unsigned int j=0; j<=i; ++j)\n+                  {\n+                    local_matrix(i,j) += (2 * (symgrad_phi_u[i] * symgrad_phi_u[j])\n+                                          - div_phi_u[i] * phi_p[j]\n+                                          - phi_p[i] * div_phi_u[j]\n+                                          + phi_p[i] * phi_p[j])\n+                                         * fe_values.JxW(q);\n+\n+                  }\n+\n+                const unsigned int component_i =\n+                  fe.system_to_component_index(i).first;\n+                local_rhs(i) += fe_values.shape_value(i,q) *\n+                                rhs_values[q](component_i) *\n+                                fe_values.JxW(q);\n+              }\n+          }\n+\n+        for (unsigned int i=0; i<dofs_per_cell; ++i)\n+          for (unsigned int j=i+1; j<dofs_per_cell; ++j)\n+            local_matrix(i,j) = local_matrix(j,i);\n+\n+        cell->get_dof_indices (local_dof_indices);\n+        constraints.distribute_local_to_global (local_matrix, local_rhs,\n+                                                local_dof_indices,\n+                                                system_matrix, system_rhs);\n+      }\n+  }\n+\n+  // @sect4{StokesProblem::assemble_multigrid\n+\n+  // Here, like step-40, we have a function that assembles everything necessary for the multigrid preconditioner\n+\n+  template <int dim>\n+  void StokesProblem<dim>::assemble_multigrid ()\n+  {\n+    mg_matrices = 0;\n+\n+    QGauss<dim>   quadrature_formula(degree+2);\n+\n+    FEValues<dim> fe_values (velocity_fe, quadrature_formula,\n+                             update_values    |\n+                             update_quadrature_points  |\n+                             update_JxW_values |\n+                             update_gradients);\n+\n+    const unsigned int   dofs_per_cell   = velocity_fe.dofs_per_cell;\n+\n+    const unsigned int   n_q_points      = quadrature_formula.size();\n+\n+    FullMatrix<double>   cell_matrix (dofs_per_cell, dofs_per_cell);\n+\n+    std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);\n+\n+    const RightHandSide<dim>          right_hand_side;\n+    std::vector<Vector<double> >      rhs_values (n_q_points,\n+                                                  Vector<double>(dim+1));\n+\n+    const FEValuesExtractors::Vector velocities (0);\n+    const FEValuesExtractors::Scalar pressure (dim);\n+\n+    std::vector<SymmetricTensor<2,dim> > symgrad_phi_u (dofs_per_cell);\n+    std::vector<double>                  div_phi_u   (dofs_per_cell);\n+    std::vector<double>                  phi_p       (dofs_per_cell);\n+\n+    std::vector<std::vector<bool> > interface_dofs\n+      = mg_constrained_dofs.get_refinement_edge_indices ();\n+    std::vector<std::vector<bool> > boundary_interface_dofs\n+      = mg_constrained_dofs.get_refinement_edge_boundary_indices ();\n+\n+    std::vector<ConstraintMatrix> boundary_constraints (triangulation.n_levels());\n+    std::vector<ConstraintMatrix> boundary_interface_constraints (triangulation.n_levels());\n+    for (unsigned int level=0; level<triangulation.n_levels(); ++level)\n+      {\n+        boundary_constraints[level].add_lines (interface_dofs[level]);\n+        boundary_constraints[level].add_lines (mg_constrained_dofs.get_boundary_indices()[level]);\n+        boundary_constraints[level].close ();\n+\n+        boundary_interface_constraints[level]\n+        .add_lines (boundary_interface_dofs[level]);\n+        boundary_interface_constraints[level].close ();\n+      }\n+\n+    // This iterator goes over all cells (not just active)\n+    typename DoFHandler<dim>::cell_iterator cell = velocity_dof_handler.begin(),\n+                                            endc = velocity_dof_handler.end();\n+\n+    for (; cell!=endc; ++cell)\n+      {\n+        fe_values.reinit (cell);\n+        cell_matrix = 0;\n+\n+        right_hand_side.vector_value_list(fe_values.get_quadrature_points(),\n+                                          rhs_values);\n+\n+        for (unsigned int q=0; q<n_q_points; ++q)\n+          {\n+            for (unsigned int k=0; k<dofs_per_cell; ++k)\n+              {\n+                symgrad_phi_u[k] = fe_values[velocities].symmetric_gradient (k, q);\n+              }\n+\n+            for (unsigned int i=0; i<dofs_per_cell; ++i)\n+              {\n+                for (unsigned int j=0; j<=i; ++j)\n+                  {\n+                    cell_matrix(i,j) += (symgrad_phi_u[i]\n+                                         * symgrad_phi_u[j])\n+                                        * fe_values.JxW(q);\n+                  }\n+              }\n+          }\n+\n+\n+        for (unsigned int i=0; i<dofs_per_cell; ++i)\n+          for (unsigned int j=i+1; j<dofs_per_cell; ++j)\n+            cell_matrix(i,j) = cell_matrix(j,i);\n+\n+        cell->get_mg_dof_indices (local_dof_indices);\n+\n+        boundary_constraints[cell->level()]\n+        .distribute_local_to_global (cell_matrix,\n+                                     local_dof_indices,\n+                                     mg_matrices[cell->level()]);\n+\n+        for (unsigned int i=0; i<dofs_per_cell; ++i)\n+          for (unsigned int j=0; j<dofs_per_cell; ++j)\n+            if ( !(interface_dofs[cell->level()][local_dof_indices[i]]==true &&\n+                   interface_dofs[cell->level()][local_dof_indices[j]]==false))\n+              cell_matrix(i,j) = 0;\n+\n+        boundary_interface_constraints[cell->level()]\n+        .distribute_local_to_global (cell_matrix,\n+                                     local_dof_indices,\n+                                     mg_interface_matrices[cell->level()]);\n+      }\n+  }\n+\n+// @sect4{StokesProblem::solve}\n+\n+// This function sets up things differently based on if you want to use ILU or GMG as a preconditioner.  Both methods share\n+// the same solver (GMRES) but require a different preconditioner to be assembled.  Here we time not only the entire solve\n+// function, but we separately time the set-up of the preconditioner as well as the GMRES solve.\n+  template <int dim>\n+  void StokesProblem<dim>::solve ()\n+  {\n+    SolverControl solver_control (system_matrix.m(),\n+                                  1e-6*system_rhs.l2_norm());\n+\n+    GrowingVectorMemory<BlockVector<double> > vector_memory;\n+    SolverGMRES<BlockVector<double> >::AdditionalData gmres_data;\n+    gmres_data.max_n_tmp_vectors = 100;\n+\n+    SolverGMRES<BlockVector<double> > gmres(solver_control, vector_memory,\n+                                            gmres_data);\n+\n+\n+    if (use_multigrid==false)\n+      {\n+\n+        computing_timer.enter_subsection (\"Solve - Set-up Preconditioner\");\n+\n+        std::cout << \"   Computing preconditioner...\" << std::endl << std::flush;\n+\n+        SparseILU<double>       A_preconditioner;\n+        A_preconditioner.initialize (system_matrix.block(0,0),SparseILU<double>::AdditionalData());\n+\n+\n+        SparseMatrix<double> pressure_mass_matrix;\n+        pressure_mass_matrix.reinit(sparsity_pattern.block(1,1));\n+        pressure_mass_matrix.copy_from(system_matrix.block(1,1));\n+        system_matrix.block(1,1) = 0;\n+\n+\n+        SparseILU<double> pmass_preconditioner;\n+        pmass_preconditioner.initialize (pressure_mass_matrix,\n+                                         SparseILU<double>::AdditionalData());\n+\n+        bool use_expensive = false;\n+        unsigned int its_A = 0, its_S = 0;\n+        // If this cheaper solver is not desired, then simply short-cut\n+        // the attempt at solving with the cheaper preconditioner that consists\n+        // of only a single V-cycle\n+        const BlockSchurPreconditioner<typename InnerPreconditioner<dim>::type,\n+              SparseILU<double>>\n+              preconditioner (system_matrix,\n+                              pressure_mass_matrix,\n+                              pmass_preconditioner, A_preconditioner,\n+                              use_expensive);\n+        computing_timer.leave_subsection();\n+        computing_timer.enter_subsection (\"Solve - GMRES\");\n+        gmres.solve (system_matrix,\n+                     solution,\n+                     system_rhs,\n+                     preconditioner);\n+        computing_timer.leave_subsection();\n+\n+        its_A += preconditioner.n_iterations_A();\n+        its_S += preconditioner.n_iterations_S();\n+\n+        constraints.distribute (solution);\n+\n+        std::cout << \" \"\n+                  << solver_control.last_step()\n+                  << \" block GMRES iterations\";\n+      }\n+    else\n+      {\n+        computing_timer.enter_subsection (\"Solve - Set-up Preconditioner\");\n+        // Transfer operators between levels\n+        MGTransferPrebuilt<Vector<double> > mg_transfer(hanging_node_constraints, mg_constrained_dofs);\n+        mg_transfer.build_matrices(velocity_dof_handler);\n+\n+        // Coarse grid solver\n+        FullMatrix<double> coarse_matrix;\n+        coarse_matrix.copy_from (mg_matrices[0]);\n+        MGCoarseGridHouseholder<> coarse_grid_solver;\n+        coarse_grid_solver.initialize (coarse_matrix);\n+\n+        typedef PreconditionSOR<SparseMatrix<double> > Smoother;\n+        mg::SmootherRelaxation<Smoother, Vector<double> > mg_smoother;\n+        mg_smoother.initialize(mg_matrices);\n+        mg_smoother.set_steps(2);\n+\n+        // Multigrid, when used as a preconditioner for CG, expects the smoother to be symmetric, and this takes care of that\n+        mg_smoother.set_symmetric(true);\n+\n+        mg::Matrix<Vector<double> > mg_matrix(mg_matrices);\n+        mg::Matrix<Vector<double> > mg_interface_up(mg_interface_matrices);\n+        mg::Matrix<Vector<double> > mg_interface_down(mg_interface_matrices);\n+\n+        // Now, we are ready to set up the V-cycle operator and the multilevel preconditioner.\n+        Multigrid<Vector<double> > mg(velocity_dof_handler,\n+                                      mg_matrix,\n+                                      coarse_grid_solver,\n+                                      mg_transfer,\n+                                      mg_smoother,\n+                                      mg_smoother);\n+        mg.set_edge_matrices(mg_interface_down, mg_interface_up);\n+\n+        // The velocity_dof_handler takes care of fact that we want block(0,0) here, as that is A.\n+        PreconditionMG<dim, Vector<double>, MGTransferPrebuilt<Vector<double> > >\n+        A_Multigrid(velocity_dof_handler, mg, mg_transfer);\n+\n+        SparseMatrix<double> pressure_mass_matrix;\n+        pressure_mass_matrix.reinit(sparsity_pattern.block(1,1));\n+        pressure_mass_matrix.copy_from(system_matrix.block(1,1));\n+        system_matrix.block(1,1) = 0;\n+        SparseILU<double> pmass_preconditioner;\n+        pmass_preconditioner.initialize (pressure_mass_matrix,\n+                                         SparseILU<double>::AdditionalData());\n+\n+        bool use_expensive = false;\n+        unsigned int its_A = 0, its_S = 0;","path":"examples/step-55/step-55.cc","position":1001,"original_position":1001,"commit_id":"d650abfbbb6c38f6e8eb2975804fa85954cee523","original_commit_id":"d650abfbbb6c38f6e8eb2975804fa85954cee523","user":{"login":"tjhei","id":1531285,"avatar_url":"https://avatars.githubusercontent.com/u/1531285?v=3","gravatar_id":"","url":"https://api.github.com/users/tjhei","html_url":"https://github.com/tjhei","followers_url":"https://api.github.com/users/tjhei/followers","following_url":"https://api.github.com/users/tjhei/following{/other_user}","gists_url":"https://api.github.com/users/tjhei/gists{/gist_id}","starred_url":"https://api.github.com/users/tjhei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjhei/subscriptions","organizations_url":"https://api.github.com/users/tjhei/orgs","repos_url":"https://api.github.com/users/tjhei/repos","events_url":"https://api.github.com/users/tjhei/events{/privacy}","received_events_url":"https://api.github.com/users/tjhei/received_events","type":"User","site_admin":false},"body":"You never read from these variables!","created_at":"2016-02-07T14:58:33Z","updated_at":"2016-02-07T14:58:33Z","html_url":"https://github.com/tjhei/dealii/pull/1#discussion_r52118673","pull_request_url":"https://api.github.com/repos/tjhei/dealii/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/comments/52118673"},"html":{"href":"https://github.com/tjhei/dealii/pull/1#discussion_r52118673"},"pull_request":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/tjhei/dealii/pulls/1","id":58547830,"html_url":"https://github.com/tjhei/dealii/pull/1","diff_url":"https://github.com/tjhei/dealii/pull/1.diff","patch_url":"https://github.com/tjhei/dealii/pull/1.patch","issue_url":"https://api.github.com/repos/tjhei/dealii/issues/1","number":1,"state":"open","locked":false,"title":"Step 55 discussion","user":{"login":"tjhei","id":1531285,"avatar_url":"https://avatars.githubusercontent.com/u/1531285?v=3","gravatar_id":"","url":"https://api.github.com/users/tjhei","html_url":"https://github.com/tjhei","followers_url":"https://api.github.com/users/tjhei/followers","following_url":"https://api.github.com/users/tjhei/following{/other_user}","gists_url":"https://api.github.com/users/tjhei/gists{/gist_id}","starred_url":"https://api.github.com/users/tjhei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjhei/subscriptions","organizations_url":"https://api.github.com/users/tjhei/orgs","repos_url":"https://api.github.com/users/tjhei/repos","events_url":"https://api.github.com/users/tjhei/events{/privacy}","received_events_url":"https://api.github.com/users/tjhei/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-02-07T14:40:58Z","updated_at":"2016-02-07T14:58:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a49e93b35bce51a8fcbd0a2764e804bc3e7b79a9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/tjhei/dealii/pulls/1/commits","review_comments_url":"https://api.github.com/repos/tjhei/dealii/pulls/1/comments","review_comment_url":"https://api.github.com/repos/tjhei/dealii/pulls/comments{/number}","comments_url":"https://api.github.com/repos/tjhei/dealii/issues/1/comments","statuses_url":"https://api.github.com/repos/tjhei/dealii/statuses/d650abfbbb6c38f6e8eb2975804fa85954cee523","head":{"label":"rrgrove6:step-55","ref":"step-55","sha":"d650abfbbb6c38f6e8eb2975804fa85954cee523","user":{"login":"rrgrove6","id":7593038,"avatar_url":"https://avatars.githubusercontent.com/u/7593038?v=3","gravatar_id":"","url":"https://api.github.com/users/rrgrove6","html_url":"https://github.com/rrgrove6","followers_url":"https://api.github.com/users/rrgrove6/followers","following_url":"https://api.github.com/users/rrgrove6/following{/other_user}","gists_url":"https://api.github.com/users/rrgrove6/gists{/gist_id}","starred_url":"https://api.github.com/users/rrgrove6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrgrove6/subscriptions","organizations_url":"https://api.github.com/users/rrgrove6/orgs","repos_url":"https://api.github.com/users/rrgrove6/repos","events_url":"https://api.github.com/users/rrgrove6/events{/privacy}","received_events_url":"https://api.github.com/users/rrgrove6/received_events","type":"User","site_admin":false},"repo":{"id":40205539,"name":"dealii","full_name":"rrgrove6/dealii","owner":{"login":"rrgrove6","id":7593038,"avatar_url":"https://avatars.githubusercontent.com/u/7593038?v=3","gravatar_id":"","url":"https://api.github.com/users/rrgrove6","html_url":"https://github.com/rrgrove6","followers_url":"https://api.github.com/users/rrgrove6/followers","following_url":"https://api.github.com/users/rrgrove6/following{/other_user}","gists_url":"https://api.github.com/users/rrgrove6/gists{/gist_id}","starred_url":"https://api.github.com/users/rrgrove6/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rrgrove6/subscriptions","organizations_url":"https://api.github.com/users/rrgrove6/orgs","repos_url":"https://api.github.com/users/rrgrove6/repos","events_url":"https://api.github.com/users/rrgrove6/events{/privacy}","received_events_url":"https://api.github.com/users/rrgrove6/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rrgrove6/dealii","description":"The development repository for the deal.II finite element library.","fork":true,"url":"https://api.github.com/repos/rrgrove6/dealii","forks_url":"https://api.github.com/repos/rrgrove6/dealii/forks","keys_url":"https://api.github.com/repos/rrgrove6/dealii/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rrgrove6/dealii/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rrgrove6/dealii/teams","hooks_url":"https://api.github.com/repos/rrgrove6/dealii/hooks","issue_events_url":"https://api.github.com/repos/rrgrove6/dealii/issues/events{/number}","events_url":"https://api.github.com/repos/rrgrove6/dealii/events","assignees_url":"https://api.github.com/repos/rrgrove6/dealii/assignees{/user}","branches_url":"https://api.github.com/repos/rrgrove6/dealii/branches{/branch}","tags_url":"https://api.github.com/repos/rrgrove6/dealii/tags","blobs_url":"https://api.github.com/repos/rrgrove6/dealii/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rrgrove6/dealii/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rrgrove6/dealii/git/refs{/sha}","trees_url":"https://api.github.com/repos/rrgrove6/dealii/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rrgrove6/dealii/statuses/{sha}","languages_url":"https://api.github.com/repos/rrgrove6/dealii/languages","stargazers_url":"https://api.github.com/repos/rrgrove6/dealii/stargazers","contributors_url":"https://api.github.com/repos/rrgrove6/dealii/contributors","subscribers_url":"https://api.github.com/repos/rrgrove6/dealii/subscribers","subscription_url":"https://api.github.com/repos/rrgrove6/dealii/subscription","commits_url":"https://api.github.com/repos/rrgrove6/dealii/commits{/sha}","git_commits_url":"https://api.github.com/repos/rrgrove6/dealii/git/commits{/sha}","comments_url":"https://api.github.com/repos/rrgrove6/dealii/comments{/number}","issue_comment_url":"https://api.github.com/repos/rrgrove6/dealii/issues/comments{/number}","contents_url":"https://api.github.com/repos/rrgrove6/dealii/contents/{+path}","compare_url":"https://api.github.com/repos/rrgrove6/dealii/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rrgrove6/dealii/merges","archive_url":"https://api.github.com/repos/rrgrove6/dealii/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rrgrove6/dealii/downloads","issues_url":"https://api.github.com/repos/rrgrove6/dealii/issues{/number}","pulls_url":"https://api.github.com/repos/rrgrove6/dealii/pulls{/number}","milestones_url":"https://api.github.com/repos/rrgrove6/dealii/milestones{/number}","notifications_url":"https://api.github.com/repos/rrgrove6/dealii/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rrgrove6/dealii/labels{/name}","releases_url":"https://api.github.com/repos/rrgrove6/dealii/releases{/id}","deployments_url":"https://api.github.com/repos/rrgrove6/dealii/deployments","created_at":"2015-08-04T19:44:20Z","updated_at":"2015-08-04T19:45:29Z","pushed_at":"2016-02-07T04:34:40Z","git_url":"git://github.com/rrgrove6/dealii.git","ssh_url":"git@github.com:rrgrove6/dealii.git","clone_url":"https://github.com/rrgrove6/dealii.git","svn_url":"https://github.com/rrgrove6/dealii","homepage":"http://www.dealii.org/","size":122266,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"tjhei:master","ref":"master","sha":"59f5672d640594843eff55b07529fc112145c4c0","user":{"login":"tjhei","id":1531285,"avatar_url":"https://avatars.githubusercontent.com/u/1531285?v=3","gravatar_id":"","url":"https://api.github.com/users/tjhei","html_url":"https://github.com/tjhei","followers_url":"https://api.github.com/users/tjhei/followers","following_url":"https://api.github.com/users/tjhei/following{/other_user}","gists_url":"https://api.github.com/users/tjhei/gists{/gist_id}","starred_url":"https://api.github.com/users/tjhei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjhei/subscriptions","organizations_url":"https://api.github.com/users/tjhei/orgs","repos_url":"https://api.github.com/users/tjhei/repos","events_url":"https://api.github.com/users/tjhei/events{/privacy}","received_events_url":"https://api.github.com/users/tjhei/received_events","type":"User","site_admin":false},"repo":{"id":22073053,"name":"dealii","full_name":"tjhei/dealii","owner":{"login":"tjhei","id":1531285,"avatar_url":"https://avatars.githubusercontent.com/u/1531285?v=3","gravatar_id":"","url":"https://api.github.com/users/tjhei","html_url":"https://github.com/tjhei","followers_url":"https://api.github.com/users/tjhei/followers","following_url":"https://api.github.com/users/tjhei/following{/other_user}","gists_url":"https://api.github.com/users/tjhei/gists{/gist_id}","starred_url":"https://api.github.com/users/tjhei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tjhei/subscriptions","organizations_url":"https://api.github.com/users/tjhei/orgs","repos_url":"https://api.github.com/users/tjhei/repos","events_url":"https://api.github.com/users/tjhei/events{/privacy}","received_events_url":"https://api.github.com/users/tjhei/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/tjhei/dealii","description":"","fork":true,"url":"https://api.github.com/repos/tjhei/dealii","forks_url":"https://api.github.com/repos/tjhei/dealii/forks","keys_url":"https://api.github.com/repos/tjhei/dealii/keys{/key_id}","collaborators_url":"https://api.github.com/repos/tjhei/dealii/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/tjhei/dealii/teams","hooks_url":"https://api.github.com/repos/tjhei/dealii/hooks","issue_events_url":"https://api.github.com/repos/tjhei/dealii/issues/events{/number}","events_url":"https://api.github.com/repos/tjhei/dealii/events","assignees_url":"https://api.github.com/repos/tjhei/dealii/assignees{/user}","branches_url":"https://api.github.com/repos/tjhei/dealii/branches{/branch}","tags_url":"https://api.github.com/repos/tjhei/dealii/tags","blobs_url":"https://api.github.com/repos/tjhei/dealii/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/tjhei/dealii/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/tjhei/dealii/git/refs{/sha}","trees_url":"https://api.github.com/repos/tjhei/dealii/git/trees{/sha}","statuses_url":"https://api.github.com/repos/tjhei/dealii/statuses/{sha}","languages_url":"https://api.github.com/repos/tjhei/dealii/languages","stargazers_url":"https://api.github.com/repos/tjhei/dealii/stargazers","contributors_url":"https://api.github.com/repos/tjhei/dealii/contributors","subscribers_url":"https://api.github.com/repos/tjhei/dealii/subscribers","subscription_url":"https://api.github.com/repos/tjhei/dealii/subscription","commits_url":"https://api.github.com/repos/tjhei/dealii/commits{/sha}","git_commits_url":"https://api.github.com/repos/tjhei/dealii/git/commits{/sha}","comments_url":"https://api.github.com/repos/tjhei/dealii/comments{/number}","issue_comment_url":"https://api.github.com/repos/tjhei/dealii/issues/comments{/number}","contents_url":"https://api.github.com/repos/tjhei/dealii/contents/{+path}","compare_url":"https://api.github.com/repos/tjhei/dealii/compare/{base}...{head}","merges_url":"https://api.github.com/repos/tjhei/dealii/merges","archive_url":"https://api.github.com/repos/tjhei/dealii/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/tjhei/dealii/downloads","issues_url":"https://api.github.com/repos/tjhei/dealii/issues{/number}","pulls_url":"https://api.github.com/repos/tjhei/dealii/pulls{/number}","milestones_url":"https://api.github.com/repos/tjhei/dealii/milestones{/number}","notifications_url":"https://api.github.com/repos/tjhei/dealii/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/tjhei/dealii/labels{/name}","releases_url":"https://api.github.com/repos/tjhei/dealii/releases{/id}","deployments_url":"https://api.github.com/repos/tjhei/dealii/deployments","created_at":"2014-07-21T17:16:17Z","updated_at":"2016-02-07T14:42:30Z","pushed_at":"2016-02-07T14:40:58Z","git_url":"git://github.com/tjhei/dealii.git","ssh_url":"git@github.com:tjhei/dealii.git","clone_url":"https://github.com/tjhei/dealii.git","svn_url":"https://github.com/tjhei/dealii","homepage":null,"size":134561,"stargazers_count":0,"watchers_count":0,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":1,"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/1"},"html":{"href":"https://github.com/tjhei/dealii/pull/1"},"issue":{"href":"https://api.github.com/repos/tjhei/dealii/issues/1"},"comments":{"href":"https://api.github.com/repos/tjhei/dealii/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/tjhei/dealii/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/tjhei/dealii/statuses/d650abfbbb6c38f6e8eb2975804fa85954cee523"}}}}