DOFAdmin.cc 10 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 <algorithm>

#include "QPsiPhi.h"
#include "BasisFunction.h"
#include "Boundary.h"
#include "DOFAdmin.h"
#include "ElInfo.h"
#include "Error.h"
#include "FiniteElemSpace.h"
#include "Mesh.h"
#include "DOFVector.h"
#include "DOFIterator.h"

namespace AMDiS {

  const int DOFAdmin::sizeIncrement = 10;

  DOFAdmin::DOFAdmin(Mesh* m) 
    : mesh(m), 
      nrDOF(mesh->getDim(), NO_INIT),
      nr0DOF(mesh->getDim(), NO_INIT)
Thomas Witkowski's avatar
Thomas Witkowski committed
22 23 24
  { 
    init(); 
  }
25

26
  DOFAdmin::DOFAdmin(Mesh* m, std::string aName) 
27 28 29 30 31 32 33 34
    : name(aName), 
      mesh(m), 
      nrDOF(mesh->getDim(), NO_INIT),
      nr0DOF(mesh->getDim(), NO_INIT)
  { 
    init(); 
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
35 36 37
  DOFAdmin::~DOFAdmin() 
  {}

38 39
  void DOFAdmin::init()
  {
40 41 42 43 44
    firstHole = 0;
    size = 0;
    usedCount = 0;
    holeCount = 0;
    sizeUsed = 0;
45 46 47
    dofFree.clear();
  }

48 49
  DOFAdmin& DOFAdmin::operator=(const DOFAdmin& src) 
  {
50 51 52 53 54 55 56 57 58
    if (this != &src) { 
      mesh = src.mesh;
      name = src.name;
      dofFree = src.dofFree;
      firstHole = src.firstHole;
      size = src.size;
      usedCount = src.usedCount;
      holeCount = src.holeCount;
      sizeUsed = src.sizeUsed;
59
      for (int i = 0; i <= mesh->getDim(); i++) {
60
	nrDOF[i] = src.nrDOF[i];
61
	nr0DOF[i] = src.nr0DOF[i];
62
      }
63 64
      dofIndexedList = src.dofIndexedList;
      dofContainerList = src.dofContainerList;
65
    }
66

67 68 69 70 71 72 73 74 75
    return *this;
  }
  /****************************************************************************/
  /*      use a bit vector to indicate used/unused dofs			    */
  /*      storage needed: one bit per dof                     		    */
  /****************************************************************************/

  bool DOFAdmin::operator==(const DOFAdmin& ad) const
  {
76 77 78 79 80
    if (name != ad.name) 
      return false;
    if (mesh != ad.mesh) 
      return false;

81 82 83 84 85
    return true;
  }


  DOFAdmin::DOFAdmin(const DOFAdmin&)
86
  {
87 88 89
    FUNCNAME("DOFAdmin::DOFAdmin()");

    ERROR_EXIT("TODO\n");
90
  }
91 92

  void DOFAdmin::freeDOFIndex(int dof) {
93
    FUNCNAME("DOFAdmin::freeDOFIndex()");
94

95 96
    TEST_EXIT_DBG(usedCount > 0)("no dofs in use\n");
    TEST_EXIT_DBG((dof >= 0) && (dof < size))("invalid dof index %d\n",dof);
97

98 99
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
100

101
    for (di = dofIndexedList.begin(); di != end; ++di) {
102 103 104
      (*di)->freeDOFContent(dof);
    }

105 106
    std::list<DOFContainer*>::iterator dc;
    std::list<DOFContainer*>::iterator dcend = dofContainerList.end();
107

108
    for (dc = dofContainerList.begin(); dc != dcend; ++dc) {
109 110 111 112 113
      (*dc)->freeDOFIndex(dof);
    }

    dofFree[dof] = true;

114 115
    if (static_cast<int>(firstHole) > dof) 
      firstHole = dof;
116 117 118 119 120 121 122 123 124

    usedCount--;
    holeCount++;
  }

  /****************************************************************************/

  int DOFAdmin::getDOFIndex()
  {
125
    FUNCNAME("DOFAdmin::getDOFIndex()");
126
    int dof = 0;
127 128 129

    // if there is a hole
    if (firstHole < static_cast<int>(dofFree.size())) {
130
      TEST_EXIT_DBG(dofFree[firstHole])("no hole at firstHole!\n");
131 132 133 134 135
      // its no longer a hole
      dofFree[firstHole] = false;
      dof = firstHole;
      // search new hole
      int dfsize = static_cast<int>(dofFree.size());
136 137
      int i = firstHole + 1;
      for (; i < dfsize; i++) {
138 139 140 141 142
	if (dofFree[i]) {
	  break;
	}
      }
      firstHole = i;
143
    } else {                    // if there is no hole
144 145
      // enlarge dof-list
      enlargeDOFLists(0);
146
      TEST_EXIT_DBG(firstHole < static_cast<int>(dofFree.size()))
147
	("no free entry after enlargeDOFLists\n");
148
      TEST_EXIT_DBG(dofFree[firstHole])
149 150 151 152 153 154 155
	("no free bit at firstHole\n");
      dofFree[firstHole] = false;
      dof = firstHole;
      firstHole++;
    }

    usedCount++;
156 157 158
    if (holeCount > 0) 
      holeCount--;
    sizeUsed = max(sizeUsed, dof + 1);
159 160 161 162 163 164 165 166 167

    return(dof);
  }


  /****************************************************************************/

  void DOFAdmin::enlargeDOFLists(int minsize)
  {
168
    FUNCNAME("DOFAdmin::enlargeDOFLists()");
169
  
170
    int old = size;
171 172 173 174
    if (minsize > 0) {
      if (old > minsize) return;
    }
  
175
    int newval = max(minsize, static_cast<int>((dofFree.size() + sizeIncrement)));
176 177 178 179 180 181 182 183 184 185 186

    size = newval;
  
    // stl resizes dofFree to at least newval and sets all new values true
    dofFree.resize(newval, true);

    firstHole = old;
  
    // enlarge all vectors and matrices
    // but DOFVectors<int> don't have to be changed
  
187 188
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
189

190 191
    for (di = dofIndexedList.begin(); di != end; ++di) {
      if ((*di)->getSize() < newval) {
192 193 194 195 196 197
	(*di)->resize(newval);
      }
    }
  }

  void DOFAdmin::addDOFIndexed(DOFIndexedBase* dofIndexed) {
198
    FUNCNAME("DOFAdmin::addDOFIndexed()");
199

200
    TEST_EXIT(dofIndexed)("no dofIndexed\n");
201

202 203 204 205 206 207 208 209 210 211
#ifdef _OPENMP
#pragma omp critical (dofIndexAccess)
#endif
    {
      if (dofIndexed->getSize() < size) {
	dofIndexed->resize(size);
      }
      
      dofIndexedList.push_back(dofIndexed);
    }
212 213 214 215
  }

  void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed)
  {
216 217
    FUNCNAME("DOFAdmin::removeDOFIndexed()");

218 219 220 221 222 223 224 225 226 227 228 229 230
    bool removed = false;
#ifdef _OPENMP
#pragma omp critical (dofIndexAccess)
#endif
    {
      std::list<DOFIndexedBase*>::iterator it;
      std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
      for (it = dofIndexedList.begin(); it != end; ++it) {
	if (*it == dofIndexed) {
	  dofIndexedList.erase(it);
	  removed = true;
	  break;
	}
231 232
      }
    }
233

234
    TEST_EXIT(removed)("DOFIndexed not in list\n");
235 236 237 238
  }

  void DOFAdmin::addDOFContainer(DOFContainer* cont)
  {
239
    FUNCNAME("DOFAdmin::addDOFContainer()");
240
    TEST_EXIT_DBG(cont)("no container\n");
241 242 243 244 245
    dofContainerList.push_back(cont);  
  }

  void DOFAdmin::removeDOFContainer(DOFContainer* cont)
  {
246 247
    FUNCNAME("DOFAdmin::removeDOFContainer()");

248 249
    std::list<DOFContainer*>::iterator it;
    std::list<DOFContainer*>::iterator end = dofContainerList.end();
250 251
    for (it = dofContainerList.begin(); it != end; ++it) {
      if (*it == cont) {
252 253 254 255 256 257 258 259 260 261
	dofContainerList.erase(it);
	return;
      }
    }
    ERROR("container not in list\n");
  }


  /****************************************************************************/

262
  void DOFAdmin::compress(std::vector<DegreeOfFreedom> &new_dof)
263
  {
264
    FUNCNAME("DOFAdmin::compress()");
265 266 267 268 269 270 271

    // nothing to do ?
    if (size < 1) return;
    if (usedCount < 1) return;
    if (holeCount < 1) return;

    // vector to mark used dofs
272
    for (int i = 0; i < size; i++) {
273 274 275 276 277
      new_dof[i] = -1;
    }

    // mark used dofs
    DOFIteratorBase it(this, USED_DOFS);
278 279 280
    for (it.reset(); !it.end(); ++it) {
      new_dof[it.getDOFIndex()] = 1;
    }
281
  
282 283
    int n = 0, last = 0;
    for (int i = 0; i < size; i++) {             /* create a MONOTONE compress */
284 285 286 287 288 289
      if (new_dof[i] == 1) {
	new_dof[i] = n++;
	last = i;
      }
    }
  
290
    TEST_EXIT_DBG(n == usedCount)("count %d != usedCount %d\n", n, usedCount);
291 292
  
    // mark used dofs in compressed dofFree
293
    for (int i = 0; i < n; i++) {
294 295 296
      dofFree[i] = false;
    }
    // mark unused dofs in compressed dofFree
297
    for (int i = n; i < size; i++) {
298 299 300 301 302 303 304 305
      dofFree[i] = true;
    }

    firstHole = n;  
    holeCount = 0;
    sizeUsed  = n;
  
    // get index of first changed dof
306 307
    int first = last;
    for (int i = 0; i<size; i++) {
308 309 310 311 312 313
      if ((new_dof[i] < i) && (new_dof[i] >= 0)) {
	first = i;
	break;
      }
    }

314 315 316
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
    for (di = dofIndexedList.begin(); di != end; ++di) {
317 318 319 320
      (*di)->compressDOFIndexed(first, last, new_dof);
    };

  
321 322 323
    std::list<DOFContainer*>::iterator dc;
    std::list<DOFContainer*>::iterator endc = dofContainerList.end();
    for (dc = dofContainerList.begin(); dc != endc; dc++) {
324 325 326 327 328 329 330
      (*dc)->compressDOFContainer(n, new_dof);
    };  

    return;
  }

  void DOFAdmin::setNumberOfDOFs(int i,int v) { 
331
    TEST_EXIT_DBG((0 <= i) && (4 > i))("");
332 333

    nrDOF[i] = v; 
334 335 336
  }

  void DOFAdmin::setNumberOfPreDOFs(int i, int v) { 
337
    TEST_EXIT_DBG((0 <= i) && (4 > i))(""); 
338 339

    nr0DOF[i] = v; 
340 341
  }

342 343 344 345 346
  int DOFAdmin::calcMemoryUsage()
  {
    return sizeof(DOFAdmin);
  }

347
  void DOFAdmin::serialize(std::ostream &out) 
348 349
  {
    // write name
Thomas Witkowski's avatar
Thomas Witkowski committed
350
    out << name << "\n";
351 352 353 354

    // write dofFree
    int s = static_cast<int>(dofFree.size());
    out.write(reinterpret_cast<const char*>(&s), sizeof(int));
355
    for (int i = 0; i < s; i++) {
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
      bool free = dofFree[i];
      out.write(reinterpret_cast<const char*>(&free), sizeof(bool));
    }

    // write firstHole
    out.write(reinterpret_cast<const char*>(&firstHole), sizeof(unsigned int));

    // write size
    out.write(reinterpret_cast<const char*>(&size), sizeof(int));

    // write usedCount
    out.write(reinterpret_cast<const char*>(&usedCount), sizeof(int));

    // write holeCount
    out.write(reinterpret_cast<const char*>(&holeCount), sizeof(int));

    // write sizeUsed
    out.write(reinterpret_cast<const char*>(&sizeUsed), sizeof(int));

    // write nrDOF
    nrDOF.serialize(out);

    // write nr0DOF
    nr0DOF.serialize(out);
}

382
  void DOFAdmin::deserialize(std::istream &in)
383 384 385 386 387 388 389 390 391
  {
    // read name
    in >> name;
    in.get();

    // read dofFree
    int s;
    in.read(reinterpret_cast<char*>(&s), sizeof(int));
    dofFree.resize(s);
392
    for (int i = 0; i < s; i++) {
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418
      bool free;
      in.read(reinterpret_cast<char*>(&free), sizeof(bool));
      dofFree[i] = free;
    }

    // read firstHole
    in.read(reinterpret_cast<char*>(&firstHole), sizeof(unsigned int));

    // read size
    in.read(reinterpret_cast<char*>(&size), sizeof(int));

    // read usedCount
    in.read(reinterpret_cast<char*>(&usedCount), sizeof(int));

    // read holeCount
    in.read(reinterpret_cast<char*>(&holeCount), sizeof(int));

    // read sizeUsed
    in.read(reinterpret_cast<char*>(&sizeUsed), sizeof(int));

    // read nrDOF
    nrDOF.deserialize(in);

    // read nr0DOF
    nr0DOF.deserialize(in);

419 420
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
421

422
    for (di = dofIndexedList.begin(); di != end; ++di) {
423 424 425 426 427
      (*di)->resize(size);
    }
  }

}