diff --git a/doc/istl/comm/Makefile.am b/doc/istl/comm/Makefile.am index 30ea425e2c5a0a170d610a8227dd1d2b1085c323..f4d1c6e130f3dd131c37f7b1ea696c7b04500173 100644 --- a/doc/istl/comm/Makefile.am +++ b/doc/istl/comm/Makefile.am @@ -9,6 +9,8 @@ SUFFIXES = .dvi .tex .pdf dist_pkgdata_DATA = communication.pdf communication.ps +#communication.dvi_DEPENDENCIES = communication.tex indexset.cc reverse.hh + noinst_PROGRAMS = $(MPIPROGRAMS) indexset_SOURCES = indexset.cc diff --git a/doc/istl/comm/buildindexset.hh b/doc/istl/comm/buildindexset.hh new file mode 100644 index 0000000000000000000000000000000000000000..c0b612453d50fbca68e8acbe3edc8245418b924f --- /dev/null +++ b/doc/istl/comm/buildindexset.hh @@ -0,0 +1,58 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +// $Id$ +#ifndef BUILDINDEXSET_HH +#define BUILDINDEXSET_HH + + +#include <dune/istl/indexset.hh> +#include <dune/istl/plocalindex.hh> +#include "mpi.h" + +/** + * @brief Flag for marking the indices. + */ +enum Flag {owner, overlap}; + +// The type of local index we use +typedef Dune::ParallelLocalIndex<Flag> LocalIndex; + +/** + * @brief Add indices to the example index set. + * @param indexSet The index set to build. + */ +template<class TG, int N> +void build(Dune::IndexSet<TG,LocalIndex,N>& indexSet) +{ + // + // The number of processes + int size; + MPI_Comm_size(MPI_COMM_WORLD, &size); + + // The rank of our process + int rank; + MPI_Comm_rank(MPI_COMM_WORLD, &rank); + + // Indicate that we add or remove indices. + indexSet.beginResize(); + + if(rank==0) { + indexSet.add(0, LocalIndex(0,overlap,true)); + indexSet.add(2, LocalIndex(1,owner,true)); + indexSet.add(6, LocalIndex(2,owner,true)); + indexSet.add(3, LocalIndex(3,owner,true)); + indexSet.add(5, LocalIndex(4,owner,true)); + } + + if(rank==1) { + indexSet.add(0, LocalIndex(0,owner,true)); + indexSet.add(1, LocalIndex(1,owner,true)); + indexSet.add(7, LocalIndex(2,owner,true)); + indexSet.add(5, LocalIndex(3,overlap,true)); + indexSet.add(4, LocalIndex(4,owner,true)); + } + + // Modification is over + indexSet.endResize(); +} +#endif diff --git a/doc/istl/comm/communication.tex b/doc/istl/comm/communication.tex index 2a4e59312e914f2b1589e01005a99b78b1a91090..e038f54e087ff1194b1e8c0416f9ab08c03fa596 100644 --- a/doc/istl/comm/communication.tex +++ b/doc/istl/comm/communication.tex @@ -147,6 +147,19 @@ to be persistent. Further on we will call this global identifier \lstinline!N! is used internally to specify the chunk size of the array list. +The pairs of global and local index are ordered by ascending global +index. Thus it it possible to access the pairs via +\lstinline!operator[](TG& global)! in $log(n)$ time, where $n$ is the +number of pairs in the set. + +Due to the ordering the index set can only be changed, i.~e. indices +added or deleted, in a special resize phase. By calling the functions +\lstinline!beginResize()! and \lstinline!endResize()! the programmer +indicates that the resize phase starts and ends, respectively. During +the call of \lstinline!endResize()! the deleted indices will be +removed and the added indices will be merged with the existing +ones. + To be able to attach further information to the index the only prerequesite for the type of the local index is that it is convertible to \lstinline!std::size_t! as it it meant for adressing array @@ -170,9 +183,19 @@ As the programmer often knows in advance which indices might also be present on other processes there is the possiblity to mark the index as public. -Let us look at a short example on how to use the classes: +\paragraph{Usage Examples} +Let us look at a short example on how to build an index set: + +\lstinputlisting[caption=Build an Index Set, +label=lst:build_indexset]{buildindexset.hh} + +Due to the complexity of \lstinline!operator[](TG& global)! it is +always advisable to use iterators to access the index pairs of the +set. +The following example demonstrates their usage: +\lstinputlisting[caption=Usage of Index Set Iterators, +label=lst:indexset_iterator]{reverse.hh} -\lstinputlisting[caption=build an index set, label=lst:build_indexset]{indexset.cc} \section{Remote Indices} \label{sec:remote-indices} diff --git a/doc/istl/comm/indexset.cc b/doc/istl/comm/indexset.cc index 44bf5da690b95e4879ba78e07d2e31f17e269cb5..67e9b1b10d21e1cc4d38d849b7d854d09b3ed400 100644 --- a/doc/istl/comm/indexset.cc +++ b/doc/istl/comm/indexset.cc @@ -5,12 +5,8 @@ #include <dune/istl/plocalindex.hh> #include <iostream> #include "mpi.h" - -/** - * @brief Flag for marking the indices. - */ -enum Flag {owner, overlap}; - +#include "buildindexset.hh" +#include "reverse.hh" int main(int argc, char **argv) { @@ -20,11 +16,10 @@ int main(int argc, char **argv) // The number of processes int size; + MPI_Comm_size(MPI_COMM_WORLD, &size); // The rank of our process int rank; - - MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); // The type used as the local index @@ -40,30 +35,22 @@ int main(int argc, char **argv) // The index set IndexSet indexSet; - // Indicate that we add or remove indices. - indexSet.beginResize(); + build(indexSet); - if(rank==0) { - indexSet.add(0, LocalIndex(0,overlap,true)); - indexSet.add(2, LocalIndex(1,owner,true)); - indexSet.add(6, LocalIndex(2,owner,true)); - indexSet.add(3, LocalIndex(3,owner,true)); - indexSet.add(5, LocalIndex(4,owner,true)); - } - if(rank==1) { + // Print the index set + std::cout<<indexSet<<std::endl; - indexSet.add(0, LocalIndex(0,owner,true)); - indexSet.add(1, LocalIndex(1,owner,true)); - indexSet.add(7, LocalIndex(2,owner,true)); - indexSet.add(5, LocalIndex(3,overlap,true)); - indexSet.add(4, LocalIndex(4,owner,true)); - } - // Modification is over - indexSet.endResize(); + reverseLocalIndex(indexSet); // Print the index set + if(rank==0) + std::cout<<"Reordered lcoal indices:"<<std::endl; + + MPI_Barrier(MPI_COMM_WORLD); + std::cout<<indexSet<<std::endl; + // Assign new local indices // Let MPI do a cleanup MPI_Finalize(); diff --git a/doc/istl/comm/reverse.hh b/doc/istl/comm/reverse.hh new file mode 100644 index 0000000000000000000000000000000000000000..abe015a75c9f8d3fcaede99df29ca34ec0f5777c --- /dev/null +++ b/doc/istl/comm/reverse.hh @@ -0,0 +1,40 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +// $Id$ +#ifndef REVERSE_HH +#define REVERSE_HH + +#include <dune/istl/plocalindex.hh> +#include <dune/istl/indexset.hh> + +/** + * @brief Reverse the local indices of an index set. + * + * Let the index set have N entries than the index 0 will become N-1, + * 1 become N-2, ..., and N-1 will become 0. + * @param indexSet The index set to reverse. + */ +template<typename TG, typename TL, int N> +void reverseLocalIndex(Dune::IndexSet<TG,TL,N>& indexSet) +{ + // reverse the local indices + typedef typename Dune::IndexSet<TG,TL,N>::iterator iterator; + + iterator end = indexSet.end(); + size_t maxLocal = 0; + + // find the maximal local index + for(iterator index = indexSet.begin(); index != end; ++index) { + // Get the local index + LocalIndex& local = index->local(); + maxLocal = std::max(maxLocal, local.local()); + } + + for(iterator index = indexSet.begin(); index != end; ++index) { + // Get the local index + LocalIndex& local = index->local(); + local = maxLocal--; + } + +} +#endif