CoarseningManager1d.cc 4.45 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
49
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "CoarseningManager1d.h"
#include "Mesh.h"
#include "AdaptStationary.h"
#include "AdaptInstationary.h"
#include "Traverse.h"
#include "MacroElement.h"
#include "RCNeighbourList.h"
#include "FixVec.h"
#include "DOFIndexed.h"

namespace AMDiS {

  Flag CoarseningManager1d::coarsenMesh(Mesh *aMesh)
  {
    mesh = aMesh;

    ::std::deque<MacroElement*>::const_iterator mel;
    int n_elements = mesh->getNumberOfLeaves();

    for (mel = mesh->firstMacroElement(); 
	 mel != mesh->endOfMacroElements(); 
	 mel++) 
      {
	coarsenRecursive(dynamic_cast<Line*>(const_cast<Element*>((*mel)->getElement())));
      }

    return(mesh->getNumberOfLeaves() < n_elements ? MESH_COARSENED : Flag(0));
  }

  int CoarseningManager1d::coarsenRecursive(Line *parent)
  {
    FUNCNAME("CoarseningManager1d::coarsenRecursive");
    int  mark;

    INFO(0,2)("\n");
    if (parent->isLeaf())  // leaf element, clean element marker
      {
	mark = parent->getMark();
	parent->setMark(0);
	return(mark);
      }
    else {                 // no leaf element, first coarse children
      Line *child[2];

      int  mark0 = coarsenRecursive(dynamic_cast<Line*>(const_cast<Element*>(parent->getChild(0))));
      int  mark1 = coarsenRecursive(dynamic_cast<Line*>(const_cast<Element*>( parent->getChild(1))));

      mark = max(mark0, mark1);

      child[0] = dynamic_cast<Line*>(const_cast<Element*>( parent->getChild(0)));
      child[1] = dynamic_cast<Line*>(const_cast<Element*>( parent->getChild(1))); 

      if (mark >= 0) {     // element must not be coarsend
	parent->setMark(0);
	if (child[0]) {
	  child[0]->setMark(0);
	  child[1]->setMark(0);
	}

	return(0);
      }

      /*--------------------------------------------------------------------------*/
      /*--- and now coarsen child[0] and child[1] into parent                  ---*/
      /*--------------------------------------------------------------------------*/
  
      /*--------------------------------------------------------------------------*/
      /*--- hand DOFs from children to parent, and add DOF at center           ---*/
      /*--------------------------------------------------------------------------*/

      if (mesh->getNumberOfDOFs(VERTEX) && !mesh->queryCoarseDOFs()) {
	int node = mesh->getNode(VERTEX);
	parent->setDOF(node+0, const_cast<int*>( child[0]->getDOF(node+0)));
	parent->setDOF(node+1, const_cast<int*>( child[1]->getDOF(node+1)));
      }

      if (mesh->getNumberOfDOFs(CENTER) && !mesh->queryCoarseDOFs()) {
	parent->setDOF(mesh->getNode(CENTER), mesh->getDOF(CENTER));
      }

      /*--------------------------------------------------------------------------*/
      /*  restrict dof vectors to the parents on the patch                        */
      /*--------------------------------------------------------------------------*/


      RCNeighbourList coarsenList(1); // = {{nil, 0, 0}};
      coarsenList.setElement(0, parent);
      int iadmin;
      int nrAdmin = mesh->getNumberOfDOFAdmin();
      for(iadmin = 0; iadmin < nrAdmin; iadmin++) {
	::std::list<DOFIndexedBase*>::iterator it;
	DOFAdmin* admin = const_cast<DOFAdmin*>(&(mesh->getDOFAdmin(iadmin)));
	::std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed();
	for(it = admin->beginDOFIndexed(); it != end; ++it)
	  (*it)->coarseRestrict(coarsenList, 1);
      }
 

      /*--------------------------------------------------------------------------*/
      /*--- remove all DOFs of children that are not used anymore              ---*/
      /*--------------------------------------------------------------------------*/

      if (mesh->getNumberOfDOFs(VERTEX))    /*---  midpoint of parent          ---*/
	{
	  mesh->freeDOF(const_cast<int*>( child[1]->getDOF(mesh->getNode(VERTEX))), VERTEX);
	}

      if (mesh->getNumberOfDOFs(CENTER))    /*--- center of the children       ---*/
	{
	  mesh->freeDOF(const_cast<int*>( child[0]->getDOF(mesh->getNode(CENTER))), CENTER);
	  mesh->freeDOF(const_cast<int*>( child[1]->getDOF(mesh->getNode(CENTER))), CENTER);
	}

      parent->coarsenElementData(child[0], child[1]);

      parent->setFirstChild(NULL);
      parent->setSecondChild(NULL);

      mesh->freeElement(child[0]);
      mesh->freeElement(child[1]);

      mesh->incrementNumberOfLeaves(-1);
      mesh->incrementNumberOfElements(-2);
      mesh->incrementNumberOfVertices(-1);

      mark++;
      parent->setMark(::std::min(mark,0));

      return(parent->getMark());
    }

    return(0);  /*--- statement never reached                              ---*/
  }

}