Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed extract_dofs so that it works in parallel #8302

Merged
merged 14 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 12 additions & 27 deletions include/deal.II/dofs/dof_tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -1346,22 +1346,16 @@ namespace DoFTools
* corresponds to a vector component selected by the mask above. The size
* of this array must equal DoFHandler::n_locally_owned_dofs(), which for
* sequential computations of course equals DoFHandler::n_dofs(). The
* previous contents of this array are overwritten.
* previous contents of this array are overwritten. Note that the resulting
* vector just holds the locally owned extracted degrees of freedom, which
* first have to be mapped to the global degrees of freedom, to correspond
* with them.
*/
template <int dim, int spacedim>
void
extract_dofs(const DoFHandler<dim, spacedim> &dof_handler,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs);

/**
* The same function as above, but for a hp::DoFHandler.
*/
template <int dim, int spacedim>
template <int dim, int spacedim, typename DoFHandlerType>
void
extract_dofs(const hp::DoFHandler<dim, spacedim> &dof_handler,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs);
extract_dofs(const DoFHandlerType &dof_handler,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs);

/**
* This function is the equivalent to the DoFTools::extract_dofs() functions
Expand All @@ -1387,20 +1381,11 @@ namespace DoFTools
* sequential computations of course equals DoFHandler::n_dofs(). The
* previous contents of this array are overwritten.
*/
template <int dim, int spacedim>
void
extract_dofs(const DoFHandler<dim, spacedim> &dof_handler,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs);

/**
* The same function as above, but for a hp::DoFHandler.
*/
template <int dim, int spacedim>
template <int dim, int spacedim, typename DoFHandlerType>
void
extract_dofs(const hp::DoFHandler<dim, spacedim> &dof_handler,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs);
extract_dofs(const DoFHandlerType &dof_handler,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs);

/**
* Do the same thing as the corresponding extract_dofs() function for one
Expand Down
94 changes: 18 additions & 76 deletions source/dofs/dof_tools.cc
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,14 @@ namespace DoFTools



template <int dim, int spacedim>
template <int dim, int spacedim, typename DoFHandlerType>
void
extract_dofs(const DoFHandler<dim, spacedim> &dof,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs)
extract_dofs(const DoFHandlerType &dof,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs)
{
const FiniteElement<dim, spacedim> &fe = dof.get_fe();
(void)fe;

Assert(component_mask.represents_n_components(fe.n_components()),
Assert(component_mask.represents_n_components(
dof.get_fe_collection().n_components()),
ExcMessage(
"The given component mask is not sized correctly to represent the "
"components of the given finite element."));
Expand All @@ -416,13 +414,15 @@ namespace DoFTools

// two special cases: no component is selected, and all components are
// selected; both rather stupid, but easy to catch
if (component_mask.n_selected_components(n_components(dof)) == 0)
if (component_mask.n_selected_components(
dof.get_fe_collection().n_components()) == 0)
{
std::fill_n(selected_dofs.begin(), dof.n_locally_owned_dofs(), false);
return;
}
else if (component_mask.n_selected_components(n_components(dof)) ==
n_components(dof))
else if (component_mask.n_selected_components(
dof.get_fe_collection().n_components()) ==
dof.get_fe_collection().n_components())
{
std::fill_n(selected_dofs.begin(), dof.n_locally_owned_dofs(), true);
return;
Expand All @@ -433,7 +433,7 @@ namespace DoFTools
std::fill_n(selected_dofs.begin(), dof.n_locally_owned_dofs(), false);

// get the component association of each DoF and then select the ones
// that match the given set of blocks
// that match the given set of components
std::vector<unsigned char> dofs_by_component(dof.n_locally_owned_dofs());
internal::get_component_association(dof, component_mask, dofs_by_component);

Expand All @@ -443,74 +443,16 @@ namespace DoFTools
}


// TODO: Unify the following two functions with the non-hp case

template <int dim, int spacedim>
void
extract_dofs(const hp::DoFHandler<dim, spacedim> &dof,
const ComponentMask & component_mask,
std::vector<bool> & selected_dofs)
{
const FiniteElement<dim, spacedim> &fe = dof.begin_active()->get_fe();
(void)fe;

Assert(component_mask.represents_n_components(fe.n_components()),
ExcMessage(
"The given component mask is not sized correctly to represent the "
"components of the given finite element."));
Assert(selected_dofs.size() == dof.n_dofs(),
ExcDimensionMismatch(selected_dofs.size(), dof.n_dofs()));

// two special cases: no component is selected, and all components are
// selected; both rather stupid, but easy to catch
if (component_mask.n_selected_components(n_components(dof)) == 0)
{
std::fill_n(selected_dofs.begin(), dof.n_dofs(), false);
return;
}
else if (component_mask.n_selected_components(n_components(dof)) ==
n_components(dof))
{
std::fill_n(selected_dofs.begin(), dof.n_dofs(), true);
return;
}


// preset all values by false
std::fill_n(selected_dofs.begin(), dof.n_dofs(), false);

// get the component association of each DoF and then select the ones
// that match the given set of components
std::vector<unsigned char> dofs_by_component(dof.n_dofs());
internal::get_component_association(dof, component_mask, dofs_by_component);

for (types::global_dof_index i = 0; i < dof.n_dofs(); ++i)
if (component_mask[dofs_by_component[i]] == true)
selected_dofs[i] = true;
}



template <int dim, int spacedim>
void
extract_dofs(const DoFHandler<dim, spacedim> &dof,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs)
{
// simply forward to the function that works based on a component mask
extract_dofs(dof, dof.get_fe().component_mask(block_mask), selected_dofs);
}



template <int dim, int spacedim>
template <int dim, int spacedim, typename DoFHandlerType>
void
extract_dofs(const hp::DoFHandler<dim, spacedim> &dof,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs)
extract_dofs(const DoFHandlerType &dof,
const BlockMask & block_mask,
std::vector<bool> & selected_dofs)
{
// simply forward to the function that works based on a component mask
extract_dofs(dof, dof.get_fe().component_mask(block_mask), selected_dofs);
extract_dofs<dim, spacedim, DoFHandlerType>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use DoFHandlerType::dimension and DoFHandlerType::space_dimension here and in the other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this valuable hint! Indeed this makes life so much easier.
I have (again...) a new proposal now and could merge all the ideas I had at the beginning. Let me explain in a nutshell what I tried to achieve and I begin with the testsuite (and I like it really very much):
Basically I splitted the 12a test into a dof_tools_common_parallel.h file, which is similar to the non parallel version, just with the parallel triangulation and not using (the non supported) 1d elements. So basically if someone wants to make a test for MPI in the future, he can just include this file, similar to dof_tools_common.
Further I made the check_this() template dependent of the DoFHandler type - also this means to change many code lines. The benefit is, that dof_cools_common.h can now test for both DoFHandlers (hp and not hp) without code deduplicating. I demonstrate this with the updated test dof_tools_12: it's basically the same code as before, but now tests against the normal DoFHandler and the hp::DoFHandler. The other tests could just do the same, if every function implemented the full functionality for DoFHandler and hp::DoFHandler. Until this they just have to include the dof_tools_fake_hp.inst.in so that basically just the normal DoFHandler is being tested. So in my opinion this will make testing in the future easier, when more hp::DoFHandler stuff gets merged (maybe some tests already work with the hp::DoFHandler, I didn't really look into this).

Now to the extract_dofs() function: as you proposed I changed it, that it doesn't depend on dim or spacedim template arguments and therefore auto deduction works as expected.

I still feature the problem with the different output files on my local machine and some reference output files, what I describe above - I really don't know where the different outputs come from and I don't know, why the whitespaces aren't there in the reference output files. This could be a problem with the output file of test 12a, since it includes the whitespaces in the FESystems, also the updated test 12 output files from my system include these whitespaces.
Greetings,
Mathias

dof, dof.get_fe_collection().component_mask(block_mask), selected_dofs);
}


Expand Down
16 changes: 12 additions & 4 deletions source/dofs/dof_tools.inst.in
Original file line number Diff line number Diff line change
Expand Up @@ -689,25 +689,33 @@ for (deal_II_dimension : DIMENSIONS; deal_II_space_dimension : DIMENSIONS)
&patch);

template void
extract_dofs<deal_II_dimension, deal_II_space_dimension>(
extract_dofs<deal_II_dimension,
deal_II_space_dimension,
DoFHandler<deal_II_dimension, deal_II_space_dimension>>(
const DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
const ComponentMask &,
std::vector<bool> &);

template void
extract_dofs<deal_II_dimension, deal_II_space_dimension>(
extract_dofs<deal_II_dimension,
deal_II_space_dimension,
DoFHandler<deal_II_dimension, deal_II_space_dimension>>(
const DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
const BlockMask &,
std::vector<bool> &);

template void
extract_dofs<deal_II_dimension, deal_II_space_dimension>(
extract_dofs<deal_II_dimension,
deal_II_space_dimension,
hp::DoFHandler<deal_II_dimension, deal_II_space_dimension>>(
const hp::DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
const ComponentMask &,
std::vector<bool> &);

template void
extract_dofs<deal_II_dimension, deal_II_space_dimension>(
extract_dofs<deal_II_dimension,
deal_II_space_dimension,
hp::DoFHandler<deal_II_dimension, deal_II_space_dimension>>(
const hp::DoFHandler<deal_II_dimension, deal_II_space_dimension> &,
const BlockMask &,
std::vector<bool> &);
Expand Down
3 changes: 2 additions & 1 deletion source/dofs/dof_tools_constraints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3133,7 +3133,8 @@ namespace DoFTools
{
std::vector<bool> mask(coarse_grid.get_fe(0).n_components(), false);
mask[coarse_component] = true;
extract_dofs(coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
extract_dofs<dim, spacedim, DoFHandler<dim, spacedim>>(
coarse_grid, ComponentMask(mask), coarse_dof_is_parameter);
}

// now we know that the weights in each row constitute a constraint. enter
Expand Down
8 changes: 6 additions & 2 deletions tests/dofs/dof_tools_12.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,15 @@ check_this(const DoFHandler<dim> &dof_handler)

// only select first component
mask[0] = true;
DoFTools::extract_dofs(dof_handler, ComponentMask(mask), selected_dofs);
DoFTools::extract_dofs<dim, dim, DoFHandler<dim>>(dof_handler,
ComponentMask(mask),
selected_dofs);
output_bool_vector(selected_dofs);

// also select last component
mask.back() = true;
DoFTools::extract_dofs(dof_handler, ComponentMask(mask), selected_dofs);
DoFTools::extract_dofs<dim, dim, DoFHandler<dim>>(dof_handler,
ComponentMask(mask),
selected_dofs);
output_bool_vector(selected_dofs);
}