From 308868c417207d99d2149bd070f12584f0c09b41 Mon Sep 17 00:00:00 2001
From: Markus Blatt <mblatt@dune-project.org>
Date: Wed, 27 Apr 2005 14:50:11 +0000
Subject: [PATCH] More elaborate examples for Dune::IndexSet.

[[Imported from SVN: r1972]]
---
 doc/istl/comm/Makefile.am       |  2 ++
 doc/istl/comm/buildindexset.hh  | 58 +++++++++++++++++++++++++++++++++
 doc/istl/comm/communication.tex | 27 +++++++++++++--
 doc/istl/comm/indexset.cc       | 39 ++++++++--------------
 doc/istl/comm/reverse.hh        | 40 +++++++++++++++++++++++
 5 files changed, 138 insertions(+), 28 deletions(-)
 create mode 100644 doc/istl/comm/buildindexset.hh
 create mode 100644 doc/istl/comm/reverse.hh

diff --git a/doc/istl/comm/Makefile.am b/doc/istl/comm/Makefile.am
index 30ea425e2..f4d1c6e13 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 000000000..c0b612453
--- /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 2a4e59312..e038f54e0 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 44bf5da69..67e9b1b10 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 000000000..abe015a75
--- /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
-- 
GitLab