DOFAdmin.cc 9 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
//
// Software License for AMDiS
//
// Copyright (c) 2010 Dresden University of Technology 
// All rights reserved.
// Authors: Simon Vey, Thomas Witkowski et al.
//
// This file is part of AMDiS
//
// See also license.opensource.txt in the distribution.


13
14
15
16
17
18
19
20
21
22
23
24
#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"
25
#include "Serializer.h"
26
27
28
29
30
31
32

namespace AMDiS {

  const int DOFAdmin::sizeIncrement = 10;

  DOFAdmin::DOFAdmin(Mesh* m) 
    : mesh(m), 
33
34
      nDof(mesh->getDim(), NO_INIT),
      nPreDof(mesh->getDim(), NO_INIT)
Thomas Witkowski's avatar
Thomas Witkowski committed
35
36
37
  { 
    init(); 
  }
38

39

40
  DOFAdmin::DOFAdmin(Mesh* m, std::string aName) 
41
42
    : name(aName), 
      mesh(m), 
43
44
      nDof(mesh->getDim(), NO_INIT),
      nPreDof(mesh->getDim(), NO_INIT)
45
46
47
48
  { 
    init(); 
  }

49

Thomas Witkowski's avatar
Thomas Witkowski committed
50
51
52
  DOFAdmin::~DOFAdmin() 
  {}

53

54
55
  void DOFAdmin::init()
  {
56
57
58
59
60
    firstHole = 0;
    size = 0;
    usedCount = 0;
    holeCount = 0;
    sizeUsed = 0;
61
62
63
    dofFree.clear();
  }

64

65
66
  DOFAdmin& DOFAdmin::operator=(const DOFAdmin& src) 
  {
67
68
69
70
71
72
73
74
75
    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;
76
      for (int i = 0; i <= mesh->getDim(); i++) {
77
78
	nDof[i] = src.nDof[i];
	nPreDof[i] = src.nPreDof[i];
79
      }
80
81
      dofIndexedList = src.dofIndexedList;
      dofContainerList = src.dofContainerList;
82
    }
83

84
85
    return *this;
  }
86

87
88
89

  bool DOFAdmin::operator==(const DOFAdmin& ad) const
  {
90
91
92
93
94
    if (name != ad.name) 
      return false;
    if (mesh != ad.mesh) 
      return false;

95
96
97
98
99
    return true;
  }


  DOFAdmin::DOFAdmin(const DOFAdmin&)
100
  {
101
102
103
    FUNCNAME("DOFAdmin::DOFAdmin()");

    ERROR_EXIT("TODO\n");
104
  }
105

106
107

  void DOFAdmin::freeDofIndex(int dof) 
108
  {    
109
    FUNCNAME("DOFAdmin::freeDofIndex()");
110

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

114
115
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
116

117
    for (di = dofIndexedList.begin(); di != end; ++di)
118
119
      (*di)->freeDOFContent(dof);

120
121
    std::list<DOFContainer*>::iterator dc;
    std::list<DOFContainer*>::iterator dcend = dofContainerList.end();
122

123
    for (dc = dofContainerList.begin(); dc != dcend; ++dc)
124
      (*dc)->freeDofIndex(dof);
125
126

    dofFree[dof] = true;
127
    
128
129
    if (static_cast<int>(firstHole) > dof) 
      firstHole = dof;
130
131
132
133
134

    usedCount--;
    holeCount++;
  }

135

136
137
  int DOFAdmin::getDOFIndex()
  {
138
    FUNCNAME("DOFAdmin::getDOFIndex()");
139
    int dof = 0;
140
141

    // if there is a hole
142
    if (firstHole < static_cast<int>(dofFree.size())) {      
143
      TEST_EXIT_DBG(dofFree[firstHole])("no hole at firstHole!\n");
144
145
146
147
148
      // its no longer a hole
      dofFree[firstHole] = false;
      dof = firstHole;
      // search new hole
      int dfsize = static_cast<int>(dofFree.size());
149
      int i = firstHole + 1;
150
151
      for (; i < dfsize; i++)
	if (dofFree[i])
152
	  break;
153

154
      firstHole = i;
155
    } else {                    // if there is no hole
156
      // enlarge dof-list
157
      enlargeDofLists();
158

159
      TEST_EXIT_DBG(firstHole < static_cast<int>(dofFree.size()))
160
	("no free entry after enlargeDofLists\n");
161
      TEST_EXIT_DBG(dofFree[firstHole])("no free bit at firstHole\n");
162
163
164
165
166
167
      dofFree[firstHole] = false;
      dof = firstHole;
      firstHole++;
    }

    usedCount++;
168
169
    if (holeCount > 0) 
      holeCount--;
170
    sizeUsed = std::max(sizeUsed, dof + 1);
171

172
    return dof;
173
174
  }

175

176
  void DOFAdmin::enlargeDofLists(int minsize)
177
  {
178
    FUNCNAME("DOFAdmin::enlargeDofLists()");
179
  
180
    int old = size;
181
182
183
    if (minsize > 0)
      if (old > minsize) 
	return;
184
  
185
    int newval = std::max(minsize, static_cast<int>((dofFree.size() + sizeIncrement)));
186
187
188
189
190
191
192
193
194
195
196

    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
  
197
    std::list<DOFIndexedBase*>::iterator di;
198
    for (di = dofIndexedList.begin(); di != dofIndexedList.end(); ++di)
199
      if ((*di)->getSize() < newval)
200
 	(*di)->resize(newval);
201
202
  }

203

204
205
  void DOFAdmin::addDOFIndexed(DOFIndexedBase* dofIndexed) 
  {
206
    FUNCNAME("DOFAdmin::addDOFIndexed()");
207

208
    TEST_EXIT(dofIndexed)("no dofIndexed\n");
209

210
211
212
213
#ifdef _OPENMP
#pragma omp critical (dofIndexAccess)
#endif
    {
214
      if (dofIndexed->getSize() < size)
215
216
217
218
	dofIndexed->resize(size);
      
      dofIndexedList.push_back(dofIndexed);
    }
219
220
  }

221

222
223
  void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed)
  {
224
225
    FUNCNAME("DOFAdmin::removeDOFIndexed()");

226
227
228
229
230
231
232
233
234
235
236
237
238
    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;
	}
239
240
      }
    }
241

242
    TEST_EXIT(removed)("DOFIndexed not in list!\n");
243
244
  }

245

246
247
  void DOFAdmin::addDOFContainer(DOFContainer* cont)
  {
248
    FUNCNAME("DOFAdmin::addDOFContainer()");
249

250
    TEST_EXIT_DBG(cont)("no container\n");
251

252
253
254
    dofContainerList.push_back(cont);  
  }

255

256
257
  void DOFAdmin::removeDOFContainer(DOFContainer* cont)
  {
258
259
    FUNCNAME("DOFAdmin::removeDOFContainer()");

260
261
    std::list<DOFContainer*>::iterator it;
    std::list<DOFContainer*>::iterator end = dofContainerList.end();
262
263
    for (it = dofContainerList.begin(); it != end; ++it) {
      if (*it == cont) {
264
265
266
267
	dofContainerList.erase(it);
	return;
      }
    }
268
269

    ERROR("Container not in list!\n");
270
271
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
272

273
  void DOFAdmin::compress(std::vector<DegreeOfFreedom> &newDofIndex)
274
  {
275
    FUNCNAME("DOFAdmin::compress()");
276
277

    // nothing to do ?
Thomas Witkowski's avatar
Thomas Witkowski committed
278
279
    if (size < 1 || usedCount < 1 || holeCount < 1) 
      return;
280
281

    // vector to mark used dofs
282
    for (int i = 0; i < size; i++)
283
      newDofIndex[i] = -1;
284
285
286

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

304
    // mark unused dofs in compressed dofFree
305
    for (int i = n; i < size; i++)
306
307
308
309
310
311
312
      dofFree[i] = true;

    firstHole = n;  
    holeCount = 0;
    sizeUsed  = n;
  
    // get index of first changed dof
313
    int first = last;
314
    for (int i = 0; i < size; i++) {
315
      if (newDofIndex[i] < i && newDofIndex[i] >= 0) {
316
317
318
319
	first = i;
	break;
      }
    }
320
321
322
323
    
    for (std::list<DOFIndexedBase*>::iterator di = dofIndexedList.begin(); 
	 di != dofIndexedList.end(); ++di)
      (*di)->compressDOFIndexed(first, last, newDofIndex);
324

325
326
    for (std::list<DOFContainer*>::iterator dc = dofContainerList.begin(); 
	 dc != dofContainerList.end(); ++dc)
327
      (*dc)->compressDofContainer(n, newDofIndex);
328
329
  }

Thomas Witkowski's avatar
Thomas Witkowski committed
330

331
  void DOFAdmin::setNumberOfDofs(int i, int v) 
332
  { 
333
334
335
    FUNCNAME("DOFAdmin::setNumberOfDOFs()");

    TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n");
336

337
    nDof[i] = v; 
338
339
  }

340

341
  void DOFAdmin::setNumberOfPreDofs(int i, int v) 
342
  { 
343
344
345
    FUNCNAME("DOFAdmin::setNumberOfPreDOFs()");

    TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n"); 
346

347
    nPreDof[i] = v; 
348
349
  }

350

351
352
353
354
355
  int DOFAdmin::calcMemoryUsage()
  {
    return sizeof(DOFAdmin);
  }

356

357
  void DOFAdmin::serialize(std::ostream &out) 
358
359
  {
    // write name
Thomas Witkowski's avatar
Thomas Witkowski committed
360
    out << name << "\n";
361
362
363

    // write dofFree
    int s = static_cast<int>(dofFree.size());
364
    SerUtil::serialize(out, s);
365
    for (int i = 0; i < s; i++) {
366
367
      bool free = dofFree[i];     
      SerUtil::serialize(out, free);
368
369
    }

370
371
372
373
374
    SerUtil::serialize(out, firstHole);
    SerUtil::serialize(out, size);
    SerUtil::serialize(out, usedCount);
    SerUtil::serialize(out, holeCount);
    SerUtil::serialize(out, sizeUsed);
375

376
377
    nDof.serialize(out);
    nPreDof.serialize(out);
378
379
  }

380

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

    // read dofFree
    int s;
389
    SerUtil::deserialize(in, s);
390
    dofFree.resize(s);
391
    for (int i = 0; i < s; i++) {
392
      bool free;
393
      SerUtil::deserialize(in, free);
394
395
396
      dofFree[i] = free;
    }

397
398
399
400
401
    SerUtil::deserialize(in, firstHole);
    SerUtil::deserialize(in, size);
    SerUtil::deserialize(in, usedCount);
    SerUtil::deserialize(in, holeCount);
    SerUtil::deserialize(in, sizeUsed);
402

403
404
    nDof.deserialize(in);
    nPreDof.deserialize(in);
405

406
407
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
408

409
    for (di = dofIndexedList.begin(); di != end; ++di)
410
411
412
413
      (*di)->resize(size);
  }

}