Liebe Gitlab-Nutzerin, lieber Gitlab-Nutzer,
es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Die Konten der externen Nutzer:innen sind über den Reiter "Standard" erreichbar.
Die Administratoren


Dear Gitlab user,
it is now possible to log in to our service using the ZIH login/LDAP. The accounts of external users can be accessed via the "Standard" tab.
The administrators

CoarseningManager2d.cc 6.23 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#include "CoarseningManager2d.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 {

  /****************************************************************************/
  /*  coarseTriangle:  coarses a single element of the coarsening patch; dofs */
  /*  in the interior of the element are removed; dofs for higher order       */
  /*  at the boundary or the coarsening patch still belong to                 */
  /*  the parent. Do not remove them form the mesh!!!                         */
  /****************************************************************************/

  void CoarseningManager2d::coarsenTriangle(Triangle *el)
  {
22
    FUNCNAME("CoarseningManager2d::coarseTriangle()");
23

24 25 26
    Triangle *child[2];
    child[0] = dynamic_cast<Triangle*>(const_cast<Element*>(el->getChild(0)));
    child[1] = dynamic_cast<Triangle*>(const_cast<Element*>(el->getChild(1))); 
27

28
    TEST_EXIT_DBG(child[0]->getMark() < 0  &&  child[1]->getMark() < 0)
29 30
      ("element %d with children[%d,%d] must not be coarsend!\n",
       el->getIndex(), child[0]->getIndex(), child[1]->getIndex());
31 32 33

    // remove dof from common edge of child[0] and child[1]  
    if (mesh->getNumberOfDOFs(EDGE))
34
      mesh->freeDof(const_cast<int*>(child[0]->getDOF(4)), EDGE);
35

36
    // remove dof from the barycenters of child[0] and child[1] 
37
    if (mesh->getNumberOfDOFs(CENTER)) {
38
      int node = mesh->getNode(CENTER);
39
      
40 41
      mesh->freeDof(const_cast<int*>(child[0]->getDOF(node)), CENTER);
      mesh->freeDof(const_cast<int*>(child[1]->getDOF(node)), CENTER);
42 43
    }
    
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
    el->coarsenElementData(child[0], child[1]);

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

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

    el->incrementMark();

    mesh->incrementNumberOfLeaves(-1);
    mesh->incrementNumberOfElements(-2);
    mesh->incrementNumberOfEdges(-1);
  }

  /****************************************************************************/
  /*  coarsenPatch: first rebuild the dofs on the parents then do restriction */
  /*  of data (if possible) and finally coarsen the patch elements            */
  /****************************************************************************/

  void CoarseningManager2d::coarsenPatch(RCNeighbourList *coarsenList, 
65 66
					 int n_neigh, 
					 int bound)
67
  {
68 69 70 71
    Triangle *el = 
      dynamic_cast<Triangle*>(const_cast<Element*>(coarsenList->getElement(0)));
    Triangle *neigh = 
      dynamic_cast<Triangle*>(const_cast<Element*>(coarsenList->getElement(1)));
72 73
    DegreeOfFreedom *dof[3];

74
    dof[0] = const_cast<int*>(el->getChild(0)->getDOF(2));
75
    if (mesh->getNumberOfDOFs(EDGE)) {
76 77 78 79
      dof[1] = const_cast<int*>(el->getChild(0)->getDOF(3));
      dof[2] = const_cast<int*>(el->getChild(1)->getDOF(4));
    } else {
      dof[1] = dof[2] = 0;
80
    }
81

82
    if (mesh->getNumberOfDOFs(EDGE)) {
83 84 85
      int node = mesh->getNode(EDGE);
      // get new dof on el at the midpoint of the coarsening edge

86
      if (!el->getDOF(node + 2)) {
87
	el->setDOF(node + 2, mesh->getDof(EDGE));
88 89
	if (neigh)
	  neigh->setDOF(node + 2, const_cast<int*>(el->getDOF(node + 2)));
90
      }
91
    }
92

93 94 95 96
    if (mesh->getNumberOfDOFs(EDGE) || mesh->getNumberOfDOFs(CENTER))
      coarsenList->addDOFParents(n_neigh);    

    // restrict dof vectors to the parents on the patch 
97 98

    int nrAdmin = mesh->getNumberOfDOFAdmin();
99
    for (int iadmin = 0; iadmin < nrAdmin; iadmin++) {
100
      DOFAdmin* admin = const_cast<DOFAdmin*>(&mesh->getDOFAdmin(iadmin));
101 102 103
      for (std::list<DOFIndexedBase*>::iterator it = admin->beginDOFIndexed(); 
	   it != admin->endDOFIndexed(); ++it)	
	(*it)->coarseRestrict(*coarsenList, n_neigh);            
104 105 106 107
    }

    coarsenTriangle(el);

108 109
    if (neigh) 
      coarsenTriangle(neigh);
110

111 112
    // now, remove those dofs in the coarcening edge 

113
    mesh->freeDof(dof[0], VERTEX);
114
    if (mesh->getNumberOfDOFs(EDGE)) {
115 116
      mesh->freeDof(dof[1], EDGE);
      mesh->freeDof(dof[2], EDGE);
117
    }
118 119 120 121 122

    mesh->incrementNumberOfVertices(-1);
    mesh->incrementNumberOfEdges(-1);
  }

123

124 125
  int CoarseningManager2d::coarsenFunction(ElInfo *el_info)
  {
126
    Triangle *el = dynamic_cast<Triangle*>(const_cast<Element*>(el_info->getElement()));
127
    DegreeOfFreedom *edge[2];
128
    int n_neigh, bound = 0;
129 130 131 132
    RCNeighbourList coarse_list(2);

    coarse_list.setCoarseningManager(this);

133 134 135 136 137 138
    if (el->getMark() >= 0)
      return 0; // el must not be coarsend, return
    if (!(el->getChild(0))) 
      return 0;  // single leaves don't get coarsened

    if (el->getChild(0)->getMark() >= 0  || el->getChild(1)->getMark() >= 0) {
139
      // one of the children must not be coarsend; return :( 
140 141 142
      el->setMark(0);
      return 0;
    }
143

144
    if (!el->getChild(0)->isLeaf() || !el->getChild(1)->isLeaf()) {
145
      // one of the children is not a leaf element; try again later on 
146 147 148
      doMore = true;
      return 0;
    }
149

150
    // give the refinement edge the right orientation
151

152
    if (el->getDOF(0,0) < el->getDOF(1,0)) {
153 154
      edge[0] = const_cast<int*>(el->getDOF(0));
      edge[1] = const_cast<int*>(el->getDOF(1));
155
    } else {
156 157
      edge[1] = const_cast<int*>(el->getDOF(0));
      edge[0] = const_cast<int*>(el->getDOF(1));
158
    }
159 160 161 162

    coarse_list.setElement(0, el, true);

    n_neigh = 1;
163 164 165 166
    if (coarse_list.setElement(1, el_info->getNeighbour(2))) {
      n_neigh = 2;
      coarse_list.setCoarsePatch(1, el_info->getOppVertex(2) == 2);
    }
167
  
168
    // check wether we can coarsen the patch or not                            
169 170 171 172 173

    // ==========================================================================
    // === check for periodic boundary ==========================================
    // ==========================================================================

174
    if (coarse_list.doCoarsePatch(n_neigh)) {
175 176 177 178
      int n_neigh_periodic;
      DegreeOfFreedom *next_edge[2];
      RCNeighbourList *periodicList;

179
      while (edge[0] != NULL) {
180 181 182 183 184
	periodicList = coarse_list.periodicSplit(edge, 
						 next_edge,
						 &n_neigh,
						 &n_neigh_periodic);

185
	TEST_EXIT_DBG(periodicList)("periodicList = NULL\n");
186 187 188 189 190 191 192 193 194 195 196 197

	coarsenPatch(periodicList, n_neigh_periodic, bound);

	edge[0] = next_edge[0];
	edge[1] = next_edge[1];
      }
    }

    return 0;
  }

}