On 6/26/19 3:59 AM, Alexander wrote:
> indeed, this should be possible to do it that way. Would you mind putting an 
> example to the mentioned github issue? I might give it a thought in the 
> background if I see more details.

OK, attached is some code that builds the constraints that correspond to this 
rather esoteric paper (but also one I enjoyed working on the most because it's 
just so weird!):
   https://www.math.colostate.edu/~bangerth/publications/2016-nonconforming.pdf

The paper identifies 3 different ways how one could define hanging node 
constraints for this element, and they are implemented in the function I 
attach. The code is a couple of years old, but if something doesn't compile 
any more, it should be easy to update.

Best
  Wolfgang


-- 
------------------------------------------------------------------------
Wolfgang Bangerth          email:                 bange...@colostate.edu
                            www: http://www.math.colostate.edu/~bangerth/

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/dealii/54c1affc-8964-b910-a137-dc88088355d8%40colostate.edu.
For more options, visit https://groups.google.com/d/optout.
    template <int dim>
    Solver<dim>::LinearSystem::
    LinearSystem (const DoFHandler<dim> &dof_handler)
    {
      hanging_node_constraints.clear ();

      // Implementation of the following code only for the 2d DSSY case
      Assert (dim == 2, ExcNotImplemented());
      Assert (dynamic_cast<const DSSY::FE_DSSY*>(&dof_handler.get_fe()),
              ExcNotImplemented());
      std::vector<types::global_dof_index> face_dof_indices(1);


      // Identify the following strategies outlined at the end of
      // section 4 of the paper:
      //
      // 1)  All averages are equal
      // 2)  Average on coarse face equals average of averages on child
      //     faces
      // 3)  Average jump is zero along child edges
      //
      // The following implements these strategies. select which
      // strategy you want here:
      const unsigned int strategy = 3;

      std::map<types::global_dof_index,std::set<types::global_dof_index> > depends_on;
      
      for (typename DoFHandler<dim>::active_cell_iterator
             cell = dof_handler.begin_active();
           cell != dof_handler.end(); ++cell)
        for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
          if (cell->at_boundary(f) == false)
            // check of the neighbor is refined; if so, we need to
            // treat the constraints on this interface
            if (cell->face(f)->has_children())
              {
                switch (strategy)
                  {
                  case 1:
                  {
                    cell->face(f)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_mother_face = face_dof_indices[0];
                
                    cell->face(f)->child(0)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_0 = face_dof_indices[0];

                    cell->face(f)->child(1)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_1 = face_dof_indices[0];

                    // now enter two constraints that each of the
                    // child face dofs are equal to the parent face
                    // dof
                    hanging_node_constraints.add_line (dof_on_child_face_0);
                    hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                        dof_on_mother_face,
                                                        1);
                    hanging_node_constraints.add_line (dof_on_child_face_1);
                    hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                        dof_on_mother_face,
                                                        1);

                    depends_on[dof_on_child_face_0].insert (dof_on_mother_face);
                    depends_on[dof_on_child_face_1].insert (dof_on_mother_face);

                    break;
                  }

                  case 2:
                  {
                    cell->face(f)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_mother_face = face_dof_indices[0];
                
                    cell->face(f)->child(0)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_0 = face_dof_indices[0];

                    cell->face(f)->child(1)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_1 = face_dof_indices[0];

                    // now enter a constraint that the parent face dof
                    // equals one half of the sum of the child face dofs
                    hanging_node_constraints.add_line (dof_on_mother_face);
                    hanging_node_constraints.add_entry (dof_on_mother_face,
                                                        dof_on_child_face_0, 0.5);
                    hanging_node_constraints.add_entry (dof_on_mother_face,
                                                        dof_on_child_face_1, 0.5);

                    depends_on[dof_on_mother_face].insert (dof_on_child_face_0);
                    depends_on[dof_on_mother_face].insert (dof_on_child_face_1);
                    
                    break;
                  }

                  case 3:
                  {
                    cell->face(f)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_mother_face = face_dof_indices[0];
                
                    cell->face(f)->child(0)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_0 = face_dof_indices[0];

                    cell->face(f)->child(1)->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_child_face_1 = face_dof_indices[0];

                    // for each face, define what the left and right neighbors are
                    static const unsigned int left_neighbor_faces[4]  = { 2, 3, 0, 1 };
                    static const unsigned int right_neighbor_faces[4] = { 3, 2, 1, 0 };

                    cell->face(left_neighbor_faces[f])->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_left_neighbor = face_dof_indices[0];

                    cell->face(right_neighbor_faces[f])->get_dof_indices (face_dof_indices);
                    const types::global_dof_index dof_on_right_neighbor = face_dof_indices[0];
                    
                    
                    // now enter a constraint that child face dofs are
                    // linear combinations of the parent face dofs
                    hanging_node_constraints.add_line (dof_on_child_face_0);
                    hanging_node_constraints.add_line (dof_on_child_face_1);

                    switch (f)
                      {
                      case 0:
                      case 2:
                      {
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_mother_face,
                                                            1);
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_left_neighbor,
                                                            1./4);
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_right_neighbor,
                                                            -1./4);

                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_mother_face,
                                                            1);
                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_left_neighbor,
                                                            -1./4);
                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_right_neighbor,
                                                            +1./4);
                        break;
                      }

                      case 1:
                      case 3:
                      {
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_mother_face,
                                                            1);
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_left_neighbor,
                                                            -1./4);
                        hanging_node_constraints.add_entry (dof_on_child_face_0,
                                                            dof_on_right_neighbor,
                                                            +1./4);

                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_mother_face,
                                                            1);
                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_left_neighbor,
                                                            +1./4);
                        hanging_node_constraints.add_entry (dof_on_child_face_1,
                                                            dof_on_right_neighbor,
                                                            -1./4);
                        break;
                      }
                      
                      default:
                            Assert (false, ExcInternalError());
                      }
                    

                    depends_on[dof_on_child_face_0].insert (dof_on_mother_face);
                    depends_on[dof_on_child_face_0].insert (dof_on_left_neighbor);
                    depends_on[dof_on_child_face_0].insert (dof_on_right_neighbor);

                    depends_on[dof_on_child_face_1].insert (dof_on_mother_face);
                    depends_on[dof_on_child_face_1].insert (dof_on_left_neighbor);
                    depends_on[dof_on_child_face_1].insert (dof_on_right_neighbor);
                    
                    break;
                  }

                  
                  default:
                        Assert (false, ExcNotImplemented());
                  }
              }

      std::map<unsigned int, unsigned int> chain_lengths;
      for (std::map<types::global_dof_index,std::set<types::global_dof_index> >::const_iterator
             p = depends_on.begin();
           p != depends_on.end(); ++p)
        {
          unsigned int chain_length = 0;
          std::set<types::global_dof_index> this_set = p->second;
          while (this_set.empty() == false)
            {
              ++chain_length;

              // for each dependency, check whether it is constrained itself
              std::set<types::global_dof_index> next_set;
              for (std::set<types::global_dof_index>::const_iterator q = this_set.begin();
                   q != this_set.end(); ++q)
                if (depends_on.find(*q) != depends_on.end())
                  next_set.insert (depends_on[*q].begin(),
                                   depends_on[*q].end());

              this_set = next_set;
            }
          
          ++chain_lengths[chain_length];
        }

      std::cout << "N_constraints: " << hanging_node_constraints.n_constraints() << std::endl;
      std::cout << "Chain lengths: ";
      for (std::map<unsigned int, unsigned int>::const_iterator cl = chain_lengths.begin();
           cl != chain_lengths.end(); ++cl)
        std::cout << cl->first << ":" << cl->second << ", ";
      std::cout << std::endl;
      

      DynamicSparsityPattern dsp(dof_handler.n_dofs(), dof_handler.n_dofs());
      DoFTools::make_sparsity_pattern (dof_handler, dsp);

      hanging_node_constraints.close ();
      hanging_node_constraints.condense (dsp);
      sparsity_pattern.copy_from(dsp);

      matrix.reinit (sparsity_pattern);
      rhs.reinit (dof_handler.n_dofs());
    }

Reply via email to