From ecdce6c07006c753c5229ce529feb23a6dc45a4c Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Wed, 9 Dec 2009 11:40:10 +0000
Subject: [PATCH] Mesh structure code for elements implemented.

---
 AMDiS/src/Element.h             |  7 +++
 AMDiS/src/Line.h                |  6 +++
 AMDiS/src/MeshStructure.cc      | 26 +++++++++++
 AMDiS/src/MeshStructure.h       | 12 +++--
 AMDiS/src/ParallelDomainBase.cc | 52 ++++++++++++++++++++-
 AMDiS/src/StdMpi.h              | 83 +++++++++++++++++++++++++++++----
 AMDiS/src/Tetrahedron.h         |  6 +++
 AMDiS/src/Triangle.h            |  6 +++
 8 files changed, 183 insertions(+), 15 deletions(-)

diff --git a/AMDiS/src/Element.h b/AMDiS/src/Element.h
index a831cad0..9a304a1e 100644
--- a/AMDiS/src/Element.h
+++ b/AMDiS/src/Element.h
@@ -370,6 +370,13 @@ namespace AMDiS {
     /// Returns whether Element has sideElem as one of its sides.
     virtual bool hasSide(Element *sideElem) const = 0;
 
+    /** \brief
+     * Returns for a given element type number the element type number of the children.
+     * For 1d and 2d this is always 0, because element type number are used in the 
+     * 3d case only.
+     */
+    virtual int getChildType(int elType) const = 0;
+
     /** \brief
      * Traverses an edge/face of a given element (this includes also all children of 
      * the element having the same edge/face). All vertex dofs alonge this edge/face
diff --git a/AMDiS/src/Line.h b/AMDiS/src/Line.h
index 6901c896..a32573f1 100644
--- a/AMDiS/src/Line.h
+++ b/AMDiS/src/Line.h
@@ -141,6 +141,12 @@ namespace AMDiS {
     { 
       return false; 
     }
+
+    /// Element type number is not used in 1d, so return 0.
+    inline int getChildType(int) const
+    {
+      return 0;
+    }
   
     std::string getTypeName() const 
     { 
diff --git a/AMDiS/src/MeshStructure.cc b/AMDiS/src/MeshStructure.cc
index b79b10d1..00ab6af4 100644
--- a/AMDiS/src/MeshStructure.cc
+++ b/AMDiS/src/MeshStructure.cc
@@ -54,6 +54,32 @@ namespace AMDiS {
     commit();
   }
 
+  void MeshStructure::init(Element *el, int ithSide, int elType)
+  {
+    FUNCNAME("MeshStructure::init()");
+
+    clear();
+
+    addAlongSide(el, ithSide, elType);
+
+    commit();    
+  }
+
+  void MeshStructure::addAlongSide(Element *el, int ithSide, int elType)
+  {
+    insertElement(el->isLeaf());
+    
+    if (!el->isLeaf()) {
+      int s1 = el->getSideOfChild(0, ithSide, elType);
+      int s2 = el->getSideOfChild(1, ithSide, elType);
+
+      if (s1 != -1) 
+	addAlongSide(el->getFirstChild(), s1, el->getChildType(elType));
+      if (s2 != -1)
+	addAlongSide(el->getSecondChild(), s2, el->getChildType(elType));
+    }
+  }
+
   void MeshStructure::reset() 
   {
     currentIndex = 0;
diff --git a/AMDiS/src/MeshStructure.h b/AMDiS/src/MeshStructure.h
index d5f312f8..9e5c6487 100644
--- a/AMDiS/src/MeshStructure.h
+++ b/AMDiS/src/MeshStructure.h
@@ -41,9 +41,11 @@ namespace AMDiS {
   
     void clear();
 
-    /// Creates a mesh structure code from a Mesh object by traversing it in preorder.
+    /// Creates a mesh structure code from a mesh object by traversing it in preorder.
     void init(Mesh *mesh);
 
+    void init(Element *el, int ithSide, int elType);
+
     void init(const std::vector<unsigned long int>& initCode, int n) 
     {
       code = initCode;
@@ -102,13 +104,13 @@ namespace AMDiS {
       bool cont = true;
       while (cont) {
 	if (isLeafElement())
-	  MSG("0");
+	  std::cout << "0";
 	else
-	  MSG("1");
+	  std::cout << "1";
 	
 	cont = nextElement();
       }
-      MSG("\n");
+      std::cout << std::endl;
     }
 
     /// Returns the mesh structure code.
@@ -131,6 +133,8 @@ namespace AMDiS {
     /// Insert a new element to the structure code. Is used by the init function.
     void insertElement(bool isLeaf);
 
+    void addAlongSide(Element *el, int ithSide, int elType);
+
     /// Merges two mesh structure codes to one structure code.     
     void merge(MeshStructure *structure1,
 	       MeshStructure *structure2,
diff --git a/AMDiS/src/ParallelDomainBase.cc b/AMDiS/src/ParallelDomainBase.cc
index 2fdde4b5..20026e4f 100644
--- a/AMDiS/src/ParallelDomainBase.cc
+++ b/AMDiS/src/ParallelDomainBase.cc
@@ -18,6 +18,7 @@
 #include "ElementFileWriter.h"
 #include "VertexVector.h"
 #include "StdMpi.h"
+#include "MeshStructure.h"
 
 #include "petscksp.h"
 
@@ -694,7 +695,7 @@ namespace AMDiS {
       stdMpi.send(sendIt->first, dofs);
     }
 
-    stdMpi.startCommunication();
+    stdMpi.startCommunication<int>();
 #endif
 
 #if 1
@@ -758,9 +759,56 @@ namespace AMDiS {
 
   void ParallelDomainBase::checkMeshChange()
   {
+    // === If mesh has not been changed, return. ===
+
     if (mesh->getChangeIndex() == lastMeshChangeIndex)
       return;
 
+
+    // === Create mesh structure codes for all ranks boundary elements. ===
+
+    typedef std::vector<MeshStructure> MeshCodeVec;
+    std::map<int, MeshCodeVec > sendCodes;
+
+    for (RankToBoundMap::iterator it = myIntBoundary.boundary.begin();
+	 it != myIntBoundary.boundary.end(); ++it) {    
+
+      for (std::vector<AtomicBoundary>::iterator boundIt = it->second.begin();
+	   boundIt != it->second.end(); ++boundIt) {
+
+	MeshStructure elCode;
+	elCode.init(boundIt->rankObj.el, boundIt->rankObj.ithObj, 
+		    boundIt->rankObj.elType);
+	sendCodes[it->first].push_back(elCode);
+      }
+    }
+
+    StdMpi<MeshCodeVec, MeshCodeVec> stdMpi(mpiComm);
+    stdMpi.prepareCommunication(true);
+    stdMpi.send(sendCodes);
+
+    for (RankToBoundMap::iterator it = otherIntBoundary.boundary.begin();
+	 it != otherIntBoundary.boundary.end(); ++it)
+      stdMpi.recv(it->first);
+
+    stdMpi.startCommunication<unsigned long int>();
+
+      
+#if 0
+    for (RankToBoundMap::iterator it = otherIntBoundary.boundary.begin();
+	 it != otherIntBoundary.boundary.end(); ++it) {
+
+      for (std::vector<AtomicBoundary>::iterator boundIt = it->second.begin();
+	   boundIt != it->second.end(); ++boundIt) {
+
+	MeshStructure elCode;
+	elCode.init(boundIt->rankObj.el, 
+		    boundIt->rankObj.ithObj, 
+		    boundIt->rankObj.elType);
+      }
+    }
+#endif
+
     std::cout << "MESH HAS BEEN CHANGED!" << std::endl;
     exit(0);    
 
@@ -1262,7 +1310,7 @@ namespace AMDiS {
     for (std::map<int, int>::iterator recvIt = recvNewDofs.begin();
 	 recvIt != recvNewDofs.end(); ++recvIt, i++)
       stdMpi.recv(recvIt->first, recvIt->second * 2); 
-    stdMpi.startCommunication();
+    stdMpi.startCommunication<int>();
     std::map<int, std::vector<std::pair<DegreeOfFreedom, DegreeOfFreedom> > > &dofMap = stdMpi.getRecvData();
 
     // === Change dof indices at boundary from other ranks. ===
diff --git a/AMDiS/src/StdMpi.h b/AMDiS/src/StdMpi.h
index 7365f557..56ad1a0b 100644
--- a/AMDiS/src/StdMpi.h
+++ b/AMDiS/src/StdMpi.h
@@ -24,6 +24,7 @@
 
 #include <map>
 #include "mpi.h"
+#include "MeshStructure.h"
 
 namespace AMDiS {
 
@@ -32,7 +33,16 @@ namespace AMDiS {
     return data.size() * 2;
   }
 
-  void makeIntBuf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data, int* buf)
+  int intSizeOf(std::vector<MeshStructure> &data)
+  {
+    int s = 0;
+    for (int i = 0; i < data.size(); i++)
+      s += data[i].getCode().size() + 2;
+
+    return s;
+  }
+
+  void makeBuf(std::map<const DegreeOfFreedom*, DegreeOfFreedom> &data, int* buf)
   {
     int i = 0;
     for (std::map<const DegreeOfFreedom*, DegreeOfFreedom>::iterator it = data.begin();
@@ -42,8 +52,8 @@ namespace AMDiS {
     }
   }
   
-  void makeFromIntBuf(std::vector<std::pair<DegreeOfFreedom, DegreeOfFreedom> > &data, 
-		      int *buf, int bufSize)
+  void makeFromBuf(std::vector<std::pair<DegreeOfFreedom, DegreeOfFreedom> > &data, 
+		   int *buf, int bufSize)
   {    
     if (bufSize == 0)
       return;
@@ -58,7 +68,35 @@ namespace AMDiS {
     } while (i < bufSize);
   }
 
+  void makeBuf(std::vector<MeshStructure> &data, unsigned long int *buf)
+  {
+    int pos = 0;
+    for (int i = 0; i < data.size(); i++) {
+      buf[pos++] = data[i].getCode().size();
+      buf[pos++] = data[i].getNumElements();
+      for (int j = 0; j < data[i].getCode().size(); j++)
+	buf[pos++] = data[i].getCode()[j];
+    }
+  }
 
+  void makeFromBuf(std::vector<MeshStructure> &data, unsigned long int *buf, int bufSize)
+  {
+    int pos = 0;
+
+    while (pos < bufSize) {       
+      int codeSize = buf[pos++];
+      int nElements = buf[pos++];
+      std::vector<unsigned long int> code;
+      code.reserve(codeSize);
+      for (int i = 0; i < codeSize; i++)
+	code[i] = buf[pos++];
+
+      MeshStructure meshCode;
+      meshCode.init(code, nElements);
+
+      data.push_back(meshCode);
+    }	
+  }
 
   template<typename SendT, typename RecvT>
   class StdMpi 
@@ -116,21 +154,48 @@ namespace AMDiS {
       return recvData;
     }
 
+    void commDataSize()
+    {
+      MPI::Request request[sendData.size() + recvDataSize.size()];
+      std::vector<int> sendBuffers, recvBuffers;
+      int requestCounter = 0;
+
+      int i = 0;
+      for (typename std::map<int, int>::iterator sendIt = sendDataSize.begin();
+	   sendIt != sendDataSize.end(); ++sendIt) {
+	sendBuffers.push_back(sendIt->second);
+	request[requestCounter++] =
+	  mpiComm.Isend(&(sendBuffers[i]), 1, MPI_INT, sendIt->first, 0);
+	i++;
+      }
+
+      for (std::map<int, int>::iterator recvIt = recvDataSize.begin();
+	   recvIt != recvDataSize.end(); ++recvIt)
+	request[requestCounter++] =
+	  mpiComm.Irecv(&(recvIt->second), 1, MPI_INT, recvIt->first, 0);
+      
+      MPI::Request::Waitall(requestCounter, request);      
+    }
+
+    template<class T>
     void startCommunication()
     {
       FUNCNAME("StdMpi::startCommunication()");
 
       TEST_EXIT_DBG(commPrepared)("Communication is not prepared!\n");
 
+      if (exchangeDataSize)
+	commDataSize();
+
       MPI::Request request[sendData.size() + recvDataSize.size()];
       int requestCounter = 0;
-      std::vector<int*> sendBuffers, recvBuffers;
+      std::vector<T*> sendBuffers, recvBuffers;
 
       for (typename std::map<int, SendT>::iterator sendIt = sendData.begin();
 	   sendIt != sendData.end(); ++sendIt) {
-	int bufferSize = intSizeOf(sendIt->second);
-	int* buf = new int[bufferSize];
-	makeIntBuf(sendIt->second, buf);
+	int bufferSize = sendDataSize[sendIt->first];
+	T* buf = new T[bufferSize];
+	makeBuf(sendIt->second, buf);
 
   	request[requestCounter++] = 
   	  mpiComm.Isend(buf, bufferSize, MPI_INT, sendIt->first, 0);
@@ -140,7 +205,7 @@ namespace AMDiS {
 
       for (std::map<int, int>::iterator recvIt = recvDataSize.begin();
 	   recvIt != recvDataSize.end(); ++recvIt) {
-	int* buf = new int[recvIt->second];
+	T* buf = new T[recvIt->second];
 
   	request[requestCounter++] =
   	  mpiComm.Irecv(buf, recvIt->second, MPI_INT, recvIt->first, 0);
@@ -157,7 +222,7 @@ namespace AMDiS {
       int i = 0;
       for (std::map<int, int>::iterator recvIt = recvDataSize.begin();
 	   recvIt != recvDataSize.end(); ++recvIt) {
-	makeFromIntBuf(recvData[recvIt->first], recvBuffers[i], recvIt->second);
+	makeFromBuf(recvData[recvIt->first], recvBuffers[i], recvIt->second);
 	delete [] recvBuffers[i];
 	i++;
       }      
diff --git a/AMDiS/src/Tetrahedron.h b/AMDiS/src/Tetrahedron.h
index 329d2460..4de965e2 100644
--- a/AMDiS/src/Tetrahedron.h
+++ b/AMDiS/src/Tetrahedron.h
@@ -123,6 +123,12 @@ namespace AMDiS {
     { 
       return true; 
     }
+
+    /// Return the new element type of the children.
+    inline int getChildType(int elType) const
+    {
+      return (elType + 1) % 3;
+    }
  
     std::string getTypeName() const 
     { 
diff --git a/AMDiS/src/Triangle.h b/AMDiS/src/Triangle.h
index fe2f7bd9..fa105389 100644
--- a/AMDiS/src/Triangle.h
+++ b/AMDiS/src/Triangle.h
@@ -114,6 +114,12 @@ namespace AMDiS {
       return false; 
     }
 
+    /// Element type number is not used in 2d, so return 0.
+    inline int getChildType(int) const
+    {
+      return 0;
+    }
+
     /// implements Element::getSideOfChild()
     virtual int getSideOfChild(int child, int side, int) const 
     {
-- 
GitLab