Hi, all. 

I'd like ask a question implementing periodic boundary condition. 

Modifying step-22 tutorial code, I want to solve a stokes flow at Couette 
configuration

I plan to solve it at (x,y) in [0,5] x [0,1], rectangular domain 

with boundary condition 

\vec{u} (x,1)= (1,0) (moving dragging plate)
\vec{u} (x,0)= (0,0) (stationary bottom plate) 

and periodic boundary condition at both inlet and outlet 

\vec{u}(0,y)=\vec{u}(5,y)



I think in deal.ii, this can be implemented as 

    {

      constraints.clear ();


      FEValuesExtractors::Vector velocities(0);

      DoFTools::make_hanging_node_constraints (dof_handler,

                                               constraints);

      

      // PERIODIC boundary condition

        

      std::vector<GridTools::PeriodicFacePair

      <typename DoFHandler<dim>::cell_iterator> > make_pair;

        

      GridTools::collect_periodic_faces(dof_handler,1,3

                                          /*direction*/,0

                                          ,make_pair);

        

      VectorTools::interpolate_boundary_values  (dof_handler,

                                                4,

                                                BoundaryValues<dim>(),

                                                constraints,

                                                
fe.component_mask(velocities));

        

      VectorTools::interpolate_boundary_values (dof_handler,

                                                2,

                                                ZeroFunction<dim>(dim+1),

                                                constraints,

                                                
fe.component_mask(velocities));

        

    }



However, as I run code, I get error message that 

An error occurred in line <3751> of file 
</Users/jaekwangkim/Program/dealii-8.5.0/source/grid/grid_tools.cc> in 
function

    void dealii::GridTools::collect_periodic_faces(const MeshType &, const 
types::boundary_id, const types::boundary_id, const int, 
std::vector<PeriodicFacePair<typename MeshType::cell_iterator> > &, const 
Tensor<1, MeshType::space_dimension> &, const FullMatrix<double> &) 
[MeshType = dealii::DoFHandler<2, 2>]

The violated condition was: 

    pairs1.size() == pairs2.size()

Additional information: 

    Unmatched faces on periodic boundaries


Stacktrace:

-----------

when it tried to compile  following part 

* GridTools::collect_periodic_faces(dof_handler,1,3*

*                                          /*direction*/,0*

*                                          ,make_pair);*

        

I would appreciate any comments or thoughts for possible reason of the 
problem.

I attach minimalized problem that has same problem. 



Thanks



-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dealii+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
#include <deal.II/base/quadrature_lib.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/function.h>
#include <deal.II/base/utilities.h>
#include <deal.II/lac/block_vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/grid_tools.h> //For the periodic boundary condition

#include <deal.II/dofs/dof_handler.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/dofs/dof_tools.h>

#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_values.h>

#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/error_estimator.h>

#include <deal.II/lac/sparse_direct.h>

#include <deal.II/lac/sparse_ilu.h>

#include <iostream>
#include <fstream>
#include <sstream>

namespace Step22
{
  using namespace dealii;


  template <int dim>
  struct InnerPreconditioner;

  template <>
  struct InnerPreconditioner<2>
  {
    typedef SparseDirectUMFPACK type;
  };

  template <>
  struct InnerPreconditioner<3>
  {
    typedef SparseILU<double> type;
  };



  template <int dim>
  class StokesProblem
  {
  public:
    StokesProblem (const unsigned int degree);
    void run ();

  private:
    void define_mesh ();
    void setup_dofs ();
    void assemble_system ();
    void solve ();
    void output_results ();

    const unsigned int   degree;

    Triangulation<dim>   triangulation;
    FESystem<dim>        fe;
    DoFHandler<dim>      dof_handler;

    ConstraintMatrix     constraints;

    BlockSparsityPattern      sparsity_pattern;
    BlockSparseMatrix<double> system_matrix;

    BlockVector<double> solution;
    BlockVector<double> system_rhs;

    std_cxx11::shared_ptr<typename InnerPreconditioner<dim>::type> A_preconditioner;
  };



  template <int dim>
  class BoundaryValues : public Function<dim>
  {
  public:
    BoundaryValues () : Function<dim>(dim+1) {}

    virtual double value (const Point<dim>   &p,
                          const unsigned int  component = 0) const;

    virtual void vector_value (const Point<dim> &p,
                               Vector<double>   &value) const;
  };


  template <int dim>
  double
  BoundaryValues<dim>::value (const Point<dim>  &p,
                              const unsigned int component) const
  {
    Assert (component < this->n_components,
            ExcIndexRange (component, 0, this->n_components));

    if (component == 0)
        return 1;
    return 0;
  }


  template <int dim>
  void
  BoundaryValues<dim>::vector_value (const Point<dim> &p,
                                     Vector<double>   &values) const
  {
    for (unsigned int c=0; c<this->n_components; ++c)
      values(c) = BoundaryValues<dim>::value (p, c);
  }



  template <int dim>
  class RightHandSide : public Function<dim>
  {
  public:
    RightHandSide () : Function<dim>(dim+1) {}

    virtual double value (const Point<dim>   &p,
                          const unsigned int  component = 0) const;

    virtual void vector_value (const Point<dim> &p,
                               Vector<double>   &value) const;

  };


  template <int dim>
  double
  RightHandSide<dim>::value (const Point<dim>  &/*p*/,
                             const unsigned int /*component*/) const
  {
    return 0;
  }


  template <int dim>
  void
  RightHandSide<dim>::vector_value (const Point<dim> &p,
                                    Vector<double>   &values) const
  {
    for (unsigned int c=0; c<this->n_components; ++c)
      values(c) = RightHandSide<dim>::value (p, c);
  }





  template <class MatrixType, class PreconditionerType>
  class InverseMatrix : public Subscriptor
  {
  public:
    InverseMatrix (const MatrixType         &m,
                   const PreconditionerType &preconditioner);

    void vmult (Vector<double>       &dst,
                const Vector<double> &src) const;

  private:
    const SmartPointer<const MatrixType> matrix;
    const SmartPointer<const PreconditionerType> preconditioner;
  };


  template <class MatrixType, class PreconditionerType>
  InverseMatrix<MatrixType,PreconditionerType>::InverseMatrix
  (const MatrixType         &m,
   const PreconditionerType &preconditioner)
    :
    matrix (&m),
    preconditioner (&preconditioner)
  {}



  template <class MatrixType, class PreconditionerType>
  void InverseMatrix<MatrixType,PreconditionerType>::vmult
  (Vector<double>       &dst,
   const Vector<double> &src) const
  {
    SolverControl solver_control (src.size(), 1e-6*src.l2_norm());
    SolverCG<>    cg (solver_control);

    dst = 0;

    cg.solve (*matrix, dst, src, *preconditioner);
  }



  template <class PreconditionerType>
  class SchurComplement : public Subscriptor
  {
  public:
    SchurComplement (const BlockSparseMatrix<double> &system_matrix,
                     const InverseMatrix<SparseMatrix<double>, PreconditionerType> &A_inverse);

    void vmult (Vector<double>       &dst,
                const Vector<double> &src) const;

  private:
    const SmartPointer<const BlockSparseMatrix<double> > system_matrix;
    const SmartPointer<const InverseMatrix<SparseMatrix<double>, PreconditionerType> > A_inverse;

    mutable Vector<double> tmp1, tmp2;
  };



  template <class PreconditionerType>
  SchurComplement<PreconditionerType>::SchurComplement
  (const BlockSparseMatrix<double>                              &system_matrix,
   const InverseMatrix<SparseMatrix<double>,PreconditionerType> &A_inverse)
    :
    system_matrix (&system_matrix),
    A_inverse (&A_inverse),
    tmp1 (system_matrix.block(0,0).m()),
    tmp2 (system_matrix.block(0,0).m())
  {}


  template <class PreconditionerType>
  void SchurComplement<PreconditionerType>::vmult (Vector<double>       &dst,
                                                   const Vector<double> &src) const
  {
    system_matrix->block(0,1).vmult (tmp1, src);
    A_inverse->vmult (tmp2, tmp1);
    system_matrix->block(1,0).vmult (dst, tmp2);
  }




  template <int dim>
  StokesProblem<dim>::StokesProblem (const unsigned int degree)
    :
    degree (degree),
    triangulation (Triangulation<dim>::maximum_smoothing),
    fe (FE_Q<dim>(degree+1), dim,
        FE_Q<dim>(degree), 1),
    dof_handler (triangulation)
  {}




  template <int dim>
  void StokesProblem<dim>::setup_dofs ()
  {
    A_preconditioner.reset ();
    system_matrix.clear ();

    dof_handler.distribute_dofs (fe);
    DoFRenumbering::Cuthill_McKee (dof_handler);

    std::vector<unsigned int> block_component (dim+1,0);
    block_component[dim] = 1;
    DoFRenumbering::component_wise (dof_handler, block_component);

    {
      constraints.clear ();

      FEValuesExtractors::Vector velocities(0);
      DoFTools::make_hanging_node_constraints (dof_handler,
                                               constraints);
      
      // PERIODIC boundary condition
        
      std::vector<GridTools::PeriodicFacePair
      <typename DoFHandler<dim>::cell_iterator> > make_pair;
        
      GridTools::collect_periodic_faces(dof_handler,1,3
                                          /*direction*/,0
                                          ,make_pair);
        
      VectorTools::interpolate_boundary_values  (dof_handler,
                                                4,
                                                BoundaryValues<dim>(),
                                                constraints,
                                                fe.component_mask(velocities));
        
      VectorTools::interpolate_boundary_values (dof_handler,
                                                2,
                                                ZeroFunction<dim>(dim+1),
                                                constraints,
                                                fe.component_mask(velocities));
        
    }

    constraints.close ();

    std::vector<types::global_dof_index> dofs_per_block (2);
    DoFTools::count_dofs_per_block (dof_handler, dofs_per_block, block_component);
    const unsigned int n_u = dofs_per_block[0], n_p = dofs_per_block[1];


    {
      BlockDynamicSparsityPattern dsp (2,2);

      dsp.block(0,0).reinit (n_u, n_u);
      dsp.block(1,0).reinit (n_p, n_u);
      dsp.block(0,1).reinit (n_u, n_p);
      dsp.block(1,1).reinit (n_p, n_p);

      dsp.collect_sizes();

      DoFTools::make_sparsity_pattern (dof_handler, dsp, constraints, false);
      sparsity_pattern.copy_from (dsp);
    }

    system_matrix.reinit (sparsity_pattern);

    solution.reinit (2);
    solution.block(0).reinit (n_u);
    solution.block(1).reinit (n_p);
    solution.collect_sizes ();

    system_rhs.reinit (2);
    system_rhs.block(0).reinit (n_u);
    system_rhs.block(1).reinit (n_p);
    system_rhs.collect_sizes ();
  }



  template <int dim>
  void StokesProblem<dim>::assemble_system ()
  {
    system_matrix=0;
    system_rhs=0;

    QGauss<dim>   quadrature_formula(degree+2);

    FEValues<dim> fe_values (fe, quadrature_formula,
                             update_values    |
                             update_quadrature_points  |
                             update_JxW_values |
                             update_gradients);

    const unsigned int   dofs_per_cell   = fe.dofs_per_cell;

    const unsigned int   n_q_points      = quadrature_formula.size();

    FullMatrix<double>   local_matrix (dofs_per_cell, dofs_per_cell);
    Vector<double>       local_rhs (dofs_per_cell);

    std::vector<types::global_dof_index> local_dof_indices (dofs_per_cell);

    const RightHandSide<dim>          right_hand_side;
    std::vector<Vector<double> >      rhs_values (n_q_points,
                                                  Vector<double>(dim+1));

    const FEValuesExtractors::Vector velocities (0);
    const FEValuesExtractors::Scalar pressure (dim);

    std::vector<SymmetricTensor<2,dim> > symgrad_phi_u (dofs_per_cell);
    std::vector<double>                  div_phi_u   (dofs_per_cell);
    std::vector<double>                  phi_p       (dofs_per_cell);

    typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();
    for (; cell!=endc; ++cell)
      {
        fe_values.reinit (cell);
        local_matrix = 0;
        local_rhs = 0;

        right_hand_side.vector_value_list(fe_values.get_quadrature_points(),
                                          rhs_values);

        for (unsigned int q=0; q<n_q_points; ++q)
          {
            for (unsigned int k=0; k<dofs_per_cell; ++k)
              {
                symgrad_phi_u[k] = fe_values[velocities].symmetric_gradient (k, q);
                div_phi_u[k]     = fe_values[velocities].divergence (k, q);
                phi_p[k]         = fe_values[pressure].value (k, q);
              }

            for (unsigned int i=0; i<dofs_per_cell; ++i)
              {
                for (unsigned int j=0; j<=i; ++j)
                  {
                    local_matrix(i,j) += (2 * (symgrad_phi_u[i] * symgrad_phi_u[j])
                                          - div_phi_u[i] * phi_p[j]
                                          - phi_p[i] * div_phi_u[j]
                                          + phi_p[i] * phi_p[j])
                                         * fe_values.JxW(q);

                  }


                const unsigned int component_i =
                  fe.system_to_component_index(i).first;
                local_rhs(i) += fe_values.shape_value(i,q) *
                                rhs_values[q](component_i) *
                                fe_values.JxW(q);
              }
          }


        for (unsigned int i=0; i<dofs_per_cell; ++i)
          for (unsigned int j=i+1; j<dofs_per_cell; ++j)
            local_matrix(i,j) = local_matrix(j,i);

        cell->get_dof_indices (local_dof_indices);
        constraints.distribute_local_to_global (local_matrix, local_rhs,
                                                local_dof_indices,
                                                system_matrix, system_rhs);
      }

    A_preconditioner
      = std_cxx11::shared_ptr<typename InnerPreconditioner<dim>::type>(new typename InnerPreconditioner<dim>::type());
    A_preconditioner->initialize (system_matrix.block(0,0),
                                  typename InnerPreconditioner<dim>::type::AdditionalData());

  }




  template <int dim>
  void StokesProblem<dim>::solve ()
  {
    const InverseMatrix<SparseMatrix<double>,
          typename InnerPreconditioner<dim>::type>
          A_inverse (system_matrix.block(0,0), *A_preconditioner);
    Vector<double> tmp (solution.block(0).size());

    {
      Vector<double> schur_rhs (solution.block(1).size());
      A_inverse.vmult (tmp, system_rhs.block(0));
      system_matrix.block(1,0).vmult (schur_rhs, tmp);
      schur_rhs -= system_rhs.block(1);

      SchurComplement<typename InnerPreconditioner<dim>::type>
      schur_complement (system_matrix, A_inverse);

      SolverControl solver_control (solution.block(1).size(),
                                    1e-6*schur_rhs.l2_norm());
      SolverCG<>    cg (solver_control);

      SparseILU<double> preconditioner;
      preconditioner.initialize (system_matrix.block(1,1),
                                 SparseILU<double>::AdditionalData());

      InverseMatrix<SparseMatrix<double>,SparseILU<double> >
      m_inverse (system_matrix.block(1,1), preconditioner);

      cg.solve (schur_complement, solution.block(1), schur_rhs,
                m_inverse);

      constraints.distribute (solution);

    }

    {
      system_matrix.block(0,1).vmult (tmp, solution.block(1));
      tmp *= -1;
      tmp += system_rhs.block(0);

      A_inverse.vmult (solution.block(0), tmp);

      constraints.distribute (solution);
    }
  }




  template <int dim>
  void
  StokesProblem<dim>::output_results ()
  {
    std::vector<std::string> solution_names (dim, "velocity");
    solution_names.push_back ("pressure");

    std::vector<DataComponentInterpretation::DataComponentInterpretation>
    data_component_interpretation
    (dim, DataComponentInterpretation::component_is_part_of_vector);
    data_component_interpretation
    .push_back (DataComponentInterpretation::component_is_scalar);

    DataOut<dim> data_out;
    data_out.attach_dof_handler (dof_handler);
    data_out.add_data_vector (solution, solution_names,
                              DataOut<dim>::type_dof_data,
                              data_component_interpretation);
    data_out.build_patches ();

    std::ostringstream filename;
    filename << "solution.vtk";

    std::ofstream output (filename.str().c_str());
    data_out.write_vtk (output);
  }


   template <int dim>
   void StokesProblem<dim>::define_mesh ()
   {
       const Point<2> end (5.0,1.0);
       const Point<2> start (0.0,0.0);
       GridGenerator::hyper_rectangle (triangulation, start, end, false);
       
       for (typename Triangulation<dim>::active_cell_iterator
            cell=triangulation.begin_active();
            cell!=triangulation.end(); ++cell)
       {
           for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
           {
               // You need this line to ensure that this doesn't affect anything other than bondary faces!
               if (cell->face(f)->at_boundary() == true)
               {
                   if ( std::abs(cell->face(f)->center()[0]-0.5)< 1e-10 )
                   {
                       cell->face(f)->set_boundary_id(10);
                   }
                   
                   // Boundary faces
                   static const double tol = 1e-12;
                   if ( std::abs(cell->face(f)->center()[0]-0.0)< tol )
                   {
                       cell->face(f)->set_boundary_id(1); // Will be periodic to bd_id=3
                   }
                   if ( std::abs(cell->face(f)->center()[0]-1.0)< tol )
                   {
                       cell->face(f)->set_boundary_id(3); // Will be periodic with bd_id=1
                   }
                   if ( std::abs(cell->face(f)->center()[1]-0.0)< tol )
                   {
                       cell->face(f)->set_boundary_id(2); // Dirichlet BC
                   }
                   if ( std::abs(cell->face(f)->center()[1]-1.0)< tol )
                   {
                       cell->face(f)->set_boundary_id(4); // Dirichlet BC
                   }
               }
           }
       } //end of cycle over cells
       
       triangulation.refine_global (2);
       
   }
    
  template <int dim>
  void StokesProblem<dim>::run ()
  {
      define_mesh();
      setup_dofs ();
      assemble_system ();
      solve ();
      output_results ();
  }
}



int main ()
{
  try
    {
      using namespace dealii;
      using namespace Step22;

      StokesProblem<2> flow_problem(1);
      flow_problem.run ();
    }
  catch (std::exception &exc)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Exception on processing: " << std::endl
                << exc.what() << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;

      return 1;
    }
  catch (...)
    {
      std::cerr << std::endl << std::endl
                << "----------------------------------------------------"
                << std::endl;
      std::cerr << "Unknown exception!" << std::endl
                << "Aborting!" << std::endl
                << "----------------------------------------------------"
                << std::endl;
      return 1;
    }

  return 0;
}

Reply via email to