CoarseningManager.cc 3.71 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "CoarseningManager.h"
#include "Mesh.h"
#include "AdaptStationary.h"
#include "AdaptInstationary.h"
#include "Traverse.h"
#include "MacroElement.h"
#include "RCNeighbourList.h"
#include "FixVec.h"
//#include "PeriodicBC.h"

namespace AMDiS {

  CoarseningManager* CoarseningManager::traversePtr = NULL;

  /****************************************************************************/
  /*  sets the mark on all elements that have to be coarsend                  */
  /****************************************************************************/

  int CoarseningManager::coarsenMarkFunction(ElInfo *el_info)
  {
    el_info->getElement()->setMark(traversePtr->globalMark);
    return 0;
  }

  /****************************************************************************/
  /*  tries to coarsen every element of mesh at least mark times		    */
  /****************************************************************************/

  Flag CoarseningManager::globalCoarsen(Mesh *aMesh, int mark)
  {
    if (mark >= 0) return(0);
    globalMark = mark;
    traversePtr = this;
    aMesh->traverse(-1, Mesh::CALL_LEAF_EL, coarsenMarkFunction);
    return(coarsenMesh(aMesh));
  }

  int CoarseningManager::spreadCoarsenMarkFunction(ElInfo* el_info)
  {
    Element *el = el_info->getElement();
    signed char mark;

    if (el->getChild(0))
      {  
	/****************************************************************************/
	/* interior node of the tree                                                */
	/****************************************************************************/
	mark = max(el->getChild(0)->getMark(), el->getChild(1)->getMark());
49
	el->setMark(std::min(mark + 1, 0));
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
      }
    else
      {
	/****************************************************************************/
	/* leaf node of the tree                                                    */
	/****************************************************************************/
	if (el->getMark() < 0)  el->setMark(el->getMark() - 1);
      }
    return 0;
  }

  void CoarseningManager::spreadCoarsenMark()
  {
    traversePtr = this;
    mesh->traverse(-1, 
		   Mesh::CALL_EVERY_EL_POSTORDER, 
		   spreadCoarsenMarkFunction);
  }


  /****************************************************************************/
  /*  cleanup_after_coarsen:                                   		    */
  /*  resets the element marks                                                */
  /****************************************************************************/

  int CoarseningManager::cleanUpAfterCoarsenFunction(ElInfo *el_info)
  {
    Element *el = el_info->getElement();
    el->setMark(max(el->getMark(), 0));
    return 0;
  }

  void CoarseningManager::cleanUpAfterCoarsen()
  {
    traversePtr = this;
    mesh->traverse(-1, Mesh::CALL_LEAF_EL, cleanUpAfterCoarsenFunction);
  }

  /****************************************************************************/
  /*  coarsenMesh:       							    */
  /*  traversal routine for recursiv coarsening of a triangulation            */
  /****************************************************************************/

  Flag CoarseningManager::coarsenMesh(Mesh *aMesh)
  {
    int n_elements;
    Flag flag = Mesh::CALL_EVERY_EL_POSTORDER | Mesh::FILL_NEIGH;
    ElInfo *el_info;

    mesh = aMesh;

    n_elements = mesh->getNumberOfLeaves();

    spreadCoarsenMark();

    stack = NEW TraverseStack;

    do {
      doMore = false;
      el_info = stack->traverseFirst(mesh, -1, flag);
110
111
112
113
      while (el_info) {
	coarsenFunction(el_info);
	el_info = stack->traverseNext(el_info);
      }
114
115
116
117
118
119
120
121
122
123
124
125
    } while (doMore);

    DELETE stack;

    cleanUpAfterCoarsen();

    n_elements -= mesh->getNumberOfLeaves();

    return(n_elements ? MESH_COARSENED : Flag(0));
  }

}