modifying of only one component of solution

224 views
Skip to first unread message

Marek Čapek

unread,
Aug 27, 2017, 1:53:25 PM8/27/17
to deal.II User Group
Hello,
I solve phase-field equation, i.e. Cahn-Hilliard equation.
I have the following finite elements  for the phase field and the chemical potential
components of solution

    FESystem<dim> fe_phase;

in the initialization list of constructor:

fe_phase (FE_Q<dim> (degree), 2)

(The first component - phase field, the second one - chemical potential)


I am getting the solution in

  PetscWrappers::MPI::Vector solution_phase_n;

I am interested in modifying the vector of the solution - I
want to cut the undershoots and overshoots in phase-field component
of the solution. Namely I have values of phase field like -1.005 or 1.005,
however they should be only in <-1,1>.
Is it possible to modify only the relevant parts of the
PetscWrappers::MPI::Vector ?

I want to get  afterwards the solution values and gradients using

fe_v_phase.get_function_values                 
fe_v_phase.get_function_gradients

to get the "repaired" values and gradients of phase field.

Or should I split the system, ie. firstly solve for the phase
field, then modify the phase field solution and afterwards
solve for chemical potential?

Thank You


Marek


Wolfgang Bangerth

unread,
Aug 28, 2017, 12:55:30 PM8/28/17
to dea...@googlegroups.com
On 08/27/2017 11:53 AM, Marek Čapek wrote:
>
>
> I am getting the solution in
>
> PetscWrappers::MPI::Vector solution_phase_n;
>
> I am interested in modifying the vector of the solution - I
> want to cut the undershoots and overshoots in phase-field component
> of the solution. Namely I have values of phase field like -1.005 or 1.005,
> however they should be only in <-1,1>.
> Is it possible to modify only the relevant parts of the
> PetscWrappers::MPI::Vector ?
>
> I want to get afterwards the solution values and gradients using
>
> fe_v_phase.get_function_values
> fe_v_phase.get_function_gradients
>
> to get the "repaired" values and gradients of phase field.
>
> Or should I split the system, ie. firstly solve for the phase
> field, then modify the phase field solution and afterwards
> solve for chemical potential?

The easiest solution is probably to use a
PETScWrappers::MPI::BlockVector with two blocks that corresponds to the
two variables. You would then just apply the operation on one of the
blocks. This may require you to also substructure your matrix into
blocks, but all of your solvers should continue to work. In particular,
just because your matrix is substructured does not imply that you have
to solve one equation at the time (though you can).

The alternative is to figure out which elements of your vector
correspond to the phase-field. Namespace DoFTools has functions that
give you a mask or IndexSet that indicates which variables belong to one
particular vector component. You would then just operate on those vector
elements that are listed in the mask/IndexSet.

Best
W.


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

Marek Čapek

unread,
Feb 5, 2018, 1:58:23 PM2/5/18
to deal.II User Group
Hi,
I have Cahn-Hilliard system - scalar equation for
phase field and chemical potential. I tried to modify only
the phase field part of solution in distributed code like
step-40:

template<int dim>
void Main<dim>::postprocess_solution(){

    nsSystem.computing_timer.enter_subsection("Solution postprocessing");



    std::vector<bool> selected_dofs(dofHandlerCrate.dof_handler_phase->n_locally_owned_dofs());


//here I choose to modify only the phase-field part of solution
    std::vector<bool> component_mask_vec = {true,false};

    ComponentMask component_mask(component_mask_vec);

//modified_phase_solution is the nonghosted trilinoswrappers mpi vector
    modified_phase_solution.reinit (dofHandlerCrate.dof_handler_phase->locally_owned_dofs(), MPI_COMM_WORLD);

    IndexSet locally_owned =dofHandlerCrate.dof_handler_phase->locally_owned_dofs();
    DoFTools::extract_dofs(*dofHandlerCrate.dof_handler_phase,component_mask,selected_dofs);

    for (types::global_dof_index i=0; i<dofHandlerCrate.dof_handler_phase->n_locally_owned_dofs(); ++i){
        int global_index=locally_owned.nth_index_in_set(i);
        double value = globalCrateCurrent.solution_phase_n(global_index);

    if(selected_dofs[i]==true){
                        //modify if it is phase field part of solution
             modified_phase_solution(global_index)=truncate_conc(value);
         }
    else
                       //else let it be
          modified_phase_solution(global_index)=value;

    }

    modified_phase_solution.compress(VectorOperation::insert);

//globalCrateCurrent.solution_phase_n is ghosted vector of solution
    globalCrateCurrent.solution_phase_n=modified_phase_solution;

    nsSystem.computing_timer.leave_subsection("Solution postprocessing");

}

However the solution does not get modified. It appears to me, that selected_dofs vector
is filled with false values.Maybe I use wrongly the function
DoFTools::extract_dofs for the distributed case.
Could You please provide me guidance, how to use it properly?

Thanks

Marek

Dne pondělí 28. srpna 2017 18:55:30 UTC+2 Wolfgang Bangerth napsal(a):

Marek Čapek

unread,
Feb 7, 2018, 5:13:07 PM2/7/18
to deal.II User Group
Hi,
the source code of the method

void Main<dim>::postprocess_solution(){

was correct.
The function

truncate_conc(double conc )

had a faulty implementation.
It was do-nothing implementation
on argument.


Greets

Marek




Dne pondělí 5. února 2018 19:58:23 UTC+1 Marek Čapek napsal(a):
Reply all
Reply to author
Forward
0 new messages