OOFEM 3.0
Loading...
Searching...
No Matches
domain.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 "domain.h"
36#include "parametermanager.h"
37#include "paramkey.h"
38
39#include "element.h"
40#include "timestep.h"
41#include "node.h"
42#include "elementside.h"
43#include "material.h"
44#include "crosssection.h"
45#include "load.h"
46#include "initialcondition.h"
47#include "function.h"
48#include "set.h"
49#include "engngm.h"
51#include "datastream.h"
52#include "contextioerr.h"
53#include "verbose.h"
54#include "connectivitytable.h"
55#include "outputmanager.h"
56#include "octreelocalizer.h"
57#include "nodalrecoverymodel.h"
58#include "nonlocalbarrier.h"
59#include "classfactory.h"
60#include "logger.h"
61#include "xfem/xfemmanager.h"
62#include "topologydescription.h"
63#include "errorestimator.h"
64#include "range.h"
65#include "fracturemanager.h"
66#include "datareader.h"
67#include "oofemtxtdatareader.h"
68#include "initmodulemanager.h"
69#include "exportmodulemanager.h"
70#include "xfem/enrichmentitem.h"
73#include "xfem/propagationlaw.h"
75#include "bctracker.h"
76
77#include "boundarycondition.h"
78#include "activebc.h"
79#include "simpleslavedof.h"
80#include "masterdof.h"
81
82
83#ifdef __MPI_PARALLEL_MODE
84 #include "parallel.h"
85 #include "processcomm.h"
86 #include "datastream.h"
87 #include "communicator.h"
89#endif
90
91#include <cstdarg>
92#include <cstring>
93#include <vector>
94#include <set>
95
96namespace oofem {
97Domain :: Domain(int n, int serNum, EngngModel *e) : elementPPM(),
98 dofmanPPM(),
100 bcTracker(this)
101
102 // Constructor. Creates a new domain.
103{
104 if ( !e->giveSuppressOutput() ) {
105 outputManager = std::make_unique<OutputManager>(this);
106 }
107
108 this->engineeringModel = e;
109 this->number = n;
110 this->serialNumber = serNum;
111
112 dType = _unknownMode;
113
115
116 nsd = 0;
117 axisymm = false;
119
120#ifdef __MPI_PARALLEL_MODE
122 transactionManager = NULL;
123#endif
124}
125
126Domain :: ~Domain() { }
127
128void
129Domain :: clear()
130// Clear receiver
131{
132 elementList.clear();
134 dofmanGlobal2LocalMap.clear();
135 dofManagerList.clear();
136 materialList.clear();
137 bcList.clear();
138 icList.clear();
139 functionList.clear();
140 crossSectionList.clear();
141 nonlocalBarrierList.clear();
142 setList.clear();
143 contactSurfaceList.clear();
144 xfemManager = nullptr;
145 if ( connectivityTable ) {
146 connectivityTable->reset();
147 }
148
149 spatialLocalizer = nullptr;
150
151 if ( smoother ) {
152 smoother->clear();
153 }
154
156 topology = nullptr;
157
158#ifdef __MPI_PARALLEL_MODE
159 transactionManager = nullptr;
160#endif
161}
162
163
164Element *
165Domain :: giveElement(int n)
166{
167#ifdef DEBUG
168 if ( n < 1 || n > (int)elementList.size() ) {
169 OOFEM_ERROR("undefined element (%d)", n);
170 }
171#endif
172 return this->elementList[n-1].get();
173}
174
175Element *
176Domain :: giveGlobalElement(int n)
177{
178 for ( auto &el: elementList ) {
179 if ( el->giveGlobalNumber() == n ) {
180 return el.get();
181 }
182 }
183
184 return NULL;
185}
186
187int
188Domain :: giveElementPlaceInArray(int iGlobalElNum) const
189{
190 auto res = elementGlobal2LocalMap.find(iGlobalElNum);
191
192 if ( res != elementGlobal2LocalMap.end() ) {
193 return res->second;
194 } else {
195 OOFEM_ERROR("returning -1 for iGlobalElNum: %d.", iGlobalElNum );
196 return -1;
197 }
198}
199
200int
201Domain :: giveDofManPlaceInArray(int iGlobalDofManNum) const
202{
203 auto res = dofmanGlobal2LocalMap.find(iGlobalDofManNum);
204
205 if ( res != dofmanGlobal2LocalMap.end() ) {
206 return res->second;
207 } else {
208 OOFEM_ERROR("returning -1 for iGlobalDofManNum: %d.", iGlobalDofManNum );
209 return -1;
210 }
211}
212
213const IntArray &
214Domain :: giveElementsWithMaterialNum(int iMaterialNum) const
215{
216 auto res = materialNum2ElMap.find(iMaterialNum);
217
218 if ( res != materialNum2ElMap.end() ) {
219 return res->second;
220 } else {
221 OOFEM_ERROR("Material not found.")
222 }
223}
224
225Load *
226Domain :: giveLoad(int n)
227{
228#ifdef DEBUG
229 if ( n < 1 || n > (int)bcList.size() ) {
230 OOFEM_ERROR("undefined load (%d)", n);
231 }
232 Load *answer = dynamic_cast< Load * >( bcList[n-1].get() );
233 if ( answer ) {
234 return answer;
235 } else {
236 OOFEM_ERROR("cannot cast boundary condition %d to Load class", n);
237 }
238#else
239 return static_cast< Load * >( bcList[n-1].get() );
240
241#endif
242}
243
244
246Domain :: giveBc(int n)
247{
248#ifdef DEBUG
249 if ( n < 1 || n > (int)bcList.size() ) {
250 OOFEM_ERROR("undefined bc (%d)", n);
251 }
252#endif
253 return bcList[n-1].get();
254}
255
256
258Domain :: giveIc(int n)
259{
260#ifdef DEBUG
261 if ( n < 1 || n > (int)icList.size() ) {
262 OOFEM_ERROR("undefined ic (%d)", n);
263 }
264#endif
265
266 return icList[n-1].get();
267}
268
269
270Function *
271Domain :: giveFunction(int n)
272{
273#ifdef DEBUG
274 if ( n < 1 || n > (int)functionList.size() ) {
275 OOFEM_ERROR("undefined load-time function (%d)", n);
276 }
277#endif
278
279 return functionList[n-1].get();
280}
281
282
283Material *
284Domain :: giveMaterial(int n)
285{
286#ifdef DEBUG
287 if ( n < 1 || n > (int)materialList.size() ) {
288 OOFEM_ERROR("undefined material (%d)", n);
289 }
290#endif
291
292 return materialList[n-1].get();
293}
294
296Domain :: giveSide(int n)
297{
298#ifdef DEBUG
299 if ( n < 1 || n > (int)dofManagerList.size() ) {
300 OOFEM_ERROR("undefined dofManager (%d)", n);
301 }
302
303 ElementSide *side = dynamic_cast< ElementSide * >( dofManagerList[n-1].get() );
304 if ( !side ) {
305 OOFEM_ERROR("incompatible type of dofManager %d, can not convert", n);
306 }
307 return side;
308
309#else
310 return static_cast< ElementSide * >( dofManagerList[n-1].get() );
311
312#endif
313}
314
315
317Domain :: giveDofManager(int n)
318{
319#ifdef DEBUG
320 if ( n < 1 || n > (int)dofManagerList.size() ) {
321 OOFEM_ERROR("undefined dofManager (%d)", n);
322 }
323#endif
324 return this->dofManagerList[n-1].get();
325}
326
327
329Domain :: giveGlobalDofManager(int n)
330{
331 for ( auto &dman: dofManagerList ) {
332 if ( dman->giveGlobalNumber() == n ) {
333 return dman.get();
334 }
335 }
336
337 return NULL;
338}
339
340
342Domain :: giveCrossSection(int n)
343{
344#ifdef DEBUG
345 if ( n < 1 || n > (int)crossSectionList.size() ) {
346 OOFEM_ERROR("undefined cross section (%d)", n);
347 }
348#endif
349 return crossSectionList[n-1].get();
350}
351
352
354Domain :: giveNonlocalBarrier(int n)
355{
356#ifdef DEBUG
357 if ( n < 1 || n > (int)nonlocalBarrierList.size() ) {
358 OOFEM_ERROR("undefined barrier (%d)", n);
359 }
360#endif
361 return nonlocalBarrierList[n-1].get();
362}
363
364
365Set *
366Domain :: giveSet(int n)
367{
368#ifdef DEBUG
369 if ( n < 1 || n > (int)setList.size() ) {
370 OOFEM_ERROR("undefined set (%d)", n);
371 }
372#endif
373
374 return setList[n-1].get();
375}
376
378Domain :: giveXfemManager()
379{
380#ifdef DEBUG
381 if ( !xfemManager ) {
382 OOFEM_ERROR("undefined xfem manager");
383 }
384#endif
385 return xfemManager.get();
386}
387
388bool
389Domain :: hasXfemManager()
390{
391 return xfemManager.get() != NULL;
392}
393
394
395bool
396Domain :: hasFractureManager()
397{
398 return fracManager.get() != NULL;
399}
400
402Domain :: giveFractureManager()
403{
404#ifdef DEBUG
405 if ( !fracManager ) {
406 OOFEM_ERROR("undefined fracture manager");
407 }
408#endif
409 return fracManager.get();
410}
411
414{
415 return &bcTracker;
416}
417
419Domain :: giveEngngModel()
420{
421#ifdef DEBUG
422 if ( !engineeringModel ) {
423 OOFEM_ERROR("Not defined");
424 }
425#endif
426
427 return engineeringModel;
428}
429
430
433{
434#ifdef DEBUG
435 if ( n < 1 || n > ( int ) contactSurfaceList.size() ) {
436 OOFEM_ERROR("undefined contact surface (%d)", n);
437 }
438#endif
439 return this->contactSurfaceList [ n - 1 ].get();
440}
441
442
443
444
445void Domain :: resizeDofManagers(int _newSize) { dofManagerList.resize(_newSize); }
446void Domain :: resizeElements(int _newSize) { elementList.resize(_newSize); }
447void Domain :: resizeCrossSectionModels(int _newSize) { crossSectionList.resize(_newSize); }
448void Domain :: resizeMaterials(int _newSize) { materialList.resize(_newSize); }
449void Domain :: resizeNonlocalBarriers(int _newSize) { nonlocalBarrierList.resize(_newSize); }
450void Domain :: resizeBoundaryConditions(int _newSize) { bcList.resize(_newSize); }
451void Domain :: resizeInitialConditions(int _newSize) { icList.resize(_newSize); }
452void Domain :: resizeFunctions(int _newSize) { functionList.resize(_newSize); }
453void Domain :: resizeSets(int _newSize) { setList.resize(_newSize); }
454void Domain :: resizeContactSurfaces(int _newSize) { contactSurfaceList.resize(_newSize); }
455
456void Domain :: py_setDofManager(int i, DofManager *obj) { dofManagerList[i-1].reset(obj); dofmanGlobal2LocalMap[obj->giveGlobalNumber()] = i;}
457void Domain :: py_setElement(int i, Element *obj) { elementList[i-1].reset(obj); elementGlobal2LocalMap[obj->giveGlobalNumber()] = i;}
458void Domain :: py_setCrossSection(int i, CrossSection *obj) { crossSectionList[i-1].reset(obj); }
459void Domain :: py_setMaterial(int i, Material *obj) { materialList[i-1].reset(obj); }
460void Domain :: py_setNonlocalBarrier(int i, NonlocalBarrier *obj) { nonlocalBarrierList[i-1].reset(obj); }
461void Domain :: py_setBoundaryCondition(int i, GeneralBoundaryCondition *obj) { bcList[i-1].reset(obj); }
462void Domain :: py_setInitialCondition(int i, InitialCondition *obj) { icList[i-1].reset(obj); }
463void Domain :: py_setFunction(int i, Function *obj) { functionList[i-1].reset(obj); }
464void Domain :: py_setSet(int i, Set *obj) { setList[i-1].reset(obj); }
465
466void Domain :: setDofManager(int i, std::unique_ptr<DofManager> obj) { dofmanGlobal2LocalMap[obj->giveGlobalNumber()] = i; dofManagerList[i-1] = std::move(obj); }
467void Domain :: setElement(int i, std::unique_ptr<Element> obj) { elementGlobal2LocalMap[obj->giveGlobalNumber()] = i; elementList[i-1] = std::move(obj); }
468void Domain :: setCrossSection(int i, std::unique_ptr<CrossSection> obj) { crossSectionList[i-1] = std::move(obj); }
469void Domain :: setMaterial(int i, std::unique_ptr<Material> obj) { materialList[i-1] = std::move(obj); }
470void Domain :: setNonlocalBarrier(int i, std::unique_ptr<NonlocalBarrier> obj) { nonlocalBarrierList[i-1] = std::move(obj); }
471void Domain :: setBoundaryCondition(int i, std::unique_ptr<GeneralBoundaryCondition> obj) { bcList[i-1] = std::move(obj); }
472void Domain :: setInitialCondition(int i, std::unique_ptr<InitialCondition> obj) { icList[i-1] = std::move(obj); }
473void Domain :: setFunction(int i, std::unique_ptr<Function> obj) { functionList[i-1] = std::move(obj); }
474void Domain :: setSet(int i, std::unique_ptr<Set> obj) { setList[i-1] = std::move(obj); }
475void Domain :: setXfemManager(std::unique_ptr<XfemManager> obj) { xfemManager = std::move(obj); }
476
477void Domain :: clearBoundaryConditions() { bcList.clear(); }
478void Domain :: clearElements() { elementList.clear(); }
479
481 auto &ir = dr.giveInputRecord(DataReader :: IR_domainRec, 1);
482 return this->instanciateYourself(dr,ir);
483}
484int
485Domain :: instanciateYourself(DataReader &dr, InputRecord& irDomain)
486// Creates all objects mentioned in the data file.
487{
488 int num;
489 std :: string name, topologytype;
490 int componentRecPriority = 2;
491
492 // read type of Domain to be solved
493 {
494 // ·auto &ir = dr.giveInputRecord(DataReader :: IR_domainRec, 1);
495 IR_GIVE_FIELD(irDomain, name, _IFT_Domain_type); // This is inconsistent, "domain" isn't exactly a field, but the actual record keyword.
496
497 mDomainType = name;
498
499 // irDomain.finish();
500 }
501
502 # ifdef VERBOSE
503 VERBOSE_PRINT0("Instanciating domain ", this->number);
504 # endif
505
506 resolveDomainDofsDefaults( name.c_str() );
507
508 // read output manager record
509 {
510 std :: string tmp;
511 auto &ir = dr.giveInputRecord(DataReader :: IR_outManRec, 1);
513
514 if ( !giveEngngModel()->giveSuppressOutput() ) {
515 outputManager->initializeFrom(ir);
516 }
517 ir.finish();
518 }
519
520 // XML format (and perhaps others) does not contain DomainComp nested group, rather nests everything under domain directly
521 std::shared_ptr<InputRecord> irdPtr(dr.hasFlattenedStructure()?irDomain.ptr():dr.giveInputRecord(DataReader :: IR_domainCompRec, 1).clone());
522 IR_GIVE_OPTIONAL_FIELD(*irdPtr.get(), topologytype, _IFT_Domain_topology);
523 this->nsd = -1;
525 this->axisymm = irdPtr->hasField(_IFT_Domain_axisymmetric);
526
527
528 // read nodes
529 DataReader::GroupRecords dofManagerRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_ndofman,"Nodes",DataReader::IR_dofmanRec,/*optional*/false);
530 DataReader::RecordGuard scope(dr,irdPtr.get()); // till the end of the scope
531 dofManagerList.clear();
532 dofManagerList.resize(dofManagerRecs.size());
533 int dofManagerIndex0=0;
534 for(auto& ir: dofManagerRecs){
535 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
536
537 // assign component number according to record order
538 // component number (as given in input record) becomes label
539 std :: unique_ptr< DofManager > dman( classFactory.createDofManager(name.c_str(), dofManagerIndex0+1, this) );
540 if ( !dman ) {
541 OOFEM_ERROR("Couldn't create node of type: %s\n", name.c_str());
542 }
543
544 dman->initializeFrom(ir, componentRecPriority);
545 dman->setGlobalNumber(num); // set label
546 dofManagerList[dofManagerIndex0] = std :: move(dman);
547
548 ir.finish();
549 dofManagerIndex0++;
550 }
551
552 # ifdef VERBOSE
553 VERBOSE_PRINT0("Instantiated nodes & sides ", (int)dofManagerList.size())
554 # endif
555
557
558 // read elements
559 DataReader::GroupRecords elemRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nelem,"Elements",DataReader::IR_elemRec,/*optional*/false);
560 elementList.clear();
561 elementList.resize(elemRecs.size());
562 int elemIndex0=0;
563 for(auto& ir: elemRecs){
564 // read type of element
565 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
566
567 std :: unique_ptr< Element >elem( classFactory.createElement(name.c_str(), elemIndex0+1, this) );
568 if ( !elem ) {
569 OOFEM_ERROR("Couldn't create element: %s", name.c_str());
570 }
571 elem->initializeFrom(ir, componentRecPriority);
572 elem->setGlobalNumber(num);
573 elementList[elemIndex0] = std :: move(elem);
574
575 ir.finish();
576 elemIndex0++;
577 }
578
580
581 // Support sets defined directly after the elements (special hack for backwards compatibility).
582 setList.clear();
583 if ( dr.peekNext("set") ) {
584 DataReader::GroupRecords setRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nset,"Sets",DataReader::IR_setRec,/*optional*/true);
585 setList.resize(setRecs.size());
586 for(InputRecord& ir: setRecs){
587 // read type of set
588 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
589 // Only one set for now (i don't see any need to ever introduce any other version)
590 std::unique_ptr< Set > set = std::make_unique<Set>(num, this); //classFactory.createSet(name.c_str(), num, this)
591 if ( !set ) {
592 OOFEM_ERROR("Couldn't create set: %s", name.c_str());
593 }
594
595 set->initializeFrom(ir);
596
597 // check number
598 if ( num < 1 || num > (int)setRecs.size() ) {
599 OOFEM_ERROR("Invalid set number (num=%d)", num);
600 }
601
602 if ( !setList[num - 1] ) {
603 setList[num - 1] = std :: move(set);
604 } else {
605 OOFEM_ERROR("Set entry already exist (num=%d)", num);
606 }
607
608 ir.finish();
609 }
610 }
611
612 # ifdef VERBOSE
613 VERBOSE_PRINT0("Instantiated elements ", elementList.size());
614 # endif
615
616 // read contact surfaces
617 DataReader::GroupRecords contactSurfRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_ncontactsurf,"ContactSurfaces",DataReader::IR_contactSurfaceRec,/*optional*/true);
618 contactSurfaceList.clear();
619 contactSurfaceList.resize(contactSurfRecs.size());
620
621 for(InputRecord& ir: contactSurfRecs){
622 // read type of contact surface
623 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
624
625 std::unique_ptr< ContactSurface >surface(classFactory.createContactSurface(name.c_str(), num, this) );
626 if ( !surface ) {
627 OOFEM_ERROR( "Couldn't create contact surface: %s", name.c_str() );
628 }
629
630 surface->initializeFrom(ir);
631
632 // check number
633 if ( num < 1 || num > (int)contactSurfRecs.size() ) {
634 OOFEM_ERROR("Invalid contact surface number (num=%d)", num);
635 }
636
637 if ( !contactSurfaceList [ num - 1 ] ) {
638 contactSurfaceList [ num - 1 ] = std::move(surface);
639 } else {
640 OOFEM_ERROR("Contact surface entry already exist (num=%d)", num);
641 }
642
643 ir.finish();
644 }
645
646
647
648 // read cross sections
649 DataReader::GroupRecords csRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_ncrosssect,"CrossSections",DataReader::IR_crosssectRec,/*optional*/false);
650 crossSectionList.clear();
651 crossSectionList.resize(csRecs.size());
652 for(InputRecord& ir: csRecs){
653 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
654
655 std :: unique_ptr< CrossSection >crossSection( classFactory.createCrossSection(name.c_str(), num, this) );
656 if ( !crossSection ) {
657 OOFEM_ERROR("Couldn't create crosssection: %s", name.c_str());
658 }
659
660 crossSection->initializeFrom(ir);
661
662 // check number
663 if ( ( num < 1 ) || ( num > (int)csRecs.size() ) ) {
664 OOFEM_ERROR("Invalid crossSection number (num=%d)", num);
665 }
666
667 if ( !crossSectionList[num - 1] ) {
668 crossSectionList[num - 1] = std :: move(crossSection);
669 } else {
670 OOFEM_ERROR("crossSection entry already exist (num=%d)", num);
671 }
672
673 ir.finish();
674 }
675
676 # ifdef VERBOSE
677 VERBOSE_PRINT0("Instantiated cross sections ", crossSectionList.size())
678 # endif
679
680 // read materials
681 DataReader::GroupRecords matRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nmat,"Materials",DataReader::IR_matRec,/*optional*/false);
682 materialList.clear();
683 materialList.resize(matRecs.size());
684 for(InputRecord& ir: matRecs){
685 // read type of material
686 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
687
688 std :: unique_ptr< Material >mat( classFactory.createMaterial(name.c_str(), num, this) );
689 if ( !mat ) {
690 OOFEM_ERROR("Couldn't create material: %s", name.c_str());
691 }
692
693 mat->initializeFrom(ir);
694
695 // check number
696 if ( ( num < 1 ) || ( num > (int)matRecs.size() ) ) {
697 OOFEM_ERROR("Invalid material number (num=%d)", num);
698 }
699
700 if ( !materialList[num - 1] ) {
701 materialList[num - 1] = std :: move(mat);
702 } else {
703 OOFEM_ERROR("material entry already exist (num=%d)", num);
704 }
705
706 ir.finish();
707 }
708
709 # ifdef VERBOSE
710 VERBOSE_PRINT0("Instantiated materials ", materialList.size())
711 # endif
712
713 // read barriers
714 DataReader::GroupRecords barrRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nbarrier,"NonlocalBarriers",DataReader::IR_nlocBarRec,/*optional*/true);
715 nonlocalBarrierList.clear();
716 nonlocalBarrierList.resize(barrRecs.size());
717 for(InputRecord& ir: barrRecs){
718 // read type of load
719 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
720
721 std :: unique_ptr< NonlocalBarrier >barrier( classFactory.createNonlocalBarrier(name.c_str(), num, this) );
722 if ( !barrier ) {
723 OOFEM_ERROR("Couldn't create barrier: %s", name.c_str());
724 }
725
726 barrier->initializeFrom(ir);
727
728 // check number
729 if ( ( num < 1 ) || ( num > (int)barrRecs.size() ) ) {
730 OOFEM_ERROR("Invalid barrier number (num=%d)", num);
731 }
732
733 if ( !nonlocalBarrierList[num - 1] ) {
734 nonlocalBarrierList[num - 1] = std :: move(barrier);
735 } else {
736 OOFEM_ERROR("barrier entry already exist (num=%d)", num);
737 }
738
739 ir.finish();
740 }
741
742 # ifdef VERBOSE
743 if ( !nonlocalBarrierList.empty() ) {
744 VERBOSE_PRINT0("Instantiated barriers ", nonlocalBarrierList.size());
745 }
746 # endif
747
748 // read boundary conditions
749 DataReader::GroupRecords bcRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nbc,"BoundaryConditions",DataReader::IR_bcRec,/*optional*/false);
750 bcList.clear();
751 bcList.resize(bcRecs.size());
752 for(InputRecord& ir: bcRecs){
753 // read type of bc
754 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
755
756 std :: unique_ptr< GeneralBoundaryCondition >bc( classFactory.createBoundaryCondition(name.c_str(), num, this) );
757 if ( !bc ) {
758 OOFEM_ERROR("Couldn't create boundary condition: %s", name.c_str());
759 }
760
761 bc->initializeFrom(ir);
762
763 // check number
764 if ( ( num < 1 ) || ( num > (int)bcRecs.size() ) ) {
765 OOFEM_ERROR("Invalid boundary condition number (num=%d)", num);
766 }
767
768 if ( !bcList[num - 1] ) {
769 bcList[num - 1] = std :: move(bc);
770 } else {
771 OOFEM_ERROR("boundary condition entry already exist (num=%d)", num);
772 }
773
774 ir.finish();
775 }
776
777 # ifdef VERBOSE
778 VERBOSE_PRINT0("Instantiated BCs ", bcList.size())
779 # endif
780
781 // read initial conditions
782 DataReader::GroupRecords icRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nic,"InitialConditions",DataReader::IR_icRec,/*optional*/false);
783 icList.clear();
784 icList.resize(icRecs.size());
785 for(InputRecord& ir: icRecs){
786 // read type of load
787 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
788
789 std :: unique_ptr< InitialCondition >ic( new InitialCondition(num, this) );
790 if ( !ic ) {
791 OOFEM_ERROR("Creation of IC no. %d failed", num);
792 }
793
794 ic->initializeFrom(ir);
795
796 // check number
797 if ( ( num < 1 ) || ( num > (int)icRecs.size() ) ) {
798 OOFEM_ERROR("Invalid initial condition number (num=%d)", num);
799 }
800
801 if ( !icList[num - 1] ) {
802 icList[num - 1] = std :: move(ic);
803 } else {
804 OOFEM_ERROR("initial condition entry already exist (num=%d)", num);
805 }
806
807 ir.finish();
808 }
809
810 # ifdef VERBOSE
811 VERBOSE_PRINT0("Instantiated ICs ", icList.size())
812 # endif
813
814
815 // read load time functions
816 DataReader::GroupRecords ltfRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nfunct,"LoadTimeFunctions",DataReader::IR_funcRec,/*optional*/false);
817 functionList.clear();
818 functionList.resize(ltfRecs.size());
819 for(InputRecord& ir: ltfRecs){
820 // read type of func
821 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
822
823 std :: unique_ptr< Function >func( classFactory.createFunction(name.c_str(), num, this) );
824 if ( !func ) {
825 OOFEM_ERROR("Couldn't create time function: %s", name.c_str());
826 }
827
828 func->initializeFrom(ir);
829
830 // check number
831 if ( ( num < 1 ) || ( num > (int)ltfRecs.size() ) ) {
832 OOFEM_ERROR("Invalid Function number (num=%d)", num);
833 }
834
835 if ( !functionList[num - 1] ) {
836 functionList[num - 1] = std :: move(func);
837 } else {
838 OOFEM_ERROR("Function entry already exist (num=%d)", num);
839 }
840
841 ir.finish();
842 }
843
844 # ifdef VERBOSE
845 VERBOSE_PRINT0("Instantiated load-time fncts ", functionList.size())
846 # endif
847
848 // read sets
849 if ( setList.size() == 0 ) {
850 DataReader::GroupRecords setRecs=dr.giveGroupRecords(irdPtr,_IFT_Domain_nset,"Sets",DataReader::IR_setRec,/*optional*/true);
851 setList.resize(setRecs.size());
852 for(InputRecord& ir: setRecs){
853 // read type of set
854 IR_GIVE_RECORD_KEYWORD_FIELD(ir, name, num);
855 // Only one set for now (i don't see any need to ever introduce any other version)
856 std :: unique_ptr< Set > set = std::make_unique<Set>(num, this); //classFactory.createSet(name.c_str(), num, this)
857 if ( !set ) {
858 OOFEM_ERROR("Couldn't create set: %s", name.c_str());
859 }
860
861 set->initializeFrom(ir);
862
863 // check number
864 if ( ( num < 1 ) || ( num > (int)setRecs.size() ) ) {
865 OOFEM_ERROR("Invalid set number (num=%d)", num);
866 }
867
868 if ( !setList[num - 1] ) {
869 setList[num - 1] = std :: move(set);
870 } else {
871 OOFEM_ERROR("Set entry already exist (num=%d)", num);
872 }
873
874 ir.finish();
875 }
876 }
877
878 # ifdef VERBOSE
879 if ( setList.size() ) {
880 VERBOSE_PRINT0("Instantiated sets ", setList.size());
881 }
882 # endif
883
885 if(xfmIr){
886 DataReader::RecordGuard scope(dr,xfmIr);
887 IR_GIVE_RECORD_KEYWORD_FIELD(*xfmIr, name, num);
888 xfemManager = classFactory.createXfemManager(name.c_str(), this);
889 if ( !xfemManager ) {
890 OOFEM_ERROR("Couldn't create xfemmanager: %s", name.c_str());
891 }
892
893 xfemManager->initializeFrom(*xfmIr);
894 xfemManager->instanciateYourself(dr);
895 # ifdef VERBOSE
896 VERBOSE_PRINT0("Instantiated xfem ", 1);
897 # endif
898 }
899
900
901 this->topology = NULL;
902 if ( topologytype.length() > 0 ) {
903 this->topology = classFactory.createTopology(topologytype.c_str(), this);
904 if ( !this->topology ) {
905 OOFEM_ERROR("Couldn't create topology of type '%s'", topologytype.c_str());
906 }
907
908 return this->topology->instanciateYourself(dr);
909 # ifdef VERBOSE
910 VERBOSE_PRINT0("Instantiated topologies ", topologytype.length());
911 # endif
912 }
913
914 InputRecord* fmanIr=dr.giveChildRecord(irdPtr,_IFT_Domain_nfracman,"FractureManager",DataReader::IR_fracManRec,/*optional*/true);
915 if (fmanIr) {
916 fracManager = std::make_unique<FractureManager>(this);
917 fracManager->initializeFrom(*fmanIr);
918 fracManager->instanciateYourself(dr);
919 # ifdef VERBOSE
920 VERBOSE_PRINT0("Instantiated fracture manager ", 1);
921 # endif
922 }
923
924 this->initializeFinish();
925 return 1;
926}
927
928void
930
932 //_HeatTransferMode _HeatMass1Mode // Are these deprecated?
933 // set the number of spatial dimensions
934 if (this->nsd <=0) {
935 if ( dType == _1dTrussMode ) {
936 nsd = 1;
937 } else if ( dType == _2dIncompressibleFlow || dType == _2dBeamMode || dType == _2dTrussMode || dType == _2dMindlinPlateMode || dType == _PlaneStrainMode || dType == _2dPlaneStressMode || dType == _2dPlaneStressRotMode || dType == _WarpingMode ) {
938 nsd = 2;
939 } else if ( dType == _3dIncompressibleFlow || dType == _3dShellMode || dType == _3dMode || dType == _3dDirShellMode ) {
940 nsd = 3;
941 } else if ( dType == _3dAxisymmMode ) {
942 nsd = 2;
943 axisymm = true;
944 }
945 }
946
947
948 spatialLocalizer = std::make_unique<OctreeSpatialLocalizer>(this);
949 spatialLocalizer->init();
950 connectivityTable = std::make_unique<ConnectivityTable>(this);
951 OOFEM_LOG_INFO("Spatial localizer init done\n");
952
953 // finish initialization of components (at present neded for dofManagers)
954 for ( auto &dman: dofManagerList ) {
955 dman->initializeFinish();
956 }
957
958 // change internal component references from labels to assigned local numbers
960 for ( auto &dman: this->dofManagerList ) {
961 dman->updateLocalNumbering(labelToLocNumFunctor);
962 }
963
964 for ( auto &element: this->elementList ) {
965 element->updateLocalNumbering(labelToLocNumFunctor);
966 }
967
968 for ( auto &set: setList ) {
969 set->updateLocalNumbering(labelToLocNumFunctor);
970 }
971
973
974
975 // New - in development /JB
976 // set element cross sections based on element set definition and set the corresponding
977 // material based on the cs
978 for ( int i = 1; i <= this->giveNumberOfCrossSectionModels(); i++ ) {
979 if ( int setNum = this->giveCrossSection(i)->giveSetNumber() ) {
980 Set *set = this->giveSet(setNum);
981 for ( int ielem: set->giveElementList() ) {
982 Element *element = this->giveElement( ielem );
983 // hack to set the cross section from the cross section model to the element
984 // this is obsolete feature, but supported here for backwards compatibility
985 // the supported way is to set cross section using set element properties
986 size_t indx = Element::IPK_Element_crosssect.getIndex();
987 if (this->elementPPM.getPriority(ielem, indx) <= 1) {
988 this->elementPPM.setPriority(ielem, indx, 1);
989 element->setCrossSection(i);
990 }
991 }
992 }
993 }
994
995 // process sets and apply element and dofman properties
996 for ( int i = 1; i <= this->giveNumberOfSets(); i++ ) {
997 Set *set = this->giveSet(i);
998 std::string elemProps = set->giveElementProperties();
999 if (!elemProps.empty()) {
1000 OOFEMTXTInputRecord ir (-1, elemProps);
1001 for ( int ielem: set->giveElementList() ) {
1002 Element *element = this->giveElement( ielem );
1003 element->initializeFrom(ir, 1); // initialize with priority 1 (lower than component record priority)
1004 }
1005 }
1006 std::string dofmanProps = set->giveDofManProperties();
1007 if (!dofmanProps.empty()) {
1008 OOFEMTXTInputRecord ir (-1, dofmanProps);
1009 for ( int idofman: set->giveNodeList() ) {
1010 DofManager *dofman = this->giveDofManager( idofman );
1011 dofman->initializeFrom(ir, 1); // initialize with priority 1 (lower than component record priority)
1012 }
1013 }
1014 }
1015
1016
1017 for ( auto &el: elementList ) {
1018 el->initializeFinish();
1019 }
1020}
1021
1022void
1023Domain :: postInitialize()
1024{
1025
1026 if (!spatialLocalizer) {
1027 spatialLocalizer= std::make_unique<OctreeSpatialLocalizer>(this);
1028 spatialLocalizer->init();
1029 }
1030 if (!connectivityTable) {
1031 connectivityTable = std::make_unique<ConnectivityTable>(this);
1032 }
1033
1034 if ( this->hasXfemManager() ) {
1035 this->giveXfemManager()->postInitialize();
1036 }
1037
1038 // Dofs must be created before dof managers due their post-initialization:
1039 this->createDofs();
1040
1041 for ( auto &dman: dofManagerList ) {
1042 dman->postInitialize();
1043 }
1044
1045
1046 for ( auto &el: elementList ) {
1047 el->postInitialize();
1048 }
1049 //@TODO clear parameterPriorityManager
1050
1051 for ( auto &cs: contactSurfaceList ) {
1052 cs->postInitialize();
1053 }
1054
1055
1056 for ( auto &bc: bcList ) {
1057 bc->postInitialize();
1058 }
1059
1060 this->elementPPM.clear();
1061 this->dofmanPPM.clear();
1062
1063}
1064
1065
1066std :: string
1067Domain :: errorInfo(const char *func) const
1068{
1069 return std::string("Domain::") + func + ", number: " + std::to_string(number);
1070}
1071
1072
1073const IntArray &
1074Domain :: giveDefaultNodeDofIDArry()
1075{
1076 // returns default DofID array, defining physical meaning of particular DOFs
1077 // in Node Dof collection
1078 if ( this->defaultNodeDofIDArry.giveSize() ) {
1079 return defaultNodeDofIDArry;
1080 }
1081
1082 if ( dType == _2dPlaneStressRotMode ) {
1083 defaultNodeDofIDArry = {D_u, D_v, R_w};
1084 } else if ( dType == _2dPlaneStressMode ) {
1085 defaultNodeDofIDArry = {D_u, D_v};
1086 } else if ( dType == _PlaneStrainMode ) {
1087 defaultNodeDofIDArry = {D_u, D_v};
1088 } else if ( dType == _3dMode ) {
1089 defaultNodeDofIDArry = {D_u, D_v, D_w};
1090 } else if ( dType == _3dAxisymmMode ) {
1091 defaultNodeDofIDArry = {D_u, D_v, R_w};
1092 } else if ( dType == _2dMindlinPlateMode ) {
1093 defaultNodeDofIDArry = {D_w, R_u, R_v};
1094 } else if ( dType == _3dShellMode ) {
1095 defaultNodeDofIDArry = {D_u, D_v, D_w, R_u, R_v, R_w};
1096 } else if ( dType == _2dTrussMode ) {
1097 defaultNodeDofIDArry = {D_u, D_w};
1098 } else if ( dType == _1dTrussMode ) {
1099 defaultNodeDofIDArry = {D_u};
1100 } else if ( dType == _2dBeamMode ) {
1101 defaultNodeDofIDArry = {D_u, D_w, R_v};
1102 } else if ( dType == _2dLatticeMode ) {
1103 defaultNodeDofIDArry = {D_u, D_v, R_w};
1104 } else if ( dType == _HeatTransferMode ) {
1105 defaultNodeDofIDArry = {T_f};
1106 } else if ( dType == _Mass1TransferMode ) {
1107 defaultNodeDofIDArry = {C_1};
1108 } else if ( dType == _HeatMass1Mode ) {
1109 defaultNodeDofIDArry = {T_f, C_1};
1110 } else if ( dType == _2dIncompressibleFlow ) {
1111 defaultNodeDofIDArry = {V_u, V_v, P_f};
1112 } else if ( dType == _3dIncompressibleFlow ) {
1113 defaultNodeDofIDArry = {V_u, V_v, V_w, P_f};
1114 } else if ( dType == _3dDirShellMode ) {
1115 defaultNodeDofIDArry = {D_u, D_v, D_w, W_u, W_v, W_w, Gamma};
1116 } else if ( dType == _2dLatticeMassTransportMode ) {
1117 defaultNodeDofIDArry = {P_f};
1118 } else if ( dType == _3dLatticeMassTransportMode ) {
1119 defaultNodeDofIDArry = {P_f};
1120 } else if ( dType == _3dLatticeMode ) {
1121 defaultNodeDofIDArry = {D_u, D_v, D_w, R_u, R_v, R_w};
1122 } else if ( dType == _2dLatticeHeatTransferMode ) {
1123 defaultNodeDofIDArry = {T_f};
1124 } else if ( dType == _3dLatticeHeatTransferMode ) {
1125 defaultNodeDofIDArry = {T_f};
1126 } else if ( dType == _WarpingMode ) {
1127 defaultNodeDofIDArry = {D_w};
1128 } else {
1129 OOFEM_ERROR("unknown domainType (%s)", __domainTypeToString(dType));
1130 }
1131
1132 return defaultNodeDofIDArry;
1133}
1134
1135
1136int
1137Domain :: giveNumberOfSpatialDimensions()
1138{
1139 return nsd;
1140}
1141
1142
1143bool
1144Domain :: isAxisymmetric()
1145{
1146 return axisymm;
1147}
1148
1149
1150void
1151Domain :: resolveDomainDofsDefaults(const char *typeName)
1152//
1153// resolves default number of dofs per node according to domain type name.
1154// and also resolves default dof mask according to domain type.
1155//
1156{
1157 if ( !strncmp(typeName, "2dplanestressrot", 16) ) {
1158 dType = _2dPlaneStressRotMode;
1159 } else if ( !strncmp(typeName, "2dplanestress", 12) ) {
1160 dType = _2dPlaneStressMode;
1161 } else if ( !strncmp(typeName, "planestrain", 11) ) {
1162 dType = _PlaneStrainMode;
1163 } else if ( !strncmp(typeName, "3daxisymm", 9) ) {
1164 dType = _3dAxisymmMode;
1165 } else if ( !strncmp(typeName, "2dmindlinplate", 14) ) {
1166 dType = _2dMindlinPlateMode;
1167 } else if ( !strncmp(typeName, "3dshell", 7) ) {
1168 dType = _3dShellMode;
1169 } else if ( !strncmp(typeName, "2dtruss", 7) ) {
1170 dType = _2dTrussMode;
1171 } else if ( !strncmp(typeName, "1dtruss", 7) ) {
1172 dType = _1dTrussMode;
1173 } else if ( !strncmp(typeName, "2dbeam", 6) ) {
1174 dType = _2dBeamMode;
1175 } else if ( !strncmp(typeName, "2dlattice", 9) ) {
1176 dType = _2dLatticeMode;
1177 } else if ( !strncmp(typeName, "heattransfer", 12) ) {
1178 dType = _HeatTransferMode;
1179 } else if ( !strncmp(typeName, "mass1transfer", 13) ) {
1180 dType = _Mass1TransferMode;
1181 } else if ( !strncmp(typeName, "hema1", 5) ) {
1182 dType = _HeatMass1Mode;
1183 } else if ( !strncmp(typeName, "2dincompflow", 12) ) {
1184 dType = _2dIncompressibleFlow;
1185 } else if ( !strncmp(typeName, "3dincompflow", 12) ) {
1186 dType = _3dIncompressibleFlow;
1187 } else if ( !strncmp(typeName, "3ddirshell", 10) ) {
1188 dType = _3dDirShellMode;
1189 } else if ( !strncmp(typeName, "2dmasslatticetransport", 22) ) {
1190 dType = _2dLatticeMassTransportMode;
1191 } else if ( !strncmp(typeName, "3dlattice", 9) ) {
1192 dType = _3dLatticeMode;
1193 } else if ( !strncmp(typeName, "3dmasslatticetransport", 22) ) {
1194 dType = _3dLatticeMassTransportMode;
1195 } else if ( !strncmp(typeName, "2dheatlattice", 13) ) {
1196 dType = _3dLatticeMassTransportMode;
1197 } else if ( !strncmp(typeName, "3dheatlattice", 13) ) {
1198 dType = _3dLatticeMassTransportMode;
1199 } else if ( !strncmp(typeName, "3d", 2) ) {
1200 dType = _3dMode;
1201 } else if ( !strncmp(typeName, "warping", 7) ) {
1202 dType = _WarpingMode;
1203 } else {
1204 OOFEM_ERROR("unknown domainType (%s)", typeName);
1205 return;
1206 }
1207}
1208
1209
1211Domain :: giveSmoother()
1212{
1213 return this->smoother.get();
1214}
1215
1216
1217void
1218Domain :: setSmoother(NodalRecoveryModel *newSmoother, bool destroyOld)
1219{
1220 if ( !destroyOld ) {
1221 this->smoother.release();
1222 }
1223
1224 this->smoother.reset(newSmoother);
1225}
1226
1227
1228void
1229Domain :: setTopology(TopologyDescription *topo, bool destroyOld)
1230{
1231 if ( !destroyOld ) {
1232 this->topology.release();
1233 }
1234
1235 this->topology.reset(topo);
1236}
1237
1238
1240Domain :: giveConnectivityTable()
1241//
1242// return connectivity Table - if no defined - creates new one
1243//
1244{
1245 if ( !connectivityTable ) {
1246 //connectivityTable = std::make_unique<ConnectivityTable>(this);
1247 OOFEM_LOG_ERROR("Connectivity table init error");
1248 }
1249
1250 return connectivityTable.get();
1251}
1252
1253
1255Domain :: giveSpatialLocalizer()
1256//
1257// return connectivity Table - if no defined - creates new one
1258//
1259{
1260// if (spatialLocalizer == NULL) spatialLocalizer = new DummySpatialLocalizer(1, this);
1261 if ( spatialLocalizer ) {
1262 return spatialLocalizer.get();
1263 } else {
1264 OOFEM_LOG_ERROR("Spatial localizer init failure");
1265 return nullptr;
1266 }
1267}
1268
1269void Domain :: setSpatialLocalizer(std::unique_ptr<SpatialLocalizer> sl){
1270 spatialLocalizer = std::move(sl);
1271}
1272
1273
1274void
1275Domain :: createDofs()
1276{
1277
1280 std :: vector< std :: set< int > > node_dofs( this->giveNumberOfDofManagers() );
1281 for ( auto &element: this->elementList ) {
1282 IntArray dofids;
1283 // Scan for all dofs needed by element.
1284 for ( int j = 1; j <= element->giveNumberOfNodes(); ++j ) {
1285 element->giveDofManDofIDMask(j, dofids);
1286 for ( int k = 1; k <= dofids.giveSize(); k++ ) {
1287 node_dofs [ element->giveNode(j)->giveNumber() - 1 ].insert( dofids.at(k) );
1288 }
1289 }
1290 }
1291 for ( auto &dman: this->dofManagerList ) {
1292 // Nodes can also contain their own list of dofs (typical usecase: RigidArmNode )
1293 const IntArray *dofids = dman->giveForcedDofIDs();
1294 if ( dofids ) {
1295 for ( int k = 1; k <= dofids->giveSize(); ++k ) {
1296 node_dofs [ dman->giveNumber() - 1 ].insert( dofids->at(k) );
1297 }
1298 }
1299 }
1300
1302 // Step 2. Scan all Dirichlet b.c.s (or active dofs). For every node we store a map from the dofid to it's b.c. number.
1303 // This loop won't check for slave dofs or so, and will give a bc id for every single relevant dof.
1304 // This must be a separate step since we store the inverse mapping (bc->dof instead of dof->bc) so we want to loop over all b.c.s to invert this.
1305 std :: vector< std :: map< int, int > > dof_bc( this->giveNumberOfDofManagers() );
1306 for ( int i = 1; i <= this->giveNumberOfBoundaryConditions(); ++i ) {
1307 GeneralBoundaryCondition *gbc = this->giveBc(i);
1308 if ( gbc->giveSetNumber() > 0 ) {
1309 // Loop over nodes in set and store the bc number in each dof.
1310 Set *set = this->giveSet( gbc->giveSetNumber() );
1311 ActiveBoundaryCondition *active_bc = dynamic_cast< ActiveBoundaryCondition * >(gbc);
1312 BoundaryCondition *bc = dynamic_cast< BoundaryCondition * >(gbc);
1313 if ( bc || ( active_bc && active_bc->requiresActiveDofs() ) ) {
1314 const IntArray &appliedDofs = gbc->giveDofIDs();
1315 const IntArray &nodes = set->giveNodeList();
1316 for ( int inode = 1; inode <= nodes.giveSize(); ++inode ) {
1317 for ( int idof = 1; idof <= appliedDofs.giveSize(); ++idof ) {
1318 dof_bc [ nodes.at(inode) - 1 ] [ appliedDofs.at(idof) ] = i;
1319 }
1320 }
1321 }
1322 }
1323 }
1324 // Step 2b. This step asks nodes for their bc-vector, which is the old approach to dirichlet b.c.s (i.e. this is for backwards compatibility)
1326 for ( int i = 1; i <= this->giveNumberOfDofManagers(); ++i ) {
1327 DofManager *dman = this->giveDofManager(i);
1328 const std :: map< int, int > *dmanBcs = dman->giveBcMap();
1329 if ( dmanBcs ) {
1330 dof_bc [ i - 1 ].insert( dmanBcs->begin(), dmanBcs->end() ); // This will ignore duplicated dofiditems.
1331 }
1332 }
1333
1334 // Step 2c. THis will apply BC set to internal element nodes.
1335 for ( int i = 1; i <= this->giveNumberOfBoundaryConditions(); ++i ) {
1336 GeneralBoundaryCondition *gbc = this->giveBc(i);
1337 if ( gbc->giveSetNumber() > 0 ) {
1338 // Loop over nodes in set and store the bc number in each dof.
1339 Set *set = this->giveSet( gbc->giveSetNumber() );
1340 BoundaryCondition *bc = dynamic_cast< BoundaryCondition * >(gbc);
1341 if ( bc ) {
1342 const IntArray &appliedDofs = gbc->giveDofIDs();
1343 const IntArray &internalelementnodes = set->giveInternalElementDofManagerList();
1344 for ( int indx = 1; indx <= internalelementnodes.giveSize()/2; ++indx ) {
1345 int ielem = internalelementnodes.at(indx*2-1);
1346 int idofman = internalelementnodes.at(indx*2);
1347 for ( int idof = 1; idof <= appliedDofs.giveSize(); ++idof ) {
1348 // test if element internal dofman has the dof
1349 DofManager* idman = this->giveElement(ielem)->giveInternalDofManager(idofman);
1350 if (idman && idman->hasDofID((DofIDItem) appliedDofs.at(idof))) {
1351 // assign bc to existing DOF
1352 idman->giveDofWithID((DofIDItem) appliedDofs.at(idof))->setBcId(i);
1353 }
1354 }
1355 }
1356 }
1357 }
1358 }
1359
1361 // Step 3. Same for initial conditions as for boundary conditions in step 2.
1362 std :: vector< std :: map< int, int > > dof_ic( this->giveNumberOfDofManagers() );
1363 for ( int i = 1; i <= this->giveNumberOfInitialConditions(); ++i ) {
1364 InitialCondition *ic = this->giveIc(i);
1365 if ( ic->giveSetNumber() > 0 ) {
1366 // Loop over nodes in set and store the bc number in each dof.
1367 Set *set = this->giveSet( ic->giveSetNumber() );
1368 const IntArray &appliedDofs = ic->giveDofIDs();
1369 const IntArray &nodes = set->giveNodeList();
1370 for ( int inode = 1; inode <= nodes.giveSize(); ++inode ) {
1371 for ( int idof = 1; idof <= appliedDofs.giveSize(); ++idof ) {
1372 dof_ic [ nodes.at(inode) - 1 ] [ appliedDofs.at(idof) ] = i;
1373 }
1374 }
1375 }
1376 }
1377 // Step 3b. This step asks nodes for their bc-vector, which is the old approach to dirichlet b.c.s (i.e. this is for backwards compatibility)
1379 for ( int i = 1; i <= this->giveNumberOfDofManagers(); ++i ) {
1380 DofManager *dman = this->giveDofManager(i);
1381 const std :: map< int, int > *dmanIcs = dman->giveIcMap();
1382 if ( dmanIcs ) {
1383 dof_ic [ i - 1 ].insert( dmanIcs->begin(), dmanIcs->end() ); // This will ignore duplicated dofiditems.
1384 }
1385 }
1386
1388 // Step 3. Create the dofs. This involves obtaining the correct
1389 for ( int i = 1; i <= this->giveNumberOfDofManagers(); ++i ) {
1390 DofManager *dman = this->giveDofManager(i);
1391 //printf("Dofs in node %d (of %d) = %d\n", i, this->giveNumberOfDofManagers(), node_dofs[i-1].size());
1392
1393 /* do not delete existing DOFs; that may be created during adaptive solution scheme (mesh generator applies DOFs) */
1394 if (0) dman->setNumberOfDofs(0);
1395
1396 for ( int id: node_dofs [ i - 1 ] ) {
1397 // Find bc and ic if there are any, otherwise zero.
1398 int bcid = dof_bc [ i - 1 ].find(id) != dof_bc [ i - 1 ].end() ? dof_bc [ i - 1 ] [ id ] : 0;
1399 //int icid = dof_ic [ i - 1 ].find(id) != dof_ic [ i - 1 ].end() ? dof_ic [ i - 1 ] [ id ] : 0;
1400
1401 // Determine the doftype:
1402 dofType dtype = DT_master;
1403 const std :: map< int, int > *dmanTypes = dman->giveDofTypeMap();
1404 if ( dmanTypes ) {
1405 std :: map< int, int > :: const_iterator it = dmanTypes->find(id);
1406 if ( it != dmanTypes->end() ) {
1407 dtype = ( dofType ) it->second;
1408 }
1409 }
1410 // Check if active dofs are needed:
1411 if ( bcid > 0 ) {
1412 // What should take precedence here if there is a slave node?
1413 // Right now the active b.c. overrides anything set prior, if necessary.
1414 // This seems like the most suitable choice, but it could possibly be changed.
1415 ActiveBoundaryCondition *active_bc = dynamic_cast< ActiveBoundaryCondition * >( this->giveBc(bcid) );
1416 if ( active_bc && active_bc->requiresActiveDofs() ) {
1417 dtype = DT_active;
1418 }
1419 }
1420
1421 if ( !dman->isDofTypeCompatible(dtype) ) {
1422 OOFEM_ERROR("Incompatible dof type (%d) in node %d", dtype, i);
1423 }
1424
1425 // Finally create the new DOF:
1426 //printf("Creating: node %d, id = %d, dofType = %d, bc = %d, ic = %d\n", i, id, dtype, bcid, icid);
1427 if ( !dman->hasDofID((DofIDItem)id) ) {
1428
1429 Dof *dof = classFactory.createDof(dtype, (DofIDItem)id, dman);
1430 // Slave dofs obtain their weights post-initialization, simple slave dofs must have their master node specified.
1431 if ( dtype == DT_simpleSlave ) {
1432 static_cast< SimpleSlaveDof * >(dof)->setMasterDofManagerNum( ( * dman->giveMasterMap() ) [ id ] );
1433 }
1434 dman->appendDof(dof);
1435 }
1436 }
1437 // assign bc & ic data on all dofs (existing & newly created ones)
1438 for ( Dof *dof: *dman ) {
1439 // Find bc and ic if there are any, otherwise zero.
1440 DofIDItem id = dof->giveDofID();
1441 int bcid = dof_bc [ i - 1 ].find(id) != dof_bc [ i - 1 ].end() ? dof_bc [ i - 1 ] [ id ] : 0;
1442 int icid = dof_ic [ i - 1 ].find(id) != dof_ic [ i - 1 ].end() ? dof_ic [ i - 1 ] [ id ] : 0;
1443 // preserve existing BC and IC if set (required for adaptivity, BC and IC set by mesher)
1444 if (dof->isPrimaryDof()) {
1445 if (dof->giveBcId()==0) dof->setBcId(bcid); // Note: slave dofs and such will simple ignore this.
1446 if (dof->giveIcId()==0) dof->setIcId(icid);
1447 }
1448 }
1449 }
1450
1451 // XFEM manager create additional dofs themselves:
1452 if ( this->hasXfemManager() ) {
1453 xfemManager->createEnrichedDofs();
1454 }
1455
1456}
1457
1458
1459int
1460Domain :: checkConsistency()
1461// this function transverse tree of all objects and invokes
1462// checkConsistency on this objects
1463// currently this function checks noly consistency
1464// of internal object structures, mainly whether referenced other objects
1465// are having required support
1466//
1467{
1468 int result = 1;
1469
1470 for ( auto &dman: this->dofManagerList ) {
1471 result &= dman->checkConsistency();
1472 }
1473
1474 for ( auto &element: this->elementList ) {
1475 result &= element->checkConsistency();
1476 }
1477
1478 for ( auto &material: this->materialList ) {
1479 result &= material->checkConsistency();
1480 }
1481
1482 return result;
1483}
1484
1485double
1486Domain :: giveArea()
1487{
1488 double area = 0.0;
1489 for ( auto &element: this->elementList ) {
1490 area += element->computeArea();
1491 }
1492
1493 return area;
1494}
1495
1496double
1497Domain :: giveVolume()
1498{
1499 double volume = 0.0;
1500 for ( auto &element: this->elementList ) {
1501 volume += element->computeVolume();
1502 }
1503
1504 return volume;
1505}
1506
1507double
1508Domain :: giveSize()
1509{
1510 double volume = 0.0;
1511 for ( auto &element: this->elementList ) {
1512 volume += element->computeVolumeAreaOrLength();
1513 }
1514
1515 return volume;
1516}
1517
1518int
1519Domain :: giveNextFreeDofID(int increment)
1520{
1521 if ( this->engineeringModel->isParallel() ) {
1522 OOFEM_ERROR("Additional dof id's not implemented/tested for parallel problems");
1523 }
1524
1525 int freeID = this->freeDofID;
1526 this->freeDofID += increment;
1527 return freeID;
1528}
1529
1530void
1531Domain :: resetFreeDofID()
1532{
1533 this->freeDofID = MaxDofID;
1534}
1535
1537Domain :: giveErrorEstimator()
1538{
1539 return engineeringModel->giveDomainErrorEstimator(this->number);
1540}
1541
1542
1544Domain :: giveOutputManager()
1545{
1546 return outputManager.get();
1547}
1548
1549
1551Domain :: giveTopology()
1552{
1553 return topology.get();
1554}
1555
1556
1557template< typename T >
1558void save_components(T &list, DataStream &stream, ContextMode mode)
1559{
1560 if ( !stream.write((int)list.size()) ) {
1562 }
1563 for ( const auto &object: list ) {
1564 if ( ( mode & CM_Definition ) != 0 ) {
1565 if ( stream.write( std :: string( object->giveInputRecordName() ) ) == 0 ) {
1567 }
1568 }
1569 object->saveContext(stream, mode);
1570 }
1571}
1572
1573
1574template< typename T, typename C >
1575void restore_components(T &list, DataStream &stream, ContextMode mode, const C &creator)
1576{
1577 int size = 0;
1578 if ( !stream.read(size) ) {
1580 }
1581 if ( mode & CM_Definition ) {
1582 list.clear();
1583 list.resize(size);
1584 }
1585 for ( int i = 1; i <= size; i++ ) {
1586 if ( mode & CM_Definition ) {
1587 std :: string name;
1588 if ( !stream.read(name) ) {
1590 }
1591 list[i-1] = creator(name, i);
1592 }
1593 list[i-1]->restoreContext(stream, mode);
1594 }
1595}
1596
1597
1598void
1599Domain :: saveContext(DataStream &stream, ContextMode mode)
1600{
1601 if ( !stream.write(this->giveSerialNumber()) ) {
1603 }
1604
1605 if ( ( mode & CM_Definition ) ) {
1606 save_components(this->setList, stream, mode);
1607 save_components(this->materialList, stream, mode);
1608 save_components(this->crossSectionList, stream, mode);
1609 save_components(this->icList, stream, mode);
1610 save_components(this->functionList, stream, mode);
1611 save_components(this->nonlocalBarrierList, stream, mode);
1612 }
1613
1614 save_components(this->dofManagerList, stream, mode);
1615 save_components(this->elementList, stream, mode);
1616 save_components(this->bcList, stream, mode);
1617
1618 auto ee = this->giveErrorEstimator();
1619 if ( ee ) {
1620 ee->saveContext(stream, mode);
1621 }
1622}
1623
1624
1625void
1626Domain :: restoreContext(DataStream &stream, ContextMode mode)
1627{
1628 bool domainUpdated = false;
1629 int serNum = this->giveSerialNumber();
1630 // restore domain serial number
1631 if ( !stream.read(this->serialNumber) ) {
1633 }
1634
1635 if ( ( mode & CM_Definition ) ) {
1636 // clear cached data:
1637 elementGlobal2LocalMap.clear();
1638 dofmanGlobal2LocalMap.clear();
1639
1641 xfemManager = nullptr;
1642
1643 restore_components(this->setList, stream, mode,
1644 [this] (std::string &x, int i) { return std::make_unique<Set>(i, this); });
1645 restore_components(this->materialList, stream, mode,
1646 [this] (std::string &x, int i) { return classFactory.createMaterial(x.c_str(), i, this); });
1647 restore_components(this->crossSectionList, stream, mode,
1648 [this] (std::string &x, int i) { return classFactory.createCrossSection(x.c_str(), i, this); });
1649 restore_components(this->icList, stream, mode,
1650 [this] (std::string &x, int i) { return classFactory.createInitialCondition(x.c_str(), i, this); });
1651 restore_components(this->functionList, stream, mode,
1652 [this] (std::string &x, int i) { return classFactory.createFunction(x.c_str(), i, this); });
1653 restore_components(this->nonlocalBarrierList, stream, mode,
1654 [this] (std::string &x, int i) { return classFactory.createNonlocalBarrier(x.c_str(), i, this); });
1655
1656 domainUpdated = true;
1657 } else {
1658 if ( serNum != this->giveSerialNumber() ) {
1659 // read corresponding domain
1660 OOFEM_LOG_INFO("restoring domain %d.%d\n", this->number, this->giveSerialNumber());
1661 OOFEMTXTDataReader domainDr(this->engineeringModel->giveDomainFileName(1, this->giveSerialNumber()));
1662 this->clear();
1663
1664 if ( !this->instanciateYourself(domainDr) ) {
1665 OOFEM_ERROR("domain Instanciation failed");
1666 }
1667
1668 domainUpdated = true;
1669 }
1670 }
1671
1672 restore_components(this->dofManagerList, stream, mode,
1673 [this] (std::string &x, int i) { return classFactory.createDofManager(x.c_str(), i, this); });
1674 restore_components(this->elementList, stream, mode,
1675 [this] (std::string &x, int i) { return classFactory.createElement(x.c_str(), i, this); });
1676 restore_components(this->bcList, stream, mode,
1677 [this] (std::string &x, int i) { return classFactory.createBoundaryCondition(x.c_str(), i, this); });
1678
1679 auto ee = this->giveErrorEstimator();
1680 if ( ee ) {
1681 if ( domainUpdated ) {
1682 ee->setDomain(this);
1683 }
1684 ee->restoreContext(stream, mode);
1685 }
1686
1687 if ( domainUpdated ) {
1688 if ( this->smoother ) {
1689 this->smoother->clear();
1690 }
1691 }
1692}
1693
1694#ifdef __MPI_PARALLEL_MODE
1695
1697Domain :: giveTransactionManager()
1698{
1699 if ( !transactionManager ) {
1700 transactionManager = std::make_unique<DomainTransactionManager>(this);
1701 if ( !transactionManager ) {
1702 OOFEM_ERROR("allocation failed");
1703 }
1704 }
1705
1706 return transactionManager.get();
1707}
1708
1709
1710int Domain :: commitTransactions(DomainTransactionManager *tm)
1711{
1712 if ( tm->dofmanTransactions.empty() && tm->elementTransactions.empty() ) {
1713 return 1;
1714 }
1715
1716 this->initGlobalDofManMap();
1717 for ( auto &dmanTrans: tm->dofmanTransactions ) {
1718 if ( dmanMap.find(dmanTrans.first) != dmanMap.end() ) {
1719 int lnum = dmanMap [ dmanTrans.first ]->giveNumber();
1720 DofManager *dman = dofManagerList[lnum-1].release();
1721 dmanMap.erase(dmanTrans.first);
1722 delete dman;
1723 }
1724
1725 if ( dmanTrans.second ) {
1726 dmanMap [ dmanTrans.first ] = ( DofManager * ) dmanTrans.second;
1727 }
1728 }
1729
1730 this->initGlobalElementMap();
1731 for ( auto elTrans: tm->elementTransactions ) {
1732 int gen = elTrans.first;
1733 if ( elementMap.find(gen) != elementMap.end() ) {
1734 int lnum = elementMap [ gen ]->giveNumber();
1735 Element *elem = elementList[lnum-1].release();
1736 elementMap.erase(gen);
1737 delete elem;
1738 }
1739
1740 if ( elTrans.second ) {
1741 elementMap [ gen ] = ( Element * ) elTrans.second;
1742 }
1743 }
1744
1745 /*
1746 * if (tm->transactions.empty()) return 1;
1747 *
1748 * // put existing domain dofman and element records into domain maps
1749 * this->initGlobalDofManMap ();
1750 * this->initGlobalElemMap();
1751 *
1752 * // commit all transactions
1753 * while (!tm->transactions.empty()) {
1754 * DTM_Transaction& t = tm->transactions.front();
1755 * if (t._ttype == DTT_Remove) {
1756 * if (t._ctype == DCT_DofManager) {
1757 * dmanMap.erase (t._num);
1758 * dman = dofManagerList.release (t._num-1);
1759 * delete dman;
1760 * } else if (t._ctype == DCT_Element) {
1761 * elem = elementList.release (t._num-1);
1762 * delete elem;
1763 * } else {
1764 * OOFEM_ERROR("unknown transaction component type");
1765 * }
1766 * } else if (t._ttype == DTT_ADD) {
1767 * if (t._ctype == DCT_DofManager) {
1768 * dmanMap[t._num] = (*DofManager) t._obj;
1769 * } else if (t._ctype == DCT_Element) {
1770 * elemMap[t._num] = (*Element) t._obj;
1771 * } else {
1772 * OOFEM_ERROR("unknown transaction component type");
1773 * }
1774 * } else {
1775 * OOFEM_ERROR("unknown transaction type");
1776 * }
1777 *
1778 * // Pop new transaction
1779 * tm->transactions.pop_front();
1780 * } // while (!tm->transactions.empty()) {
1781 *
1782 */
1783
1784 this->renumberDofManagers();
1785 this->renumberDofManData(tm);
1786
1787 this->renumberElements();
1788 this->renumberElementData(tm);
1789
1791 // initialize new element list
1792 std :: vector< std :: unique_ptr< Element > > elementList_new;
1793 elementList_new.reserve(elementMap.size());
1794 for ( auto &map: elementMap ) {
1795 elementList_new.emplace_back(map.second);
1796 }
1797 for ( auto &el: this->elementList ) {
1798 el.release();
1799 }
1800 this->elementList = std :: move(elementList_new);
1801
1802 // initialize new dofman list
1803 std :: vector< std :: unique_ptr< DofManager > > dofManagerList_new;
1804 dofManagerList_new.reserve(dmanMap.size());
1805 for ( auto &map: dmanMap ) {
1806 dofManagerList_new.emplace_back(map.second);
1807 }
1808 for ( auto &dman: this->dofManagerList ) {
1809 dman.release();
1810 }
1811 this->dofManagerList = std :: move(dofManagerList_new);
1812
1815
1816 tm->dofmanTransactions.clear();
1817 tm->elementTransactions.clear();
1818
1819 this->giveConnectivityTable()->reset();
1820 this->giveSpatialLocalizer()->init(true);
1821 return 1;
1822}
1823
1824
1825void
1826Domain :: initGlobalDofManMap(bool forceinit)
1827{
1828 /*
1829 * Renumber here the master node number for rigid and hanging dofs, etc;
1830 * existing local nodes need mapping from old_local to new numbering,
1831 * but received nodes need mapping from global to new numbering
1832 *
1833 * -> we need to keep the list of received nodes! (now they are only introduced into globally indexed dmanMap!);
1834 */
1835 if ( forceinit || !dmanMapInitialized ) {
1836 dmanMap.clear();
1837
1838 for ( auto &dman: dofManagerList ) {
1839 int key = dman->giveGlobalNumber();
1840 dmanMap[key] = dman.get();
1841 }
1842 }
1843}
1844
1845
1846void
1847Domain :: initGlobalElementMap(bool forceinit)
1848{
1849 if ( forceinit || !elementMapInitialized ) {
1850 elementMap.clear();
1851
1852 for ( auto &elem: elementList ) {
1853 int key = elem->giveGlobalNumber();
1854 elementMap[key] = elem.get();
1855 }
1856 }
1857}
1858
1859
1860void
1861Domain :: renumberDofManData(DomainTransactionManager *tm)
1862{
1863 SpecificEntityRenumberingFunctor< Domain > domainGToLFunctor(this, &Domain :: LB_giveUpdatedGlobalNumber);
1864 SpecificEntityRenumberingFunctor< Domain > domainLToLFunctor(this, &Domain :: LB_giveUpdatedLocalNumber);
1865
1866
1867 for ( auto &map : dmanMap ) {
1868 if ( tm->dofmanTransactions.find(map.first) != tm->dofmanTransactions.end() ) {
1869 // received dof manager -> we map global numbers to new local number
1870 map.second->updateLocalNumbering(domainGToLFunctor); // g_to_l
1871 } else {
1872 // existing dof manager -> we map old local number to new local number
1873 map.second->updateLocalNumbering(domainLToLFunctor); // l_to_l
1874 }
1875 }
1876}
1877
1878
1879void
1880Domain :: renumberElementData(DomainTransactionManager *tm)
1881{
1882 SpecificEntityRenumberingFunctor< Domain > domainGToLFunctor(this, &Domain :: LB_giveUpdatedGlobalNumber);
1883 SpecificEntityRenumberingFunctor< Domain > domainLToLFunctor(this, &Domain :: LB_giveUpdatedLocalNumber);
1884
1885 for ( auto &map : elementMap ) {
1886 if ( tm->elementTransactions.find(map.first) != tm->elementTransactions.end() ) {
1887 // received dof manager -> we map global numbers to new local number
1888 map.second->updateLocalNumbering(domainGToLFunctor); // g_to_l
1889 } else {
1890 // existing dof manager -> we map old local number to new local number
1891 map.second->updateLocalNumbering(domainLToLFunctor); // l_to_l
1892 }
1893 }
1894}
1895
1896
1897void
1898Domain :: renumberDofManagers()
1899{
1900 int _locnum = 1;
1901 for ( auto &map: dmanMap ) {
1902 map.second->setNumber(_locnum++);
1903 }
1904}
1905
1906
1907void
1908Domain :: renumberElements()
1909{
1910 int _locnum = 1;
1911 for ( auto &map: elementMap ) {
1912 map.second->setNumber(_locnum++);
1913 }
1914}
1915
1916
1917int
1918Domain :: LB_giveUpdatedLocalNumber(int num, EntityRenumberingScheme scheme)
1919{
1920 if ( scheme == ERS_DofManager ) {
1921 auto dm = this->giveDofManager(num);
1922 if ( dm ) {
1923 return dm->giveNumber();
1924 } else {
1925 OOFEM_ERROR("dofman %d moved to remote partition, updated number not available", num);
1926 }
1927 } else {
1928 OOFEM_ERROR("unsuported renumbering scheme");
1929 }
1930
1931 return 0;
1932}
1933
1934
1935int
1936Domain :: LB_giveUpdatedGlobalNumber(int num, EntityRenumberingScheme scheme)
1937{
1938 if ( scheme == ERS_DofManager ) {
1939 auto dm = dmanMap [ num ];
1940 if ( dm ) {
1941 return dm->giveNumber();
1942 } else {
1943 OOFEM_ERROR("dofman [%d] not available on local partition, updated number not available", num);
1944 return 0;
1945 }
1946 } else {
1947 OOFEM_ERROR("unsuported renumbering scheme");
1948 }
1949
1950 return 0;
1951}
1952
1953
1954int
1955Domain :: dofmanGlobal2Local(int _globnum)
1956{
1957 if ( dmanMap.find(_globnum) != dmanMap.end() ) {
1958 // dofman is already available -> update only
1959 return ( dmanMap [ _globnum ]->giveNumber() );
1960 } else {
1961 return 0;
1962 }
1963}
1964
1965
1966int
1967Domain :: elementGlobal2Local(int _globnum)
1968{
1969 if ( elementMap.find(_globnum) != elementMap.end() ) {
1970 // element is already available -> update only
1971 return ( elementMap [ _globnum ]->giveNumber() );
1972 } else {
1973 return 0;
1974 }
1975}
1976
1977#endif
1978
1979void Domain :: BuildElementPlaceInArrayMap()
1980{
1981 elementGlobal2LocalMap.clear();
1982
1983 int nelem = giveNumberOfElements();
1984
1985 for ( int i = 1; i <= nelem; i++ ) {
1986 Element *elem = this->giveElement(i);
1987 int globnum = elem->giveGlobalNumber();
1988 if ( elementGlobal2LocalMap.find(globnum) == elementGlobal2LocalMap.end() ) {
1989 // label does not exist yet
1990 elementGlobal2LocalMap [ globnum ] = i;
1991 } else {
1992 OOFEM_ERROR("Element with same global number already exist (label=%d)", globnum);
1993 }
1994 }
1995}
1996
1997void Domain :: BuildDofManPlaceInArrayMap()
1998{
1999 dofmanGlobal2LocalMap.clear();
2000
2001 int ndman = giveNumberOfDofManagers();
2002
2003 for ( int i = 1; i <= ndman; i++ ) {
2004 DofManager *dMan = this->giveDofManager(i);
2005 int globnum = dMan->giveGlobalNumber();
2006 if ( dofmanGlobal2LocalMap.find(globnum) == dofmanGlobal2LocalMap.end() ) {
2007 // label does not exist yet
2008 dofmanGlobal2LocalMap [ globnum ] = i;
2009 } else {
2010 OOFEM_ERROR("DofManagaer with same global number already exist (label=%d)", globnum);
2011 }
2012 }
2013}
2014
2015void Domain :: BuildMaterialToElementMap()
2016{
2017 materialNum2ElMap.clear();
2018
2019 int nelem = giveNumberOfElements();
2020
2021 for ( int i = 1; i <= nelem; i++ ) {
2022 Element *elem = this->giveElement(i);
2023 int matNum = elem->giveMaterialNumber();
2024 materialNum2ElMap[ matNum ].followedBy(i);
2025 }
2026}
2027
2028} // end namespace oofem
virtual bool requiresActiveDofs()
Definition activebc.h:151
Abstract base class for all contact surfaces.
Internal range-like class, return type for giveGroupRecords methods.
Definition datareader.h:137
RAII guard for DataReader::enterRecord and DataReader::leaveRecord.
Definition datareader.h:128
virtual bool peekNext(const std ::string &keyword)
Definition datareader.h:106
virtual InputRecord & giveInputRecord(InputRecordType irType, int recordId)=0
GroupRecords giveGroupRecords(const std::shared_ptr< InputRecord > &ir, InputFieldType ift, const std::string &name, InputRecordType irType, bool optional)
Definition datareader.C:46
static constexpr const char * InputRecordTags[]
Definition datareader.h:76
virtual bool hasFlattenedStructure()
Definition datareader.h:120
InputRecord * giveChildRecord(const std::shared_ptr< InputRecord > &ir, InputFieldType ift, const std::string &name, InputRecordType irType, bool optional)
Return pointer to subrecord of given type (must be exactly one); if not present, returns nullptr.
Definition datareader.C:40
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.
std ::map< int, int > * giveBcMap()
Definition dofmanager.h:421
int giveGlobalNumber() const
Definition dofmanager.h:515
bool hasDofID(DofIDItem id) const
Definition dofmanager.C:174
void setNumberOfDofs(int _ndofs)
Definition dofmanager.C:294
std ::map< int, int > * giveIcMap()
Definition dofmanager.h:427
virtual bool isDofTypeCompatible(dofType type) const
Returns true if dof of given type is allowed to be associated to receiver.
Definition dofmanager.h:468
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
std ::map< int, int > * giveMasterMap()
Definition dofmanager.h:415
void initializeFrom(InputRecord &ir) override
Definition dofmanager.h:456
std ::map< int, int > * giveDofTypeMap()
Definition dofmanager.h:409
void appendDof(Dof *dof)
Definition dofmanager.C:142
virtual void setBcId(int bcId)
Overwrites the boundary condition id (0-inactive BC), intended for specific purposes such as coupling...
Definition dof.h:382
std ::map< int, DofManager * > dofmanTransactions
std ::map< int, Element * > elementTransactions
std::unordered_map< int, IntArray > materialNum2ElMap
Definition domain.h:231
ErrorEstimator * giveErrorEstimator()
Definition domain.C:1537
std ::vector< std ::unique_ptr< DofManager > > dofManagerList
Dof manager list.
Definition domain.h:126
SpatialLocalizer * giveSpatialLocalizer()
Definition domain.C:1255
std ::unique_ptr< ConnectivityTable > connectivityTable
Definition domain.h:173
int instanciateYourself(DataReader &dr)
Definition domain.C:480
IntArray defaultNodeDofIDArry
Default dofs for a node (depends on the domain type).
Definition domain.h:153
void createDofs()
Definition domain.C:1275
int giveNumberOfBoundaryConditions() const
Returns number of boundary conditions in domain.
Definition domain.h:469
ConnectivityTable * giveConnectivityTable()
Definition domain.C:1240
int number
Domain number.
Definition domain.h:182
void BuildDofManPlaceInArrayMap()
Definition domain.C:1997
InitialCondition * giveIc(int n)
Definition domain.C:258
void clear()
Clear receiver.
Definition domain.C:129
Set * giveSet(int n)
Definition domain.C:366
std::unordered_map< int, int > elementGlobal2LocalMap
Definition domain.h:219
std ::vector< std ::unique_ptr< Set > > setList
Set list.
Definition domain.h:146
std ::vector< std ::unique_ptr< InitialCondition > > icList
Initial condition list.
Definition domain.h:142
void BuildMaterialToElementMap()
Definition domain.C:2015
int freeDofID
Keeps track of next free dof ID (for special Lagrange multipliers, XFEM and such).
Definition domain.h:238
void resolveDomainDofsDefaults(const char *)
Definition domain.C:1151
std ::unique_ptr< OutputManager > outputManager
Output manager, allowing to filter the produced output.
Definition domain.h:180
int giveNumberOfInitialConditions() const
Returns number of initial conditions in domain.
Definition domain.h:471
bool dmanMapInitialized
dmanMap init flag.
Definition domain.h:250
std ::unique_ptr< SpatialLocalizer > spatialLocalizer
Definition domain.h:178
int giveNumber()
Returns domain number.
Definition domain.h:281
void initGlobalElementMap(bool forceinit=false)
Definition domain.C:1847
std ::vector< std ::unique_ptr< NonlocalBarrier > > nonlocalBarrierList
Nonlocal barrier list.
Definition domain.h:150
void initGlobalDofManMap(bool forceinit=false)
Definition domain.C:1826
void initializeFinish()
Definition domain.C:929
std::unordered_map< int, int > dofmanGlobal2LocalMap
Definition domain.h:225
std::vector< std::unique_ptr< ContactSurface > > & giveContactSurface()
Definition domain.h:325
int giveNumberOfSets() const
Returns number of sets.
Definition domain.h:479
domainType dType
Definition domain.h:162
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
void renumberDofManagers()
Definition domain.C:1898
StateCounterType nonlocalUpdateStateCounter
Definition domain.h:202
std ::vector< std ::unique_ptr< GeneralBoundaryCondition > > bcList
Boundary condition list.
Definition domain.h:140
bool elementMapInitialized
dmanMap init flag.
Definition domain.h:254
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
std ::unique_ptr< NodalRecoveryModel > smoother
nodal recovery object associated to receiver.
Definition domain.h:189
std ::unique_ptr< TopologyDescription > topology
Topology description.
Definition domain.h:234
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
int nsd
Number of spatial dimensions.
Definition domain.h:186
void renumberDofManData(DomainTransactionManager *tm)
Definition domain.C:1861
GeneralBoundaryCondition * giveBc(int n)
Definition domain.C:246
void renumberElements()
Definition domain.C:1908
EngngModel * giveEngngModel()
Definition domain.C:419
void renumberElementData(DomainTransactionManager *tm)
Definition domain.C:1880
std ::unique_ptr< FractureManager > fracManager
Fracture Manager.
Definition domain.h:207
std ::unique_ptr< DomainTransactionManager > transactionManager
Definition domain.h:246
XfemManager * giveXfemManager()
Definition domain.C:378
std::vector< std::unique_ptr< ContactSurface > > contactSurfaceList
Contact surface list.
Definition domain.h:148
std ::vector< std ::unique_ptr< Element > > elementList
Element list.
Definition domain.h:124
ParameterManager elementPPM
Definition domain.h:133
int giveSerialNumber()
Returns domain serial (version) number.
Definition domain.h:285
EngngModel * engineeringModel
Definition domain.h:167
bool axisymm
Definition domain.h:187
std ::unique_ptr< XfemManager > xfemManager
XFEM Manager.
Definition domain.h:204
std ::vector< std ::unique_ptr< CrossSection > > crossSectionList
Cross section list.
Definition domain.h:128
bool hasXfemManager()
Definition domain.C:389
std ::map< int, Element * > elementMap
Global element map (index is global of man number).
Definition domain.h:252
void BuildElementPlaceInArrayMap()
Definition domain.C:1979
std ::map< int, DofManager * > dmanMap
Global dof manager map (index is global of man number).
Definition domain.h:248
int giveNumberOfCrossSectionModels() const
Returns number of cross section models in domain.
Definition domain.h:467
ParameterManager dofmanPPM
Definition domain.h:134
std ::vector< std ::unique_ptr< Material > > materialList
Material list.
Definition domain.h:138
std ::vector< std ::unique_ptr< Function > > functionList
Load time function list.
Definition domain.h:144
std::string mDomainType
Definition domain.h:191
BCTracker bcTracker
BC tracker (keeps track of BCs applied wia sets to components).
Definition domain.h:212
CrossSection * giveCrossSection(int n)
Definition domain.C:342
BCTracker * giveBCTracker()
Definition domain.C:413
int giveGlobalNumber() const
Definition element.h:1129
static ParamKey IPK_Element_crosssect
Definition element.h:199
virtual void setCrossSection(int csIndx)
Definition element.h:692
void initializeFrom(InputRecord &ir, int priority) override
Definition element.C:687
int giveMaterialNumber() const
Definition element.h:665
bool giveSuppressOutput() const
Definition engngm.h:369
int number
Receivers id.
Definition engngm.h:245
virtual const IntArray & giveDofIDs() const
const IntArray & giveDofIDs()
virtual void giveRecordKeywordField(std ::string &answer, int &value)=0
Reads the record id field (type of record) and its corresponding number.
virtual std::shared_ptr< InputRecord > clone() const =0
std::shared_ptr< InputRecord > ptr()
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
Renumbering functor based on provided maps.
std::string giveElementProperties() const
Definition set.h:181
const IntArray & giveInternalElementDofManagerList()
Definition set.C:166
const IntArray & giveElementList()
Definition set.C:158
std::string giveDofManProperties() const
Definition set.h:182
const IntArray & giveNodeList()
Definition set.C:168
#define THROW_CIOERR(e)
#define CM_Definition
Definition contextmode.h:47
#define _IFT_Domain_topology
Definition domain.h:69
#define _IFT_Domain_axisymmetric
Definition domain.h:74
#define _IFT_Domain_ncontactsurf
Definition domain.h:71
#define _IFT_Domain_nfunct
Definition domain.h:66
#define _IFT_Domain_nic
Definition domain.h:65
#define _IFT_Domain_nfracman
Definition domain.h:73
#define _IFT_Domain_nxfemman
Definition domain.h:70
#define _IFT_Domain_numberOfSpatialDimensions
[in,optional] Specifies how many spatial dimensions the domain has.
Definition domain.h:72
#define _IFT_Domain_nmat
Definition domain.h:62
#define _IFT_Domain_ncrosssect
Definition domain.h:63
#define _IFT_Domain_ndofman
Definition domain.h:60
#define _IFT_Domain_nbc
Definition domain.h:64
#define _IFT_Domain_nbarrier
Definition domain.h:68
#define _IFT_Domain_nset
Definition domain.h:67
#define _IFT_Domain_nelem
Definition domain.h:61
#define _IFT_Domain_type
This is trouble, will not work with dynamic input record.
Definition domain.h:59
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_RECORD_KEYWORD_FIELD(__ir, __name, __value)
Definition inputrecord.h:82
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_ERROR(...)
Definition logger.h:138
@ MaxDofID
Definition dofiditem.h:117
long ContextMode
Definition contextmode.h:43
void save_components(T &list, DataStream &stream, ContextMode mode)
Definition domain.C:1558
dofType
Dof Type, determines the type of DOF created.
Definition doftype.h:48
void restore_components(T &list, DataStream &stream, ContextMode mode, const C &creator)
Definition domain.C:1575
const char * __domainTypeToString(domainType _value)
Definition cltypes.C:321
ClassFactory & classFactory
@ CIO_IOERR
General IO error.
#define VERBOSE_PRINT0(str, number)
Definition verbose.h:56

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