Some context: 
I am trying to model a waveguide which would require me to solve the double 
curl equation curlxcurlxE-cE=0 where c is some constant(real or imaginary) 
subject to nxE=nxf on different parts of the boundary where f can be real 
or imaginary also. 

The problem requires the use of Nedelec elements but you already know that. 
Since the problem is complex I am breaking it down into two with FEsystem. 
I am trying to approach this by solving this simple system before 
complicating things:
curlxcurlxE_r-cE_r=0
nxE_r=1   on an "inlet"
nxE_r=0   everywhere else 
and 
curlxcurlxE_i-cE_i=0
nxE_i=1   on an "inlet"
nxE_i=0   everywhere else 

These two systems are uncoupled and exactly the same. The issue has been 
that my BCs aren't being applied for the second part of the equation. I am 
using VectorTools::project_boundary_values_curl_conforming_l2(). The first 
part of the equation gives a solution (inaccurate but that's not my issue 
here) with the BCs applied. 

I print out the sparsity pattern and there seems to be a difference between 
applying BCs and not applying them which makes me conclude that 
project_boundary_values_curl_conforming_l2 is effecting the matrix. 
I printed out the global right hand side for a smaller problem and the 
second half of it, which is the half that is related to the second problem, 
is just zeros so my guess is that 
constraints.distribute_local_to_global(cell_matrix, cell_rhs, 
local_dof_indices, system_matrix, system_rhs) isn't applying the BC in the 
cell_rhs when FENedelec systems are involved. 

I have attached my code here.
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 [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/dealii/8c95e3cb-1643-4cbf-a79f-b7ebc7f02104n%40googlegroups.com.
#include <deal.II/base/function.h>
#include <deal.II/base/quadrature_lib.h>

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

#include <deal.II/fe/fe_nedelec.h>
#include <deal.II/fe/fe_values.h>
#include <deal.II/fe/mapping_q.h>
#include <deal.II/fe/mapping_q1.h>

#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_refinement.h>
#include <deal.II/grid/grid_tools.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_out.h>

#include <deal.II/lac/affine_constraints.h>
#include <deal.II/lac/dynamic_sparsity_pattern.h>
#include <deal.II/lac/full_matrix.h>
#include <deal.II/lac/sparse_direct.h>
#include <deal.II/lac/sparse_matrix.h>
#include <deal.II/lac/vector.h>

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

#include <deal.II/lac/precondition.h>
#include <deal.II/lac/solver_cg.h>

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


#include <deal.II/lac/block_sparse_matrix.h>
#include <deal.II/lac/block_vector.h>

#include <vector>
using namespace dealii; 

// Perfect conductor BC nxE=0
  class PerfConductor : public Function<3>
  {
  public:
    PerfConductor(): Function<3>(3)  
    {}

    void vector_value_list(const std::vector<Point<3>> &points,
                      std::vector<Vector<double>> &  values) const override;
  };

    void PerfConductor::vector_value_list(const std::vector<Point<3>> &points,
                      std::vector<Vector<double>> &  values) const 
 {
    for (unsigned int i = 0; i < points.size(); ++i)
      {
        values[i][0] = 0.0;
        values[i][1] = 0.0;
        values[i][2] = 0.0;        
      }
  }


//Inlet BC nXE=1
  class Inlet: public Function<3>
  {
  public:
    Inlet(): Function<3>(3)  
    {}

    void vector_value_list(const std::vector<Point<3>> &points,
                      std::vector<Vector<double>> &  values) const override;
  };

  void Inlet::vector_value_list(const std::vector<Point<3>> &points,
                      std::vector<Vector<double>> &  values) const 
 {
    for (unsigned int i = 0; i < points.size(); ++i)
      {
        values[i][0] = 1.0;
        values[i][1] = 0.0;
        values[i][2] = 0.0;
      }
  }



class Nedlec
{
  public:
  Nedlec();
  void run();

  private:
  void make_grid();
  void setup_system();
  void assemble_system();
  void solve();
  void output_results() const;


  Triangulation<3> triangulation;
  DoFHandler<3>           dof_handler;
  FESystem<3>              fe; 
  AffineConstraints<double> constraints;

  SparsityPattern           sparsity_pattern;
  SparseMatrix<double>      system_matrix;
  Vector<double>            solution;
  Vector<double>            system_rhs;


};

//Constructor
Nedlec::Nedlec()   
    : dof_handler(triangulation)
    , fe(FE_Nedelec<3>(0), 2)  
{}


//makegrid
void Nedlec::make_grid()
{
  Point<3> p1(0,0,0) , p2 (0.2,0.1,1) ;
  
  GridGenerator::hyper_rectangle(triangulation,p1,p2); 
  triangulation.begin_active()->face(4)->set_boundary_id(1);  //set the 4th boundary id to 1 to apply dirichlet BC
  triangulation.refine_global(2);

  for (const auto &cell : dof_handler.active_cell_iterators())
  {
    cell->set_refine_flag(RefinementCase<3>::cut_z);
  }

  triangulation.execute_coarsening_and_refinement();
  
    for (const auto &cell : dof_handler.active_cell_iterators())
  {
    cell->set_refine_flag(RefinementCase<3>::cut_z);
  }


  triangulation.execute_coarsening_and_refinement();
  
  std::ofstream out("grid-1.vtk");
  GridOut       grid_out;
  grid_out.write_vtk(triangulation, out);
  std::cout << "Grid written to grid-1.vtk" << std::endl;
  std::cout << "Number of active cells = " << triangulation.n_active_cells() << std::endl ;
 
}

void Nedlec::setup_system()

{   

    dof_handler.distribute_dofs(fe);


    constraints.clear();

    PerfConductor perfBC;
    //Apply perfect conductor BC on the walls with ID0 and for the real part of the eqaution
    VectorTools::project_boundary_values_curl_conforming_l2(
        dof_handler,
        0,
        perfBC,
        0,
        constraints,
        StaticMappingQ1<3>::mapping);

   //Apply perfect conductor BC on the walls with ID0 and for the imaginary part of the eqaution
      VectorTools::project_boundary_values_curl_conforming_l2(
        dof_handler,
        3,
        perfBC,
        0,
        constraints,
        StaticMappingQ1<3>::mapping);

 std::cout << "PEC was applied" << std::endl; 

    Inlet InletBC;
//Apply inlet  BC on the walls with ID1 and for the real part of the eqaution
    VectorTools::project_boundary_values_curl_conforming_l2(
        dof_handler,
        0,
        InletBC,
        1,
        constraints,
        StaticMappingQ1<3>::mapping);

//Apply inlet  BC on the walls with ID1 and for the complex part of the eqaution
        VectorTools::project_boundary_values_curl_conforming_l2(
        dof_handler,
        3,
        InletBC,
        1,
        constraints,
        StaticMappingQ1<3>::mapping);

     std::cout << "Inlet BC was applied" << std::endl; 

    constraints.close();


    DynamicSparsityPattern sp(dof_handler.n_dofs(),dof_handler.n_dofs());
    DoFTools::make_sparsity_pattern(dof_handler,
                                    sp,
                                    constraints,
                                    false);

    sparsity_pattern.copy_from(sp);
    system_matrix.reinit(sparsity_pattern);
    solution.reinit(dof_handler.n_dofs());
    system_rhs.reinit(dof_handler.n_dofs());


  //can only print psarsity pattern for small meshes. St golbal refinement to 2 when using this
   std::ofstream out("sparsity_pattern.svg");
   sparsity_pattern.print_svg(out);  

  std::cout << "Number of degress of freedom = " << dof_handler.n_dofs() << std::endl ;



   
}

void Nedlec::assemble_system()
{
  QGauss<3> quad(1*1+1); //Recommended qguass but not sure
  FEValues<3>     fe_values(fe, quad,
                                 update_values | update_gradients |
                                   update_quadrature_points |
                                   update_JxW_values);

  //extractors for real and imaginary part
  const FEValuesExtractors::Vector realpart(0);
  const FEValuesExtractors::Vector imagpart(3);

 

  const unsigned int dofs_per_cell = fe.dofs_per_cell;
  std::cout<< "Dofs per cell = " << dofs_per_cell << std::endl;
  FullMatrix<double> cell_matrix(dofs_per_cell, dofs_per_cell);
  Vector<double>     cell_rhs(dofs_per_cell);

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

  for (const auto &cell : dof_handler.active_cell_iterators())
  {
      fe_values.reinit(cell);
      cell_matrix = 0;
      cell_rhs    = 0;

      for (const unsigned int q: fe_values.quadrature_point_indices())
      {
               for (unsigned int i = 0; i < dofs_per_cell; ++i)
              {
                for (unsigned int j = 0; j < dofs_per_cell; ++j)
                  {
                    cell_matrix(i, j) +=
                      (fe_values[realpart].curl(i, q) * fe_values[realpart].curl(j, q)  //curl u curl v
                      -
                       1757*fe_values[realpart].value(i, q) *    fe_values[realpart].value(j, q)  //u v
                        +
                        fe_values[imagpart].curl(i, q) * fe_values[imagpart].curl(j, q)  //curl u curl v
                     -
                        1757*fe_values[imagpart].value(i, q) *    fe_values[imagpart].value(j, q)  //u v

                       ) 
                      *
                      fe_values.JxW(q) ;
                      

                  }
              }
    
      }


    cell->get_dof_indices(local_dof_indices);
    //Apply BC 
    constraints.distribute_local_to_global(
    cell_matrix, cell_rhs, local_dof_indices, system_matrix, system_rhs);

  }

  std::cout<<"System Assemble complete" << std::endl;
  


}

 void Nedlec::solve()
 {  std::cout<< "Solving" << std::endl ;
   
   SparseDirectUMFPACK direct;
   direct.initialize(system_matrix);
   direct.vmult(solution, system_rhs);

   constraints.distribute(solution);

   std::cout << "Soution ended" <<std::endl; 
   
  }

 void Nedlec::output_results() const
{
  std::vector<std::string> solution_names(3, "E_real");
  for(int i=0; i<3; i++)
  solution_names.emplace_back("E_imag");

   std::vector<DataComponentInterpretation::DataComponentInterpretation>
     interpretation(6,
                    DataComponentInterpretation::component_is_part_of_vector);

   interpretation[3]=(DataComponentInterpretation::component_is_part_of_vector);
  DataOut<3> data_out;
  data_out.add_data_vector(dof_handler,
                           solution,
                           solution_names,
                           interpretation);
  data_out.build_patches();
  std::ofstream output("solution.vtu");
  data_out.write_vtu(output);


  // DataOut<3> data_out;
  // data_out.attach_dof_handler(dof_handler);
  // data_out.add_data_vector(solution, "solution");
  // data_out.build_patches();
  // std::ofstream output("solution.vtk");
  // data_out.write_vtk(output);

}


void Nedlec::run()
{
  make_grid() ; 
  setup_system() ; 
  assemble_system();
  
  solve();
  output_results();
}


int main()
{ 
  Nedlec  my_nedlec; 
  my_nedlec.run(); 
  
}

Reply via email to