sorry, I still have a problem with applying periodic boundary constraint on distributed mesh.
bellow the email is an example that apply the constraints. I tested some cases with this piece of code, it works well on 2 dimensional, but when going to 3 dimensional cases, it will get incorrect results, depends on the number of dofs: when the number of dofs is small, the result is right, when the number of dofs is large, the results is wrong.
It looks like the Constraint Matrix only knows 'locally_relevant_dofs', if the dof I want to constraint is outside of this range,the ConstraintMatrix could not handle it.
Thanks in advance!
*********************************************************************************************************************************************8
template <int dim>
void
NavierStokesProjection<dim>:: setup_periodic_boundary_constraints ()
{
unsigned int myid = Utilities::MPI::this_mpi_process(mpi_communicator);
const unsigned int n_processes = Utilities::System::
get_n_mpi_processes(mpi_communicator);
const QGauss<dim-1> quad_vel(deg+2);
const QGauss<dim-1> quad_pres(deg+1);
FEFaceValues<dim> feface_vel (fe_velocity,quad_vel,
update_quadrature_points);
FEFaceValues<dim> feface_pres (fe_pressure,quad_pres,
update_quadrature_points);
const unsigned int dpc_v = fe_velocity.dofs_per_cell;
const unsigned int dpc_p = fe_pressure.dofs_per_cell;
std::vector< double > global_dofs_positions_vel,global_dofs_positions_pres;
std::vector< double > global_dofs_positions_vel_buff,global_dofs_positions_pres_buff;
const unsigned int nfpc = GeometryInfo<dim>::faces_per_cell;
const unsigned int nvpc = GeometryInfo<dim>::vertices_per_face;
u_constraints.clear ();
u_constraints.reinit(locally_relevant_dofs_velocity);
DoFTools::make_hanging_node_constraints (dof_handler_velocity,
u_constraints);
//
v_constraints.clear ();
v_constraints.reinit(locally_relevant_dofs_velocity);
DoFTools::make_hanging_node_constraints (dof_handler_velocity,
v_constraints);
//
w_constraints.clear ();
w_constraints.reinit(locally_relevant_dofs_velocity);
DoFTools::make_hanging_node_constraints (dof_handler_velocity,
w_constraints);
//
//
p_constraints.clear ();
p_constraints.reinit(locally_relevant_dofs_pressure);
DoFTools::make_hanging_node_constraints (dof_handler_pressure,
p_constraints);
for(typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler_velocity.begin_active ();
cell != dof_handler_velocity.end (); ++cell )
if (cell->is_locally_owned())
for(unsigned int f=0; f<nfpc; ++f)
{
if( ( cell->at_boundary())
&& (cell->face(f)->boundary_indicator() == 4 ) )
{
typename DoFHandler<dim>::active_cell_iterator
pres_cell (&triangulation,
cell->level(),
cell->index(),
&dof_handler_pressure);
const typename DoFHandler<dim>::active_face_iterator
face_v = cell->face(f);
const typename DoFHandler<dim>::active_face_iterator
face_p = pres_cell->face(f);
const unsigned int dpfv
=face_v->get_dof_handler().get_fe().dofs_per_face;
const unsigned int dpfp
=face_p->get_dof_handler().get_fe().dofs_per_face;
std::vector<unsigned int> ldi_v (dpfv);
std::vector<unsigned int> ldi_p (dpfp);
face_v->get_dof_indices (ldi_v);
face_p->get_dof_indices (ldi_p);
feface_vel.reinit(cell,f);
feface_pres.reinit(pres_cell,f);
const std::vector< Point<dim> > points_v =
feface_vel.get_present_fe_values().get_quadrature_points();
const std::vector< Point<dim> > points_p =
feface_pres.get_present_fe_values().get_quadrature_points();
for(unsigned int i=0; i<dpfv; ++i)
{
global_dofs_positions_vel.push_back(ldi_v[i]);
global_dofs_positions_vel.push_back(points_v[i][0]);
global_dofs_positions_vel.push_back(points_v[i][1]);
}
for(unsigned int i=0; i<dpfp; ++i)
{
global_dofs_positions_pres.push_back(ldi_p[i]);
global_dofs_positions_pres.push_back(points_p[i][0]);
global_dofs_positions_pres.push_back(points_p[i][1]);
}
} //
} //
MPI_Barrier(mpi_communicator);
unsigned int len_v = global_dofs_positions_vel.size();
const unsigned int max_len_v = Utilities::MPI::max(len_v,mpi_communicator);
const unsigned int num_periodic_dofs_vel = Utilities::MPI::sum(len_v,mpi_communicator);
unsigned int len_p = global_dofs_positions_pres.size();
const unsigned int max_len_p = Utilities::MPI::max(len_p,mpi_communicator);
const unsigned int num_periodic_dofs_pres = Utilities::MPI::sum(len_p,mpi_communicator);
global_dofs_positions_vel_buff.resize(max_len_v*n_processes);
global_dofs_positions_pres_buff.resize(max_len_p*n_processes);
if(len_v<max_len_v)
for(unsigned int k=0; k<(max_len_v-len_v); ++k)
global_dofs_positions_vel.push_back(-10e6);
if(len_p<max_len_p)
for(unsigned int k=0; k<(max_len_p-len_p); ++k)
global_dofs_positions_pres.push_back(-10e6);
//
//
MPI_Allgather(&global_dofs_positions_vel[0], max_len_v, MPI_DOUBLE,
&global_dofs_positions_vel_buff[0], max_len_v, MPI_DOUBLE, mpi_communicator);
MPI_Allgather(&global_dofs_positions_pres[0], max_len_p, MPI_DOUBLE,
&global_dofs_positions_pres_buff[0], max_len_p, MPI_DOUBLE, mpi_communicator);
unsigned int buff_size_vel = global_dofs_positions_vel_buff.size();
unsigned int buff_size_pres = global_dofs_positions_pres_buff.size();
std::vector< double >velocity_dofs, pressure_dofs;
for(unsigned int i=0; i<buff_size_vel; ++i)
if(global_dofs_positions_vel_buff[i]!=-10e6)
velocity_dofs.push_back(global_dofs_positions_vel_buff[i]);
for(unsigned int i=0; i<buff_size_pres; ++i)
if(global_dofs_positions_pres_buff[i]!=-10e6)
pressure_dofs.push_back(global_dofs_positions_pres_buff[i]);
unsigned int size_vel = velocity_dofs.size();
unsigned int size_pres = pressure_dofs.size();
Assert(size_vel== num_periodic_dofs_vel,
ExcMessage("Wrong number of periodic dofs for velocity!"));
Assert(size_pres== num_periodic_dofs_pres,
ExcMessage("Wrong number of periodic dofs for pressure!"));
for(typename DoFHandler<dim>::active_cell_iterator
cell = dof_handler_velocity.begin_active ();
cell != dof_handler_velocity.end (); ++cell )
if (cell->is_locally_owned())
for(unsigned int f=0; f<nfpc; ++f)
{
if( ( cell->at_boundary())
&& (cell->face(f)->boundary_indicator() == 5 ) )
{
typename DoFHandler<dim>::active_cell_iterator
pres_cell (&triangulation,
cell->level(),
cell->index(),
&dof_handler_pressure);
const typename DoFHandler<dim>::active_face_iterator
face_v = cell->face(f);
const typename DoFHandler<dim>::active_face_iterator
face_p = pres_cell->face(f);
const unsigned int dpfv
=face_v->get_dof_handler().get_fe().dofs_per_face;
const unsigned int dpfp
=face_p->get_dof_handler().get_fe().dofs_per_face;
std::vector<unsigned int> ldi_v (dpfv),ldi_p(dpfp);
face_v->get_dof_indices (ldi_v);
face_p->get_dof_indices (ldi_p);
feface_vel.reinit(cell,f);
feface_pres.reinit(pres_cell,f);
const std::vector< Point<dim> > points_v =
feface_vel.get_present_fe_values().get_quadrature_points();
const std::vector< Point<dim> > points_p =
feface_pres.get_present_fe_values().get_quadrature_points();
unsigned int search_step = dim;
for(unsigned int i=0; i<dpfv; ++i)
for(unsigned int j=0; j<num_periodic_dofs_vel; j=j+search_step)
if( (std::fabs(points_v[i][0]-velocity_dofs[j+1])<1e-8) &&
(std::fabs(points_v[i][1]-velocity_dofs[j+2])<1e-8) )
// if(!u_constraints.is_inhomogeneously_constrained(ldi_v[i]))
{
u_constraints.add_line (ldi_v[i]);
v_constraints.add_line (ldi_v[i]);
w_constraints.add_line (ldi_v[i]);
u_constraints.add_entry (ldi_v[i],
(int)velocity_dofs[j],
1.0);
v_constraints.add_entry (ldi_v[i],
(int)velocity_dofs[j],
1.0);
w_constraints.add_entry (ldi_v[i],
(int)velocity_dofs[j],
1.0);
}
for(unsigned int i=0; i<dpfp; ++i)
for(unsigned int j=0; j<num_periodic_dofs_pres; j=j+search_step)
if( (std::fabs(points_p[i][0]-pressure_dofs[j+1])<1e-8) &&
(std::fabs(points_p[i][1]-pressure_dofs[j+2])<1e-8) )
// if(!p_constraints.is_inhomogeneously_constrained(ldi_p[i]))
{
p_constraints.add_line (ldi_p[i]);
p_constraints.add_entry (ldi_p[i],
(int)pressure_dofs[j],
1.0);
}
} //
}//
u_constraints.close ();
v_constraints.close ();
w_constraints.close ();
p_constraints.close ();
}
**************************************************************************************************************************************************************
On Friday, September 28, 2012 2:31:29 AM UTC+8, Timo Heister wrote: