Hi all,

I was following tutorial 22 and 34 to implement inhomogeneous Dirichlet
boundary conditions using the ConsraintMatrix class but couldn't get it
right. I think the problem mainly lies in the assemblage part (i was
solving the basic Poisson's eq.)

        if(constraints.is_inhomogeneously_constrained
           (local_dof_indices[i])){
          for(unsigned int j=0; j <dofs_per_cell; ++j){
            matrix_for_bc(j,i) +=
              grad_basis_phi[i] * grad_basis_phi[j] *
              fe_values.JxW(q);
          }//j-loop
        }//if
    ...
    constraints.distribute_local_to_global(local_rhs,
                                           local_dof_indices,
                                           rhs,
                                           matrix_for_bc);

However, when I comment out the if statement, the program seems to work
correctly. The code is attached in this email. 
Your help will be greatly appreciated. 

Thanks!

Huan
#include <base/quadrature_lib.h>
#include <base/logstream.h>
#include <base/utilities.h>
#include <base/timer.h>
 
#include <lac/full_matrix.h>
#include <lac/sparse_matrix.h>
#include <lac/solver_gmres.h>
#include <lac/solver_cg.h>
#include <lac/block_sparsity_pattern.h>
#include <lac/constraint_matrix.h>
#include <lac/precondition.h>
 
#include <grid/tria.h>
#include <grid/grid_generator.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/grid_tools.h>
#include <grid/grid_refinement.h>
 
#include <dofs/dof_handler.h>
#include <dofs/dof_renumbering.h>
#include <dofs/dof_accessor.h>
#include <dofs/dof_tools.h>
 
#include <fe/fe_q.h>
#include <fe/fe_system.h>
#include <fe/fe_values.h>
 
#include <numerics/vectors.h>
#include <numerics/matrices.h>
#include <numerics/data_out.h>
#include <numerics/error_estimator.h>
#include <numerics/solution_transfer.h>
 
#include <lac/trilinos_sparse_matrix.h>
#include <lac/trilinos_block_sparse_matrix.h>
#include <lac/trilinos_vector.h>
#include <lac/trilinos_block_vector.h>
#include <lac/trilinos_precondition.h>
 
#include <fstream>
#include <sstream>
#include<cstdlib>

using namespace dealii;

namespace EquationData{
  //geometry info
  const double xl = 0.0;
  const double xr = numbers::PI;
  const double yb = 0.0;
  const double yt = numbers::PI;

  // 2d version
  const Point<2> left_bottom(xl, yb);
  const Point<2> right_top(xr, yt);
  
  //solution


  template<int dim>
  class ExactSolution : public Function<dim>{
  public:
    ExactSolution() : Function<dim>(1){}
    virtual double value(const Point<dim> &p,
			 const unsigned int component = 0) const;
  };

  template<int dim>
  double ExactSolution<dim>::value(const Point<dim> &p,
				  const unsigned int component)const{
    return std::sin(p[0]);
  }//value()


  template<int dim>
  class RightHandSide : public Function<dim>{
  public:
    RightHandSide() : Function<dim>(1){}
    virtual double value(const Point<dim> &p,
			 const unsigned int component = 0) const;
  };

  template<int dim>
  double RightHandSide<dim>::value(const Point<dim> &p,
				  const unsigned int component)const{
    return std::sin(p[0]);
  }//value()
  
}//namespace EquationData


template<int dim>
class PoissonProblem{
public:
  PoissonProblem();
  void run();
private:
  void setup_dofs();
  void assemble_system();
  void assemble_stiffness_matrix();
  void solve();
  void compute_errors() const;
  
  Triangulation<dim> triangulation;

  const unsigned int 	degree;
  FE_Q<dim> 		fe;
  DoFHandler<dim> 	dof_handler;
  ConstraintMatrix 	constraints;

  SparsityPattern 	sparsity_pattern;
  SparseMatrix<double> 	stiffness_matrix;

  Vector<double> solution;

  Vector<double> rhs;
  
};//class PoissonProblem


template<int dim>
PoissonProblem<dim>::PoissonProblem()
  :
  triangulation(Triangulation<dim>::maximum_smoothing),
  degree(1),
  fe(degree),
  dof_handler(triangulation)
{}


template<int dim>
void PoissonProblem<dim>::setup_dofs(){
  {
    dof_handler.distribute_dofs(fe);
    constraints.clear();
    //let's assume dirichlet boundary condition.
    VectorTools::interpolate_boundary_values
      (dof_handler,
       0,
       EquationData::ExactSolution<dim>(),
       constraints);
    DoFTools::make_hanging_node_constraints(dof_handler,
					    constraints);
    constraints.close();
  }//localize

  std::cout << "Number of active cells: "
	    << triangulation.n_active_cells()
	    << " ( on "
	    << triangulation.n_levels()
	    << " levels )"
	    << std::endl
	    << "Number of degrees of freedom: "
	    <<  dof_handler.n_dofs()
	    << std::endl << std::endl;

  {
    stiffness_matrix.clear();
    
    sparsity_pattern.reinit(dof_handler.n_dofs(),
			    dof_handler.n_dofs(),
			    dof_handler.max_couplings_between_dofs());
    
    DoFTools::make_sparsity_pattern(dof_handler, sparsity_pattern,
				    constraints, false);
    
    sparsity_pattern.compress();
    stiffness_matrix.reinit(sparsity_pattern);
  }//localize

  solution.reinit(dof_handler.n_dofs());

  rhs.reinit(dof_handler.n_dofs());
    
}//setup_dofs()





template<int dim>
void
PoissonProblem<dim>::assemble_system(){

  stiffness_matrix = 0;
  rhs = 0;
  
  const QGauss<dim> quadrature_formula(degree + 2);

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

  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<unsigned int> local_dof_indices(dofs_per_cell);

  std::vector<double> basis_phi(dofs_per_cell);
  std::vector<Tensor<1,dim> > grad_basis_phi(dofs_per_cell);

  typename DoFHandler<dim>::active_cell_iterator
    cell = dof_handler.begin_active(),
    endc = dof_handler.end();

  EquationData::RightHandSide<dim> rhs_function;

  FullMatrix<double> matrix_for_bc(dofs_per_cell,
				   dofs_per_cell);
  
  for(; cell != endc; ++cell){
    local_matrix = 0;
    local_rhs = 0;
    matrix_for_bc = 0;
    fe_values.reinit(cell);
        
    for(unsigned int q=0; q<n_q_points;++q){
      for(unsigned int k=0; k<dofs_per_cell; ++k){
	basis_phi[k] = fe_values.shape_value(k,q);
	grad_basis_phi[k] = fe_values.shape_grad(k,q);
      }//k-loop

      for(unsigned int i=0; i<dofs_per_cell;++i){
	for(unsigned int j =0; j < dofs_per_cell; ++j){
	  local_matrix(i,j) +=
	    grad_basis_phi[i] * grad_basis_phi[j] * fe_values.JxW(q);
	}//j-loop
	local_rhs(i) +=
	  rhs_function.value(fe_values.quadrature_point(q))
	  * basis_phi[i]* fe_values.JxW(q);

	if(constraints.is_inhomogeneously_constrained
	   (local_dof_indices[i])){
	  for(unsigned int j=0; j <dofs_per_cell; ++j){
	    matrix_for_bc(j,i) +=
	      grad_basis_phi[i] * grad_basis_phi[j] *
	      fe_values.JxW(q);
	  }//j-loop
	}//if
      }//i-loop
    }//q-loop
    cell->get_dof_indices(local_dof_indices);
//     constraints.distribute_local_to_global(local_matrix,
// 					   local_rhs,
// 					   local_dof_indices,
// 					   stiffness_matrix,
// 					   rhs);
    constraints.distribute_local_to_global(local_matrix,
					   local_dof_indices,
					   stiffness_matrix);
    
    constraints.distribute_local_to_global(local_rhs,
					   local_dof_indices,
					   rhs,
					   matrix_for_bc);
  }//cell-loop
}//assemble_system()



template<int dim>
void PoissonProblem<dim>::solve(){
  //one update in Newton's method
  
  std::cout << "    Solving ..." << std::endl;
    
  assemble_system();
  {
    SolverControl solver_control(stiffness_matrix.m(),
				 1e-12*rhs.l2_norm());

    SolverCG<> cg(solver_control);

    
//     for(unsigned int i = 0; i < solution.size(); ++i){
//       if(constraints.is_constrained(i))
// 	solution(i) = 0;
//     }//i-loop
    
    cg.solve(stiffness_matrix, solution,
	     rhs, PreconditionIdentity());

    constraints.distribute(solution);

    std::cout << "    "
	      << solver_control.last_step()
	      << "  CG iterations for solution."
	      << std::endl;
    
    double min_phi = solution(0),
      max_phi = solution(0);

    for(unsigned int i=0; i < solution.size(); ++i){
      min_phi = std::min<double>(min_phi, solution(i));
      max_phi = std::max<double>(max_phi, solution(i));      
    }//i-loop

    std::cout << "    solution range: "
	      << min_phi << ' ' << max_phi
	      << std::endl;
    
  }//localize

}//solve()



template<int dim>
void PoissonProblem<dim>::compute_errors()const{
  EquationData::ExactSolution<dim> exact_solution;
  Vector<double> cellwise_errors(triangulation.n_active_cells());

  QTrapez<1> q_trapez;
  QIterated<dim> quadrature(q_trapez, degree+2);

  VectorTools::integrate_difference(dof_handler,
				    solution,
				    exact_solution,
				    cellwise_errors,
				    quadrature,
				    VectorTools::L2_norm);
  const double L2_error = cellwise_errors.l2_norm();
  std::cout << "Errors:  " << L2_error << std::endl;
  
}//compute_errors()

template<int dim>
void PoissonProblem<dim>::run(){
  const unsigned int initial_refinement = 2;

  GridGenerator::hyper_rectangle(triangulation,
				 EquationData::left_bottom,
				 EquationData::right_top);

 start_time_iteration:

  unsigned int step_number = 0;
  
  triangulation.refine_global(initial_refinement);

  double time = 0;

  do{//time marching

    triangulation.refine_global(1);

    setup_dofs();

    solve();
    
    compute_errors();
    
    std::cout << std::endl;

    ++step_number;
    
  }while(step_number < 4);

  std::cout << "job done!" << std::endl;
  
}//run()

int main(int argc, char* argv[]){
  try{
    deallog.depth_console(0);

    PoissonProblem<2> problem;
    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;
}
_______________________________________________
dealii mailing list http://poisson.dealii.org/mailman/listinfo/dealii

Reply via email to