DOFAdmin.cc 9.63 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
#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;

  void DOFAdmin::init()
  {
    firstHole = size = usedCount = holeCount = sizeUsed = 0;
    dofFree.clear();
  }


  DOFAdmin::DOFAdmin(Mesh* m) 
    : mesh(m), 
      nrDOF(mesh->getDim(), NO_INIT),
      nr0DOF(mesh->getDim(), NO_INIT)
  { init(); }

31
  DOFAdmin::DOFAdmin(Mesh* m,std::string aName) 
32
33
34
35
36
37
38
39
40
41
    : name(aName), 
      mesh(m), 
      nrDOF(mesh->getDim(), NO_INIT),
      nr0DOF(mesh->getDim(), NO_INIT)
  { 
    init(); 
  }

  DOFAdmin& DOFAdmin::operator=(const DOFAdmin& src) 
  {
42
43
44
45
46
47
48
49
50
51
52
    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;
      for (int i = 0; i < 4; nrDOF[i] = src.nrDOF[i++]) {
	nr0DOF[i] = src.nr0DOF[i];
53
      };
54
55
      dofIndexedList = src.dofIndexedList;
      dofContainerList = src.dofContainerList;
56
57
58
59
60
61
62
63
64
65
    }
    return *this;
  }
  /****************************************************************************/
  /*      use a bit vector to indicate used/unused dofs			    */
  /*      storage needed: one bit per dof                     		    */
  /****************************************************************************/

  bool DOFAdmin::operator==(const DOFAdmin& ad) const
  {
66
67
68
69
70
    if (name != ad.name) 
      return false;
    if (mesh != ad.mesh) 
      return false;

71
72
73
74
75
76
77
78
    return true;
  }


  DOFAdmin::DOFAdmin(const DOFAdmin&)
  {}

  void DOFAdmin::freeDOFIndex(int dof) {
79
    FUNCNAME("DOFAdmin::freeDOFIndex()");
80

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

84
85
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
86
87
88
89
90

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

91
92
    std::list<DOFContainer*>::iterator dc;
    std::list<DOFContainer*>::iterator dcend = dofContainerList.end();
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110

    for(dc = dofContainerList.begin(); dc != dcend; ++dc) {
      (*dc)->freeDOFIndex(dof);
    }

    dofFree[dof] = true;

    if (static_cast<int>(firstHole) > dof) firstHole = dof;

    usedCount--;
    holeCount++;
  }

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

  int DOFAdmin::getDOFIndex()
  {
    FUNCNAME("DOFAdmin::getDOFIndex");
111
    int dof = 0;
112
113
114

    // if there is a hole
    if (firstHole < static_cast<int>(dofFree.size())) {
115
      TEST_EXIT_DBG(dofFree[firstHole])("no hole at firstHole!\n");
116
117
118
119
120
      // its no longer a hole
      dofFree[firstHole] = false;
      dof = firstHole;
      // search new hole
      int dfsize = static_cast<int>(dofFree.size());
121
122
      int i = 0;
      for (i = firstHole + 1; i < dfsize; i++) {
123
124
125
126
127
	if (dofFree[i]) {
	  break;
	}
      }
      firstHole = i;
128
    } else {                    // if there is no hole
129
130
      // enlarge dof-list
      enlargeDOFLists(0);
131
      TEST_EXIT_DBG(firstHole < static_cast<int>(dofFree.size()))
132
	("no free entry after enlargeDOFLists\n");
133
      TEST_EXIT_DBG(dofFree[firstHole])
134
135
136
137
138
139
140
	("no free bit at firstHole\n");
      dofFree[firstHole] = false;
      dof = firstHole;
      firstHole++;
    }

    usedCount++;
141
142
143
    if (holeCount > 0) 
      holeCount--;
    sizeUsed = max(sizeUsed, dof + 1);
144
145
146
147
148
149
150
151
152
153
154

    return(dof);
  }


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

  void DOFAdmin::enlargeDOFLists(int minsize)
  {
    FUNCNAME("DOFAdmin::enlargeDOFLists");
  
155
    int old = size;
156
157
158
159
    if (minsize > 0) {
      if (old > minsize) return;
    }
  
160
    int newval = max(minsize, static_cast<int>((dofFree.size() + sizeIncrement)));
161
162
163
164
165
166
167
168
169
170
171

    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
  
172
173
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
174

175
176
    for (di = dofIndexedList.begin(); di != end; ++di) {
      if ((*di)->getSize() < newval) {
177
178
179
180
181
182
	(*di)->resize(newval);
      }
    }
  }

  void DOFAdmin::addDOFIndexed(DOFIndexedBase* dofIndexed) {
183
184
    FUNCNAME("DOFAdmin::addDOFIndexed()");
    TEST_EXIT_DBG(dofIndexed)("no dofIndexed\n");
185

186
    if (dofIndexed->getSize() < size) {
187
188
      dofIndexed->resize(size);
    }
189

190
191
192
193
194
    dofIndexedList.push_back(dofIndexed);
  }

  void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed)
  {
195
196
    FUNCNAME("DOFAdmin::removeDOFIndexed()");

197
198
    std::list<DOFIndexedBase*>::iterator it;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
199
200
    for (it = dofIndexedList.begin(); it != end; ++it) {
      if (*it == dofIndexed) {
201
202
203
204
	dofIndexedList.erase(it);
	return;
      }
    }
205

206
207
208
209
210
    ERROR("DOFIndexed not in list\n");
  }

  void DOFAdmin::addDOFContainer(DOFContainer* cont)
  {
211
    FUNCNAME("DOFAdmin::addDOFContainer()");
212
    TEST_EXIT_DBG(cont)("no container\n");
213
214
215
216
217
    dofContainerList.push_back(cont);  
  }

  void DOFAdmin::removeDOFContainer(DOFContainer* cont)
  {
218
219
    FUNCNAME("DOFAdmin::removeDOFContainer()");

220
221
    std::list<DOFContainer*>::iterator it;
    std::list<DOFContainer*>::iterator end = dofContainerList.end();
222
223
    for (it = dofContainerList.begin(); it != end; ++it) {
      if (*it == cont) {
224
225
226
227
228
229
230
231
232
233
	dofContainerList.erase(it);
	return;
      }
    }
    ERROR("container not in list\n");
  }


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

234
  void DOFAdmin::compress(std::vector<DegreeOfFreedom> &new_dof)
235
  {
236
    FUNCNAME("DOFAdmin::compress()");
237
238
239
240
241
242
243

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

    // vector to mark used dofs
244
    for (int i = 0; i < size; i++) {
245
246
247
248
249
      new_dof[i] = -1;
    }

    // mark used dofs
    DOFIteratorBase it(this, USED_DOFS);
250
251
252
    for (it.reset(); !it.end(); ++it) {
      new_dof[it.getDOFIndex()] = 1;
    }
253
  
254
255
    int n = 0, last = 0;
    for (int i = 0; i < size; i++) {             /* create a MONOTONE compress */
256
257
258
259
260
261
      if (new_dof[i] == 1) {
	new_dof[i] = n++;
	last = i;
      }
    }
  
262
    TEST_EXIT_DBG(n == usedCount)("count %d != usedCount %d\n", n, usedCount);
263
264
  
    // mark used dofs in compressed dofFree
265
    for (int i = 0; i < n; i++) {
266
267
268
      dofFree[i] = false;
    }
    // mark unused dofs in compressed dofFree
269
    for (int i = n; i < size; i++) {
270
271
272
273
274
275
276
277
      dofFree[i] = true;
    }

    firstHole = n;  
    holeCount = 0;
    sizeUsed  = n;
  
    // get index of first changed dof
278
279
    int first = last;
    for (int i = 0; i<size; i++) {
280
281
282
283
284
285
      if ((new_dof[i] < i) && (new_dof[i] >= 0)) {
	first = i;
	break;
      }
    }

286
287
288
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
    for (di = dofIndexedList.begin(); di != end; ++di) {
289
290
291
292
      (*di)->compressDOFIndexed(first, last, new_dof);
    };

  
293
294
295
    std::list<DOFContainer*>::iterator dc;
    std::list<DOFContainer*>::iterator endc = dofContainerList.end();
    for (dc = dofContainerList.begin(); dc != endc; dc++) {
296
297
298
299
300
301
302
      (*dc)->compressDOFContainer(n, new_dof);
    };  

    return;
  }

  void DOFAdmin::setNumberOfDOFs(int i,int v) { 
303
    TEST_EXIT_DBG((0 <= i) && (4 > i))("");
304
305

    nrDOF[i] = v; 
306
307
308
  }

  void DOFAdmin::setNumberOfPreDOFs(int i, int v) { 
309
    TEST_EXIT_DBG((0 <= i) && (4 > i))(""); 
310
311

    nr0DOF[i] = v; 
312
313
314
  }

  DOFAdmin::~DOFAdmin()
315
  {}
316

317
  void DOFAdmin::serialize(std::ostream &out) 
318
319
  {
    // write name
320
    out << name << std::endl;
321
322
323
324

    // write dofFree
    int s = static_cast<int>(dofFree.size());
    out.write(reinterpret_cast<const char*>(&s), sizeof(int));
325
    for (int i = 0; i < s; i++) {
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
      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);
}

352
  void DOFAdmin::deserialize(std::istream &in)
353
354
355
356
357
358
359
360
361
  {
    // read name
    in >> name;
    in.get();

    // read dofFree
    int s;
    in.read(reinterpret_cast<char*>(&s), sizeof(int));
    dofFree.resize(s);
362
    for (int i = 0; i < s; i++) {
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
      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);

389
390
    std::list<DOFIndexedBase*>::iterator di;
    std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end();
391

392
    for (di = dofIndexedList.begin(); di != end; ++di) {
393
394
395
396
397
      (*di)->resize(size);
    }
  }

}