Hello dealii-team,

I have created a failing test case in serial when hanging nodes+periodic 
constraints are mixed. 

*The algorithm of the test is follows: (attached *
*minimalExampleHangingNodesPeriodicConstraintsBug.cc)*

1) Create a hypercube (-20,20) with origin at the center

2) Set periodic boundary conditions on the hypercube

3) Perform two levels of mesh refinement:- a) one step uniform refinement 
hypercube to get 8 cells ,and b) then pick one of the 8 cells and refine 
only that cell which creates hanging nodes on the faces. Finally I get 15 
cells (see attached image).

4) Create two constraintMatrices: *constraints* and 
*onlyHangingNodeConstraints.*
*                constraints:* both hanging node and periodic constraints
                 *onlyHangingNodeConstraints:* just hanging node constraints

5) Create two nodal vectors vec1 and vec2 with nodal value = 
nodal_coordinate.norm(). Set and distribute vec1 using  *constraints. *Set 
and distribute vec2 using *onlyHangingNodeConstraints.*

6) Print l2 norm of vec1 and vec2.

*The issue:*

Since the nodal value = nodal_coordinate.norm() is intrinsically periodic 
(the domain being a hypercube with origin at the center), I would expect 
vec1 and vec2 to have the same l2 norm. However I get different l2 norm 
values:
L2 Norm vec1 (distributed using combined constraints): 178.494
L2 Norm vec2 (distributed using only hanging node constraints): 176.271

If I modify step 3) to: a)  two step uniform refinement hypercube to get 64 
cells ,and b) then pick one of the interior cells and refine only that cell 
which creates hanging nodes only in the interior. Total (71 cells). The l2 
norm of vec1 and vec2 matches in this case:
L2 Norm vec1 (distributed using combined constraints): 278.505
L2 Norm vec2 (distributed using only hanging node constraints): 278.505 

Thanks,
Sambit

-- 
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 all deal.II header file
#include <deal.II/base/quadrature.h>
#include <deal.II/base/function.h>
#include <deal.II/base/logstream.h>
#include <deal.II/base/timer.h>
#include <deal.II/base/table.h>
#include <deal.II/lac/vector.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/constraint_matrix.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping_q1.h>
#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/grid_generator.h>
#include <deal.II/dofs/dof_tools.h>
#include <deal.II/dofs/dof_handler.h>
#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/base/tensor_function.h>
#include <deal.II/base/point.h>
#include <deal.II/base/conditional_ostream.h>
#include <deal.II/base/utilities.h>
#include <deal.II/lac/lapack_full_matrix.h>
#include <deal.II/numerics/matrix_tools.h>
#include <deal.II/numerics/error_estimator.h>
#include <deal.II/base/parameter_handler.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/tria_boundary_lib.h>
#include <deal.II/grid/grid_tools.h>
#include <deal.II/grid/grid_in.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/dofs/dof_renumbering.h>
#include <deal.II/dofs/dof_accessor.h>
#include <deal.II/lac/solver_cg.h>
#include <deal.II/lac/solver_gmres.h>
#include <deal.II/lac/solver_bicgstab.h>
#include <deal.II/lac/precondition.h>
#include <deal.II/distributed/tria.h>
#include <deal.II/lac/parallel_vector.h>
#include <deal.II/matrix_free/matrix_free.h>
#include <deal.II/matrix_free/fe_evaluation.h>
#include <deal.II/lac/slepc_solver.h>
#include <deal.II/base/config.h>
#include <deal.II/base/smartpointer.h>
//Include generic C++ headers
#include <fstream>
#include <iostream>


using namespace dealii;
int main (int argc, char *argv[])
{
  Utilities::MPI::MPI_InitFinalize mpi_initialization(argc, argv);

  const double L=20;
  Triangulation<3,3> triangulation;
  GridGenerator::hyper_cube (triangulation, -L, L);

  //mark faces
  typename Triangulation<3,3>::active_cell_iterator cell = triangulation.begin_active(), endc = triangulation.end();
  for(; cell!=endc; ++cell)
  {
      for(unsigned int f=0; f < GeometryInfo<3>::faces_per_cell; ++f)
	{
	  const Point<3> face_center = cell->face(f)->center();
	  if(cell->face(f)->at_boundary())
	    {
	      if (std::abs(face_center[0]-L)<1.0e-5)
		cell->face(f)->set_boundary_id(1);
	      else if (std::abs(face_center[0]+L)<1.0e-5)
		cell->face(f)->set_boundary_id(2);
	      else if (std::abs(face_center[1]-L)<1.0e-5)
		cell->face(f)->set_boundary_id(3);
	      else if (std::abs(face_center[1]+L)<1.0e-5)
		cell->face(f)->set_boundary_id(4);
	      else if (std::abs(face_center[2]-L)<1.0e-5)
		cell->face(f)->set_boundary_id(5);
	      else if (std::abs(face_center[2]+L)<1.0e-5)
		cell->face(f)->set_boundary_id(6);
	    }
	}
  }

  std::vector<GridTools::PeriodicFacePair<typename Triangulation<3,3>::cell_iterator> > periodicity_vector;
  for (int i = 0; i < 3; ++i)
  {
      GridTools::collect_periodic_faces(triangulation, /*b_id1*/ 2*i+1, /*b_id2*/ 2*i+2,/*direction*/ i, periodicity_vector);
  }
  triangulation.add_periodicity(periodicity_vector);
  std::cout << "Periodic Facepairs size: " << periodicity_vector.size() << std::endl;

  //FIXME: two cases of mesh refinement, both having two levels of refinement to create hanging nodes
  //Case 0 which has hanging node constraint on periodic face is the buggy case
  //Case 1 which has hanging node constraints in the interior works fine
  const unsigned int Case=0;

  if (Case==0)
  {
     triangulation.refine_global(1);
     //pick the first cell and refine
     cell = triangulation.begin_active();
     cell->set_refine_flag();
     triangulation.execute_coarsening_and_refinement();
  }
  else if (Case==1)
  {
      triangulation.refine_global(2);
      //pick an interior cell and refine again
      cell = triangulation.begin_active();
      endc =  triangulation.end();
      for (; cell!=endc; ++cell)
      {
	  Point<3> cellCentroid=cell->center();

	  if (std::fabs(cellCentroid[0]-L/4.0)<1e-5
	      && std::fabs(cellCentroid[1]-L/4.0)<1e-5
	      && std::fabs(cellCentroid[2]-L/4.0)<1e-5)
	      cell->set_refine_flag();

      }
      triangulation.execute_coarsening_and_refinement();
  }


  std::cout << "number of elements: "
	<< triangulation.n_global_active_cells()
	<< std::endl;
  /////

  FESystem<3> FE(FE_Q<3>(QGaussLobatto<1>(2)), 1); //linear shape function
  DoFHandler<3> dofHandler (triangulation);
  dofHandler.distribute_dofs(FE);

  ///creating combined constraint matrix
  ConstraintMatrix constraints;
  constraints.clear();
  DoFTools::make_hanging_node_constraints(dofHandler, constraints);
  std::vector<GridTools::PeriodicFacePair<typename DoFHandler<3>::cell_iterator> > periodicity_vectorDof;
  for (int i = 0; i < 3; ++i)
    {
      GridTools::collect_periodic_faces(dofHandler, /*b_id1*/ 2*i+1, /*b_id2*/ 2*i+2,/*direction*/ i, periodicity_vectorDof);
    }
  DoFTools::make_periodicity_constraints<DoFHandler<3> >(periodicity_vectorDof, constraints);
  constraints.close();

  std::cout<< "size of constraint matrix: "<< constraints.n_constraints()<<std::endl;
  std::cout<< "printing constraint matrix ...."<<std::endl;
  constraints.print(std::cout);


  ///create only hanging node constraint matrix
  ConstraintMatrix onlyHangingNodeConstraints;onlyHangingNodeConstraints.clear();
  DoFTools::make_hanging_node_constraints(dofHandler, onlyHangingNodeConstraints);
  onlyHangingNodeConstraints.close();

  Vector<double> vec1;
  vec1.reinit(dofHandler.n_dofs());
  vec1=0;

  Vector<double> vec2;
  vec2.reinit(dofHandler.n_dofs());
  vec2=0;

  const unsigned int vertices_per_cell=GeometryInfo<3>::vertices_per_cell;
  std::vector<bool> vertex_touched(dofHandler.get_triangulation().n_vertices(),
				       false);

  DoFHandler<3>::active_cell_iterator
  cellDof = dofHandler.begin_active(),
  endcDof = dofHandler.end();
  for (; cellDof!=endcDof; ++cellDof)
  for (unsigned int i=0; i<vertices_per_cell; ++i)
  {
	    const unsigned global_vertex_no = cellDof->vertex_index(i);

	    if (vertex_touched[global_vertex_no])
	       continue;
	    vertex_touched[global_vertex_no]=true;
	    Point<3> nodalCoor = cellDof->vertex(i);

	    const unsigned int globalDofIndex=cellDof->vertex_dof_index(i,0);

	    if(!constraints.is_constrained(globalDofIndex))
	       vec1[globalDofIndex]=nodalCoor.norm();

	    if(!onlyHangingNodeConstraints.is_constrained(globalDofIndex))
	       vec2[globalDofIndex]=nodalCoor.norm();
  }

  constraints.distribute(vec1);
  std::cout<<"L2 Norm vec1 (distributed using combined constraints): "<<vec1.l2_norm()<<std::endl;

  onlyHangingNodeConstraints.distribute(vec2);
  std::cout<<"L2 Norm vec2 (distributed using only hanging node constraints): "<<vec2.l2_norm()<<std::endl;
}

Reply via email to