OOFEM 3.0
Loading...
Searching...
No Matches
engngm.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// Milan ?????????????????
36//#include "gpinitmodule.h"
37// Milan ?????????????????
38
39#include "nummet.h"
40#include "sparsemtrx.h"
41#include "engngm.h"
42#include "oofemcfg.h"
43#include "timestep.h"
44#include "metastep.h"
45#include "element.h"
46#include "set.h"
47#include "load.h"
48#include "bodyload.h"
49#include "boundaryload.h"
50#include "nodalload.h"
51#include "oofemenv.h"
52#include "timer.h"
53#include "dofmanager.h"
54#include "node.h"
55#include "activebc.h"
56#include "Contact/contactbc.h"
57#include "timestep.h"
58#include "verbose.h"
59#include "datastream.h"
60#include "oofemtxtdatareader.h"
61#include "sloangraph.h"
62#include "logger.h"
63#include "errorestimator.h"
64#include "contextioerr.h"
65#include "outputmanager.h"
66#include "exportmodulemanager.h"
67#include "initmodulemanager.h"
68#include "feinterpol3d.h"
69#include "classfactory.h"
70#include "xfem/xfemmanager.h"
71#include "parallelcontext.h"
74#include "nodalrecoverymodel.h"
76
77
78#ifdef __MPI_PARALLEL_MODE
79 #include "problemcomm.h"
80 #include "processcomm.h"
81 #include "loadbalancer.h"
82#endif
83
84#ifdef __MPM_MODULE
85 #include "mpm/mpm.h"
86#endif
87
88#include <cstdio>
89#include <cstdarg>
90#include <ctime>
91#ifdef _OPENMP
92 #include <omp.h>
93#endif
94#ifdef __OOFEG
95 #include "oofeggraphiccontext.h"
96#endif
97
98namespace oofem {
99EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPrescribedNeqs(),
101 initModuleManager(this),
102 monitorManager(this),
103 timeStepController( std::make_unique<TimeStepController>( this ) )
104{
105 suppressOutput = false;
106
107 number = i;
108 numberOfSteps = 0;
111 renumberFlag = false;
113 ndomains = 0;
114 nMetaSteps = 0;
115 profileOpt = false;
117
118 outputStream = NULL;
119
121
124 pMode = _processor; // for giveContextFile()
126
127 master = _master; // master mode by default
128 // create context if in master mode; otherwise request context from master
129 if ( master ) {
130 context = master->giveContext();
131 } else {
133 }
134
135 parallelFlag = 0;
136 numProcs = 1;
137 rank = 0;
138 nonlocalExt = 0;
139#ifdef __MPI_PARALLEL_MODE
140 loadBalancingFlag = false;
142 lb = NULL;
143 lbm = NULL;
144 communicator = NULL;
145 nonlocCommunicator = NULL;
146 commBuff = NULL;
147 #ifdef __USE_MPI
148 comm = MPI_COMM_SELF;
149 #endif
150#endif
151}
152
153
154EngngModel :: ~EngngModel()
155{
156 // master deletes the context
157 if ( master == NULL ) {
158 delete context;
159 }
160
161 //fclose (inputStream) ;
162 if ( outputStream ) {
163 fclose(outputStream);
164 }
165
166#ifdef __MPI_PARALLEL_MODE
167 delete communicator;
168 delete nonlocCommunicator;
169 delete commBuff;
170#endif
171}
172
173
174void EngngModel :: setParallelMode(bool newParallelFlag)
175{
176 parallelFlag = newParallelFlag;
177 if ( parallelFlag ) {
178 initParallel();
179 }
180}
181
182
183void
184EngngModel :: Instanciate_init()
185{
186 // create domains
187 domainNeqs.clear();
188 domainNeqs.resize(ndomains);
189 domainPrescribedNeqs.clear();
191 domainList.clear();
192 domainList.reserve(ndomains);
193 for ( int i = 1; i <= ndomains; i++ ) {
194 domainList.push_back(std::make_unique<Domain>(i, 0, this));
195 }
196
197 this->initParallelContexts();
198}
199
200
201int EngngModel :: instanciateYourself(DataReader &dr, InputRecord &ir, const char *dataOutputFileName, const char *desc)
202{
203 std::shared_ptr<InputRecord> irPtr(ir.ptr());
204 Timer timer;
205 timer.startTimer();
206
208
209 bool inputReaderFinish = true;
210
211 this->coreOutputFileName = std :: string(dataOutputFileName);
212 this->dataOutputFileName = std :: string(dataOutputFileName);
213
214 if ( this->giveProblemMode() == _postProcessor ) {
215 // modify output file name to prevent output to be lost
216 this->dataOutputFileName.append(".oofeg");
217 }
218
219
220 this->Instanciate_init(); // Must be done after initializeFrom
221
222
223 this->startTime = time(NULL);
224
225# ifdef VERBOSE
226 OOFEM_LOG_DEBUG( "Reading all data from \"%s\"\n", referenceFileName.c_str() );
227# endif
228
229 simulationDescription = std::string(desc);
230
231 try {
232 // instanciate receiver
233 this->initializeFrom(*irPtr);
234
235 // initialize the time step controller, its metasptes, and its associated time reduction strategy
236 timeStepController->initializeFrom( ir );
237 if ( timeStepController->giveNumberOfMetaSteps() == 0 ) {
238 inputReaderFinish = false;
239 timeStepController->instanciateDefaultMetaStep( ir );
240 } else {
241 // records for metasteps are under this one (no-op for text reader)
242 DataReader::RecordGuard guard(dr,&ir);
243 timeStepController->instanciateMetaSteps( dr );
244 }
245
246 {
247 /* This is somewhat messy since we want the XML input format NOT to nest modules under Analysis, keeping them under the top-level <oofem> tag instead */
248 auto irParent=(dr.hasFlattenedStructure()?dr.giveTopInputRecord()->ptr():irPtr);
249 DataReader::RecordGuard scope(dr,irParent.get());
250 // instanciate initialization module manager
251 initModuleManager.instanciateYourself(dr, irParent, "ninitmodules", "InitModules",DataReader::IR_expModuleRec);
252 // instanciate export module manager
253 exportModuleManager.instanciateYourself(dr, irParent, "nmodules", "ExportModules",DataReader::IR_expModuleRec);
254 // instanciate monitor manager
255 monitorManager.instanciateYourself(dr, irParent, "nmonitors", "Monitors",DataReader::IR_expModuleRec);
256 this->giveContext()->giveFieldManager()->instanciateYourself(dr, *irPtr);
257 /* on the other hand, MPM stuff *should* be nested under Analysis, so pass irPtr there */
258 #ifdef __MPM_MODULE
259 // instanciate mpm stuff (variables, terms, and integrals)
260 this->instanciateMPM(dr,*irPtr);
261 #endif
262 }
263 this->instanciateDomains(dr);
264
265 exportModuleManager.initialize();
266
267 // Milan ??????????????????
268 //GPImportModule* gim = new GPImportModule(this);
269 //gim -> getInput();
270 // Milan ??????????????????
271
272 if ( this->nMetaSteps == 0 ) {
273 inputReaderFinish = false;
274 this->instanciateDefaultMetaStep(*irPtr);
275 }
276
277 // check emodel input record if no default metastep, since all has been read
278 if ( inputReaderFinish ) {
279 irPtr->finish();
280 }
281 } catch ( InputException &e ) {
282 OOFEM_ERROR("Error initializing from user input: %s\n", e.what());
283 }
284
285 timer.stopTimer();
286 OOFEM_LOG_DEBUG( "Problem instantiation done in %.2fs\n", timer.getUtime() );
287 return 1;
288}
289
290
291void
292EngngModel :: initializeFrom(InputRecord &ir)
293{
294 numberOfSteps = 1;
296 if ( numberOfSteps <= 0 ) {
297 OOFEM_ERROR("nsteps not specified, bad format");
298 }
299
302 if ( contextOutputStep ) {
304 }
305
306 renumberFlag = false;
308 profileOpt = false;
310
311 // get explicit nmsteps param (text), or size of the <Metasteps> sub-group (xml)
312 /* needs to use clone() and not ptr()... unclear why; the ownership of InputRecord should be specified better */
314
315 int _val = 1;
317 nonLinFormulation = ( fMode ) _val;
318
319 int eeTypeId = -1;
321 if ( eeTypeId >= 0 ) {
322 this->defaultErrEstimator = classFactory.createErrorEstimator( ( ErrorEstimatorType ) eeTypeId, 1, this->giveDomain(1) );
323 this->defaultErrEstimator->initializeFrom(ir);
324 }
325
327 // fprintf (stderr, "Parallel mode is %d\n", parallelFlag);
328
329#ifdef __MPI_PARALLEL_MODE
330 /* Load balancing support */
331 _val = 0;
333 loadBalancingFlag = _val;
334
335 _val = 0;
338
339#endif
340
342
343 if ( suppressOutput ) {
344 //printf("Suppressing output.\n");
345 }
346 else {
347
348 if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) {
349 OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str());
350 }
351
352 fprintf(outputStream, "%s", PRG_HEADER);
353 fprintf(outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) );
354 fprintf(outputStream, "%s\n", simulationDescription.c_str());
355
356#ifdef __MPI_PARALLEL_MODE
357 if ( this->isParallel() ) {
358 fprintf(outputStream, "Problem rank is %d/%d on %s\n\n", this->rank, this->numProcs, this->processor_name);
359 }
360#endif
361 }
362}
363
364
365int
366EngngModel :: instanciateDomains(DataReader &dr)
367{
368 int result = 1;
369 // read problem domains
370 auto Idomain=domainList.begin();
371 for(size_t i=0; i<domainList.size(); i++){
373 DataReader::RecordGuard guard(dr,&rec);
374 result&=(*Idomain)->instanciateYourself(dr,rec);
375 }
376 this->postInitialize();
377 return result;
378}
379
380
381int
382EngngModel :: instanciateMetaSteps(DataReader &dr)
383{
384 // create meta steps
385 metaStepList.clear();
386 metaStepList.reserve(nMetaSteps);
387 for ( int i = 1; i <= this->nMetaSteps; i++ ) {
388 //MetaStep *mstep = new MetaStep(i, this);
389 metaStepList.emplace_back(i, this);
390 }
391
392 // read problem domains
393 auto mrecs=dr.giveGroupRecords("Metasteps",DataReader::IR_mstepRec,nMetaSteps);
394 int i=0;
395 for(InputRecord& mrec: mrecs){
396 metaStepList[i++].initializeFrom(mrec);
397 }
398
399 this->numberOfSteps = metaStepList.size();
400 return 1;
401}
402
403
404int
405EngngModel :: instanciateDefaultMetaStep(InputRecord &ir)
406{
407 if ( numberOfSteps == 0 ) {
408 OOFEM_ERROR("nsteps cannot be zero");
409 }
410
411 // create default meta steps
412 this->nMetaSteps = 1;
413 metaStepList.clear();
414 //MetaStep *mstep = new MetaStep(1, this, numberOfSteps, *ir);
415 metaStepList.emplace_back(1, this, numberOfSteps, ir);
416
417 return 1;
418}
419
420#ifdef __MPM_MODULE
421int
422EngngModel:: instanciateMPM (DataReader &dr, InputRecord &ir) {
423 std::shared_ptr<InputRecord> irPtr(ir.ptr());
424 std::string name;
425 int num=-1;
426 DataReader::RecordGuard scope(dr,irPtr.get());
427 for(auto& mir: dr.giveGroupRecords(irPtr,"nvariables","MPMVariables",DataReader::IR_mpmVarRec,/*optional*/true)){
428 IR_GIVE_FIELD(mir, name, "name");
429 std::unique_ptr< Variable > var = std :: make_unique< Variable >();
430 var->initializeFrom(mir);
431 variableMap[name] = std::move(var);
432 }
433 //if(variableMap.empty()) OOFEM_ERROR("No MPM Variables defined.");
434 for(auto& mir: dr.giveGroupRecords(irPtr,"nterms","MPMTerms",DataReader::IR_mpmTermRec,/*optional*/true)){
435 IR_GIVE_RECORD_KEYWORD_FIELD(mir, name, num);
436 std::unique_ptr< Term > term = classFactory.createTerm(name.c_str());
437 term->initializeFrom(mir, this);
438 termList.push_back(std::move(term));
439 }
440 //if(termList.empty()) OOFEM_ERROR("No MPM Terms defined.");
441 for(auto& mir: dr.giveGroupRecords(irPtr,"nintegrals","MPMIntegrals",DataReader::IR_mpmIntegralRec,/*optional*/true)){
442 std::unique_ptr< Integral > integral = std :: make_unique< Integral >(nullptr, &dummySet, nullptr);
443 integral->initializeFrom(mir, this);
444 this->addIntegral(std::move(integral));
445 }
446 //if(integralList.empty()) OOFEM_ERROR("No MPM Integrals defined.");
447 return 1;
448}
449
450#endif
451int
452EngngModel :: giveNumberOfDomainEquations(int id, const UnknownNumberingScheme &num)
453{
454 //
455 // returns number of equations of current problem
456 // this method is implemented here, because some method may add some
457 // conditions into the system and this may results into increased number of
458 // equations.
459 //
462 }
463
464 return num.isDefault() ? domainNeqs.at(id) : domainPrescribedNeqs.at(id);
465}
466
467
468int
469EngngModel :: forceEquationNumbering(int id)
470{
471 // forces equation renumbering for current time step
472 // intended mainly for problems with changes of static system
473 // during solution
474 // OUTPUT:
475 // sets this->numberOfEquations and this->numberOfPrescribedEquations and returns this value
476
477 Domain *domain = this->giveDomain(id);
478 TimeStep *currStep = this->giveCurrentStep();
479
480 this->domainNeqs.at(id) = 0;
481 this->domainPrescribedNeqs.at(id) = 0;
482
483 if ( !this->profileOpt ) {
484 for ( auto &node : domain->giveDofManagers() ) {
485 node->askNewEquationNumbers(currStep);
486 }
487
488 for ( auto &elem : domain->giveElements() ) {
489 int nnodes = elem->giveNumberOfInternalDofManagers();
490 for ( int k = 1; k <= nnodes; k++ ) {
491 elem->giveInternalDofManager(k)->askNewEquationNumbers(currStep);
492 }
493 }
494
495 // For special boundary conditions;
496 for ( auto &bc : domain->giveBcs() ) {
497 int nnodes = bc->giveNumberOfInternalDofManagers();
498 for ( int k = 1; k <= nnodes; k++ ) {
499 bc->giveInternalDofManager(k)->askNewEquationNumbers(currStep);
500 }
501 }
502 } else {
503 // invoke profile reduction
504 int initialProfile, optimalProfile;
505 Timer timer;
506 OOFEM_LOG_INFO("\nRenumbering DOFs with Sloan's algorithm...\n");
507 timer.startTimer();
508
509 SloanGraph graph(domain);
510 graph.initialize();
511 graph.tryParameters(0, 0);
512 initialProfile = graph.giveOptimalProfileSize();
513 graph.tryParameters(2, 1);
514 graph.tryParameters(1, 0);
515 graph.tryParameters(5, 1);
516 graph.tryParameters(10, 1);
517 optimalProfile = graph.giveOptimalProfileSize();
518
519 timer.stopTimer();
520
521 OOFEM_LOG_DEBUG( "Sloan's algorithm done in %.2fs\n", timer.getUtime() );
522 OOFEM_LOG_DEBUG("Nominal profile %d (old) %d (new)\n", initialProfile, optimalProfile);
523
524 //FILE* renTableFile = fopen ("rentab.dat","w");
525 //graph.writeOptimalRenumberingTable (renTableFile);
526 graph.askNewOptimalNumbering(currStep);
527 }
528
529 return domainNeqs.at(id);
530}
531
532
533int
534EngngModel :: forceEquationNumbering()
535{
536 // set numberOfEquations counter to zero
537 this->numberOfEquations = 0;
539
540 OOFEM_LOG_DEBUG("Renumbering dofs in all domains\n");
541 for ( int i = 1; i <= this->giveNumberOfDomains(); i++ ) {
542 domainNeqs.at(i) = 0;
544 }
545
547
548 for ( int i = 1; i <= this->giveNumberOfDomains(); i++ ) {
550 }
551
552 for ( std :: size_t i = 1; i <= parallelContextList.size(); i++ ) {
553 this->parallelContextList[i-1].init((int)i);
554 }
555
556
557 return this->numberOfEquations;
558}
559
560void
562{
563 // needed only of BCs are changing, no way to get this information now
564 // so to be safe, we alvays reinitialize
565#ifdef _OPENMP
566#pragma omp single
567#endif
568 for ( auto &domain: domainList ) {
569 domain->giveBCTracker()->initialize();
570 }
571}
572
573void
574EngngModel :: solveYourself()
575{
576 int smstep = 1;
577
578 this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer);
579
580 TimeStep *timeStep = this->giveCurrentStep();
581 if ( timeStep ) {
582 smstep = timeStepController->giveMetaStepNumber();
583 }
584
585
586 for ( int imstep = smstep; imstep <= timeStepController->giveNumberOfMetaSteps(); imstep++ ) { //loop over meta steps
587 auto activeMStep = this->giveMetaStep(imstep);
588 // update state according to new meta step
589 timeStepController->setCurrentMetaStepNumber( imstep - 1 );
590 timeStepController->initMetaStepAttributes( activeMStep );
591 double msFinalTime = activeMStep->giveFinalTime() - this->giveInitialTime();
592 //
593 do {
594 this->timer.startTimer(EngngModelTimer :: EMTT_SolutionStepTimer);
595 this->timer.initTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
596
597 this->preInitializeNextStep();
598 this->giveNextStep();
599 //hack for nlinear static - should be deleted when the time step controller is fully integrated
600 this->giveCurrentStep()->setMetaStepNumber(imstep);
601
602 // renumber equations if necessary. Ensure to call forceEquationNumbering() for staggered problems
603 if ( this->requiresEquationRenumbering( this->giveCurrentStep() ) ) {
605 }
606
607 OOFEM_LOG_DEBUG("Number of equations %d\n", this->giveNumberOfDomainEquations( 1, EModelDefaultEquationNumbering()) );
608
609 this->initializeYourself( this->giveCurrentStep() );
610 // solving the step
611 auto repeat = true;
612 auto nReductions = 0;
613 while ( repeat ) {
614 // try to solve the step, ask time step reduction strategy to reduce time step in case of convergence issues
615 this->giveCurrentStep()->numberOfAttempts = 1 + nReductions;
616 try {
617 this->solveYourselfAt( this->giveCurrentStep() );
618 auto nIter = this->giveCurrentStep()->numberOfIterations;
619 this->adaptTimeStep( nIter );
620 repeat = false;
621 } catch ( ConvergenceException &ce ) {
622 if ( timeStepController->giveCurrentMetaStep()->giveTimeStepReductionStrategy()->giveReductionFlag() ) {
623 timeStepController->reduceTimeStep();
624 OOFEM_LOG_INFO( "--------------------------------------------------------------------------------------\nRestarting step with new time step increment %e due to convergence problem \n--------------------------------------------------------------------------------------\n", this->giveCurrentStep()->giveTimeIncrement() );
625 OOFEM_LOG_INFO( "%s\n", ce.what() );
626 this->initStepIncrements();
627 this->restartYourself( this->giveCurrentStep() );
628 nReductions++;
629 if ( nReductions > activeMStep->giveNumberOfMaxTimeStepReductions() ) {
630 OOFEM_ERROR( "Maximum number of time step reductions has been reached." );
631 }
632 } else { // else: do nothing, i.e., continue with the analysis
633
634 repeat = false;
635 }
636 }
637 }
638 // this->solveYourselfAt( this->giveCurrentStep() );
639 this->updateYourself( this->giveCurrentStep() );
640
641 this->timer.stopTimer(EngngModelTimer :: EMTT_SolutionStepTimer);
642 double _steptime = this->giveSolutionStepTime();
643 this->giveCurrentStep()->solutionTime = _steptime;
644
645 this->terminate( this->giveCurrentStep() );
646
647
648 OOFEM_LOG_INFO("EngngModel info: user time consumed by solution step %d: %.2fs\n",
649 this->giveCurrentStep()->giveNumber(), _steptime);
650
651
652 if ( !suppressOutput ) {
653 fprintf(this->giveOutputStream(), "\nUser time consumed by solution step %d: %.3f [s]\n\n",
654 this->giveCurrentStep()->giveNumber(), _steptime);
655 }
656
657#ifdef __MPI_PARALLEL_MODE
658 if ( loadBalancingFlag ) {
659 this->balanceLoad( this->giveCurrentStep() );
660 }
661
662#endif
663 } while ( this->giveCurrentStep()->giveTargetTime() < msFinalTime );
664 }
665}
666
667
668void
669EngngModel :: updateAttributes(MetaStep *mStep)
670{
671 MetaStep *mStep1 = timeStepController->giveMetaStep( mStep->giveNumber() ); //this line ensures correct input file in staggered problem
672 auto &ir = mStep1->giveAttributesRecord();
673
674 if ( this->giveNumericalMethod(mStep1) ) {
675 this->giveNumericalMethod(mStep1)->initializeFrom(ir);
676 }
677
678#ifdef __MPI_PARALLEL_MODE
679 if ( this->giveLoadBalancer() ) {
680 this->giveLoadBalancer()->initializeFrom(ir);
681 }
682
683 if ( this->giveLoadBalancerMonitor() ) {
684 this->giveLoadBalancerMonitor()->initializeFrom(ir);
685 }
686
687#endif
688}
689
690
691void
692EngngModel :: updateYourself(TimeStep *tStep)
693{
694 for ( auto &domain: domainList ) {
695# ifdef VERBOSE
696 VERBOSE_PRINT0( "Updating domain ", domain->giveNumber() )
697# endif
698
699 for ( auto &dman : domain->giveDofManagers() ) {
700 dman->updateYourself(tStep);
701 }
702
703 // Update xfem manager if it is present
704 if ( domain->hasXfemManager() ) {
705 domain->giveXfemManager()->updateYourself(tStep);
706 }
707
708# ifdef VERBOSE
709 VERBOSE_PRINT0("Updated nodes ", domain->giveNumberOfDofManagers())
710# endif
711
712
713 for ( auto &elem : domain->giveElements() ) {
714 // skip remote elements (these are used as mirrors of remote elements on other domains
715 // when nonlocal constitutive models are used. They introduction is necessary to
716 // allow local averaging on domains without fine grain communication between domains).
717 if ( elem->giveParallelMode() == Element_remote ) {
718 continue;
719 }
720
721 elem->updateYourself(tStep);
722 }
723
724# ifdef VERBOSE
725 VERBOSE_PRINT0("Updated Elements ", domain->giveNumberOfElements())
726# endif
727
728 for ( auto &bc : domain->giveBcs() ) {
729 bc->updateYourself(tStep);
730 }
731# ifdef VERBOSE
732 VERBOSE_PRINT0("Updated BCs ", domain->giveNumberOfBoundaryConditions())
733# endif
734 }
735
736
737
738}
739
740void
741EngngModel :: terminate(TimeStep *tStep)
742{
743 if ( !suppressOutput ) {
744 this->doStepOutput(tStep);
745 fflush( this->giveOutputStream() );
746 } else {
747 exportModuleManager.doOutput(tStep);
748 }
750
751 this->saveStepContext(tStep, CM_State | CM_Definition);
752}
753
754
755void
756EngngModel :: doStepOutput(TimeStep *tStep)
757{
758 if ( !suppressOutput ) {
759 this->printOutputAt(this->giveOutputStream(), tStep);
760 fflush( this->giveOutputStream() );
761 }
762
763 // export using export manager
764 exportModuleManager.doOutput(tStep);
765}
766
767void
768EngngModel :: saveStepContext(TimeStep *tStep, ContextMode mode)
769{
771 ( this->giveContextOutputMode() == COM_UserDefined && tStep->giveNumber() % this->giveContextOutputStep() == 0 ) ) {
772
773 auto fname = this->giveContextFileName(this->giveCurrentStep()->giveNumber(), this->giveCurrentStep()->giveVersion());
774 FileDataStream stream(fname, true);
775 this->saveContext(stream, mode);
776 }
777}
778
779
780void
781EngngModel :: printOutputAt(FILE *file, TimeStep *tStep)
782{
783 int domCount = 0;
784
785 for ( auto &domain: domainList ) {
786 domCount += domain->giveOutputManager()->testTimeStepOutput(tStep);
787 }
788
789 if ( domCount == 0 ) {
790 return; // do not print even Solution step header
791 }
792
793 fprintf(file, "\n==============================================================");
794 fprintf(file, "\nOutput for time %.8e ", tStep->giveTargetTime() * this->giveVariableScale(VST_Time) );
795 fprintf(file, "\n==============================================================\n");
796 for ( auto &domain: domainList ) {
797 fprintf( file, "Output for domain %3d\n", domain->giveNumber() );
798
799 domain->giveOutputManager()->doDofManOutput(file, tStep);
800 domain->giveOutputManager()->doElementOutput(file, tStep);
801 }
802}
803
804
805void
806EngngModel :: printOutputAt(FILE *file, TimeStep *tStep, const IntArray &nodeSets, const IntArray &elementSets)
807{
808 for ( auto &domain: domainList ) {
809 int dnum = domain->giveNumber();
810 fprintf( file, "Output for domain %3d\n", dnum );
811 int nset = nodeSets.giveSize() < dnum ? 0 : nodeSets.at(dnum);
812 int eset = elementSets.giveSize() < dnum ? 0 : elementSets.at(dnum);
813
814 this->outputNodes(file, *domain, tStep, nset);
815 this->outputElements(file, *domain, tStep, eset);
817#if 0
818 this->outputReactionForces(file, *domain, tStep, nset);
819#endif
820 }
821}
822
823
824void
825EngngModel :: outputNodes(FILE *file, Domain &domain, TimeStep *tStep, int setNum)
826{
827 fprintf(file, "\n\nNode output:\n------------------\n");
828
829 if ( setNum == 0 ) { // No set specified, export all
830 for ( auto &dman : domain.giveDofManagers() ) {
831 if ( dman->giveParallelMode() == DofManager_null ) {
832 continue;
833 }
834 dman->printOutputAt(file, tStep);
835 }
836 } else {
837 auto &nodes = domain.giveSet(setNum)->giveNodeList();
838
839 for ( int inode : nodes ) {
840 auto dman = domain.giveDofManager(inode);
841 if ( dman->giveParallelMode() == DofManager_null ) {
842 continue;
843 }
844 dman->printOutputAt(file, tStep);
845 }
846 }
847 fprintf(file, "\n\n");
848}
849
850
851void
852EngngModel :: outputElements(FILE *file, Domain &domain, TimeStep *tStep, int setNum)
853{
854 fprintf(file, "\n\nElement output:\n---------------\n");
855
856 if ( setNum == 0 ) {
857 for ( auto &elem : domain.giveElements() ) {
858 if ( elem->giveParallelMode() == Element_remote ) {
859 continue;
860 }
861 elem->printOutputAt(file, tStep);
862 }
863 } else {
864 auto &elements = domain.giveSet(setNum)->giveElementList();
865 for ( int ielem : elements ) {
866 auto element = domain.giveElement(ielem);
867 if ( element->giveParallelMode() == Element_remote ) {
868 continue;
869 }
870 element->printOutputAt(file, tStep);
871 }
872 }
873 fprintf(file, "\n\n");
874}
875
876
877void EngngModel :: printYourself()
878{
879 printf("\nEngineeringModel: instance %s\n", this->giveClassName() );
880 printf("number of steps: %d\n", this->giveNumberOfSteps() );
881 printf("number of eq's : %d\n", numberOfEquations);
882}
883
884void EngngModel :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *tStep)
885{
886 iDof->printSingleOutputAt(stream, tStep, 'd', VM_Total);
887}
888
889void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma,
890 const UnknownNumberingScheme &s, Domain *domain)
891{
892 IntArray loc;
893 FloatMatrix mat, R;
894#ifdef _OPENMP
895 omp_lock_t writelock;
896 omp_init_lock(&writelock);
897#endif
898
899 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
900 int nelem = domain->giveNumberOfElements();
901#ifdef _OPENMP
902#pragma omp parallel for shared(answer) private(mat, R, loc)
903#endif
904 for ( int ielem = 1; ielem <= nelem; ielem++ ) {
905 auto element = domain->giveElement(ielem);
906 // skip remote elements (these are used as mirrors of remote elements on other domains
907 // when nonlocal constitutive models are used. They introduction is necessary to
908 // allow local averaging on domains without fine grain communication between domains).
909 if ( element->giveParallelMode() == Element_remote || !element->isActivated(tStep) || !this->isElementActivated(element) ) {
910 continue;
911 }
912
913 ma.matrixFromElement(mat, *element, tStep);
914
915 if ( mat.isNotEmpty() ) {
916 ma.locationFromElement(loc, *element, s);
918 if ( element->giveRotationMatrix(R) ) {
919 mat.rotatedWith(R);
920 }
921
922#ifdef _OPENMP
923 #pragma omp critical
924#endif
925 if ( answer.assemble(loc, mat) == 0 ) {
926 OOFEM_ERROR("sparse matrix assemble error");
927 }
928 }
929 }
930
931#ifdef _OPENMP
932#pragma omp parallel for shared(answer) private(mat, R, loc)
933#endif
934 //for ( auto &bc : domain->giveBcs() ) { //problems with OPENMP
935 for (size_t i = 0; i < domain->giveBcs().size(); i++) {
936 auto &bc = domain->giveBcs()[i];
937 auto abc = dynamic_cast< ActiveBoundaryCondition * >(bc.get());
938 if ( abc ) {
941#ifdef _OPENMP
942 ma.assembleFromActiveBC(answer, *abc, tStep, s, s, &writelock);
943#else
944 ma.assembleFromActiveBC(answer, *abc, tStep, s, s);
945#endif
946 } else if ( bc->giveSetNumber() ) {
947 if ( !bc->isImposed(tStep) ) continue;
948 auto load = dynamic_cast< Load * >(bc.get());
949 if ( !load ) continue;
950 // Now we assemble the corresponding load type for the respective components in the set:
951 IntArray loc, bNodes;
952 FloatMatrix mat, R;
953 BodyLoad *bodyLoad;
954 SurfaceLoad* sLoad;
955 EdgeLoad* eLoad;
956 Set *set = domain->giveSet( bc->giveSetNumber() );
957
958 if ( ( bodyLoad = dynamic_cast< BodyLoad * >(load) ) ) { // Body load:
959 const IntArray &elements = set->giveElementList();
960 for ( auto ielem : elements ) {
961 auto element = domain->giveElement( ielem );
962 mat.clear();
963 ma.matrixFromLoad(mat, *element, bodyLoad, tStep);
964
965 if ( mat.isNotEmpty() ) {
966 if ( element->giveRotationMatrix(R) ) {
967 mat.rotatedWith(R);
968 }
969
970 ma.locationFromElement(loc, *element, s);
971#ifdef _OPENMP
972 omp_set_lock(&writelock);
973#endif
974 answer.assemble(loc, mat);
975#ifdef _OPENMP
976 omp_unset_lock(&writelock);
977#endif
978 }
979 }
980 } else if ( ( sLoad = dynamic_cast< SurfaceLoad * >(load) ) ) {
981 const auto &surfaces = set->giveBoundaryList();
982 for ( int ibnd = 1; ibnd <= surfaces.giveSize() / 2; ++ibnd ) {
983 auto element = domain->giveElement( surfaces.at(ibnd * 2 - 1) );
984 int boundary = surfaces.at(ibnd * 2);
985 mat.clear();
986 ma.matrixFromSurfaceLoad(mat, *element, sLoad, boundary, tStep);
987
988 if ( mat.isNotEmpty() ) {
989 bNodes = element->giveInterpolation()->boundaryGiveNodes(boundary, element->giveGeometryType());
990 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
991 mat.rotatedWith(R);
992 }
993
994 ma.locationFromElementNodes(loc, *element, bNodes, s);
995
996#ifdef _OPENMP
997 omp_set_lock(&writelock);
998#endif
999 answer.assemble(loc, mat);
1000#ifdef _OPENMP
1001 omp_unset_lock(&writelock);
1002#endif
1003 }
1004 }
1005 } else if ( ( eLoad = dynamic_cast< EdgeLoad * >(load) ) ) {
1006 const auto &edges = set->giveEdgeList();
1007 for ( int ibnd = 1; ibnd <= edges.giveSize() / 2; ++ibnd ) {
1008 auto element = domain->giveElement( edges.at(ibnd * 2 - 1) );
1009 int boundary = edges.at(ibnd * 2);
1010 mat.clear();
1011 ma.matrixFromEdgeLoad(mat, *element, eLoad, boundary, tStep);
1012
1013 if ( mat.isNotEmpty() ) {
1014 bNodes = element->giveInterpolation()->boundaryEdgeGiveNodes(boundary, element->giveGeometryType());
1015 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
1016 mat.rotatedWith(R);
1017 }
1018
1019 ma.locationFromElementNodes(loc, *element, bNodes, s);
1020#ifdef _OPENMP
1021 omp_set_lock(&writelock);
1022#endif
1023 answer.assemble(loc, mat);
1024#ifdef _OPENMP
1025 omp_unset_lock(&writelock);
1026#endif
1027 }
1028 }
1029 }
1030 }
1031 }
1032
1033 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1034
1035 answer.assembleBegin();
1036 answer.assembleEnd();
1037}
1038
1039
1040void EngngModel :: assemble(SparseMtrx &answer, TimeStep *tStep, const MatrixAssembler &ma,
1042 Domain *domain)
1043// Same as assemble, but with different numbering for rows and columns
1044{
1045 IntArray r_loc, c_loc, dofids(0);
1046 FloatMatrix mat, R;
1047#ifdef _OPENMP
1048 omp_lock_t writelock;
1049 omp_init_lock(&writelock);
1050#endif
1051
1052 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1053 int nelem = domain->giveNumberOfElements();
1054#ifdef _OPENMP
1055#pragma omp parallel for shared(answer) private(mat, R, r_loc, c_loc)
1056#endif
1057 for ( int ielem = 1; ielem <= nelem; ielem++ ) {
1058 Element *element = domain->giveElement(ielem);
1059
1060 if ( element->giveParallelMode() == Element_remote || !element->isActivated(tStep) || !this->isElementActivated(element) ) {
1061 continue;
1062 }
1063
1064 ma.matrixFromElement(mat, *element, tStep);
1065 if ( mat.isNotEmpty() ) {
1066 ma.locationFromElement(r_loc, *element, rs);
1067 ma.locationFromElement(c_loc, *element, cs);
1068 // Rotate it
1070 if ( element->giveRotationMatrix(R) ) {
1071 mat.rotatedWith(R);
1072 }
1073
1074#ifdef _OPENMP
1075 #pragma omp critical
1076#endif
1077 if ( answer.assemble(r_loc, c_loc, mat) == 0 ) {
1078 OOFEM_ERROR("sparse matrix assemble error");
1079 }
1080 }
1081 }
1082
1083#ifdef _OPENMP
1084#pragma omp parallel for shared(answer) private(mat, R, r_loc, c_loc)
1085#endif
1086 //for ( auto &gbc : domain->giveBcs() ) { //problems with OPENMP
1087 for (size_t i = 0; i < domain->giveBcs().size(); i++) {
1088 auto &gbc = domain->giveBcs()[i];
1089 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( gbc.get() );
1090 if ( bc != NULL ) {
1091#ifdef _OPENMP
1092 ma.assembleFromActiveBC(answer, *bc, tStep, rs, cs, &writelock);
1093#else
1094 ma.assembleFromActiveBC(answer, *bc, tStep, rs, cs);
1095#endif
1096 }
1097 }
1098
1099 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1100
1101 answer.assembleBegin();
1102 answer.assembleEnd();
1103}
1104
1105
1106void EngngModel :: assembleVector(FloatArray &answer, TimeStep *tStep,
1107 const VectorAssembler &va, ValueModeType mode,
1108 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms)
1109{
1110 if ( eNorms ) {
1111 int maxdofids = domain->giveMaxDofID();
1112#ifdef __MPI_PARALLEL_MODE
1113 if ( this->isParallel() ) {
1114 int val;
1115 MPI_Allreduce(& maxdofids, & val, 1, MPI_INT, MPI_MAX, this->comm);
1116 maxdofids = val;
1117 }
1118#endif
1119 eNorms->resize(maxdofids);
1120 eNorms->zero();
1121 }
1122
1123 this->assembleVectorFromDofManagers(answer, tStep, va, mode, s, domain, eNorms);
1124 this->assembleVectorFromElements(answer, tStep, va, mode, s, domain, eNorms);
1125 this->assembleVectorFromBC(answer, tStep, va, mode, s, domain, eNorms);
1126
1127 if ( this->isParallel() ) {
1128 if ( eNorms ) {
1129 FloatArray localENorms = * eNorms;
1130 this->giveParallelContext(domain->giveNumber())->accumulate(localENorms, *eNorms);
1131 }
1132 }
1133}
1134
1135
1136void EngngModel :: assembleVectorFromDofManagers(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode,
1137 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms)
1138{
1140 IntArray loc, dofids;
1141 FloatArray charVec;
1142 FloatMatrix R;
1143 IntArray dofIDarry;
1144 int nnode = domain->giveNumberOfDofManagers();
1145
1146 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1147 // Note! For normal master dofs, loc is unique to each node, but there can be slave dofs, so we must keep it shared, unfortunately.
1148#ifdef _OPENMP
1149#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids)
1150#endif
1151 for ( int i = 1; i <= nnode; i++ ) {
1152 DofManager *node = domain->giveDofManager(i);
1153
1154 charVec.clear();
1155 for ( int iload : *node->giveLoadArray() ) { // to more than one load
1156 Load *load = domain->giveLoad(iload);
1157 va.vectorFromNodeLoad(charVec, *node, static_cast< NodalLoad* >(load), tStep, mode);
1158
1159 if ( node->giveParallelMode() == DofManager_shared ) {
1160 charVec.times( 1. / ( node->givePartitionsConnectivitySize() ) );
1161 }
1162
1163 if ( charVec.isNotEmpty() ) {
1164 if ( node->computeM2LTransformation(R, dofIDarry) ) {
1165 charVec.rotatedWith(R, 't');
1166 }
1167
1168 if ( load->giveDofIDs().giveSize() ) {
1169 node->giveLocationArray(load->giveDofIDs(), loc, s);
1170 } else {
1171 node->giveCompleteLocationArray(loc, s);
1172 }
1173#ifdef _OPENMP
1174 #pragma omp critical
1175#endif
1176 {
1177 answer.assemble(charVec, loc);
1178 if ( eNorms ) {
1179 node->giveCompleteMasterDofIDArray(dofids);
1180 eNorms->assembleSquared(charVec, dofids);
1181 }
1182 }
1183 }
1184 }
1185 }
1186
1187 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1188}
1189
1190
1191void EngngModel :: assembleVectorFromBC(FloatArray &answer, TimeStep *tStep,
1192 const VectorAssembler &va, ValueModeType mode,
1193 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms)
1194{
1195 int nbc = domain->giveNumberOfBoundaryConditions();
1196#ifdef _OPENMP
1197 omp_lock_t writelock;
1198 omp_init_lock(&writelock);
1199#endif
1200
1201 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1202#ifdef _OPENMP
1203#pragma omp parallel for shared(answer, eNorms)
1204#endif
1205 for ( int i = 1; i <= nbc; ++i ) {
1206 GeneralBoundaryCondition *bc = domain->giveBc(i);
1208 Load *load;
1209
1210 if ( ( abc = dynamic_cast< ActiveBoundaryCondition * >(bc) ) ) {
1211#ifdef _OPENMP
1212 va.assembleFromActiveBC(answer, *abc, tStep, mode, s, eNorms, &writelock);
1213#else
1214 va.assembleFromActiveBC(answer, *abc, tStep, mode, s, eNorms);
1215#endif
1216 } else if ( bc->giveSetNumber() && ( load = dynamic_cast< Load * >(bc) ) && bc->isImposed(tStep) ) {
1217 // Now we assemble the corresponding load type fo the respective components in the set:
1218 IntArray dofids, loc;
1219 FloatArray charVec;
1220 FloatMatrix R;
1221 BodyLoad *bodyLoad;
1222 BoundaryLoad *bLoad;
1223 //BoundaryEdgeLoad *eLoad;
1224 NodalLoad *nLoad;
1225 Set *set = domain->giveSet( bc->giveSetNumber() );
1226
1227 if ( ( bodyLoad = dynamic_cast< BodyLoad * >(load) ) ) { // Body load:
1228 const IntArray &elements = set->giveElementList();
1229 for ( int ielem = 1; ielem <= elements.giveSize(); ++ielem ) {
1230 Element *element = domain->giveElement( elements.at(ielem) );
1231 if ( element->isActivated(tStep) && this->isElementActivated(element) ) {
1232 charVec.clear();
1233 va.vectorFromLoad(charVec, *element, bodyLoad, tStep, mode);
1234
1235 if ( charVec.isNotEmpty() ) {
1236 if ( element->giveRotationMatrix(R) ) {
1237 charVec.rotatedWith(R, 't');
1238 }
1239
1240 va.locationFromElement(loc, *element, s, & dofids);
1241#ifdef _OPENMP
1242 omp_set_lock(&writelock);
1243#endif
1244 answer.assemble(charVec, loc);
1245 if ( eNorms ) {
1246 eNorms->assembleSquared(charVec, dofids);
1247 }
1248#ifdef _OPENMP
1249 omp_unset_lock(&writelock);
1250#endif
1251 }
1252 }
1253 }
1254 } else if ( ( bLoad = dynamic_cast< BoundaryLoad * >(load) ) && (load->giveBCGeoType()==SurfaceLoadBGT)) { // Surface load:
1255 const IntArray &boundaries = set->giveBoundaryList();
1256 for ( int ibnd = 1; ibnd <= boundaries.giveSize() / 2; ++ibnd ) {
1257 Element *element = domain->giveElement( boundaries.at(ibnd * 2 - 1) );
1258 if ( element->isActivated(tStep) && this->isElementActivated(element) ) {
1259
1260 int boundary = boundaries.at(ibnd * 2);
1261 charVec.clear();
1262 va.vectorFromSurfaceLoad(charVec, *element, bLoad, boundary, tStep, mode);
1263
1264 if ( charVec.isNotEmpty() ) {
1265 //element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary);
1266 auto bNodes = element->giveBoundarySurfaceNodes(boundary);
1267 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
1268 charVec.rotatedWith(R, 't');
1269 }
1270
1271 va.locationFromElementNodes(loc, *element, bNodes, s, & dofids);
1272#ifdef _OPENMP
1273 omp_set_lock(&writelock);
1274#endif
1275 answer.assemble(charVec, loc);
1276
1277 if ( eNorms ) {
1278 eNorms->assembleSquared(charVec, dofids);
1279 }
1280#ifdef _OPENMP
1281 omp_unset_lock(&writelock);
1282#endif
1283 }
1284 }
1285 }
1286 } else if ( ( bLoad = dynamic_cast< BoundaryLoad * >(load) ) && (load->giveBCGeoType()==EdgeLoadBGT) ) { // Edge load:
1287 const IntArray &edgeBoundaries = set->giveEdgeList();
1288 for ( int ibnd = 1; ibnd <= edgeBoundaries.giveSize() / 2; ++ibnd ) {
1289 Element *element = domain->giveElement( edgeBoundaries.at(ibnd * 2 - 1) );
1290 if ( element->isActivated(tStep) && this->isElementActivated(element) ) {
1291 int boundary = edgeBoundaries.at(ibnd * 2);
1292 charVec.clear();
1293 va.vectorFromEdgeLoad(charVec, *element, bLoad, boundary, tStep, mode);
1294
1295 if ( charVec.isNotEmpty() ) {
1296 //element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary);
1297 auto bNodes = element->giveBoundaryEdgeNodes(boundary);
1298 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
1299 charVec.rotatedWith(R, 't');
1300 }
1301
1302 va.locationFromElementNodes(loc, *element, bNodes, s, & dofids);
1303#ifdef _OPENMP
1304 omp_set_lock(&writelock);
1305#endif
1306 answer.assemble(charVec, loc);
1307
1308 if ( eNorms ) {
1309 eNorms->assembleSquared(charVec, dofids);
1310 }
1311#ifdef _OPENMP
1312 omp_unset_lock(&writelock);
1313#endif
1314 }
1315 }
1316 }
1317 } else if ( ( nLoad = dynamic_cast< NodalLoad * >(load) ) ) { // Nodal load:
1318 const IntArray &nodes = set->giveNodeList();
1319 for ( int idman = 1; idman <= nodes.giveSize(); ++idman ) {
1320 DofManager *node = domain->giveDofManager( nodes.at(idman) );
1321 charVec.clear();
1322 va.vectorFromNodeLoad(charVec, *node, nLoad, tStep, mode);
1323
1324 if ( charVec.isNotEmpty() ) {
1325 if ( node->computeM2LTransformation(R, nLoad->giveDofIDs()) ) {
1326 charVec.rotatedWith(R, 't');
1327 }
1328
1329 node->giveLocationArray(nLoad->giveDofIDs(), loc, s);
1330#ifdef _OPENMP
1331 omp_set_lock(&writelock);
1332#endif
1333 answer.assemble(charVec, loc);
1334
1335 if ( eNorms ) {
1336 eNorms->assembleSquared(charVec, dofids);
1337 }
1338#ifdef _OPENMP
1339 omp_unset_lock(&writelock);
1340#endif
1341 }
1342 }
1343 }
1344 }
1345 }
1346
1347 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1348}
1349
1350
1351void EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tStep,
1352 const VectorAssembler &va, ValueModeType mode,
1353 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms)
1354//
1355// for each element in domain
1356// and assembling every contribution to answer
1357//
1358{
1359 IntArray loc, dofids;
1360 FloatMatrix R;
1361 FloatArray charVec;
1362 int nelem = domain->giveNumberOfElements();
1363 bool assembleFlag = false;
1364
1367 if ( this->isParallel() ) {
1368 // Copies internal (e.g. Gauss-Point) data from remote elements to make sure they have all information necessary for nonlocal averaging.
1370 }
1371
1372 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1374#ifdef _OPENMP
1375#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids)
1376#endif
1377 for ( int i = 1; i <= nelem; i++ ) {
1378
1379 Element *element = domain->giveElement(i);
1380
1381 // skip remote elements (these are used as mirrors of remote elements on other domains
1382 // when nonlocal constitutive models are used. They introduction is necessary to
1383 // allow local averaging on domains without fine grain communication between domains).
1384 if ( element->giveParallelMode() == Element_remote ) {
1385 continue;
1386 }
1387
1388 if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) {
1389 continue;
1390 }
1391
1392 va.vectorFromElement(charVec, *element, tStep, mode);
1393
1394 if ( charVec.isNotEmpty() ) {
1395 if ( element->giveRotationMatrix(R) ) {
1396 charVec.rotatedWith(R, 't');
1397 }
1398 va.locationFromElement(loc, *element, s, & dofids);
1399#ifdef _OPENMP
1400#pragma omp critical
1401#endif
1402 {
1403 answer.assemble(charVec, loc);
1404 if ( eNorms ) {
1405 eNorms->assembleSquared(charVec, dofids);
1406 }
1407 }
1408 }
1409 }
1410
1411#ifdef _OPENMP
1412#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids)
1413#endif
1414 for ( int i = 1; i <= nelem; i++ ) {
1415 Element *element = domain->giveElement(i);
1416
1417 // skip remote elements (these are used as mirrors of remote elements on other domains
1418 // when nonlocal constitutive models are used. They introduction is necessary to
1419 // allow local averaging on domains without fine grain communication between domains).
1420 if ( element->giveParallelMode() == Element_remote ) {
1421 continue;
1422 }
1423
1424 if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) {
1425 continue;
1426 }
1427
1428 // obtain form element its body, surface, edge, and point loads
1429 const IntArray& list = element->giveBodyLoadList();
1430 if (!list.isEmpty()) {
1431 for (int iload=1; iload<=list.giveSize(); iload++) { // loop over body loads
1432 BodyLoad *bodyLoad;
1433 if ((bodyLoad = dynamic_cast< BodyLoad * >(domain->giveLoad(list.at(iload))))) {
1434 charVec.clear();
1435 va.vectorFromLoad(charVec, *element, bodyLoad, tStep, mode);
1436
1437 if ( charVec.isNotEmpty() ) {
1438 if ( element->giveRotationMatrix(R) ) {
1439 charVec.rotatedWith(R, 't');
1440 }
1441
1442 va.locationFromElement(loc, *element, s, & dofids);
1443#ifdef _OPENMP
1444#pragma omp critical
1445#endif
1446 {
1447 answer.assemble(charVec, loc);
1448 if ( eNorms ) {
1449 eNorms->assembleSquared(charVec, dofids);
1450 }
1451 }
1452 }
1453 }
1454
1455 } // loop over body load list
1456 } // if (!(list = element->giveBodyLoadList()).isEmpty())
1457 }
1458
1459#ifdef _OPENMP
1460#pragma omp parallel for shared(answer, eNorms) private(R, charVec, loc, dofids, assembleFlag)
1461#endif
1462 for ( int i = 1; i <= nelem; i++ ) {
1463 Element *element = domain->giveElement(i);
1464
1465 // skip remote elements (these are used as mirrors of remote elements on other domains
1466 // when nonlocal constitutive models are used. They introduction is necessary to
1467 // allow local averaging on domains without fine grain communication between domains).
1468 if ( element->giveParallelMode() == Element_remote ) {
1469 continue;
1470 }
1471
1472 if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) {
1473 continue;
1474 }
1475
1476 // obtain from element its boundaryloads (surface+edge)
1477 const IntArray& list2 = element->giveBoundaryLoadList();
1478
1479 for (int j=1; j<=list2.giveSize()/2; j++) { // loop over boundary loads
1480 int iload = list2.at(j * 2 - 1) ;
1481 int boundary = list2.at(j * 2);
1482 SurfaceLoad *sLoad;
1483 EdgeLoad *eLoad;
1484 assembleFlag = false;
1485 IntArray bNodes;
1486
1487 if ((eLoad = dynamic_cast< EdgeLoad * >(domain->giveLoad(iload)))) {
1488 charVec.clear();
1489 va.vectorFromEdgeLoad(charVec, *element, eLoad, boundary, tStep, mode);
1490
1491 if ( charVec.isNotEmpty() ) {
1492 //element->giveInterpolation()->boundaryEdgeGiveNodes(bNodes, boundary);
1493 bNodes = element->giveBoundaryEdgeNodes(boundary);
1494 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
1495 charVec.rotatedWith(R, 't');
1496 }
1497 assembleFlag = true;
1498 }
1499 } else if ((sLoad = dynamic_cast< SurfaceLoad * >(domain->giveLoad(iload)))) {
1500 charVec.clear();
1501 va.vectorFromSurfaceLoad(charVec, *element, sLoad, boundary, tStep, mode);
1502
1503 if ( charVec.isNotEmpty() ) {
1504 //element->giveInterpolation()->boundaryGiveNodes(bNodes, boundary);
1505 bNodes = element->giveBoundarySurfaceNodes(boundary);
1506 if ( element->computeDofTransformationMatrix(R, bNodes, true) ) {
1507 charVec.rotatedWith(R, 't');
1508 }
1509 assembleFlag = true;
1510 }
1511 } else {
1512 OOFEM_ERROR ("Unsupported element boundary load type");
1513 }
1514
1515 if ( assembleFlag ) {
1516 // assemble the contribution
1517 va.locationFromElementNodes(loc, *element, bNodes, s, & dofids);
1518#ifdef _OPENMP
1519#pragma omp critical
1520#endif
1521 {
1522 answer.assemble(charVec, loc);
1523 if ( eNorms ) {
1524 eNorms->assembleSquared(charVec, dofids);
1525 }
1526 }
1527 } // end loop over lement boundary loads
1528 }
1529
1530 } // end loop over elements
1531
1532 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1533}
1534
1535void
1536EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, CharType type, Domain *domain)
1537{
1538 // Simply assembles contributions from each element in domain
1539 IntArray loc;
1540 FloatArray charVec, delta_u;
1541 FloatMatrix charMatrix, R;
1542 int nelems = domain->giveNumberOfElements();
1544
1546 answer.zero();
1547
1548 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1549
1550#ifdef _OPENMP
1551//#pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u)
1552#endif
1553 for ( int i = 1; i <= nelems; i++ ) {
1554 Element *element = domain->giveElement(i);
1555
1556 // Skip remote elements (these are used as mirrors of remote elements on other domains
1557 // when nonlocal constitutive models are used. Their introduction is necessary to
1558 // allow local averaging on domains without fine grain communication between domains).
1559 if ( element->giveParallelMode() == Element_remote ) {
1560 continue;
1561 }
1562
1563 if ( !element->isActivated(tStep) || !this->isElementActivated(element) ) {
1564 continue;
1565 }
1566
1567 element->giveLocationArray(loc, dn);
1568
1569 // Take the tangent from the previous step
1572
1573 element->giveCharacteristicMatrix(charMatrix, type, tStep);
1574 if ( charMatrix.isNotEmpty() ) {
1576
1577#if 0
1578 element->computeVectorOf(VM_Incremental, tStep, delta_u);
1579#else
1580 element->computeVectorOf(VM_Total, tStep, delta_u);
1581 FloatArray tmp;
1582
1583 if ( tStep->isTheFirstStep() ) {
1584 tmp = delta_u;
1585 tmp.zero();
1586 } else {
1587 element->computeVectorOf(VM_Total, tStep->givePreviousStep(), tmp);
1588 }
1589
1590 delta_u.subtract(tmp);
1591#endif
1592
1593 charVec.beProductOf(charMatrix, delta_u);
1594 if ( element->giveRotationMatrix(R) ) {
1595 charVec.rotatedWith(R, 't');
1596 }
1597
1599#ifdef _OPENMP
1600#pragma omp critical
1601#endif
1602 {
1603 answer.assemble(charVec, loc);
1604 }
1605 }
1606 }
1607
1608
1609 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1610}
1611
1612
1613void
1614EngngModel :: assemblePrescribedExtrapolatedForces(FloatArray &answer, TimeStep *tStep, CharType type, Domain *domain)
1615{
1616 // Simply assembles contributions from each element in domain
1617 IntArray loc;
1618 FloatArray charVec, delta_u;
1619 FloatMatrix charMatrix, R;
1620 int nelems = domain->giveNumberOfElements();
1622
1624 answer.zero();
1625
1626 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1627
1628#ifdef _OPENMP
1629//#pragma omp parallel for shared(answer) private(R, charMatrix, charVec, loc, delta_u)
1630#endif
1631 for ( int i = 1; i <= nelems; i++ ) {
1632 Element *element = domain->giveElement(i);
1633
1634 // Skip remote elements (these are used as mirrors of remote elements on other domains
1635 // when nonlocal constitutive models are used. Their introduction is necessary to
1636 // allow local averaging on domains without fine grain communication between domains).
1637 if ( element->giveParallelMode() == Element_remote ) {
1638 continue;
1639 }
1640
1641 if ( !element->isActivated(tStep) ) {
1642 continue;
1643 }
1644
1645 element->giveLocationArray(loc, dn);
1646
1647 // Take the tangent from the previous step
1650 element->giveCharacteristicMatrix(charMatrix, type, tStep);
1651 element->computeVectorOfPrescribed(VM_Incremental, tStep, delta_u);
1652 if ( charMatrix.isNotEmpty() ) {
1653 charVec.beProductOf(charMatrix, delta_u);
1654 if ( element->giveRotationMatrix(R) ) {
1655 charVec.rotatedWith(R, 't');
1656 }
1657
1659 #ifdef _OPENMP
1660 #pragma omp critical
1661 #endif
1662 {
1663 answer.assemble(charVec, loc);
1664 }
1665 }
1666 }
1667
1668 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer);
1669}
1670
1671
1672
1673void
1674EngngModel :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d)
1675{
1676 OOFEM_ERROR("Unknown Type of component.");
1677}
1678
1679
1680void
1681EngngModel :: updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d)
1682{
1683 OOFEM_ERROR("updateSolution is not implemented.");
1684}
1685
1686
1687void
1688EngngModel :: updateInternalRHS(FloatArray &answer, TimeStep *tStep, Domain *d, FloatArray *eNorms)
1689{
1690 OOFEM_ERROR("updateInternalRHS is not implemented.");
1691}
1692
1693
1694void
1695EngngModel :: updateMatrix(SparseMtrx &mat, TimeStep *tStep, Domain *d)
1696{
1697 OOFEM_ERROR("updateMatrix is not implemented.");
1698}
1699
1700
1701void
1702EngngModel :: initStepIncrements()
1703//
1704// resets all temp data in elements and their gps so only
1705// non temp variables remain.
1706// this function can be used if called before this->terminate()
1707// for current step restart, because it causes complete reset
1708// of temp variables.
1709//
1710{
1711 for ( auto &domain: domainList ) {
1712 for ( auto &elem : domain->giveElements() ) {
1713 // skip remote elements (these are used as mirrors of remote elements on other domains
1714 // when nonlocal constitutive models are used. They introduction is necessary to
1715 // allow local averaging on domains without fine grain communication between domains).
1716 if ( elem->giveParallelMode() == Element_remote ) {
1717 continue;
1718 }
1719
1720 elem->initForNewStep();
1721 }
1722 }
1723}
1724
1725
1726
1727void
1728EngngModel :: initForNewIteration(Domain *d, TimeStep *tStep, int niter, const FloatArray &solutionVector)
1729//
1730// init the data before new iteration
1731// needed by contact implementation
1732{
1733 auto s = solutionVector;
1734 if(s.giveSize()) {
1735 this->updateSolution(s, tStep, d);
1736 }
1737 for ( int i = 1; i <= d->giveNumberOfBoundaryConditions(); ++i ) {
1738 ContactBoundaryCondition *contact_bc = dynamic_cast< ContactBoundaryCondition * >( d->giveBc(i) );
1739 if(contact_bc) {
1740 contact_bc->initForNewIteration(tStep, niter);
1741 }
1742 }
1743
1744}
1745
1746
1747
1748void
1749EngngModel :: updateDomainLinks()
1750{
1751 this->giveExportModuleManager()->initialize();
1752}
1753
1754
1755void EngngModel :: saveContext(DataStream &stream, ContextMode mode)
1756//
1757// this procedure is used mainly for two reasons:
1758//
1759// - to save context of current model in order to be able to backtrace
1760// computational history (useful in nonlinear analysis, when you want
1761// explore another, previously detected load path
1762//
1763// - to save context of current model in order to enable
1764// possibility of post-processing.
1765//
1766// saving context means: (if needed may be enhanced)
1767//
1768// - save EngngModel state varialbles as displacement, velocity, .. vectors
1769// - save Elements stress, strain and material history.
1770//
1771// This version saves only Element and Material properties.
1772//
1773{
1774 contextIOResultType iores;
1775
1776 if ( !stream.write(giveCurrentStep()->giveNumber()) ) {
1778 }
1779
1780 giveCurrentStep()->saveContext(stream);
1781
1782 if ( !stream.write(numberOfEquations) ) {
1784 }
1785
1786 if ( ( iores = domainNeqs.storeYourself(stream) ) != CIO_OK ) {
1787 THROW_CIOERR(iores);
1788 }
1789
1790 if ( !stream.write(numberOfPrescribedEquations) ) {
1792 }
1793
1794 if ( ( iores = domainPrescribedNeqs.storeYourself(stream) ) != CIO_OK ) {
1795 THROW_CIOERR(iores);
1796 }
1797
1798 if ( !stream.write(renumberFlag) ) {
1800 }
1801
1802 for ( auto &domain: domainList ) {
1803 domain->saveContext(stream, mode);
1804 }
1805
1806 // store nMethod
1807 NumericalMethod *nmethod = this->giveNumericalMethod( this->giveMetaStep( giveCurrentStep()->giveMetaStepNumber() ) );
1808 if ( nmethod ) {
1809 nmethod->saveContext(stream, mode);
1810 }
1811}
1812
1813
1814void EngngModel :: restoreContext(DataStream &stream, ContextMode mode)
1815//
1816// this procedure is used mainly for two reasons:
1817//
1818// - to restore context of current model in order to be able to backtrace
1819// computational history (useful in nonlinear analysis, when you want
1820// explore another, previously detected load path
1821//
1822// - to restore context of current model in order to enable
1823// possibility of post-processing.
1824//
1825// restoring context means: (if needed may be enhanced)
1826//
1827// - rest. EngngModel state varialbles as displacement, velocity, .. vectors
1828// - rest. Elements stress, strain and material history.
1829//
1830// This version loads only Element and Material properties.
1831//
1832// This function is inverse to the saveContext() member function
1833{
1834 contextIOResultType iores;
1835
1836 // restore solution step
1837 int istep;
1838 if ( !stream.read(istep) ) {
1840 }
1841
1842 if ( !currentStep ) {
1843 currentStep = std::make_unique<TimeStep>(istep, this, 0, 0., 0., 0);
1844 }
1845
1846 currentStep->restoreContext(stream);
1847
1848 // this->updateAttributes (currentStep);
1849
1850 int pmstep = currentStep->giveMetaStepNumber();
1851 if ( nMetaSteps ) {
1852 if ( !this->giveMetaStep(pmstep)->isStepValid(istep - 1) ) {
1853 pmstep--;
1854 }
1855 }
1856
1857 previousStep = std::make_unique<TimeStep>(istep - 1, this, pmstep, currentStep->giveTargetTime ( ) - currentStep->giveTimeIncrement(),
1858 currentStep->giveTimeIncrement(), currentStep->giveSolutionStateCounter() - 1);
1859
1860 // restore numberOfEquations and domainNeqs array
1861 if ( !stream.read(numberOfEquations) ) {
1863 }
1864
1865 if ( ( iores = domainNeqs.restoreYourself(stream) ) != CIO_OK ) {
1866 THROW_CIOERR(iores);
1867 }
1868
1869 // restore numberOfPrescribedEquations and domainNeqs array
1870 if ( !stream.read(numberOfPrescribedEquations) ) {
1872 }
1873
1874 if ( ( iores = domainPrescribedNeqs.restoreYourself(stream) ) != CIO_OK ) {
1875 THROW_CIOERR(iores);
1876 }
1877
1878 // restore renumber flag
1879 if ( !stream.read(renumberFlag) ) {
1881 }
1882
1883 for ( auto &domain: domainList ) {
1884 domain->restoreContext(stream, mode);
1885 }
1886
1887 // restore nMethod
1888 NumericalMethod *nmethod = this->giveNumericalMethod( this->giveCurrentMetaStep() );
1889 if ( nmethod ) {
1890 nmethod->restoreContext(stream, mode);
1891 }
1892
1893 this->updateDomainLinks();
1894 this->updateAttributes( this->giveCurrentMetaStep() );
1895 this->initStepIncrements();
1896}
1897
1898
1899MetaStep *
1900EngngModel :: giveCurrentMetaStep()
1901{
1902 return this->giveMetaStep( this->giveCurrentStep()->giveMetaStepNumber() );
1903}
1904
1905
1906std ::string
1907EngngModel :: giveContextFileName(int tStepNumber, int stepVersion) const
1908{
1909 std :: string fname = this->coreOutputFileName;
1910 char fext [ 100 ];
1911 sprintf(fext, ".%d.%d.osf", tStepNumber, stepVersion);
1912 return fname + fext;
1913}
1914
1915
1916std :: string
1917EngngModel :: giveDomainFileName(int domainNum, int domainSerNum) const
1918{
1919 std :: string fname = this->coreOutputFileName;
1920 char fext [ 100 ];
1921 sprintf(fext, ".domain.%d.%d.din", domainNum, domainSerNum);
1922 return fname + fext;
1923}
1924
1925std :: string
1926EngngModel :: errorInfo(const char *func) const
1927{
1928 if ( this->isParallel() ) {
1929 return std::string(this->giveClassName()) + "::" + func + ", Rank: " + std::to_string(rank);
1930 } else {
1931 return std::string(this->giveClassName()) + "::" + func;
1932 }
1933}
1934
1935Domain *
1936EngngModel :: giveDomain(int i)
1937{
1938 if ( ( i > 0 ) && ( i <= (int)this->domainList.size() ) ) {
1939 return this->domainList[i-1].get();
1940 } else {
1941 OOFEM_ERROR("Undefined domain");
1942 }
1943
1944 // return NULL;
1945}
1946
1947void
1948EngngModel :: setDomain(int i, Domain *ptr, bool iDeallocateOld)
1949{
1950 if ( i < 1 || i > (int)this->domainList.size() ) {
1951 OOFEM_ERROR("Domain index %d out of range [1,%d]", i, (int)this->domainList.size());
1952 }
1953 if ( !iDeallocateOld ) {
1954 this->domainList[i-1].release();
1955 }
1956 this->domainList[i-1].reset(ptr);
1957}
1958
1959
1961EngngModel :: giveParallelContext(int i)
1962{
1963 if ( i > (int)parallelContextList.size() ) {
1964 OOFEM_ERROR("context not initialized for this problem");
1965 }
1966
1967 return &this->parallelContextList[i-1];
1968}
1969
1970void
1971EngngModel :: initParallelContexts()
1972{
1973 parallelContextList.clear();
1974 for ( int i = 0; i < this->giveNumberOfDomains(); ++i ) {
1975 parallelContextList.emplace_back(this);
1976 }
1977}
1978
1979void
1980EngngModel :: letOutputBaseFileNameBe(const std :: string &src)
1981{
1982 this->dataOutputFileName = src;
1983
1984 if ( outputStream ) fclose(outputStream);
1985
1986 if ( !suppressOutput ) {
1987 if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) {
1988 OOFEM_ERROR("Can't open output file %s", this->dataOutputFileName.c_str());
1989 }
1990 }
1991}
1992
1993FILE *
1994EngngModel :: giveOutputStream()
1995// Returns an output stream on the data file of the receiver.
1996{
1997 if ( !outputStream ) {
1998 OOFEM_ERROR("No output stream opened!");
1999 }
2000
2001 return outputStream;
2002}
2003
2004double
2005EngngModel :: giveSolutionStepTime()
2006{
2007 return this->timer.getUtime(EngngModelTimer :: EMTT_SolutionStepTimer);
2008}
2009
2010void
2011EngngModel :: giveAnalysisTime(int &rhrs, int &rmin, int &rsec, int &uhrs, int &umin, int &usec)
2012{
2013 double rtsec = this->timer.getWtime(EngngModelTimer :: EMTT_AnalysisTimer);
2014 double utsec = this->timer.getUtime(EngngModelTimer :: EMTT_AnalysisTimer);
2015 rsec = rmin = rhrs = 0;
2016 usec = umin = uhrs = 0;
2017 this->timer.convert2HMS(rhrs, rmin, rsec, rtsec);
2018 this->timer.convert2HMS(uhrs, umin, usec, utsec);
2019}
2020
2021void
2022EngngModel :: terminateAnalysis()
2023{
2024 int rsec = 0, rmin = 0, rhrs = 0;
2025 int usec = 0, umin = 0, uhrs = 0;
2026 time_t endTime = time(NULL);
2027 this->timer.stopTimer(EngngModelTimer :: EMTT_AnalysisTimer);
2028
2029
2030 // compute real time consumed
2031 this->giveAnalysisTime(rhrs, rmin, rsec, uhrs, umin, usec);
2032
2033 if(!suppressOutput) {
2034 FILE *out = this->giveOutputStream();
2035 fprintf(out, "\nFinishing analysis on: %s\n", ctime(& endTime) );
2036 fprintf(out, "Real time consumed: %03dh:%02dm:%02ds\n", rhrs, rmin, rsec);
2037 fprintf(out, "User time consumed: %03dh:%02dm:%02ds\n\n\n", uhrs, umin, usec);
2038 }
2039
2040 OOFEM_LOG_FORCED("\n\nANALYSIS FINISHED\n\n\n");
2041 OOFEM_LOG_FORCED("Real time consumed: %03dh:%02dm:%02ds\n", rhrs, rmin, rsec);
2042 OOFEM_LOG_FORCED("User time consumed: %03dh:%02dm:%02ds\n", uhrs, umin, usec);
2043 exportModuleManager.terminate();
2044}
2045
2046int
2047EngngModel :: checkProblemConsistency()
2048{
2049 int result = 1;
2050
2051 result &= this->checkConsistency();
2052
2053 for ( auto &domain: domainList ) {
2054 result &= domain->checkConsistency();
2055 }
2056
2057# ifdef VERBOSE
2058 if ( result ) {
2059 OOFEM_LOG_DEBUG("Consistency check: OK\n");
2060 } else {
2061 VERBOSE_PRINTS("Consistency check", "failed")
2062 exit(1);
2063 }
2064
2065# endif
2066
2067 return result;
2068}
2069
2070
2071void
2072EngngModel :: postInitialize()
2073{
2074 timeStepController->postInitialize();
2075
2076 for ( auto &domain: domainList ) {
2077 domain->postInitialize();
2078 }
2079}
2080
2081void
2082EngngModel :: init()
2083{
2084 initModuleManager.doInit();
2085}
2086
2087
2088void
2089EngngModel :: initParallel()
2090{
2091 #ifdef __USE_MPI
2092 int len;
2093 MPI_Get_processor_name(processor_name, & len);
2094 this->comm = MPI_COMM_WORLD;
2095 MPI_Comm_rank(this->comm, & this->rank);
2096 MPI_Comm_size(this->comm, & numProcs);
2097 #else
2098 OOFEM_ERROR("Can't do it, only compiled for sequential runs");
2099 #endif
2100 #ifdef __VERBOSE_PARALLEL
2101 OOFEM_LOG_RELEVANT("[%d/%d] Running on %s\n", rank, numProcs, processor_name);
2102 #endif
2103}
2104
2105
2111
2112#ifdef __OOFEG
2113void EngngModel :: drawYourself(oofegGraphicContext &gc)
2114{
2115 OGC_PlotModeType plotMode = gc.giveIntVarPlotMode();
2116
2117 if ( ( plotMode == OGC_nodeAnnotation ) || ( plotMode == OGC_nodeGeometry ) || ( plotMode == OGC_essentialBC ) ||
2118 ( plotMode == OGC_naturalBC ) || ( plotMode == OGC_nodeScalarPlot ) || ( plotMode == OGC_nodeVectorPlot ) ) {
2119 this->drawNodes(gc);
2120 } else {
2121 this->drawElements(gc);
2122 }
2123}
2124
2125void EngngModel :: drawElements(oofegGraphicContext &gc)
2126{
2127 Domain *d = this->giveDomain( gc.getActiveDomain() );
2128 TimeStep *tStep = this->giveCurrentStep();
2129 for ( auto &elem : d->giveElements() ) {
2130 elem->drawYourself(gc, tStep);
2131 }
2132}
2133
2134void EngngModel :: drawNodes(oofegGraphicContext &gc)
2135{
2136 Domain *d = this->giveDomain( gc.getActiveDomain() );
2137 TimeStep *tStep = this->giveCurrentStep();
2138 for ( auto &dman : d->giveDofManagers() ) {
2139 dman->drawYourself(gc, tStep);
2140 }
2141}
2142
2143#endif
2144
2145
2146void
2147EngngModel :: initializeCommMaps(bool forceInit)
2148{
2149#ifdef __MPI_PARALLEL_MODE
2150 // Set up communication patterns.
2151 communicator->setUpCommunicationMaps(this, true, forceInit);
2152 if ( nonlocalExt ) {
2153 nonlocCommunicator->setUpCommunicationMaps(this, true, forceInit);
2154 }
2155#else
2156 OOFEM_ERROR("Can't set up comm maps, parallel support not compiled");
2157#endif
2158}
2159
2160
2161int
2162EngngModel :: updateSharedDofManagers(FloatArray &answer, const UnknownNumberingScheme &s, int ExchangeTag)
2163{
2164 if ( isParallel() ) {
2165#ifdef __MPI_PARALLEL_MODE
2166 int result = 1;
2167 #ifdef __VERBOSE_PARALLEL
2168 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Packing data", this->giveRank() );
2169 #endif
2170
2172 tmp.array = & answer;
2173 tmp.numbering = & s;
2174 result &= communicator->packAllData(this, & tmp, & EngngModel :: packDofManagers);
2175
2176 #ifdef __VERBOSE_PARALLEL
2177 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Exchange started", this->giveRank() );
2178 #endif
2179
2180 result &= communicator->initExchange(ExchangeTag);
2181
2182 #ifdef __VERBOSE_PARALLEL
2183 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Receiving and unpacking", this->giveRank() );
2184 #endif
2185
2186 result &= communicator->unpackAllData(this, & tmp, & EngngModel :: unpackDofManagers);
2187 result &= communicator->finishExchange();
2188 return result;
2189#else
2190 OOFEM_ERROR("Support for parallel mode not compiled in.");
2191#endif
2192 } else {
2193 return 1;
2194 }
2195
2196}
2197
2198
2199int
2200EngngModel :: exchangeRemoteElementData(int ExchangeTag)
2201{
2202
2203 if ( isParallel() && nonlocalExt ) {
2204#ifdef __MPI_PARALLEL_MODE
2205 int result = 1;
2206 #ifdef __VERBOSE_PARALLEL
2207 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Packing remote element data", this->giveRank() );
2208 #endif
2209
2210 result &= nonlocCommunicator->packAllData(this, & EngngModel :: packRemoteElementData);
2211
2212 #ifdef __VERBOSE_PARALLEL
2213 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Remote element data exchange started", this->giveRank() );
2214 #endif
2215
2216 result &= nonlocCommunicator->initExchange(ExchangeTag);
2217
2218 #ifdef __VERBOSE_PARALLEL
2219 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Receiveng and Unpacking remote element data", this->giveRank() );
2220 #endif
2221
2222 if ( !( result &= nonlocCommunicator->unpackAllData(this, & EngngModel :: unpackRemoteElementData) ) ) {
2223 OOFEM_ERROR("Receiveng and Unpacking remote element data");
2224 }
2225
2226 result &= nonlocCommunicator->finishExchange();
2227 return result;
2228#else
2229 OOFEM_ERROR("Support for parallel mode not compiled in.");
2230#endif
2231 } else {
2232 return 1;
2233 }
2234}
2235
2236#ifdef __MPI_PARALLEL_MODE
2237void
2238EngngModel :: balanceLoad(TimeStep *tStep)
2239{
2241 this->giveLoadBalancer();
2242 if ( !lb ) {
2243 OOFEM_WARNING("No load balancer found, skipping load balancing step");
2244 return;
2245 }
2246
2247 //print statistics for current step
2248 lb->printStatistics();
2249
2250 if ( tStep->isNotTheLastStep() ) {
2251 LoadBalancerMonitor :: LoadBalancerDecisionType _d = lbm->decide(tStep);
2252 if ( ( _d == LoadBalancerMonitor :: LBD_RECOVER ) ||
2254 this->timer.startTimer(EngngModelTimer :: EMTT_LoadBalancingTimer);
2255
2256 // determine nwe partitioning
2257 lb->calculateLoadTransfer();
2258 // pack e-model solution data into dof dictionaries
2259 this->packMigratingData(tStep);
2260 // migrate data
2261 lb->migrateLoad( this->giveDomain(1) );
2262 // renumber itself
2263 this->forceEquationNumbering();
2264 // re-init export modules
2265 this->giveExportModuleManager()->initialize();
2266 #ifdef __VERBOSE_PARALLEL
2267 // debug print
2269 int nnodes = giveDomain(1)->giveNumberOfDofManagers();
2270 int myrank = this->giveRank();
2271 fprintf(stderr, "\n[%d] Nodal Table\n", myrank);
2272 for ( int i = 1; i <= nnodes; i++ ) {
2273 if ( giveDomain(1)->giveDofManager(i)->giveParallelMode() == DofManager_local ) {
2274 fprintf( stderr, "[%d]: %5d[%d] local ", myrank, i, giveDomain(1)->giveDofManager(i)->giveGlobalNumber() );
2275 } else if ( giveDomain(1)->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
2276 fprintf( stderr, "[%d]: %5d[%d] shared ", myrank, i, giveDomain(1)->giveDofManager(i)->giveGlobalNumber() );
2277 }
2278
2279 for ( Dof *dof: *giveDomain(1)->giveDofManager(i) ) {
2280 fprintf( stderr, "(%d)", dof->giveEquationNumber(dn) );
2281 }
2282
2283 fprintf(stderr, "\n");
2284 }
2285
2286 #endif
2287 // unpack (restore) e-model solution data from dof dictionaries
2288 this->unpackMigratingData(tStep);
2289
2290 this->timer.stopTimer(EngngModelTimer :: EMTT_LoadBalancingTimer);
2291 double _steptime = this->timer.getUtime(EngngModelTimer :: EMTT_LoadBalancingTimer);
2292 OOFEM_LOG_INFO("[%d] EngngModel info: user time consumed by load rebalancing %.2fs\n",
2293 this->giveRank(), _steptime);
2294 }
2295 }
2296}
2297
2298
2299int
2300EngngModel :: packRemoteElementData(ProcessCommunicator &processComm)
2301{
2302 int result = 1;
2303 const IntArray &toSendMap = processComm.giveToSendMap();
2304 CommunicationBuffer &send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff();
2305 Domain *domain = this->giveDomain(1);
2306
2307
2308 for ( int ielem : toSendMap ) {
2309 result &= domain->giveElement( ielem )->packUnknowns( send_buff, this->giveCurrentStep() );
2310 }
2311
2312 return result;
2313}
2314
2315
2316int
2317EngngModel :: unpackRemoteElementData(ProcessCommunicator &processComm)
2318{
2319 int result = 1;
2320 const IntArray &toRecvMap = processComm.giveToRecvMap();
2321 CommunicationBuffer &recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff();
2322 Domain *domain = this->giveDomain(1);
2323
2324
2325 for ( int ielem : toRecvMap ) {
2326 Element *element = domain->giveElement( ielem );
2327 if ( element->giveParallelMode() == Element_remote ) {
2328 result &= element->unpackAndUpdateUnknowns( recv_buff, this->giveCurrentStep() );
2329 } else {
2330 OOFEM_ERROR("element is not remote");
2331 }
2332 }
2333
2334 return result;
2335}
2336
2337
2338int
2339EngngModel :: packDofManagers(ArrayWithNumbering *srcData, ProcessCommunicator &processComm)
2340{
2341 FloatArray *src = srcData->array;
2342 const UnknownNumberingScheme &s = * srcData->numbering;
2343 int result = 1;
2344 Domain *domain = this->giveDomain(1);
2345 const IntArray &toSendMap = processComm.giveToSendMap();
2347
2350 for ( int inode : toSendMap ) {
2351 DofManager *dman = domain->giveDofManager( inode );
2352 for ( auto &jdof: *dman ) {
2353 if ( jdof->isPrimaryDof() ) {
2354 int eqNum = jdof->giveEquationNumber(s);
2355 if ( eqNum ) {
2356 result &= pcbuff->write( src->at(eqNum) );
2357 }
2358 }
2359 }
2360 }
2361
2362 return result;
2363}
2364
2365
2366int
2367EngngModel :: unpackDofManagers(ArrayWithNumbering *destData, ProcessCommunicator &processComm)
2368{
2369 FloatArray *dest = destData->array;
2370 const UnknownNumberingScheme &s = * destData->numbering;
2371 int result = 1;
2372 Domain *domain = this->giveDomain(1);
2373 const IntArray &toRecvMap = processComm.giveToRecvMap();
2375 double value;
2376
2379 for ( int inode : toRecvMap ) {
2380 DofManager *dman = domain->giveDofManager( inode );
2381 dofManagerParallelMode dofmanmode = dman->giveParallelMode();
2382 for ( auto &jdof: *dman ) {
2383 int eqNum = jdof->giveEquationNumber(s);
2384 if ( jdof->isPrimaryDof() && eqNum ) {
2385 result &= pcbuff->read(value);
2386 if ( dofmanmode == DofManager_shared ) {
2387 dest->at(eqNum) += value;
2388 } else if ( dofmanmode == DofManager_remote ) {
2389 dest->at(eqNum) = value;
2390 } else {
2391 OOFEM_ERROR("unknown dof namager parallel mode");
2392 }
2393 }
2394 }
2395 }
2396
2397 return result;
2398}
2399
2400#endif
2401} // end namespace oofem
std::unique_ptr< Term > createTerm(const char *name)
Base class for contact boundary conditions.
Definition contactbc.h:79
virtual void initForNewIteration(TimeStep *tStep, int iter)
Called at the beginning of a new nonlinear iteration.
Definition contactbc.C:53
const char * what() const noexcept override
RAII guard for DataReader::enterRecord and DataReader::leaveRecord.
Definition datareader.h:128
virtual std::string giveReferenceName() const =0
Gives the reference file name (e.g. file name).
virtual InputRecord * giveTopInputRecord()
Definition datareader.h:100
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
virtual bool hasFlattenedStructure()
Definition datareader.h:120
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.
void giveLocationArray(const IntArray &dofIDArry, IntArray &locationArray, const UnknownNumberingScheme &s) const
Definition dofmanager.C:185
virtual bool computeM2LTransformation(FloatMatrix &answer, const IntArray &dofIDArry)
Definition dofmanager.C:864
void giveCompleteLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s) const
Definition dofmanager.C:237
void giveCompleteMasterDofIDArray(IntArray &dofIDArray) const
Definition dofmanager.C:257
int givePartitionsConnectivitySize()
Definition dofmanager.C:934
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition dofmanager.C:507
IntArray * giveLoadArray()
Definition dofmanager.C:90
dofManagerParallelMode giveParallelMode() const
Definition dofmanager.h:526
virtual void printSingleOutputAt(FILE *file, TimeStep *tStep, char ch, ValueModeType mode, double scale=1.0)
Definition dof.C:76
int giveNumberOfBoundaryConditions() const
Returns number of boundary conditions in domain.
Definition domain.h:469
Set * giveSet(int n)
Definition domain.C:366
int giveNumber()
Returns domain number.
Definition domain.h:281
int giveNumberOfElements() const
Returns number of elements in domain.
Definition domain.h:463
std ::vector< std ::unique_ptr< DofManager > > & giveDofManagers()
Definition domain.h:427
Load * giveLoad(int n)
Definition domain.C:226
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
std ::vector< std ::unique_ptr< GeneralBoundaryCondition > > & giveBcs()
Definition domain.h:349
DofManager * giveDofManager(int n)
Definition domain.C:317
Element * giveElement(int n)
Definition domain.C:165
GeneralBoundaryCondition * giveBc(int n)
Definition domain.C:246
int giveMaxDofID()
Definition domain.h:641
std ::vector< std ::unique_ptr< Element > > & giveElements()
Definition domain.h:294
virtual bool giveRotationMatrix(FloatMatrix &answer)
Definition element.C:298
virtual bool computeDofTransformationMatrix(FloatMatrix &answer, const IntArray &nodes, bool includeInternal)
Definition element.C:342
virtual void giveCharacteristicMatrix(FloatMatrix &answer, CharType type, TimeStep *tStep)
Definition element.C:620
virtual bool isActivated(TimeStep *tStep)
Definition element.C:838
virtual IntArray giveBoundaryEdgeNodes(int boundary, bool includeHierarchical=false) const
Definition element.C:892
int packUnknowns(DataStream &buff, TimeStep *tStep)
Definition element.C:1718
void computeVectorOfPrescribed(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:212
const IntArray & giveBodyLoadList() const
Definition element.h:361
virtual IntArray giveBoundarySurfaceNodes(int boundary, bool includeHierarchical=false) const
Definition element.C:898
const IntArray & giveBoundaryLoadList() const
Definition element.h:365
void giveLocationArray(IntArray &locationArray, const UnknownNumberingScheme &s, IntArray *dofIds=NULL) const
Definition element.C:429
int unpackAndUpdateUnknowns(DataStream &buff, TimeStep *tStep)
Definition element.C:1733
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
elementParallelMode giveParallelMode() const
Definition element.h:1139
void printOutputAt(FILE *file, TimeStep *tStep) override
Definition element.C:804
virtual void initStepIncrements()
Definition engngm.C:1702
EngngModelContext * context
Context.
Definition engngm.h:277
void assembleVectorFromDofManagers(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1136
virtual void updateYourself(TimeStep *tStep)
Definition engngm.C:692
virtual void initializeYourself(TimeStep *tStep)
Definition engngm.C:561
int parallelFlag
Flag indicating that the receiver runs in parallel.
Definition engngm.h:281
std::unique_ptr< LoadBalancer > lb
Load Balancer.
Definition engngm.h:304
std ::vector< std ::unique_ptr< Domain > > domainList
List of problem domains.
Definition engngm.h:217
enum fMode nonLinFormulation
Type of non linear formulation (total or updated formulation).
Definition engngm.h:283
std::unique_ptr< TimeStepController > timeStepController
Time Step controller is responsible for collecting data from analysis, elements, and materials,...
Definition engngm.h:287
virtual void drawNodes(oofegGraphicContext &gc)
Definition engngm.C:2134
virtual void preInitializeNextStep()
Does a pre-initialization of the next time step (implement if necessarry).
Definition engngm.h:749
int instanciateDomains(DataReader &dr)
Instanciate problem domains by calling their instanciateYourself() service.
Definition engngm.C:366
virtual LoadBalancer * giveLoadBalancer()
Definition engngm.h:1206
bool force_load_rebalance_in_first_step
Debug flag forcing load balancing after first step.
Definition engngm.h:309
int numberOfEquations
Total number of equation in current time step.
Definition engngm.h:221
int numProcs
Total number of collaborating processes.
Definition engngm.h:291
virtual void balanceLoad(TimeStep *tStep)
Definition engngm.C:2238
int rank
Domain rank in a group of collaborating processes (0..groupSize-1).
Definition engngm.h:289
MPI_Comm comm
Communication object for this engineering model.
Definition engngm.h:299
virtual TimeStep * giveCurrentStep(bool force=false)
Definition engngm.h:717
virtual int giveNumberOfDomainEquations(int di, const UnknownNumberingScheme &num)
Definition engngm.C:452
std::string dataOutputFileName
Path to output stream.
Definition engngm.h:248
void assembleVectorFromElements(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1351
virtual FieldPtr giveField(FieldType key, TimeStep *)
Definition engngm.h:545
virtual LoadBalancerMonitor * giveLoadBalancerMonitor()
Definition engngm.h:1208
int giveRank() const
Returns domain rank in a group of collaborating processes (0..groupSize-1).
Definition engngm.h:1154
void outputElements(FILE *file, Domain &domain, TimeStep *tStep, int setNum)
Definition engngm.C:852
ExportModuleManager * giveExportModuleManager()
Returns receiver's export module manager.
Definition engngm.h:791
ProblemCommunicator * communicator
Communicator.
Definition engngm.h:315
std::string simulationDescription
Definition engngm.h:339
virtual TimeStep * giveNextStep()
Returns next time step (next to current step) of receiver.
Definition engngm.h:747
EngngModelContext * giveContext()
Context requesting service.
Definition engngm.h:1174
bool renumberFlag
Renumbering flag (renumbers equations after each step, necessary if Dirichlet BCs change).
Definition engngm.h:229
EngngModel(int i, EngngModel *_master=NULL)
Definition engngm.C:99
std ::unique_ptr< TimeStep > previousStep
Previous time step.
Definition engngm.h:243
int giveNumberOfDomains()
Returns number of domains in problem.
Definition engngm.h:365
std::string giveContextFileName(int tStepNumber, int stepVersion) const
Definition engngm.C:1907
virtual void adaptTimeStep(double nIter)
Definition engngm.h:729
double giveSolutionStepTime()
Definition engngm.C:2005
ContextOutputMode giveContextOutputMode() const
Definition engngm.h:402
std::string coreOutputFileName
String with core output file name.
Definition engngm.h:250
virtual NumericalMethod * giveNumericalMethod(MetaStep *mStep)
Returns reference to receiver's numerical method.
Definition engngm.h:789
int equationNumberingCompleted
Equation numbering completed flag.
Definition engngm.h:233
bool profileOpt
Profile optimized numbering flag (using Sloan's algorithm).
Definition engngm.h:231
char processor_name[PROCESSOR_NAME_LENGTH]
Processor name.
Definition engngm.h:296
MetaStep * giveCurrentMetaStep()
Returns current meta step.
Definition engngm.C:1900
std::string referenceFileName
String with reference file name.
Definition engngm.h:254
int ndomains
Number of receiver domains.
Definition engngm.h:215
virtual void solveYourselfAt(TimeStep *tStep)
Definition engngm.h:484
ProblemCommunicator * nonlocCommunicator
NonLocal Communicator. Necessary when nonlocal constitutive models are used.
Definition engngm.h:318
void setUDContextOutputMode(int cStep)
Definition engngm.h:418
int numberOfSteps
Total number of time steps.
Definition engngm.h:219
virtual int checkConsistency()
Definition engngm.h:1091
Domain * giveDomain(int n)
Definition engngm.C:1936
virtual void doStepOutput(TimeStep *tStep)
Definition engngm.C:756
std ::unique_ptr< TimeStep > currentStep
Current time step.
Definition engngm.h:241
virtual int instanciateDefaultMetaStep(InputRecord &ir)
Instanciate default metastep, if nmsteps is zero.
Definition engngm.C:405
int nonlocalExt
Flag indicating if nonlocal extension active, which will cause data to be sent between shared element...
Definition engngm.h:293
bool loadBalancingFlag
If set to true, load balancing is active.
Definition engngm.h:307
FILE * giveOutputStream()
Returns file descriptor of output file.
Definition engngm.C:1994
int giveNumberOfSteps(bool force=false)
Definition engngm.h:777
time_t startTime
Solution start time.
Definition engngm.h:271
MetaStep * giveMetaStep(int i)
Returns the i-th meta step.
Definition engngm.h:773
EngngModelTimer timer
E-model timer.
Definition engngm.h:279
void assembleVectorFromBC(FloatArray &answer, TimeStep *tStep, const VectorAssembler &va, ValueModeType mode, const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms=NULL)
Definition engngm.C:1191
@ RemoteElementExchangeTag
Definition engngm.h:321
InitModuleManager initModuleManager
Initialization module manager.
Definition engngm.h:262
std ::vector< ParallelContext > parallelContextList
List where parallel contexts are stored.
Definition engngm.h:323
virtual ParallelContext * giveParallelContext(int n)
Definition engngm.C:1961
std ::vector< MetaStep > metaStepList
List of problem metasteps.
Definition engngm.h:237
int exchangeRemoteElementData(int ExchangeTag)
Definition engngm.C:2200
virtual void updateSolution(FloatArray &solutionVector, TimeStep *tStep, Domain *d)
Definition engngm.C:1681
problemMode pMode
Domain mode.
Definition engngm.h:267
virtual void terminate(TimeStep *tStep)
Definition engngm.C:741
virtual void initParallelContexts()
Definition engngm.C:1971
int nMetaSteps
Number of meta steps.
Definition engngm.h:235
virtual int forceEquationNumbering(int i)
Definition engngm.C:469
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition engngm.h:313
virtual void postInitialize()
Definition engngm.C:2072
ExportModuleManager exportModuleManager
Export module manager.
Definition engngm.h:260
void saveStepContext(TimeStep *tStep, ContextMode mode)
Definition engngm.C:768
ContextOutputMode contextOutputMode
Domain context output mode.
Definition engngm.h:256
void Instanciate_init()
Definition engngm.C:184
EngngModel * master
Master e-model; if defined receiver is in maintained (slave) mode.
Definition engngm.h:274
virtual void unpackMigratingData(TimeStep *tStep)
Definition engngm.h:1084
std::unique_ptr< LoadBalancerMonitor > lbm
Definition engngm.h:305
virtual void restartYourself(TimeStep *tS)
Definition engngm.h:477
virtual void drawElements(oofegGraphicContext &gc)
Definition engngm.C:2125
virtual void updateDomainLinks()
Definition engngm.C:1749
virtual void initializeFrom(InputRecord &ir)
Definition engngm.C:292
virtual void printOutputAt(FILE *file, TimeStep *tStep)
Definition engngm.C:781
void giveAnalysisTime(int &rhrs, int &rmin, int &rsec, int &uhrs, int &umin, int &usec)
Definition engngm.C:2011
bool suppressOutput
Flag for suppressing output to file.
Definition engngm.h:337
MonitorManager monitorManager
Monitor manager.
Definition engngm.h:264
FILE * outputStream
Output stream.
Definition engngm.h:252
virtual double giveInitialTime()
return time at the begining of analysis
Definition engngm.h:797
void initParallel()
Request domain rank and problem size.
Definition engngm.C:2089
virtual const char * giveClassName() const =0
Returns class name of the receiver.
bool isParallel() const
Returns true if receiver in parallel mode.
Definition engngm.h:1152
virtual void updateAttributes(MetaStep *mStep)
Definition engngm.C:669
virtual void saveContext(DataStream &stream, ContextMode mode)
Definition engngm.C:1755
int number
Receivers id.
Definition engngm.h:245
problemMode giveProblemMode() const
Returns domain mode.
Definition engngm.h:440
int contextOutputStep
Definition engngm.h:257
virtual bool requiresEquationRenumbering(TimeStep *tStep)
Definition engngm.h:915
IntArray domainPrescribedNeqs
Number of prescribed equations per domain.
Definition engngm.h:227
std::unique_ptr< ErrorEstimator > defaultErrEstimator
Error estimator. Useful for adaptivity, or simply printing errors output.
Definition engngm.h:285
void outputNodes(FILE *file, Domain &domain, TimeStep *tStep, int setNum)
Definition engngm.C:825
int numberOfPrescribedEquations
Total number or prescribed equations in current time step.
Definition engngm.h:223
virtual void packMigratingData(TimeStep *tStep)
Definition engngm.h:1077
problemScale pScale
Multiscale mode.
Definition engngm.h:269
IntArray domainNeqs
Number of equations per domain.
Definition engngm.h:225
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
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 assembleSquared(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:637
void subtract(const FloatArray &src)
Definition floatarray.C:320
void times(double s)
Definition floatarray.C:834
bool isNotEmpty() const
Returns true if receiver is not empty.
Definition floatarray.h:263
void rotatedWith(const FloatMatrix &r, char mode='n')
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
bool isNotEmpty() const
Tests for empty matrix.
virtual bcGeomType giveBCGeoType() const
virtual const IntArray & giveDofIDs() const
virtual bool isImposed(TimeStep *tStep)
virtual bool hasField(InputFieldType id)=0
Returns true if record contains field identified by idString keyword.
DataReader * giveReader() const
virtual std::shared_ptr< InputRecord > clone() const =0
std::shared_ptr< InputRecord > ptr()
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 matrixFromElement(FloatMatrix &mat, Element &element, TimeStep *tStep) const
virtual void matrixFromSurfaceLoad(FloatMatrix &mat, Element &element, BoundaryLoad *load, int boundary, TimeStep *tStep) const
virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds=nullptr) const
virtual void assembleFromActiveBC(SparseMtrx &k, ActiveBoundaryCondition &bc, TimeStep *tStep, const UnknownNumberingScheme &s_r, const UnknownNumberingScheme &s_c, void *lock=nullptr) const
virtual void matrixFromEdgeLoad(FloatMatrix &mat, Element &element, BoundaryLoad *load, int edge, TimeStep *tStep) const
virtual void locationFromElementNodes(IntArray &loc, Element &element, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds=nullptr) const
virtual void matrixFromLoad(FloatMatrix &mat, Element &element, BodyLoad *load, TimeStep *tStep) const
int giveNumber()
Returns receiver's number.
Definition metastep.h:116
InputRecord & giveAttributesRecord()
Returns e-model attributes.
Definition metastep.h:122
@ TimeStepTermination
Definition monitor.h:61
virtual void restoreContext(DataStream &stream, ContextMode mode)
Definition nummet.h:117
virtual void saveContext(DataStream &stream, ContextMode mode)
Definition nummet.h:116
CommunicationBuffer & giveRecvBuff()
int read(int *data, std::size_t count) override
Reads count integer values into array pointed by data.
Definition processcomm.h:94
CommunicationBuffer & giveSendBuff()
int write(const int *data, std::size_t count) override
Writes count integer values from array pointed by data.
Definition processcomm.h:86
const IntArray & giveToRecvMap()
ProcessCommunicatorBuff * giveProcessCommunicatorBuff()
Returns communication buffer.
const IntArray & giveToSendMap()
const IntArray & giveEdgeList()
Definition set.C:162
const IntArray & giveBoundaryList()
Definition set.C:160
const IntArray & giveElementList()
Definition set.C:158
const IntArray & giveNodeList()
Definition set.C:168
void initialize()
Initialize graph from domain description.
Definition sloangraph.C:69
void askNewOptimalNumbering(TimeStep *tStep)
Numbers all the DOFs according to the optimal renumbering found.
Definition sloangraph.C:543
int giveOptimalProfileSize()
Returns the optimal profile found.
Definition sloangraph.h:143
void tryParameters(int wdeg, int wdis)
Definition sloangraph.C:600
virtual int assembleBegin()
Starts assembling the elements.
Definition sparsemtrx.h:234
virtual int assemble(const IntArray &loc, const FloatMatrix &mat)=0
virtual int assembleEnd()
Returns when assemble is completed.
Definition sparsemtrx.h:236
double giveTargetTime()
Returns target time.
Definition timestep.h:164
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
bool isTheFirstStep()
Definition timestep.C:148
bool isNotTheLastStep()
Definition timestep.C:142
virtual void assembleFromActiveBC(FloatArray &answer, ActiveBoundaryCondition &bc, TimeStep *tStep, ValueModeType mode, const UnknownNumberingScheme &s, FloatArray *eNorms, void *lock=nullptr) const
virtual void vectorFromElement(FloatArray &vec, Element &element, TimeStep *tStep, ValueModeType mode) const
virtual void vectorFromNodeLoad(FloatArray &vec, DofManager &dman, NodalLoad *load, TimeStep *tStep, ValueModeType mode) const
virtual void vectorFromSurfaceLoad(FloatArray &vec, Element &element, BoundaryLoad *load, int boundary, TimeStep *tStep, ValueModeType mode) const
virtual void vectorFromEdgeLoad(FloatArray &vec, Element &element, BoundaryLoad *load, int edge, TimeStep *tStep, ValueModeType mode) const
virtual void locationFromElement(IntArray &loc, Element &element, const UnknownNumberingScheme &s, IntArray *dofIds=nullptr) const
Default implementation takes all the DOF IDs.
virtual void locationFromElementNodes(IntArray &loc, Element &element, const IntArray &bNodes, const UnknownNumberingScheme &s, IntArray *dofIds=nullptr) const
Default implementation takes all the DOF IDs.
virtual void vectorFromLoad(FloatArray &vec, Element &element, BodyLoad *load, TimeStep *tStep, ValueModeType mode) const
#define THROW_CIOERR(e)
#define CM_State
Definition contextmode.h:46
#define CM_Definition
Definition contextmode.h:47
#define _IFT_EngngModel_nmsteps
Definition engngm.h:82
#define _IFT_EngngModel_nsteps
Definition engngm.h:78
#define _IFT_EngngModel_forceloadBalancingFlag
Definition engngm.h:87
#define _IFT_EngngModel_profileOpt
Definition engngm.h:81
#define _IFT_EngngModel_suppressOutput
Definition engngm.h:94
#define _IFT_EngngModel_loadBalancingFlag
Definition engngm.h:86
#define _IFT_EngngModel_parallelflag
Definition engngm.h:85
#define _IFT_EngngModel_renumberFlag
Definition engngm.h:80
#define _IFT_EngngModel_eetype
Definition engngm.h:84
#define _IFT_EngngModel_nonLinFormulation
Definition engngm.h:83
#define _IFT_EngngModel_contextoutputstep
Definition engngm.h:79
#define OOFEM_WARNING(...)
Definition error.h:80
#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_RELEVANT(...)
Definition logger.h:142
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define OOFEM_LOG_FORCED(...)
Definition logger.h:141
long ContextMode
Definition contextmode.h:43
Set dummySet(0, nullptr)
Definition set.h:208
@ Element_remote
Element in active domain is only mirror of some remote element.
Definition element.h:89
fMode
Definition fmode.h:42
@ UNKNOWN
Unknown.
Definition fmode.h:43
@ SurfaceLoadBGT
Distributed surface load.
Definition bcgeomtype.h:45
@ EdgeLoadBGT
Distributed edge load.
Definition bcgeomtype.h:44
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
@ COM_Required
If required (for backtracking computation).
@ COM_Always
Enable for post-processing.
@ COM_UserDefined
Input attribute of domain (each n-th step).
@ COM_NoContext
No context.
ClassFactory & classFactory
std::shared_ptr< Field > FieldPtr
Definition field.h:78
@ _processor
Definition problemmode.h:40
@ _postProcessor
Definition problemmode.h:41
@ CIO_IOERR
General IO error.
@ macroScale
Definition problemmode.h:46
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
OOFEM_EXPORT const char * PRG_HEADER
Definition oofemcfg.C:22
#define VERBOSEPARALLEL_PRINT(service, str, rank)
Definition parallel.h:50
Helper struct to pass array and numbering scheme as a single argument.
Definition engngm.h:197
const UnknownNumberingScheme * numbering
Definition engngm.h:199
#define VERBOSE_PRINTS(str, str1)
Definition verbose.h:55
#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