Hello everybody,

I'm using the deal.ii library for assembling a FE-system of equations of 
the heat equation. I'm using a locally refined grid with *hanging nodes*. 
The deal.ii library is only used for assembling since I want to use the 
system of equations as optimization-constraints within a PDE-constrained 
optimization problem. The drawback of this approach is that I cannot make 
use of the deal-functions handling hanging nodes. This is due to the fact 
that the hanging-node-constraints have to be considered within the system 
of equations and cannot be applied afterwards with the 
ConstraintMatrix::distribute(solution) function.
The upside is, the system of equation needn't to be positive definite, 
since the NLP-solver I'm using handles every kind of equations. So, I 
decided to integrate the hanging-node-constraints into the system of 
equations by myself. From my point of view this is no big deal: I deleted 
all rows considering hanging nodes of the system matrix and right hand side 
and added the hanging-node-constraints instead.
For reasons of verification I solved this system of equations with a direct 
solver and everything looked fine. But when I compared it to the solution 
of the system of equations handling the hanging nodes with the 
deal-functions, I recognized a difference between both solutions. So I went 
on debugging by making the problem as small as possible: I changed the 
dimension to 2D and generated a minimal grid:

9 --10 -- 2 ------ 3
|    |    |        |
6 -- 7 -- 8        |
|    |    |        |
4 -- 5 -- 0 ------ 1

having only one hanging node (8). Also the system of equations became very 
easy:

(1      )     (1  )
( 1     )     (2  )
(  ...  ) x = (...)
(    1  )     (8  ) <-(constrained by node 0 and 2)
(     1 )     (9  )
(      1)     (10 )

When I used my code:

void setup_system () {
    dof_handler.distribute_dofs ( fe );

    solution.reinit ( dof_handler.n_dofs() );
    system_rhs.reinit ( dof_handler.n_dofs() );  

    constraints.clear ();
    DoFTools::make_hanging_node_constraints ( dof_handler,
            constraints );
    constraints.close ();

    DynamicSparsityPattern dsp ( dof_handler.n_dofs() );
    DoFTools::make_sparsity_pattern ( dof_handler,
                                      dsp,
                                      constraints,
                                      /*keep_constrained_dofs = */ true );

    sparsity_pattern.copy_from ( dsp );
    system_matrix.reinit ( sparsity_pattern );
}

void assemble_system () {
    FullMatrix<double> cell_matrix ( 1, 1 );
    cell_matrix.set(0, 0, 1.0);
    std::vector<types::global_dof_index> local_dof_indices ( 1 );
    for (unsigned int i=0; i<dof_handler.n_dofs(); i++) {
        local_dof_indices[0]= i;
        user_distribute_local_to_global(cell_matrix, local_dof_indices, 
system_matrix);
        user_distribute_local_to_global(i, (double) i, system_rhs);
    }
    
    constrain_system_matrix();
}

void user_distribute_local_to_global(FullMatrix<double> cell_matrix,
            std::vector<types::global_dof_index> local_dof_indices, 
SparseMatrix<double> &global_matrix){

    for ( unsigned int i = 0; i < cell_matrix.m(); i++ ) {
        for ( unsigned int j = 0; j < cell_matrix.n(); j++ ) {
            if ( !constraints.is_constrained ( local_dof_indices[i] ) ) {
                global_matrix.set ( local_dof_indices[i], local_dof_indices[
j],
                                     global_matrix.el ( local_dof_indices[i
], local_dof_indices[j] )
                                        + cell_matrix( i, j ) );
            }
        }
    }
}

void user_distribute_local_to_global(unsigned int index, double value, 
Vector<double> &global_vec){

    if ( !constraints.is_constrained( index ) ) {
        global_vec[index]=value;
    }
    
}

void constrain_system_matrix() {
    const std::vector< std::pair< types::global_dof_index, double > > * 
constr_pair_ptr;    
    for ( unsigned int i=0; i<dof_handler.n_dofs(); i++ ) {
        constr_pair_ptr=constraints.get_constraint_entries ( i );
        if ( constr_pair_ptr ) {
            for ( unsigned int j=0; j< ( *constr_pair_ptr ).size(); j++ ) {
                system_matrix.set ( i, ( *constr_pair_ptr ) [j].first
                            ,-1.0*( *constr_pair_ptr ) [j].second );
            }
            system_matrix.set(i,i, 1.);
        }
    }
}

- in my humble opinion - everything went fine. The solution is as expected:

x=(0, 1, 2, 3, 4, 5, 6, 7, 1, 9, 10)
                           ^------------ (constrained by node 0 and 2: 0.5 * 
0 + 0.5 * 2 = 1)

But when I used the deal-functions:

void setup_system () {
    dof_handler.distribute_dofs ( fe );

    solution.reinit ( dof_handler.n_dofs() );
    system_rhs.reinit ( dof_handler.n_dofs() );  

    constraints.clear ();
    DoFTools::make_hanging_node_constraints ( dof_handler,
            constraints );
    constraints.close ();

    DynamicSparsityPattern dsp ( dof_handler.n_dofs() );
    DoFTools::make_sparsity_pattern ( dof_handler,
                                      dsp,
                                      constraints,
                                      /*keep_constrained_dofs = */ true );

    sparsity_pattern.copy_from ( dsp );
    system_matrix.reinit ( sparsity_pattern );
}


void assemble_system () {
    FullMatrix<double> cell_matrix ( 1, 1 );
    cell_matrix.set(0, 0, 1.0);
    std::vector<types::global_dof_index> local_dof_indices ( 1 );
    for (unsigned int i=0; i<dof_handler.n_dofs(); i++) {
        local_dof_indices[0]= i;
        constraints.distribute_local_to_global ( cell_matrix,
                                                 local_dof_indices,
                                                 system_matrix);
        constraints.distribute_local_to_global ( i,
                                                 (double) i,
                                                 system_rhs );
    }
}

void solve () {
    
    //...

    constraints.distribute ( solution );
}

the solution confused me:

x=(2.33333, 1, 4.33333, 3, 4, 5, 6, 7, 3.33333, 9, 10)


Also the system of equations in the deal-functions-case looks wired:

(1.25   0.25       )     (4  )
(     1            )     (1  )
(0.25   1.25       )     (6  )
(            1     )     (3  )
(             ...  ) x = (...)
(               1  )     (0  )
(                1 )     (9  )
(                 1)     (10 )

So, what am I doing wrong? Am I using the deal-functions in a wrong manner? 
In my humble opinion the way I'm treating the hanging node is correct. But 
the fact that my results differ crucially from what deal is doing makes me 
doubtful.

I'd be pleased about any help. Sorry for the long post.

Thanks a lot in advance,
Heinrich


-- 
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].
For more options, visit https://groups.google.com/d/optout.

Reply via email to