DoFTools::extract_locally_relevant_dofs (dof_handler_1,locally_relevant_dofs_1);
#0 2 libdeal_II.g.8.2.pre.dylib 0x0000000108ad3e26 dealii::TrilinosWrappers::internal::VectorReference::operator double() const 426: 2 libdeal_II.g.8.2.pre.dylib 0x0000000108ad3e26 dealii::TrilinosWrappers::internal::VectorReference::operator double() const #1 3 libdeal_II.g.8.2.pre.dylib 0x00000001070521ff void dealii::FETools::interpolate<2, 2, dealii::DoFHandler, dealii::DoFHandler, dealii::TrilinosWrappers::MPI::Vector, dealii::TrilinosWrappers::MPI::Vector>(dealii::DoFHandler<2, 2> const&, dealii::TrilinosWrappers::MPI::Vector const&, dealii::DoFHandler<2, 2> const&, dealii::ConstraintMatrix const&, dealii::TrilinosWrappers::MPI::Vector&) 3671: 3 libdeal_II.g.8.2.pre.dylib 0x00000001070521ff void dealii::FETools::interpolate<2, 2, dealii::DoFHandler, dealii::DoFHandler, dealii::TrilinosWrappers::MPI::Vector, dealii::TrilinosWrappers::MPI::Vector>(dealii::DoFHandler<2, 2> const&, dealii::TrilinosWrappers::MPI::Vector const&, dealii::DoFHandler<2, 2> const&, dealii::ConstraintMatrix const&, dealii::TrilinosWrappers::MPI::Vector&) #2 4 problem 0x00000001058e8393 main 1063: 4 problem 0x00000001058e8393 main #3 5 libdyld.dylib 0x00007fff90a455fd start 1: 5 libdyld.dylib 0x00007fff90a455fd start #4 6 ??? 0x0000000000000001 0x0 1: 6 ??? 0x0000000000000001 0x0
I will take a look at that soon.
Some information to help with parallel debugging:
https://code.google.com/p/dealii/wiki/FrequentlyAskedQuestions#How_do_I_debug_MPI_programs?
To get your started:
please print the locally owned and locally relevant IndexSets of both
CPUs. Is index 7 in there?
project from locally_relevant(dof_1) to locally_owned(dof_2)p=0owned_1: {[0,2]}relevant_1: {[0,5]}n_dofs_1: 6owned_2: {[0,6]}n_dofs_2: 15p=1owned_1: {[3,5]}relevant_1: {[0,5]}n_dofs_1: 6owned_2: {[7,14]}n_dofs_2: 15
You tried to access element 0 of a distributed vector, but this element is not stored on the current processor. Note: The elements stored on the current processor are within the range 7 through 14
triangulation.locally_owned_subdomain() == numbers::invalid_subdomain_id.
project from locally_relevant(dof_1) to locally_owned(dof_2)p=0owned_1: {[0,2]}relevant_1: {[0,5]}n_dofs_1: 6owned_2: {[0,6]}n_dofs_2: 15
locally owned subdomain_id = 4294967295cells considered for interpolation:id of cell1: 0_0: dofs of cell2: 0 7 1 2 3 8 4 5 6id of cell1: 1_0: dofs of cell2: 7 9 2 10 8 11 12 13 14
p=1owned_1: {[3,5]}relevant_1: {[0,5]}n_dofs_1: 6owned_2: {[7,14]}n_dofs_2: 15
locally owned subdomain_id = 4294967295cells considered for interpolation:id of cell1: 0_0: dofs of cell2: 0 7 1 2 3 8 4 5 6id of cell1: 1_0: dofs of cell2: 7 9 2 10 8 11 12 13 14cells subdomain_ids are: 0 1invalid subdomain id: 4294967295
cell2->get_dof_indices(dofs);
> So interpolation actually visits all cells, be it those owned by current
> processor or not.
Well, you will be running into this problem in many places. You either:
a) implement new functions for interpolate() etc. that take a
subdomainid as an argument and only look at the specified subdomain.
b) change the definition of is_ghost()/is_artificial(). This would
require what I suggested earlier (creating a new type of
Triangulation).
Option a) is certainly easier for now (just add one function), but
there are many places in the library that behave similarly and I don't
like the idea of introducing new variants of many (dozens of?)
functions.
Option b) is actually not that much work, because you don't need to
implement a lot in the new Triangulation class. The only reason to
have it is so that we can detect that this type is used and report
correct values for is_ghost(), is_artificial() etc.. I think the only
thing to implement in the new class is:
1. locally_owned_elements
2. after refining the mesh call partition(), then mark all cells
except own and ghost as artificial by setting the subdomain to
artificial.
>> Option b) is actually not that much work, because you don't need to
>> implement a lot in the new Triangulation class. The only reason to
>> have it is so that we can detect that this type is used and report
>> correct values for is_ghost(), is_artificial() etc.. I think the only
>> thing to implement in the new class is:
>> 1. locally_owned_elements
>
> locally owned cells?
Well, I was thinking about locally_owned_dofs, so some code needs to
be put into DoFHandler.
const IndexSet& DoFHandler< dim, spacedim >::locally_owned_dofs ( const unsigned int level ) const
> I guess in general after calling GridTools::partition_triangulation
> (n_mpi_processes, triangulation)
> user did not decide yet which processor uses which part of triangulation.
> Supposedly this derived Triangulation class could receive an integer in
> constructor
> (in a normal cases - this_mpi_process)
> to be used as an output of triangulation.locally_owned_subdomain() ?
> Is it what you mean?
Correct, my idea is to have a class parallel::shared::Triangulation
that takes an MPI_Comm and internally handles partitioning (mapped to
MPI_rank). If you implement the handling of ghost_cells() correctly
(in the same way we do for distributed::Triangulation), all algorithms
like interpolate() will work correctly.
>> except own and ghost as artificial by setting the subdomain to
>> artificial.
>
> So the same question of effectively marking ghost cells...
Correct. But this would happen once after refinement and not every
time you need to know if a cell is a ghost cell. We do this in
distributed::Tria using:
1. mark all vertices of own cells as "interesting"
2. iterate over all cells that are not ours, if one of the vertices is
"interesting", this is a ghost cell.
3. all other cells are artificial
>> Well, I was thinking about locally_owned_dofs, so some code needs to
>> be put into DoFHandler.
>
>
> I guess you mean to do dynamic casting in
>
> const IndexSet& DoFHandler< dim, spacedim >::locally_owned_dofs ( const
> unsigned int level ) const
>
> and call an internal function (the one I wrote in the other thread) if it is
> of parallel::shared::Triangulation type?
Yes. If you look into DoFHandler this is handled using Policy classes.
Adding another policy requires writing a couple of functions (and they
basically call existing functionality).
[0]PETSC ERROR: Caught signal number 11 SEGV: Segmentation Violation, probably memory access out of range
DoFHandler does different things depending on the kind of
Triangulation used. Take a look at
internal::DoFHandler::Policy::PolicyBase.
Note that we need to do some extra stuff to get the hp::DoFHandler to
work with this.
PETSc takes over the crash handler. You have a SEGV somewhere in your
code. Try to run your code in a debugger (and learning to use valgrind
is also a good idea).
Why did you change the logic for get_dof_indices()? Asking for DoFs of
artificial cells doesn't make much sense, does it? I know that the
information is there, but it might be cleaner to not allow asking for
this information. Do you agree?
dof_tools.cc: leave this Assert in there. It never hurts to have extra checks.
Do you have write access to the deal.II repo? I think it makes sense
to create a branch for this.
> i used valgrind and gdb for my personal projects, but i struggle making Gdb
> debug a shared library (deal.II).
> After stepping in main() of the program, gdb shows nothing for "info
> shared", even though the executable is linked against the debug version of
> deal.II.
> Could you briefly tell your workflow/steps/Gdb settings to debug deal.II
> with Gdb from a command line?
No settings/setup or anything. You run your application linking to
deal.II and you can step into the code as is.
What happens if you step into a deal.II function? Is gdb complaining
about missing source?
Are you building and installing deal.II as an out of source build (I am)?
> yes, i do. Although so far i submitted only to complex branch, supposedly
> the write access is not restricted to operations.
> But in order not to mess things up, i would appreciate if you create a
> branch for this task and i will submit work there.
Will do.
DoFRenumbering::subdomain_wise (dof_handler);(gdb) sProgram received signal SIGSEGV, Segmentation fault.0x0000000102cb7864 in ?? ()
(gdb) bt#0 0x0000000102cb7864 in ?? ()#1 0x00000001175a5e00 in ?? ()#2 0x0000000000000005 in ?? ()#3 0x00007fff5fbfde50 in ?? ()#4 0x00007fff5fbfe630 in ?? ()#5 0xffffffffffffffff in ?? ()#6 0x00007fff5fbfe3f0 in ?? ()#7 0x00007fff5fbfe630 in ?? ()#8 0x0000000000000029 in ?? ()#9 0x0000000f00000002 in ?? ()#10 0x00007fff5fbfe3f0 in ?? ()#11 0x00007fff5fbfe630 in ?? ()#12 0x0000000000000002 in ?? ()#13 0x000000011882dd50 in ?? ()#14 0x000000011882dd60 in ?? ()#15 0x000000011882dd60 in ?? ()#16 0x0000000118d02850 in ?? ()#17 0x00000001175a1000 in ?? ()#18 0x0000000000000000 in ?? ()
for (; cell != endc; ++cell)if ((subdomain_id == numbers::invalid_subdomain_id)||(cell->subdomain_id() == subdomain_id))next_free_dof= Implementation::distribute_dofs_on_cell (dof_handler,cell,next_free_dof);
> Do you propose to derive a policy ParallelShared from Sequential and
> re-implement some functions (which?)?
> If everything have to be changed, then one can derive it from PolicyBase, of
> course, but I hope it is not the case...
Good question. Either you keep track of all cells (and have no
artificial cells), or you need to base your implementation on the
parallel one that is used with p4est that ignores artificial cells and
does some MPI communication. The latter has the advantage that it
scales a lot better with large number of unknowns.
> What i miss is at what point Policy is connected to Triangulation class,
> where does it happen?
Not at all. It gets called by dof_handler.distribute_dofs()
> 3) a policy for shared triangulation is derived from the normal one with a
> couple of tweaks to calculate properly number_cache (locally_owned_dofs,
> locally_relevant_dofs == all_dofs, etc)
>
> hopefully that logic works straight away for hp-refinement and
> FETools::interpolate.
Argh. Now we are running into the next problem: the policy stuff only
works for non-hp DoFHandlers so far. I don't know what the current
status of merging hp::DoFHandler into DoFHandler is. So if you don't
want to take up that task, you need to leave everything as is (no
artificial cells, dofs are known on all machines).
But for large numbers of unknowns, the shared triangulation approach doesn't
work anyway. In fact I think that you should be able to use the sequential
policy without any modification at all, but it might be a nice feature if you
derived your own policy ParallelShared from Sequential that essentially does
the following:
void ParallelShared::distribute_dofs (...) {
this->Sequential::distribute_dofs (...);
DoFRenumbering::subdomain_wise (...);
}
since this is what one typically wants to do right anyway. I guess this is
essentially your strategy #3 in a following email, where you add another
couple of things after the call to subdomain_wise().
(Note that we allocate memory for all DoFs on all cells we locally store, so
not enumerating them just because they are on a subdomain we don't own on the
current processor doesn't actually save any memory.)
> For Sequential-like policy I copy-paste-modify
> Sequential<dim,spacedim>::distribute_dofs() and renumber_dofs() to store
> proper values in
> number_cache.locally_owned_dofs.
I don't know if you already committed this, but please don't do copy-paste but
instead create a derived class whose member functions just call the base
class's functions at the top and then compute whatever other data you need.
number_cache.locally_owned_dofs = IndexSet (number_cache.n_global_dofs);
number_cache.locally_owned_dofs.add_range (0, number_cache.n_global_dofs);
if we deal with parallel::shared::Triangulation.
And another is to add DoFRenumbering::SubdomainWise.
btw, I am was wrong, i did not add renumbering so far. The reason is, it is not strictly speaking, necessary.
At least for Trilinos vectors this should work with or without renumbering. Thus i kept it outside of the distribute_dofs().
IndexSet of locally_owned DoFs should be correct for either case.
But adding renumbering is easy, let me know if you think it really should be there.
Regards,
Denis.
> why would there be any problems with hp::DoFHandler?
> There is no policy used in hp::DoFHandler, but I added some dynamic casts to
> check for triangulation class.
I think Timo was thinking of equipping hp::DoFHandler with policies like we do
with ::DoFHandler, or merging the two altogether.
> One thing would be to change:
>
> number_cache.locally_owned_dofs= IndexSet(number_cache.n_global_dofs);
>
> number_cache.locally_owned_dofs.add_range (0,number_cache.n_global_dofs);
>
>
> if we deal with parallel::shared::Triangulation.
Yes. But that shouldn't be too difficult.
> And another is to add DoFRenumbering::SubdomainWise.
This should almost be trivial. If you see how it's done for ::DoFHandler, you
will immediately see how to do it for hp::DoFHandler. Or even be able to
implement it in a function that works on a generic DH argument.
> btw, I am was wrong, i did not add renumbering so far. The reason is, it is
> not strictly speaking, necessary.
>
> At least for Trilinos vectors this should work with or without renumbering.
> Thus i kept it outside of the distribute_dofs().
Right. But wouldn't it be convenient to do? It's definitely necessary for
PETSc, and it's almost certainly inefficient to not do with Trilinos.
#include <deal.II/dofs/dof_renumbering.h>
> doing that parallel::shared::Triangulation, i would say there are some
> problems with using policies.
> Main thing is that it returns IndexSet and thus before you finish with policy
> some simple things like
> DoFHandler.n_dofs() are undefined. Therefore I can not use almost any function
> like get_subdomain_association()
> within the policy.
Ah, right. Was that the reason why you didn't want to call
DoFRenumbering::component_wise from the policy?
> One way out I see is to pass a reference to number_cache so that it does not
> return it, but rather populate the one belonging to DoFHandler.
I think that's not unreasonable.
You have a circular list of header file inclusions (fe_collection.h includes
fe.h which includes mapping.h which includes dof_handler.h which includes
dof_renumbering.h which needs hp/dof_handler.h which needs fe_collection.h).
I've made a couple of modifications on mainline for this. Can you do a merge
from mainline to your branch and try again?
$svn merge ^/trunksvn: E195016: Merge tracking not allowed with missing subtrees; try restoring these items first:/Users/davydden/libs-sources/dealii/deal.II-trunk/deal.II/doc/users/Config.sample
$ svn status! deal.II/doc/users/Config.sample$ svn revert deal.II/doc/users/Config.sampleReverted 'deal.II/doc/users/Config.sample'$ svn status! deal.II/doc/users/config.sample
But maybe Denis did not check out the whole repository or ran the
command inside "deal.II"?
$ svn status! deal.II/doc/users/Config.sample
Just revert the file.
$ svn status! deal.II/doc/users/Config.sample
$ svn revert deal.II/doc/users/Config.sampleReverted 'deal.II/doc/users/Config.sample'$ svn status! deal.II/doc/users/config.sample
$ svn revert deal.II/doc/users/config.sampleReverted 'deal.II/doc/users/config.sample'
$ svn status! deal.II/doc/users/Config.sample
If you want, I can do the merge from mainline for you.
you can try "rm -rf deal.II/doc/users" and then "svn up"
! deal.II/doc/users/Config.sample! deal.II/doc/users/config.sample
$ svn upUpdating '.':Restored 'deal.II/doc/users'Restored 'deal.II/doc/users/title.html'Restored 'deal.II/doc/users/Config.sample'Restored 'deal.II/doc/users/toc.html'Restored 'deal.II/doc/users/index.html'Restored 'deal.II/doc/users/navbar.html'Restored 'deal.II/doc/users/CMakeLists.txt.sample'Restored 'deal.II/doc/users/CMakeLists.txt.sample2'Restored 'deal.II/doc/users/CMakeLists.txt.sample3'Restored 'deal.II/doc/users/doxygen.html'Restored 'deal.II/doc/users/cmakelists.html'Restored 'deal.II/doc/users/cmake.html'
>> If you want, I can do the merge from mainline for you.
>
> Please, do so.
done.
> (I submitted the results to cdash, but cdash decided to not show the
> test results)
correction, here are the results (ignore the tests in fe/*):
http://cdash.kyomu.43-1.org/viewTest.php?onlyfailed&buildid=5545
4226 - gla/vec_05.mpirun=4.debug (Failed)4227 - gla/vec_05.mpirun=4.release (Failed)
5295 - mpi/codim_01.mpirun=3.debug (Failed)
5505 - mpi/multigrid_adaptive.mpirun=1.debug (Failed)5506 - mpi/multigrid_adaptive.mpirun=1.release (Failed)
5915 - mpi/step-40_direct_solver.mpirun=10.debug (Failed)5916 - mpi/step-40_direct_solver.mpirun=10.release (Failed)5917 - mpi/step-40_direct_solver.mpirun=3.debug (Failed)5918 - mpi/step-40_direct_solver.mpirun=3.release (Failed)5919 - mpi/step-40_direct_solver.mpirun=4.debug (Failed)5920 - mpi/step-40_direct_solver.mpirun=4.release (Failed)
> Should we add things like:
> n_locally_owned_active_cells(), n_global_active_cells(),
> n_locally_owned_active_cells_per_processor()
> or not? This would simplify step-18 so we don't need
> GridTools::count_cells_with_subdomain_association().
Yes, definitely.
W.
./ Something is wrong in the number cache. In test sharedtria/dof_01 this fails:
Assert(dof_handler.n_locally_owned_dofs() ==
dof_handler.n_locally_owned_dofs_per_processor()[triangulation.locally_owned_subdomain()],
ExcInternalError());
template <class DH>
void
subdomain_wise (DH &dof_handler)
{
std::vector<types::global_dof_index> renumbering(dof_handler.n_dofs(),
DH::invalid_dof_index);
compute_subdomain_wise(renumbering, dof_handler);
dof_handler.renumber_dofs(renumbering);
}
Whereas for component wise it is n_locally_owned_dofs:
template <int dim, int spacedim>
void
component_wise (DoFHandler<dim,spacedim> &dof_handler,
const std::vector<unsigned int> &component_order_arg)
{
std::vector<types::global_dof_index> renumbering (dof_handler.n_locally_owned_dofs(),
DoFHandler<dim>::invalid_dof_index);
...
dof_handler.renumber_dofs (renumbering);
}
Of course, for usual triangulation this does not matter as NumberCache is kept independent on MPI processors and
n_dofs()==n_locally_owned_dofs();
For the new class, however, the two are different!
Without going into many lines of code, I assume for Sequential<dim,spacedim>::renumber_dofs, renumbering should be of n_dofs(), right?
Are there any cases in the library when it is called with renumbering.size() < n_dofs()?
Hopefully what is written for component_wise renumbering also make sense when n_locally_owned_dofs < n_dofs?
I suppose that's exactly what is called for distributed triangulation, right?
So it seems to me that in order to safely use Sequential renumbering within the new class,
those "renumbering" should be gathered among processors.
Can i gather them as-is, or i need to be more careful about it?
Regards,
Denis.
> So it seems to me that in order to safely use Sequential renumbering within
> the new class,
>
> those "renumbering" should be gathered among processors.
>
> Can i gather them as-is, or i need to be more careful about it?
Because all the unknowns are known on each processor, you should
handle it exactly as in the serial case (use n_dofs()). This way no
communication is needed.
Because all the unknowns are known on each processor, you should
handle it exactly as in the serial case (use n_dofs()). This way no
communication is needed.
if (is_level_operation)
{
//we are dealing with mg dofs, skip foreign level cells:
if ((start->get_dof_handler().get_tria().locally_owned_subdomain() != numbers::invalid_subdomain_id)
&&
(cell->level_subdomain_id()!=start->get_dof_handler().get_tria().locally_owned_subdomain()))
continue;
}
else
{
//we are dealing with active dofs, skip the loop if not locally
// owned:
if (!cell->active() || !cell->is_locally_owned())
continue;
> Now it seems to me that it is easier to do some communication inside
> renumbering policy class a-la distributed case.
Not sure. Because every process knows all DoFs, you would need to
transfer every new DoF to every other process.
if (const parallel::distributed::Triangulation<dim,spacedim> *tria
= (dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>
(&start->get_dof_handler().get_tria())))
so dof_renumbering.cc as-is will not work at all, irrespectively of what is inside Policy class.
Everything what is inside those if's, as far as i can see,
applies to parallel::shared::Triangulation as well.
How about yet another class from which both distributed and shared are derived, say parallel::Triangulation<> ?
It can be abstract and only provide abstract common methods which both shared and distributed implement.
And then used only for casting in such situations.
Any better solution?
> and also have a quick look of my modifications.
will do (but it might take a little longer, I am traveling again). Is
any of the renumbering working already?
> Will be waiting for the test suite results...
some of the shared tria stuff is not compiling with clang. I will take
a look at it:
http://cdash.kyomu.43-1.org/index.php?project=deal.II&subproject=branch_sharedtria
i will have a look and see if i can trigger it on smaller meshes/test cases....funny enough it did work on 4 element mesh, which makes things more tricky to debug...
std::vector<types::global_dof_index> new_numbers_copy (new_numbers);
MPI_Barrier (tr->get_communicator ());
MPI_Allgather (&new_numbers_copy[0], new_numbers_copy.size (),
DEAL_II_DOF_INDEX_MPI_TYPE,
&gathered_new_numbers[0], new_numbers_copy.size (),
DEAL_II_DOF_INDEX_MPI_TYPE,
tr->get_communicator ());
I just run all sharedtria tests on the git repo, they all failed.I will have a look what's wrong there, maybe some sources for diff are missing...