From 16c7d489550cb24b9262cbf6146b161e2dd3944b Mon Sep 17 00:00:00 2001 From: turcksin Date: Wed, 9 Oct 2013 21:34:07 +0000 Subject: [PATCH] Replace Threads by WorkStream in dof_tools_constraints.cc git-svn-id: https://svn.dealii.org/trunk@31191 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/source/dofs/dof_tools_constraints.cc | 281 +++++++++++-------- 1 file changed, 161 insertions(+), 120 deletions(-) diff --git a/deal.II/source/dofs/dof_tools_constraints.cc b/deal.II/source/dofs/dof_tools_constraints.cc index d0f497919b..9dabf622e9 100644 --- a/deal.II/source/dofs/dof_tools_constraints.cc +++ b/deal.II/source/dofs/dof_tools_constraints.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -2118,29 +2119,67 @@ namespace DoFTools namespace internal { + namespace Assembler + { + struct Scratch + { + Scratch() {}; + }; + + + template + struct CopyData + { + CopyData(unsigned int const &coarse_component, + std::vector const &weight_mapping); + + CopyData(CopyData const &data); + + unsigned int coarse_component; + unsigned int dofs_per_cell; + std::vector parameter_dof_indices; + std::vector weight_mapping; + std::vector > global_parameter_representation; + }; + + + + template + CopyData::CopyData(unsigned int const &coarse_component, + std::vector const &weight_mapping) : + coarse_component(coarse_component), + weight_mapping(weight_mapping) + {} + + + + template + CopyData::CopyData(CopyData const &data) : + coarse_component(data.coarse_component), + dofs_per_cell(data.dofs_per_cell), + parameter_dof_indices(data.parameter_dof_indices), + weight_mapping(data.weight_mapping), + global_parameter_representation(data.global_parameter_representation) + {} + } + namespace { /** * This is a function that is called by the _2 function and that - * operates on a range of cells only. It is used to split up the - * whole range of cells into chunks which are then worked on in - * parallel, if multithreading is available. + * operates on one cell only. It is worked in parallel if + * multhithreading is available. */ template - void - compute_intergrid_weights_3 ( - const dealii::DoFHandler &coarse_grid, - const unsigned int coarse_component, - const InterGridMap > &coarse_to_fine_grid_map, - const std::vector > ¶meter_dofs, - const std::vector &weight_mapping, - std::vector > &weights, - const typename dealii::DoFHandler::active_cell_iterator &begin, - const typename dealii::DoFHandler::active_cell_iterator &end) - { - // aliases to the finite elements used by the dof handlers: - const FiniteElement &coarse_fe = coarse_grid.get_fe(); + void compute_intergrid_weights_3 ( + typename dealii::DoFHandler::active_cell_iterator const &cell, + Assembler::Scratch const &scratch, + Assembler::CopyData ©_data, + FiniteElement const &coarse_fe, + InterGridMap > const &coarse_to_fine_grid_map, + std::vector > const ¶meter_dofs) + { // for each cell on the parameter grid: find out which degrees of // freedom on the fine grid correspond in which way to the degrees // of freedom on the parameter grid @@ -2187,84 +2226,103 @@ namespace DoFTools // vector to hold the representation of a single degree of freedom // on the coarse grid (for the selected fe) on the fine grid - const types::global_dof_index n_fine_dofs = weight_mapping.size(); - dealii::Vector global_parameter_representation (n_fine_dofs); + const types::global_dof_index n_fine_dofs = copy_data.weight_mapping.size(); + + copy_data.dofs_per_cell = coarse_fe.dofs_per_cell; + copy_data.parameter_dof_indices.resize(copy_data.dofs_per_cell); + + + // get the global indices of the parameter dofs on this + // parameter grid cell + cell->get_dof_indices (copy_data.parameter_dof_indices); + + // loop over all dofs on this cell and check whether they are + // interesting for us + for (unsigned int local_dof=0; local_dof (n_fine_dofs)); + + // distribute the representation of + // @p{local_parameter_dof} on the parameter grid cell + // @p{cell} to the global data space + coarse_to_fine_grid_map[cell]-> + set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof], + copy_data.global_parameter_representation.back()); + } + } - typename dealii::DoFHandler::active_cell_iterator cell; - std::vector parameter_dof_indices (coarse_fe.dofs_per_cell); - for (cell=begin; cell!=end; ++cell) + + /** + * This is a function that is called by the _2 function and that + * operates on one cell only. It is worked in parallel if + * multhithreading is available. + */ + template + void copy_intergrid_weights_3(Assembler::CopyData const ©_data, + FiniteElement const &coarse_fe, + std::vector > &weights) + { + unsigned int pos(0); + for (unsigned int local_dof=0; local_dofget_dof_indices (parameter_dof_indices); - - // loop over all dofs on this cell and check whether they are - // interesting for us - for (unsigned int local_dof=0; - local_dof - set_dof_values_by_interpolation (parameter_dofs[local_parameter_dof], - global_parameter_representation); - // now that we've got the global representation of each - // parameter dof, we've only got to clobber the non-zero - // entries in that vector and store the result - // - // what we have learned: if entry @p{i} of the global - // vector holds the value @p{v[i]}, then this is the - // weight with which the present dof contributes to - // @p{i}. there may be several such @p{i}s and their - // weights' sum should be one. Then, @p{v[i]} should be - // equal to @p{\sum_j w_{ij} p[j]} with @p{p[j]} be the - // values of the degrees of freedom on the coarse grid. - // we can thus compute constraints which link the degrees - // of freedom @p{v[i]} on the fine grid to those on the - // coarse grid, @p{p[j]}. Now to use these as real - // constraints, rather than as additional equations, we - // have to identify representants among the @p{i} for - // each @p{j}. this will be done by simply taking the - // first @p{i} for which @p{w_{ij}==1}. - // - // guard modification of the weights array by a Mutex. - // since it should happen rather rarely that there are - // several threads operating on different intergrid - // weights, have only one mutex for all of them - static Threads::Mutex mutex; - Threads::Mutex::ScopedLock lock (mutex); - for (types::global_dof_index i=0; i void compute_intergrid_weights_2 ( - const dealii::DoFHandler &coarse_grid, - const unsigned int coarse_component, + const dealii::DoFHandler &coarse_grid, + const unsigned int coarse_component, const InterGridMap > &coarse_to_fine_grid_map, - const std::vector > ¶meter_dofs, - const std::vector &weight_mapping, + const std::vector > ¶meter_dofs, + const std::vector &weight_mapping, std::vector > &weights) { - // simply distribute the range of cells to different threads - typedef typename dealii::DoFHandler::active_cell_iterator active_cell_iterator; - std::vector > - cell_intervals = Threads::split_range (coarse_grid.begin_active(), - coarse_grid.end(), - multithread_info.n_threads()); - - // TODO: use WorkStream here - - Threads::TaskGroup<> tasks; - void (*fun_ptr) (const dealii::DoFHandler &, - const unsigned int , - const InterGridMap > &, - const std::vector > &, - const std::vector &, - std::vector > &, - const typename dealii::DoFHandler::active_cell_iterator &, - const typename dealii::DoFHandler::active_cell_iterator &) - = &compute_intergrid_weights_3; - for (unsigned int i=0; i copy_data(coarse_component,weight_mapping); + + WorkStream::run(coarse_grid.begin_active(),coarse_grid.end(), + static_cast + ::active_cell_iterator const &,Assembler::Scratch const &,Assembler::CopyData + &)> > (std_cxx1x::bind(compute_intergrid_weights_3,std_cxx1x::_1,std_cxx1x::_2, + std_cxx1x::_3,std_cxx1x::cref(coarse_grid.get_fe()),std_cxx1x::cref(coarse_to_fine_grid_map), + std_cxx1x::cref(parameter_dofs))), static_cast const &)> > (std_cxx1x::bind(copy_intergrid_weights_3, + std_cxx1x::_1,std_cxx1x::cref(coarse_grid.get_fe()),std_cxx1x::ref(weights))),scratch, + copy_data); } -- 2.39.5