DOFAdmin.cc 9.69 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
#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(); }

  DOFAdmin::DOFAdmin(Mesh* m,::std::string aName) 
    : 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
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

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

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

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

    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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

    return(dof);
  }


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

  void DOFAdmin::enlargeDOFLists(int minsize)
  {
    FUNCNAME("DOFAdmin::enlargeDOFLists");
    int              old, newval; //, i, j;
  
    old = size;
    if (minsize > 0) {
      if (old > minsize) return;
    }
  
    newval = max(minsize, static_cast<int>((dofFree.size() + sizeIncrement)));

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

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

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

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

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

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

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

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

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

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

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


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

  void DOFAdmin::compress(::std::vector<DegreeOfFreedom> &new_dof)
  {
237
238
    FUNCNAME("DOFAdmin::compress()");
    int i,n,first,last=0;
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261

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

    // vector to mark used dofs
    for(i=0; i < size; i++) {
      new_dof[i] = -1;
    }

    // mark used dofs
    DOFIteratorBase it(this, USED_DOFS);
    for (it.reset(); !it.end(); ++it) new_dof[it.getDOFIndex()] = 1;
  
    n = 0;
    for (i = 0; i < size; i++) {             /* create a MONOTONE compress */
      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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  
    // mark used dofs in compressed dofFree
    for(i=0; i < n; i++) {
      dofFree[i] = false;
    }
    // mark unused dofs in compressed dofFree
    for(i=n; i < size; i++) {
      dofFree[i] = true;
    }

    firstHole = n;  
    holeCount = 0;
    sizeUsed  = n;
  
    // get index of first changed dof
    first = last;
    for (i=0; i<size; i++) {
      if ((new_dof[i] < i) && (new_dof[i] >= 0)) {
	first = i;
	break;
      }
    }

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

  
    ::std::list<DOFContainer*>::iterator dc;
    ::std::list<DOFContainer*>::iterator endc = dofContainerList.end();
    for(dc = dofContainerList.begin(); dc != endc; dc++) {
      (*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
315
316
317
318
319
320
321
322
323
324
325
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
352
353
354
355
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
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  }

  DOFAdmin::~DOFAdmin()
  {
  }

  void DOFAdmin::serialize(::std::ostream &out) 
  {
    // write name
    out << name << ::std::endl;

    // write dofFree
    int i;
    int s = static_cast<int>(dofFree.size());
    out.write(reinterpret_cast<const char*>(&s), sizeof(int));
    for (i = 0; i < s; i++) {
      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);
}

  void DOFAdmin::deserialize(::std::istream &in)
  {
    // read name
    in >> name;
    in.get();

    // read dofFree
    int i;
    int s;
    in.read(reinterpret_cast<char*>(&s), sizeof(int));
    dofFree.resize(s);
    for (i = 0; i < s; i++) {
      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);

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

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

}