OOFEM 3.0
Loading...
Searching...
No Matches
dofmanager.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
35#include "dofmanager.h"
36#include "masterdof.h"
37#include "simpleslavedof.h"
38#include "timestep.h"
39#include "load.h"
40#include "floatarray.h"
41#include "floatmatrix.h"
42#include "intarray.h"
43#include "classfactory.h"
44#include "datastream.h"
45#include "contextioerr.h"
46#include "mathfem.h"
47#include "dynamicinputrecord.h"
48#include "domain.h"
51#include "engngm.h"
52#include "paramkey.h"
53
54namespace oofem {
55
56
69
70
71DofManager :: DofManager(int n, Domain *aDomain) :
72 FEMComponent(n, aDomain), dofArray(), loadArray(),
75{
76 isBoundaryFlag = false;
77 hasSlaveDofs = false;
79}
80
81
82DofManager :: ~DofManager()
83{
84 for ( Dof *dof: dofArray ) {
85 delete dof;
86 }
87}
88
89
90IntArray *DofManager :: giveLoadArray()
91// Returns the list containing the number of every nodal loads that act on
92// the receiver. If this list does not exist yet, constructs it. This list
93// is not to be confused with the load vector.
94{
95 return & loadArray;
96}
97
98
99void DofManager :: setLoadArray(IntArray &la)
100{
101 this->loadArray = la;
102}
103
104
105void DofManager :: computeLoadVector(FloatArray &answer, Load *load, CharType type, TimeStep *tStep, ValueModeType mode)
106{
107 if ( load->giveBCGeoType() != NodalLoadBGT ) {
108 OOFEM_ERROR("incompatible load type applied");
109 }
110
111 answer.clear();
112 if ( type != ExternalForcesVector ) {
113 return;
114 }
115
116 if ( load->giveDofIDs().giveSize() == 0 ) {
117 load->computeComponentArrayAt(answer, tStep, mode);
118 } else {
119 answer.resize(this->giveNumberOfDofs());
120 FloatArray tmp;
121 load->computeComponentArrayAt(tmp, tStep, mode);
122 answer.assemble(tmp, load->giveDofIDs());
123 }
124}
125
126
127Dof *DofManager :: giveDofWithID(int dofID) const
128// Returns the degree of freedom of the receiver with 'dofID'.
129{
130 auto pos = this->findDofWithDofId( ( DofIDItem ) dofID );
131
132#ifdef DEBUG
133 if ( pos == this->end() ) {
134 OOFEM_ERROR("dof with given DofID does not exists");
135 }
136#endif
137
138 return *pos;
139}
140
141
142void DofManager :: appendDof(Dof *dof)
143// appends a Dof to the end position in dofArray
144// because dofArray is not resizeable, the data need
145// to be copied out of the dofArray, dofArray deleted
146// and again constructed with new Dof
147{
148#ifdef DEBUG
149 // check if dofID of DOF to be added not already present
150 if ( this->findDofWithDofId( dof->giveDofID() ) != this->end() ) {
151 OOFEM_ERROR("DOF with dofID %d already present (dofman %d)", dof->giveDofID(), this->number);
152 }
153#endif
154
155 this->dofArray.push_back(dof);
156}
157
158
159void DofManager :: removeDof(DofIDItem id)
160{
161 int i = 0;
162 for ( Dof *dof: *this ) {
163 if ( dof->giveDofID() == id ) {
164 delete dof;
165 this->dofArray.erase( i + this->begin() );
166 return;
167 }
168 i++;
169 }
170 OOFEM_WARNING("no DOF with dofID %d found", id);
171}
172
173
174bool DofManager :: hasDofID(DofIDItem id) const
175{
176 for ( Dof *dof: *this ) {
177 if ( dof->giveDofID() == id ) {
178 return true;
179 }
180 }
181 return false;
182}
183
184
185void DofManager :: giveLocationArray(const IntArray &dofIDArry, IntArray &locationArray, const UnknownNumberingScheme &s) const
186{
187 if ( !hasSlaveDofs ) {
188 int size;
189 // prevents some size problem when connecting different elements with
190 // different number of dofs
191 size = dofIDArry.giveSize();
192 locationArray.resize(size);
193 for ( int i = 1; i <= size; i++ ) {
194 auto pos = this->findDofWithDofId( ( DofIDItem ) dofIDArry.at(i) );
195 if ( pos == this->end() ) {
196 OOFEM_ERROR("incompatible dof (%d) requested", dofIDArry.at(i));
197 }
198
199 locationArray.at(i) = s.giveDofEquationNumber( *pos );
200 }
201 } else {
202 IntArray mstrEqNmbrs;
203 locationArray.clear();
204
205 for ( int dofid: dofIDArry ) {
206 auto pos = this->findDofWithDofId( ( DofIDItem ) dofid );
207 if ( pos == this->end() ) {
208 OOFEM_ERROR("incompatible dof (%d) requested", dofid);
209 }
210 (*pos)->giveEquationNumbers(mstrEqNmbrs, s);
211 locationArray.followedBy(mstrEqNmbrs);
212 }
213 }
214}
215
216
217void DofManager :: giveMasterDofIDArray(const IntArray &dofIDArry, IntArray &masterDofIDs) const
218{
219 if ( !hasSlaveDofs ) {
220 masterDofIDs = dofIDArry;
221 } else {
222 IntArray temp;
223 masterDofIDs.clear();
224
225 for ( int dofid: dofIDArry ) {
226 auto pos = this->findDofWithDofId( ( DofIDItem ) dofid );
227 if ( pos == this->end() ) {
228 OOFEM_ERROR("incompatible dof (%d) requested", dofid);
229 }
230 (*pos)->giveDofIDs(temp);
231 masterDofIDs.followedBy(temp);
232 }
233 }
234}
235
236
237void DofManager :: giveCompleteLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s) const
238{
239 if ( !hasSlaveDofs ) {
240 // prevents some size problem when connecting different elements with
241 // different number of dofs
242 locationArray.resizeWithValues(0, this->giveNumberOfDofs());
243 for ( Dof *dof: *this ) {
244 locationArray.followedBy( s.giveDofEquationNumber( dof ) );
245 }
246 } else {
247 IntArray temp;
248 locationArray.resize(0);
249 for ( Dof *dof: *this ) {
250 dof->giveEquationNumbers(temp, s);
251 locationArray.followedBy(temp);
252 }
253 }
254}
255
256
257void DofManager :: giveCompleteMasterDofIDArray(IntArray &dofIDArray) const
258{
259 if ( !hasSlaveDofs ) {
260 dofIDArray.resizeWithValues(0, this->giveNumberOfDofs());
261 for ( Dof *dof: *this ) {
262 dofIDArray.followedBy( dof->giveDofID() );
263 }
264 } else {
265 IntArray temp;
266 for ( Dof *dof: *this ) {
267 dof->giveDofIDs(temp);
268 dofIDArray.followedBy(temp);
269 }
270 }
271}
272
273
274std :: vector< Dof* > :: const_iterator DofManager :: findDofWithDofId(DofIDItem dofID) const
275{
276 int i = 0;
277 for ( Dof *dof: *this ) {
278 if ( dof->giveDofID() == dofID ) {
279 return this->begin() + i;
280 }
281 i++;
282 }
283 return this->end();
284}
285
286
287int DofManager :: giveNumberOfDofs() const
288// Returns the number of degrees of freedom of the receiver.
289{
290 return (int)dofArray.size();
291}
292
293
294void DofManager :: setNumberOfDofs(int _ndofs)
295{
296 for ( Dof *dof: *this ) {
297 delete dof;
298 }
299 this->dofArray.assign(_ndofs, NULL);
300}
301
302
303void DofManager :: askNewEquationNumbers(TimeStep *tStep)
304{
305 for ( Dof *dof: *this ) {
306 dof->askNewEquationNumber(tStep);
307 }
308}
309
310
311int DofManager :: giveNumberOfPrimaryMasterDofs(const IntArray &dofIDArray) const
312{
313 if ( !hasSlaveDofs ) {
314 return dofIDArray.giveSize();
315 }
316
317 int answer = 0;
318
319 for ( int dofid: dofIDArray ) {
320 auto pos = this->findDofWithDofId((DofIDItem)dofid);
321#ifdef DEBUG
322 if ( pos == this->end() ) {
323 OOFEM_ERROR("Dof with ID %d doesn't exist", dofid);
324 }
325#endif
326 answer += (*pos)->giveNumberOfPrimaryMasterDofs();
327 }
328
329 return answer;
330}
331
332
333void
334DofManager :: initializeFrom(InputRecord &ir, int priority)
335{
336 bool boundaryFlag, sharedFlag, remoteFlag, nullFlag;
337 ParameterManager &ppm = this->giveDomain()->dofmanPPM;
338 PM_UPDATE_PARAMETER(loadArray, ppm, ir, this->number, IPK_DofManager_load, priority) ;
339
341 PM_UPDATE_PARAMETER(mBC, ppm, ir, this->number, IPK_DofManager_bc, priority) ;
342 PM_UPDATE_TEMP_PARAMETER(IntArray, ppm, ir, this->number, IPK_DofManager_ic, priority) ;
344 PM_CHECK_FLAG_AND_REPORT(ppm, ir, this->number, IPK_DofManager_boundaryflag, priority, boundaryFlag) ;
345 if ( boundaryFlag ) {
346 isBoundaryFlag = true;
347 }
349 PM_CHECK_FLAG_AND_REPORT(ppm, ir, this->number, IPK_DofManager_sharedflag, priority, sharedFlag) ;
350 PM_CHECK_FLAG_AND_REPORT(ppm, ir, this->number, IPK_DofManager_remoteflag, priority, remoteFlag) ;
351 PM_CHECK_FLAG_AND_REPORT(ppm, ir, this->number, IPK_DofManager_nullflag, priority, nullFlag) ;
352 if ( sharedFlag ) {
354 } else if ( remoteFlag ) {
356 } else if ( nullFlag ) {
358 } else {
360 }
362
363
364
365}
366
367void DofManager :: initializeFinish()
368{
369 IntArray dofIDArry;
370 ParameterManager &ppm = this->giveDomain()->dofmanPPM;
371
372 if ( ppm.checkIfSet(this->number, IPK_DofManager_dofidmask.getIndex()) ) {
373 dofIDArry = dofidmask;
374 } else {
375 dofIDArry = domain->giveDefaultNodeDofIDArry();
376 }
377
378 bool hasBc, hasIc, hasTypeinfo;
379 hasBc = ppm.checkIfSet(this->number, IPK_DofManager_bc.getIndex());
380 hasIc = ppm.checkIfSet(this->number, IPK_DofManager_ic.getIndex());
381 hasTypeinfo = ppm.checkIfSet(this->number, IPK_DofManager_doftypemask.getIndex());
382
383 if ((hasIc || hasBc || hasTypeinfo) && dofidmask.isEmpty()) {
384 this->dofidmask = dofIDArry;
385 }
386
387 if ( hasBc ) {
388 if ( mBC.giveSize() != dofIDArry.giveSize() ) {
389 OOFEM_ERROR("bc size mismatch. Size is %d and need %d", mBC.giveSize(), dofIDArry.giveSize());
390 }
391 this->dofBCmap.clear();
392 for ( int i = 1; i <= mBC.giveSize(); ++i ) {
393 if ( mBC.at(i) > 0 ) {
394 ( this->dofBCmap ) [ dofIDArry.at(i) ] = mBC.at(i);
395 }
396 }
397 }
398
399 if ( hasIc ) {
400 auto val = ppm.getTempParam(this->number, IPK_DofManager_ic.getIndex());
401 IntArray ic (std::get<IntArray>(*val));
402 if ( ic.giveSize() != dofIDArry.giveSize() ) {
403 OOFEM_ERROR("ic size mismatch. Size is %d and need %d", ic.giveSize(), dofIDArry.giveSize());
404 }
405 this->dofICmap.clear();
406 for ( int i = 1; i <= ic.giveSize(); ++i ) {
407 if ( ic.at(i) > 0 ) {
408 ( this->dofICmap ) [ dofIDArry.at(i) ] = ic.at(i);
409 }
410 }
411 }
412
413 if ( hasTypeinfo ) {
414 auto val = ppm.getTempParam(this->number, IPK_DofManager_doftypemask.getIndex());
415 IntArray dofTypeMask (std::get<IntArray>(*val));
416 if ( dofTypeMask.giveSize() != dofIDArry.giveSize() ) {
417 OOFEM_ERROR("dofTypeMask size mismatch. Size is %d and need %d", dofTypeMask.giveSize(), dofIDArry.giveSize());
418 }
419
420 this->dofTypemap.clear();
421 for ( int i = 1; i <= dofidmask.giveSize(); ++i ) {
422 if ( dofTypeMask.at(i) != DT_master ) {
423 ( this->dofTypemap ) [ dofIDArry.at(i) ] = dofTypeMask.at(i);
424 }
425 }
426 // For simple slave dofs:
427 if ( dofTypeMask.contains(DT_simpleSlave) ) {
428 // get mastermask from temp storage
429 auto val = ppm.getTempParam(this->number, IPK_DofManager_mastermask.getIndex());
430 IntArray masterMask (std::get<IntArray>(*val));
431 if ( masterMask.giveSize() != dofIDArry.giveSize() ) {
432 OOFEM_ERROR("mastermask size mismatch");
433 }
434 this->dofMastermap.clear();
435 for ( int i = 1; i <= masterMask.giveSize(); ++i ) {
436 if ( masterMask.at(i) > 0 ) {
437 ( this->dofMastermap ) [ dofIDArry.at(i) ] = masterMask.at(i);
438 }
439 }
440 }
441 }
442}
443
444void DofManager :: postInitialize()
445{
446 hasSlaveDofs = false;
447 for ( Dof *dof: *this ) {
448 if ( !dof->isPrimaryDof() ) {
449 hasSlaveDofs = true;
450 continue;
451 }
452 }
453}
454
455void DofManager :: giveInputRecord(DynamicInputRecord &input)
456{
457 FEMComponent :: giveInputRecord(input);
458
459 IntArray mbc, dofids;
460 // Ignore here mBC and dofidmask as they may not correspod to actual state.
461 // They just decribe the state at init, but after some dofs may have been
462 // added dynamically (xfem, subdivision, etc).
463 for ( Dof *dof: *this ) {
464 dofids.followedBy(dof->giveDofID(),3);
465 if (dof->giveBcId()) mbc.followedBy(dof->giveBcId(),3);
466 else mbc.followedBy(0,3);
467 }
468 input.setField(mbc, IPK_DofManager_bc.getNameCStr());
469 input.setField(dofids, IPK_DofManager_dofidmask.getNameCStr());
470
471
472 if ( !this->dofTypemap.empty() ) {
473 IntArray typeMask( this->dofidmask.giveSize() );
474 for ( int i = 1; i <= dofidmask.giveSize(); ++i ) {
475 typeMask.at(i) = this->dofTypemap[ dofidmask.at(i) ];
476 }
477 input.setField(typeMask, IPK_DofManager_doftypemask.getNameCStr());
478 }
479
480 if ( !this->dofMastermap.empty() ) {
481 IntArray masterMask( this->dofidmask.giveSize() );
482 for ( int i = 1; i <= dofidmask.giveSize(); ++i ) {
483 masterMask.at(i) = this->dofMastermap[ dofidmask.at(i) ];
484 }
485 input.setField(masterMask, IPK_DofManager_mastermask.getNameCStr());
486 }
487
488 if ( isBoundaryFlag ) {
489 input.setField(IPK_DofManager_boundaryflag.getNameCStr());
490 }
491
492
493 if ( this->partitions.giveSize() > 0 ) {
494 input.setField(this->partitions, IPK_DofManager_partitions.getNameCStr());
495 }
496
498 input.setField(IPK_DofManager_sharedflag.getNameCStr());
499 } else if ( parallel_mode == DofManager_remote ) {
500 input.setField(IPK_DofManager_remoteflag.getNameCStr());
501 } else if ( parallel_mode == DofManager_null ) {
502 input.setField(IPK_DofManager_nullflag.getNameCStr());
503 }
504}
505
506
507void DofManager :: printOutputAt(FILE *stream, TimeStep *tStep)
508{
509 EngngModel *emodel = this->giveDomain()->giveEngngModel();
510
511 fprintf( stream, "%-8s%8d (%8d):\n", this->giveClassName(), this->giveLabel(), this->giveNumber() );
512 for ( Dof *dof: *this ) {
513 emodel->printDofOutputAt(stream, dof, tStep);
514 }
515}
516
517
518void DofManager :: printYourself()
519// Prints the receiver on screen.
520{
521 printf("DofManager %d\n", number);
522 for ( Dof *dof: *this ) {
523 dof->printYourself();
524 }
525
526 loadArray.printYourself();
527 printf("\n");
528}
529
530
531void DofManager :: updateYourself(TimeStep *tStep)
532// Updates the receiver at end of step.
533{
534 for ( Dof *dof: *this ) {
535 dof->updateYourself(tStep);
536 }
537}
538
539
540void DofManager :: saveContext(DataStream &stream, ContextMode mode)
541{
542 FEMComponent :: saveContext(stream, mode);
543
544 if ( mode & CM_Definition ) {
545 if ( !stream.write(this->giveNumberOfDofs()) ) {
547 }
548
549 int _val;
550 for ( auto &dof : *this ) {
551 _val = dof->giveDofType();
552 if ( !stream.write(_val) ) {
554 }
555 _val = dof->giveDofID();
556 if ( !stream.write(_val) ) {
558 }
559 dof->saveContext(stream, mode);
560 }
561
563 if ( ( iores = loadArray.storeYourself(stream) ) != CIO_OK ) {
564 THROW_CIOERR(iores);
565 }
566
567 if ( !stream.write(isBoundaryFlag) ) {
569 }
570
571 if ( !stream.write(hasSlaveDofs) ) {
573 }
574
575 if ( !stream.write(globalNumber) ) {
577 }
578
579 _val = parallel_mode;
580 if ( !stream.write(_val) ) {
582 }
583
584 if ( ( iores = partitions.storeYourself(stream) ) != CIO_OK ) {
585 THROW_CIOERR(iores);
586 }
587 } else {
588 for ( auto &dof : *this ) {
589 dof->saveContext(stream, mode);
590 }
591 }
592}
593
594
595void DofManager :: restoreContext(DataStream &stream, ContextMode mode)
596{
598
599 FEMComponent :: restoreContext(stream, mode);
600
601 if ( mode & CM_Definition ) {
602 int _numberOfDofs;
603 if ( !stream.read(_numberOfDofs) ) {
605 }
606
607 // allocate new ones
608 for ( auto &d: dofArray) { delete d; }
609 dofArray.clear();
610
611 for ( int i = 0; i < _numberOfDofs; i++ ) {
612 int dtype, dofid;
613 if ( !stream.read(dtype) ) {
615 }
616 if ( !stream.read(dofid) ) {
618 }
619 Dof *dof = classFactory.createDof( ( dofType ) dtype, (DofIDItem)dofid, this );
620 dof->restoreContext(stream, mode);
621 this->appendDof(dof);
622 }
623
624 if ( ( iores = loadArray.restoreYourself(stream) ) != CIO_OK ) {
625 THROW_CIOERR(iores);
626 }
627
628 if ( !stream.read(isBoundaryFlag) ) {
630 }
631
632 if ( !stream.read(hasSlaveDofs) ) {
634 }
635
636 if ( !stream.read(globalNumber) ) {
638 }
639
640 int _val;
641 if ( !stream.read(_val) ) {
643 }
644
646 if ( ( iores = partitions.restoreYourself(stream) ) != CIO_OK ) {
647 THROW_CIOERR(iores);
648 }
649 } else {
650 for ( auto &dof : this->dofArray ) {
651 dof->restoreContext(stream, mode);
652 }
653 }
654}
655
656
657void DofManager :: giveUnknownVector(FloatArray &answer, const IntArray &dofIDArry, ValueModeType mode, TimeStep *tStep, bool padding)
658{
659 answer.resize( dofIDArry.giveSize() );
660 if ( dofIDArry.giveSize() == 0 ) return;
661
662 int k = 0;
663 for ( auto &dofid: dofIDArry ) {
664 auto pos = this->findDofWithDofId( ( DofIDItem ) dofid );
665 if ( pos == this->end() ) {
666 if ( padding ) {
667 answer.at(++k) = 0.;
668 }
669 continue;
670 }
671 answer.at(++k) = (*pos)->giveUnknown(mode, tStep);
672 }
673 answer.resizeWithValues(k);
674
675 // Transform to global c.s.
676 FloatMatrix L2G;
677 if ( this->computeL2GTransformation(L2G, dofIDArry) ) {
678 answer.rotatedWith(L2G, 'n');
679 }
680}
681
682
683void DofManager :: giveUnknownVector(FloatArray &answer, const IntArray &dofIDArry,
684 PrimaryField &field, ValueModeType mode, TimeStep *tStep, bool padding)
685{
686 answer.resize( dofIDArry.giveSize() );
687
688 int k = 0;
689 for ( auto &dofid: dofIDArry ) {
690 auto pos = this->findDofWithDofId( ( DofIDItem ) dofid );
691 if ( pos == this->end() ) {
692 if ( padding ) {
693 answer.at(++k) = 0.;
694 }
695 continue;
696 }
697 answer.at(++k) = (*pos)->giveUnknown(field, mode, tStep);
698 }
699 answer.resizeWithValues(k);
700
701 // Transform to global c.s.
702 FloatMatrix L2G;
703 if ( this->computeL2GTransformation(L2G, dofIDArry) ) {
704 answer.rotatedWith(L2G, 'n');
705 }
706}
707
708
709void DofManager :: giveCompleteUnknownVector(FloatArray &answer, ValueModeType mode, TimeStep *tStep)
710{
711 int i = 1;
712 answer.resize(this->giveNumberOfDofs());
713 for ( Dof *dof: *this ) {
714 answer.at(i) = dof->giveUnknown(mode, tStep);
715 i++;
716 }
717}
718
719
720void DofManager :: givePrescribedUnknownVector(FloatArray &answer, const IntArray &dofIDArry,
721 ValueModeType mode, TimeStep *tStep)
722{
723 answer.resize(dofIDArry.giveSize());
724
725 int j = 1;
726 for ( int dofid: dofIDArry ) {
727 answer.at(j++) = this->giveDofWithID( dofid )->giveBcValue(mode, tStep);
728 }
729
730 // Transform to global c.s.
731 FloatMatrix L2G;
732 if ( this->computeL2GTransformation(L2G, dofIDArry) ) {
733 answer.rotatedWith(L2G, 'n');
734 }
735}
736
737
738void DofManager :: giveUnknownVectorOfType(FloatArray &answer, UnknownType ut, ValueModeType mode, TimeStep *tStep)
739{
740 int k = 1;
741 FloatArray localVector(3);
742 IntArray dofIDArry(3);
743
744 // This is a bit cumbersome. I first construct the local vector, which might have a odd order, e.g [D_w, D_u], which is later added to the global vector "answer"
745 // I also store the dof id's, so that I can construct the local 2 global transformation afterwards (if its necessary). / Mikael
746 for ( Dof *d: *this ) {
747 double val = d->giveUnknown(mode, tStep);
748 if ( ut == DisplacementVector || ut == EigenVector ) { // Just treat eigenvectors as displacement vectors (they are redundant)
749 if ( d->giveDofID() == D_u ) {
750 dofIDArry.at(k) = D_u;
751 localVector.at(k) = val;
752 k++;
753 } else if ( d->giveDofID() == D_v ) {
754 dofIDArry.at(k) = D_v;
755 localVector.at(k) = val;
756 k++;
757 } else if ( d->giveDofID() == D_w ) {
758 dofIDArry.at(k) = D_w;
759 localVector.at(k) = val;
760 k++;
761 }
762 } else if ( ut == VelocityVector ) {
763 if ( d->giveDofID() == V_u ) {
764 dofIDArry.at(k) = V_u;
765 localVector.at(k) = val;
766 k++;
767 } else if ( d->giveDofID() == V_v ) {
768 dofIDArry.at(k) = V_v;
769 localVector.at(k) = val;
770 k++;
771 } else if ( d->giveDofID() == V_w ) {
772 dofIDArry.at(k) = V_w;
773 localVector.at(k) = val;
774 k++;
775 }
776 } else {
777 OOFEM_ERROR("Can't produce vector for unknown type: %d", ut);
778 }
779 }
780
781 FloatMatrix L2G;
782 if ( this->computeL2GTransformation(L2G, dofIDArry) ) {
783 // Transform to global c.s.
784 answer.beProductOf(L2G, localVector);
785 } else {
786 // No local c.s, just copy the values to respective index;
787 answer.resize(3);
788 answer.zero();
789 for ( int i = 1; i <= k; i++ ) {
790 if ( dofIDArry.at(i) == D_u || dofIDArry.at(i) == V_u ) {
791 answer.at(1) = localVector.at(i);
792 } else if ( dofIDArry.at(i) == D_v || dofIDArry.at(i) == V_v ) {
793 answer.at(2) = localVector.at(i);
794 } else if ( dofIDArry.at(i) == D_w || dofIDArry.at(i) == V_w ) {
795 answer.at(3) = localVector.at(i);
796 }
797 }
798 }
799}
800
801
802bool DofManager :: hasAnySlaveDofs()
803{
804 for ( Dof *dof: *this ) {
805 if ( !dof->isPrimaryDof() ) {
806 return true;
807 }
808 }
809
810 return false;
811}
812
813
814bool DofManager :: giveMasterDofMans(IntArray &masters)
815{
816 IntArray _dof_masters;
817 bool answer = false;
818
819 masters.clear();
820 for ( Dof *dof: *this ) {
821 if ( !dof->isPrimaryDof() ) {
822 answer = true;
823 dof->giveMasterDofManArray(_dof_masters);
824 for ( int j = 1; j <= _dof_masters.giveSize(); j++ ) {
825 masters.insertSortedOnce(_dof_masters.at(j), 2);
826 }
827 }
828 }
829
830 return answer;
831}
832
833bool DofManager :: computeM2GTransformation(FloatMatrix &answer, const IntArray &dofMask)
834// computes transformation matrix of receiver.
835// transformation should include transformation from global cs to nodal cs,
836// as well as further necessary transformations (for example in case
837// rigid arms this must include transformation to master dofs).
838{
839 FloatMatrix L2G, M2L;
840
841 bool hasL2G = computeL2GTransformation(L2G, dofMask);
842 bool hasM2L = computeM2LTransformation(M2L, dofMask);
843
844 if ( !hasL2G && !hasM2L ) {
845 answer.clear();
846 return false;
847 } else if ( hasL2G && hasM2L ) {
848 answer.beProductOf(L2G, M2L);
849 } else if ( hasL2G ) {
850 answer = L2G;
851 } else {
852 answer = M2L;
853 }
854 return true;
855}
856
857
858bool DofManager :: computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry)
859{
860 return false;
861}
862
863
864bool DofManager :: computeM2LTransformation(FloatMatrix &answer, const IntArray &dofIDArry)
865{
866 if ( !this->hasAnySlaveDofs() ) {
867 return false;
868 }
869
870 FloatArray mstrContrs;
871
872 if ( dofIDArry.isEmpty() ) {
874 int cols = 0;
875 for ( Dof *dof: *this ) {
876 cols += dof->giveNumberOfPrimaryMasterDofs();
877 }
878 answer.resize( this->giveNumberOfDofs(), cols );
879 answer.zero();
880
881 int k = 1, i = 1;
882 for ( Dof *dof: *this ) {
883 dof->computeDofTransformation(mstrContrs);
884 answer.copySubVectorRow(mstrContrs, i, k);
885 k += mstrContrs.giveSize();
886 i++;
887 }
888 } else {
889 answer.resize( dofIDArry.giveSize(), giveNumberOfPrimaryMasterDofs(dofIDArry) );
890 answer.zero();
891
892 int k = 1;
893 for ( int i = 1; i <= dofIDArry.giveSize(); i++ ) {
894 this->giveDofWithID(dofIDArry.at(i))->computeDofTransformation(mstrContrs);
895 answer.copySubVectorRow(mstrContrs, i, k);
896 k += mstrContrs.giveSize();
897 }
898 }
899 return true;
900}
901
902
903bool DofManager :: requiresTransformation()
904{
905 return this->hasAnySlaveDofs();
906}
907
908
909void DofManager :: updateLocalNumbering(EntityRenumberingFunctor &f)
910{
911 //update masterNode numbering
912 if ( !this->dofMastermap.empty() ) {
913 for ( auto & mapper: this->dofMastermap ) {
914 mapper.second = f( mapper.second, ERS_DofManager );
915 }
916 }
917
918 for ( Dof *dof: *this ) {
919 dof->updateLocalNumbering(f);
920 }
921}
922
923
924void DofManager :: mergePartitionList(IntArray &_p)
925{
926 // more optimized version can be made requiring sorted partition list of receiver
927 int size = _p.giveSize();
928 for ( int i = 1; i <= size; i++ ) {
929 partitions.insertOnce( _p.at(i) );
930 }
931}
932
933
934int DofManager :: givePartitionsConnectivitySize()
935{
936 int n = partitions.giveSize();
937 int myrank = this->giveDomain()->giveEngngModel()->giveRank();
938 if ( partitions.findFirstIndexOf(myrank) ) {
939 return n;
940 } else {
941 return n + 1;
942 }
943}
944
945
946bool DofManager :: isLocal()
947{
949 return true;
950 }
951
953 // determine if problem is the lowest one sharing the dofman; if yes the receiver is responsible to
954 // deliver number
955 int n = partitions.giveSize();
956 int myrank = this->giveDomain()->giveEngngModel()->giveRank();
957 int minrank = myrank;
958
959 for ( int j = 1; j <= n; j++ ) {
960 minrank = min( minrank, partitions.at(j) );
961 }
962
963 if ( minrank == myrank ) {
964 return true;
965 }
966 }
967
968 return false;
969}
970
971} // end namespace oofem
virtual int read(int *data, std::size_t count)=0
Reads count integer values into array pointed by data.
virtual int write(const int *data, std::size_t count)=0
Writes count integer values from array pointed by data.
IntArray dofidmask
List of additional dof ids to include.
Definition dofmanager.h:132
static ParamKey IPK_DofManager_remoteflag
Definition dofmanager.h:156
static ParamKey IPK_DofManager_dofidmask
Definition dofmanager.h:146
static ParamKey IPK_DofManager_mastermask
Definition dofmanager.h:150
static ParamKey IPK_DofManager_nullflag
Definition dofmanager.h:157
int giveNumberOfDofs() const
Definition dofmanager.C:287
dofManagerParallelMode parallel_mode
Definition dofmanager.h:123
virtual bool computeM2LTransformation(FloatMatrix &answer, const IntArray &dofIDArry)
Definition dofmanager.C:864
bool hasSlaveDofs
Flag indicating whether receiver has slave DOFs.
Definition dofmanager.h:115
int giveLabel() const
Definition dofmanager.h:516
const char * giveClassName() const override
Definition dofmanager.h:556
IntArray loadArray
List of applied loads.
Definition dofmanager.h:108
int giveNumberOfPrimaryMasterDofs(const IntArray &dofIDArray) const
Definition dofmanager.C:311
std::vector< Dof * >::const_iterator findDofWithDofId(DofIDItem dofID) const
Definition dofmanager.C:274
static ParamKey IPK_DofManager_boundaryflag
Definition dofmanager.h:152
std ::map< int, int > dofICmap
Map from DofIDItem to ic (to be removed).
Definition dofmanager.h:140
static ParamKey IPK_DofManager_doftypemask
Definition dofmanager.h:151
static ParamKey IPK_DofManager_globnum
Definition dofmanager.h:153
std ::map< int, int > dofMastermap
Map from DofIDItem to master node.
Definition dofmanager.h:136
static ParamKey IPK_DofManager_load
Definition dofmanager.h:147
std ::map< int, int > dofTypemap
Map from DofIDItem to dofType.
Definition dofmanager.h:134
static ParamKey IPK_DofManager_partitions
Definition dofmanager.h:154
std::vector< Dof * > dofArray
Array of DOFs.
Definition dofmanager.h:106
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
std ::map< int, int > dofBCmap
Map from DofIDItem to bc (to be removed).
Definition dofmanager.h:138
std::vector< Dof * >::iterator begin()
Definition dofmanager.h:161
virtual bool computeL2GTransformation(FloatMatrix &answer, const IntArray &dofIDArry)
Definition dofmanager.C:858
std::vector< Dof * >::iterator end()
Definition dofmanager.h:162
IntArray partitions
Definition dofmanager.h:129
void appendDof(Dof *dof)
Definition dofmanager.C:142
virtual bool hasAnySlaveDofs()
Definition dofmanager.C:802
static ParamKey IPK_DofManager_ic
Definition dofmanager.h:149
static ParamKey IPK_DofManager_bc
Definition dofmanager.h:148
static ParamKey IPK_DofManager_sharedflag
Definition dofmanager.h:155
virtual int giveNumberOfPrimaryMasterDofs()
Definition dof.h:252
virtual void giveMasterDofManArray(IntArray &answer)
Definition dof.C:180
virtual void giveEquationNumbers(IntArray &masterEqNumbers, const UnknownNumberingScheme &s)
Definition dof.C:61
virtual int askNewEquationNumber(TimeStep *tStep)=0
DofIDItem giveDofID() const
Definition dof.h:276
virtual double giveUnknown(ValueModeType mode, TimeStep *tStep)=0
virtual void updateLocalNumbering(EntityRenumberingFunctor &f)
Definition dof.h:315
virtual bool isPrimaryDof()
Definition dof.h:287
virtual void computeDofTransformation(FloatArray &masterContribs)
Definition dof.C:173
virtual void printYourself()
Prints the receiver state on stdout.
Definition dof.C:107
virtual void updateYourself(TimeStep *tStep)
Definition dof.h:336
virtual void giveDofIDs(IntArray &masterDofIDs)
Definition dof.C:67
virtual int giveBcId()=0
virtual void restoreContext(DataStream &stream, ContextMode mode)
Restores the receiver state previously written in stream.
Definition dof.C:147
void setField(int item, InputFieldType id)
virtual void printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep)
Definition engngm.C:884
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
FEMComponent(int n, Domain *d)
Definition femcmpnn.h:88
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void copySubVectorRow(const FloatArray &src, int sr, int sc)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void zero()
Zeroes all coefficient of receiver.
virtual bcGeomType giveBCGeoType() const
virtual const IntArray & giveDofIDs() const
bool insertSortedOnce(int value, int allocChunk=0)
Definition intarray.C:309
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resizeWithValues(int n, int allocChunk=0)
Definition intarray.C:64
void resize(int n)
Definition intarray.C:73
bool contains(int value) const
Definition intarray.h:292
bool isEmpty() const
Definition intarray.h:217
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
Definition load.C:84
bool checkIfSet(size_t componentIndex, size_t paramIndex)
std::optional< paramValue > getTempParam(size_t componentIndex, size_t paramIndex) const
virtual int giveDofEquationNumber(Dof *dof) const =0
#define THROW_CIOERR(e)
#define CM_Definition
Definition contextmode.h:47
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
long ContextMode
Definition contextmode.h:43
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
@ NodalLoadBGT
Concentrated nodal load.
Definition bcgeomtype.h:42
dofManagerParallelMode
In parallel mode, this type indicates the mode of DofManager.
Definition dofmanager.h:66
@ DofManager_local
Definition dofmanager.h:67
@ DofManager_shared
Definition dofmanager.h:68
@ DofManager_null
Definition dofmanager.h:74
@ DofManager_remote
Definition dofmanager.h:71
dofType
Dof Type, determines the type of DOF created.
Definition doftype.h:48
ClassFactory & classFactory
@ CIO_IOERR
General IO error.
#define PM_UPDATE_TEMP_PARAMETER(_type, _pm, _ir, _componentnum, _paramkey, _prio)
#define PM_CHECK_FLAG_AND_REPORT(_pm, _ir, _componentnum, _paramkey, _prio, _flag)
#define PM_UPDATE_PARAMETER(_val, _pm, _ir, _componentnum, _paramkey, _prio)

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011