|
OOFEM
2.1
|
00001 /* 00002 * 00003 * ##### ##### ###### ###### ### ### 00004 * ## ## ## ## ## ## ## ### ## 00005 * ## ## ## ## #### #### ## # ## 00006 * ## ## ## ## ## ## ## ## 00007 * ## ## ## ## ## ## ## ## 00008 * ##### ##### ## ###### ## ## 00009 * 00010 * 00011 * OOFEM : Object Oriented Finite Element Code 00012 * 00013 * Copyright (C) 1993 - 2013 Borek Patzak 00014 * 00015 * 00016 * 00017 * Czech Technical University, Faculty of Civil Engineering, 00018 * Department of Structural Mechanics, 166 29 Prague, Czech Republic 00019 * 00020 * This program is free software; you can redistribute it and/or modify 00021 * it under the terms of the GNU General Public License as published by 00022 * the Free Software Foundation; either version 2 of the License, or 00023 * (at your option) any later version. 00024 * 00025 * This program is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 * GNU General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU General Public License 00031 * along with this program; if not, write to the Free Software 00032 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00033 */ 00034 00035 // Milan ????????????????? 00036 //#include "gpinitmodule.h" 00037 // Milan ????????????????? 00038 00039 #include "nummet.h" 00040 #include "sparsemtrx.h" 00041 #include "engngm.h" 00042 #include "timestep.h" 00043 #include "metastep.h" 00044 #include "element.h" 00045 #include "oofemcfg.h" 00046 #include "timer.h" 00047 #include "dofmanager.h" 00048 #include "node.h" 00049 #include "activebc.h" 00050 #include "timestep.h" 00051 #include "verbose.h" 00052 #include "datastream.h" 00053 #include "oofemtxtdatareader.h" 00054 #include "sloangraph.h" 00055 #include "logger.h" 00056 #include "errorestimator.h" 00057 #include "contextioerr.h" 00058 #include "xfemmanager.h" 00059 #include "outputmanager.h" 00060 #include "exportmodulemanager.h" 00061 #include "initmodulemanager.h" 00062 #include "usrdefsub.h" 00063 00064 #ifdef __PARALLEL_MODE 00065 #include "problemcomm.h" 00066 #include "processcomm.h" 00067 #endif 00068 00069 #include <cstdio> 00070 #include <cstdarg> 00071 #include <ctime> 00072 // include unistd.h; needed for access 00073 #ifdef HAVE_UNISTD_H 00074 #include <unistd.h> 00075 #elif _MSC_VER 00076 #include <io.h> 00077 #endif 00078 00079 #ifdef __OOFEG 00080 #include "oofeggraphiccontext.h" 00081 #endif 00082 00083 00084 namespace oofem { 00085 EngngModel :: EngngModel(int i, EngngModel *_master) : domainNeqs(), domainPrescribedNeqs() 00086 // constructor 00087 { 00088 number = i; 00089 currentStep = NULL; 00090 previousStep = NULL; 00091 stepWhenIcApply = NULL; 00092 defaultErrEstimator = NULL; 00093 numberOfSteps = 0; 00094 numberOfEquations = 0; 00095 numberOfPrescribedEquations = 0; 00096 renumberFlag = false; 00097 equationNumberingCompleted = 0; 00098 ndomains = 0; 00099 nMetaSteps = 0; 00100 nxfemman = 0; 00101 profileOpt = false; 00102 nonLinFormulation = UNKNOWN; 00103 00104 outputStream = NULL; 00105 00106 domainList = new AList< Domain >(0); 00107 metaStepList = new AList< MetaStep >(0); 00108 xfemManagerList = new AList< XfemManager >(0); 00109 00110 contextOutputMode = COM_NoContext; 00111 contextOutputStep = 0; 00112 pMode = _processor; // for giveContextFile() 00113 pScale = macroScale; 00114 00115 exportModuleManager = new ExportModuleManager(this); 00116 initModuleManager = new InitModuleManager(this); 00117 master = _master; // master mode by default 00118 // create context if in master mode; otherwise request context from master 00119 if ( master ) { 00120 context = master->giveContext(); 00121 } else { 00122 context = new EngngModelContext(); 00123 } 00124 00125 parallelFlag = 0; 00126 #ifdef __PARALLEL_MODE 00127 loadBalancingFlag = false; 00128 force_load_rebalance_in_first_step = false; 00129 lb = NULL; 00130 lbm = NULL; 00131 communicator = NULL; 00132 nonlocCommunicator = NULL; 00133 commBuff = NULL; 00134 #endif 00135 00136 #ifdef __PETSC_MODULE 00137 petscContextList = new AList< PetscContext >(0); 00138 #endif 00139 } 00140 00141 #if 0 00142 EngngModel :: EngngModel(int i, char *s, EngngModel *_master) : domainNeqs(), domainPrescribedNeqs() 00143 // constructor 00144 { 00145 number = i; 00146 currentStep = NULL; 00147 previousStep = NULL; 00148 stepWhenIcApply = NULL; 00149 defaultErrEstimator = NULL; 00150 numberOfSteps = 0; 00151 numberOfEquations = 0; 00152 numberOfPrescribedEquations = 0; 00153 renumberFlag = false; 00154 equationNumberingCompleted = 0; 00155 ndomains = 0; 00156 nMetaSteps = 0; 00157 nxfemman = 0; 00158 00159 outputStream = NULL; 00160 00161 domainList = new AList< Domain >(0); 00162 metaStepList = new AList< MetaStep >(0); 00163 xfemManagerList = new AList< XfemManager >(0); 00164 00165 exportModuleManager = new ExportModuleManager(this); 00166 initModuleManager = new InitModuleManager(this); 00167 master = _master; // master mode by default 00168 // create context if in master mode; otherwise request context from master 00169 if ( master ) { 00170 context = master->giveContext(); 00171 } else { 00172 context = new EngngModelContext(); 00173 } 00174 00175 parallelFlag = 0; 00176 #ifdef __PARALLEL_MODE 00177 loadBalancingFlag = false; 00178 force_load_rebalance_in_first_step = false; 00179 lb = NULL; 00180 lbm = NULL; 00181 #endif 00182 00183 #ifdef __PETSC_MODULE 00184 petscContextList = new AList< PetscContext >(0); 00185 #endif 00186 } 00187 #endif 00188 00189 EngngModel :: ~EngngModel() 00190 // destructor 00191 { 00192 if ( previousStep == currentStep ) { 00193 if ( previousStep != NULL ) { 00194 delete this->currentStep; 00195 } 00196 } else { 00197 if ( currentStep != NULL ) { 00198 delete currentStep; 00199 } 00200 00201 if ( previousStep != NULL ) { 00202 delete previousStep; 00203 } 00204 } 00205 00206 if ( stepWhenIcApply != NULL ) { 00207 delete stepWhenIcApply; 00208 } 00209 00210 delete domainList; 00211 delete metaStepList; 00212 delete xfemManagerList; 00213 00214 #ifdef __PETSC_MODULE 00215 delete petscContextList; 00216 #endif 00217 00218 if ( exportModuleManager ) { 00219 delete exportModuleManager; 00220 } 00221 00222 if ( initModuleManager ) { 00223 delete initModuleManager; 00224 } 00225 00226 // master deletes the context 00227 if ( master == NULL ) { 00228 delete context; 00229 } 00230 00231 //fclose (inputStream) ; 00232 if ( outputStream ) { 00233 fclose(outputStream); 00234 } 00235 00236 if ( defaultErrEstimator ) { 00237 delete defaultErrEstimator; 00238 } 00239 00240 #ifdef __PARALLEL_MODE 00241 if ( loadBalancingFlag ) { 00242 if ( lb ) { 00243 delete lb; 00244 } 00245 00246 if ( lbm ) { 00247 delete lbm; 00248 } 00249 } 00250 00251 if ( communicator ) delete communicator; 00252 if ( nonlocCommunicator ) delete nonlocCommunicator; 00253 if ( commBuff ) delete commBuff; 00254 #endif 00255 } 00256 00257 00258 void EngngModel :: setParallelMode(bool parallelFlag) 00259 { 00260 this->parallelFlag = parallelFlag; 00261 if ( this->parallelFlag ) { 00262 #ifndef __PARALLEL_MODE 00263 OOFEM_ERROR("EngngModel :: setParallelMode - Can't do it, only compiled for sequential runs"); 00264 #else 00265 initParallel(); 00266 #endif 00267 } 00268 } 00269 00270 00271 void 00272 EngngModel :: Instanciate_init(const char *dataOutputFileName, int ndomains) 00273 { 00274 Domain *domain; 00275 00276 this->coreOutputFileName = std :: string(dataOutputFileName); 00277 this->dataOutputFileName = std :: string(dataOutputFileName); 00278 00279 if ( this->giveProblemMode() == _postProcessor ) { 00280 // modify output file name to prevent output to be lost 00281 this->dataOutputFileName.append(".oofeg"); 00282 } 00283 00284 if ( ( outputStream = fopen(this->dataOutputFileName.c_str(), "w") ) == NULL ) { 00285 _error2( "instanciateYourself: Can't open output file %s", this->dataOutputFileName.c_str() ); 00286 } 00287 00288 00289 // create domains 00290 domainNeqs.resize(ndomains); 00291 domainPrescribedNeqs.resize(ndomains); 00292 domainList->growTo(ndomains); 00293 for ( int i = 1; i <= ndomains; i++ ) { 00294 domain = new Domain(i, 0, this); 00295 domainList->put(i, domain); 00296 } 00297 00298 this->ndomains = ndomains; 00299 00300 #ifdef __PETSC_MODULE 00301 this->initPetscContexts(); 00302 #endif 00303 } 00304 00305 00306 int EngngModel :: instanciateYourself(DataReader *dr, InputRecord *ir, const char *dataOutputFileName, const char *desc) 00307 // simple input - only number of steps variable is read 00308 { 00309 bool inputReaderFinish = true; 00310 00311 this->Instanciate_init(dataOutputFileName, this->ndomains); 00312 00313 fprintf(outputStream, "%s", PRG_HEADER); 00314 this->startTime = time(NULL); 00315 //this->startClock= this-> getClock(); 00316 fprintf( outputStream, "\nStarting analysis on: %s\n", ctime(& this->startTime) ); 00317 00318 fprintf(outputStream, "%s\n", desc); 00319 00320 # ifdef VERBOSE 00321 OOFEM_LOG_DEBUG( "Reading all data from input file %s\n", dr->giveDataSourceName() ); 00322 # endif 00323 #ifdef __PARALLEL_MODE 00324 if ( this->isParallel() ) { 00325 fprintf(outputStream, "Problem rank is %d/%d on %s\n\n", this->rank, this->numProcs, this->processor_name); 00326 } 00327 00328 #endif 00329 00330 // instanciate receiver 00331 this->initializeFrom(ir); 00332 exportModuleManager->initializeFrom(ir); 00333 initModuleManager->initializeFrom(ir); 00334 00335 if ( this->nMetaSteps == 0 ) { 00336 inputReaderFinish = false; 00337 this->instanciateDefaultMetaStep(ir); 00338 } else { 00339 this->instanciateMetaSteps(dr); 00340 } 00341 00342 // instanciate initialization module manager 00343 initModuleManager->instanciateYourself(dr, ir); 00344 // instanciate export module manager 00345 exportModuleManager->instanciateYourself(dr, ir); 00346 this->instanciateDomains(dr); 00347 00348 exportModuleManager->initialize(); 00349 00350 // Milan ?????????????????? 00351 //GPImportModule* gim = new GPImportModule(this); 00352 //gim -> getInput(); 00353 // Milan ?????????????????? 00354 00355 // instantiate xfemmanager 00356 XfemManager *xm; 00357 xfemManagerList->growTo(nxfemman); 00358 for ( int i = 1; i <= this->nxfemman; i++ ) { 00359 xm = new XfemManager(this, i); 00360 ir = dr->giveInputRecord(DataReader :: IR_xfemManRec, 1); 00361 // XfemManager has to be put into xfemManagerList before xm->initializeFrom, otherwise Enrichmentitem cannot access XfemManager 00362 // or we have to make a reference from EnrichmentItem also 00363 xfemManagerList->put(i, xm); 00364 xm->initializeFrom(ir); 00365 xm->instanciateYourself(dr); 00366 int last = xm->computeFictPosition(); 00367 this->setNumberOfEquations(1, last); 00368 xm->updateIntegrationRule(); 00369 } 00370 00371 // check emodel input record if no default metastep, since all has been read 00372 if ( inputReaderFinish ) { 00373 ir->finish(); 00374 } 00375 00376 return 1; 00377 } 00378 00379 IRResultType 00380 EngngModel :: initializeFrom(InputRecord *ir) 00381 { 00382 const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro 00383 IRResultType result; // Required by IR_GIVE_FIELD macro 00384 00385 IR_GIVE_FIELD(ir, numberOfSteps, IFT_EngngModel_nsteps, "nsteps"); // Macro 00386 if ( numberOfSteps <= 0 ) { 00387 _error("instanciateFrom: nsteps not specified, bad format"); 00388 } 00389 00390 contextOutputStep = 0; 00391 IR_GIVE_OPTIONAL_FIELD(ir, contextOutputStep, IFT_EngngModel_contextoutputstep, "contextoutputstep"); // Macro 00392 if ( contextOutputStep ) { 00393 this->setUDContextOutputMode(contextOutputStep); 00394 } 00395 00396 renumberFlag = false; 00397 IR_GIVE_OPTIONAL_FIELD(ir, renumberFlag, IFT_EngngModel_renumberFlag, "renumber"); // Macro 00398 profileOpt = false; 00399 IR_GIVE_OPTIONAL_FIELD(ir, profileOpt, IFT_EngngModel_profileOpt, "profileopt"); // Macro 00400 nMetaSteps = 0; 00401 IR_GIVE_OPTIONAL_FIELD(ir, nMetaSteps, IFT_EngngModel_nmsteps, "nmsteps"); // Macro 00402 nxfemman = 0; 00403 IR_GIVE_OPTIONAL_FIELD(ir, nxfemman, IFT_EngngModel_nxfemman, "nxfemman"); // Macro 00404 int _val = 1; 00405 IR_GIVE_OPTIONAL_FIELD(ir, _val, IFT_EngngModel_nonLinFormulation, "nonlinform"); 00406 nonLinFormulation = ( fMode ) _val; 00407 00408 int eeTypeId = -1; 00409 IR_GIVE_OPTIONAL_FIELD(ir, eeTypeId, IFT_EngngModel_eetype, "eetype"); 00410 if ( eeTypeId >= 0 ) { 00411 this->defaultErrEstimator = CreateUsrDefErrorEstimator( ( ErrorEstimatorType ) eeTypeId, 1, this->giveDomain(1) ); 00412 this->defaultErrEstimator->initializeFrom(ir); 00413 } 00414 00415 #ifdef __PARALLEL_MODE 00416 IR_GIVE_OPTIONAL_FIELD(ir, parallelFlag, IFT_EngngModel_parallelflag, "parallelflag"); // Macro 00417 // fprintf (stderr, "Parallel mode is %d\n", parallelFlag); 00418 00419 /* Load balancing support */ 00420 _val = 0; 00421 IR_GIVE_OPTIONAL_FIELD(ir, _val, IFT_NonLinearStatic_loadBalancingFlag, "lbflag"); // Macro 00422 loadBalancingFlag = _val; 00423 00424 _val = 0; 00425 IR_GIVE_OPTIONAL_FIELD(ir, _val, IFT_NonLinearStatic_forceloadBalancingFlag, "forcelb1"); // Macro 00426 force_load_rebalance_in_first_step = _val; 00427 00428 #endif 00429 return IRRT_OK; 00430 } 00431 00432 00433 int 00434 EngngModel :: instanciateDomains(DataReader *dr) 00435 { 00436 int result = 1; 00437 // read problem domains 00438 for ( int i = 1; i <= this->ndomains; i++ ) { 00439 result &= domainList->at(i)->instanciateYourself(dr); 00440 domainList->at(i)->postInitialize(); 00441 } 00442 00443 return result; 00444 } 00445 00446 00447 int 00448 EngngModel :: instanciateMetaSteps(DataReader *dr) 00449 { 00450 int result = 1; 00451 MetaStep *mstep; 00452 00453 // create meta steps 00454 metaStepList->growTo(nMetaSteps); 00455 for ( int i = 1; i <= this->nMetaSteps; i++ ) { 00456 mstep = new MetaStep(i, this); 00457 metaStepList->put(i, mstep); 00458 } 00459 00460 // read problem domains 00461 for ( int i = 1; i <= this->nMetaSteps; i++ ) { 00462 InputRecord *ir = dr->giveInputRecord(DataReader :: IR_mstepRec, i); 00463 result &= metaStepList->at(i)->initializeFrom(ir); 00464 } 00465 00466 // set meta step bounds 00467 int istep = this->giveNumberOfFirstStep(); 00468 for ( int i = 1; i <= this->nMetaSteps; i++ ) { 00469 istep = metaStepList->at(i)->setStepBounds(istep); 00470 } 00471 00472 this->numberOfSteps = istep - 1; 00473 OOFEM_LOG_RELEVANT("Total number of solution steps %d\n", numberOfSteps); 00474 return result; 00475 } 00476 00477 00478 int 00479 EngngModel :: instanciateDefaultMetaStep(InputRecord *ir) 00480 { 00481 MetaStep *mstep; 00482 00483 if ( numberOfSteps == 0 ) { 00484 _error("instanciateDefaultMetaStep: nsteps cannot be zero"); 00485 } 00486 00487 // create default meta steps 00488 this->nMetaSteps = 1; 00489 metaStepList->growTo(nMetaSteps); 00490 mstep = new MetaStep(1, this, numberOfSteps, *ir); 00491 metaStepList->put(1, mstep); 00492 00493 // set meta step bounds 00494 int istep = this->giveNumberOfFirstStep() - 1; 00495 metaStepList->at(1)->setStepBounds(istep + 1); 00496 00497 OOFEM_LOG_RELEVANT("Total number of solution steps %d\n", numberOfSteps); 00498 return 1; 00499 } 00500 00501 00502 int 00503 EngngModel :: giveNumberOfEquations(EquationID) 00504 { 00505 // 00506 // returns number of equations of current problem 00507 // this method is implemented here, because some method may add some 00508 // conditions in to system and this may results into increased number of 00509 // equations. 00510 // 00511 if ( equationNumberingCompleted ) { 00512 return numberOfEquations; 00513 } 00514 00515 return this->forceEquationNumbering(); 00516 } 00517 00518 int 00519 EngngModel :: giveNumberOfPrescribedEquations(EquationID) 00520 { 00521 // 00522 // returns number of equations of current problem 00523 // this method is implemented here, because some method may add some 00524 // conditions in to system and this may results into increased number of 00525 // equations. 00526 // 00527 if ( !equationNumberingCompleted ) { 00528 this->forceEquationNumbering(); 00529 } 00530 00531 return numberOfPrescribedEquations; 00532 } 00533 00534 int 00535 EngngModel :: giveNumberOfDomainEquations(int id, EquationID) 00536 { 00537 // 00538 // returns number of equations of current problem 00539 // this method is implemented here, because some method may add some 00540 // conditions into the system and this may results into increased number of 00541 // equations. 00542 // 00543 if ( !equationNumberingCompleted ) { 00544 this->forceEquationNumbering(); 00545 } 00546 00547 return domainNeqs.at(id); 00548 } 00549 00550 00551 int 00552 EngngModel :: giveNumberOfPrescribedDomainEquations(int id, EquationID) 00553 { 00554 // 00555 // returns number of equations of current problem 00556 // this method is implemented here, because some method may add some 00557 // conditions in to system and this may results into increased number of 00558 // equations. 00559 // 00560 if ( equationNumberingCompleted ) { 00561 return domainPrescribedNeqs.at(id); 00562 } 00563 00564 this->forceEquationNumbering(); 00565 return domainPrescribedNeqs.at(id); 00566 } 00567 00568 int 00569 EngngModel :: forceEquationNumbering(int id) 00570 { 00571 // forces equation renumbering for current time step 00572 // intended mainly for problems with changes of static system 00573 // during solution 00574 // OUTPUT: 00575 // sets this->numberOfEquations and this->numberOfPrescribedEquations and returns this value 00576 00577 int nnodes, nelem, nbc; 00578 Element *elem; 00579 Domain *domain = this->giveDomain(id); 00580 TimeStep *currStep = this->giveCurrentStep(); 00581 IntArray loc; 00582 00583 this->domainNeqs.at(id) = 0; 00584 this->domainPrescribedNeqs.at(id) = 0; 00585 00586 nnodes = domain->giveNumberOfDofManagers(); 00587 nelem = domain->giveNumberOfElements(); 00588 nbc = domain->giveNumberOfBoundaryConditions(); 00589 00590 if ( !this->profileOpt ) { 00591 for ( int i = 1; i <= nnodes; i++ ) { 00592 domain->giveDofManager(i)->askNewEquationNumbers(currStep); 00593 } 00594 00595 for ( int i = 1; i <= nelem; ++i ) { 00596 elem = domain->giveElement(i); 00597 nnodes = elem->giveNumberOfInternalDofManagers(); 00598 for ( int k = 1; k <= nnodes; k++ ) { 00599 elem->giveInternalDofManager(k)->askNewEquationNumbers(currStep); 00600 } 00601 } 00602 00603 // For special boundary conditions; 00604 for ( int i = 1; i <= nbc; ++i ) { 00605 GeneralBoundaryCondition *bc = domain->giveBc(i); 00606 nnodes = bc->giveNumberOfInternalDofManagers(); 00607 for ( int k = 1; k <= nnodes; k++ ) { 00608 bc->giveInternalDofManager(k)->askNewEquationNumbers(currStep); 00609 } 00610 } 00611 } else { 00612 // invoke profile reduction 00613 int initialProfile, optimalProfile; 00614 Timer timer; 00615 OOFEM_LOG_INFO("\nRenumbering DOFs with Sloan's algorithm...\n"); 00616 timer.startTimer(); 00617 00618 SloanGraph graph(domain); 00619 graph.initialize(); 00620 graph.tryParameters(0, 0); 00621 initialProfile = graph.giveOptimalProfileSize(); 00622 graph.tryParameters(2, 1); 00623 graph.tryParameters(1, 0); 00624 graph.tryParameters(5, 1); 00625 graph.tryParameters(10, 1); 00626 optimalProfile = graph.giveOptimalProfileSize(); 00627 00628 timer.stopTimer(); 00629 00630 OOFEM_LOG_DEBUG( "Sloan's algorithm done in %.2fs\n", timer.getUtime() ); 00631 OOFEM_LOG_DEBUG("Nominal profile %d (old) %d (new)\n", initialProfile, optimalProfile); 00632 00633 //FILE* renTableFile = fopen ("rentab.dat","w"); 00634 //graph.writeOptimalRenumberingTable (renTableFile); 00635 graph.askNewOptimalNumbering(currStep); 00636 } 00637 00638 return domainNeqs.at(id); 00639 } 00640 00641 00642 int 00643 EngngModel :: forceEquationNumbering() 00644 { 00645 // set numberOfEquations counter to zero 00646 this->numberOfEquations = 0; 00647 this->numberOfPrescribedEquations = 0; 00648 00649 OOFEM_LOG_DEBUG("Renumbering dofs in all domains\n"); 00650 for ( int i = 1; i <= this->ndomains; i++ ) { 00651 domainNeqs.at(i) = 0; 00652 this->numberOfEquations += this->forceEquationNumbering(i); 00653 } 00654 00655 equationNumberingCompleted = 1; 00656 00657 for ( int i = 1; i <= this->ndomains; i++ ) { 00658 //this->numberOfPrescribedEquations+=giveNumberOfPrescribedDomainEquations(i); 00659 this->numberOfPrescribedEquations += domainPrescribedNeqs.at(i); 00660 } 00661 00662 #ifdef __PETSC_MODULE 00663 for ( int i = 1; i <= petscContextList->giveSize(); i++ ) { 00664 this->petscContextList->at(i)->init(i); 00665 } 00666 00667 #endif 00668 00669 00670 return this->numberOfEquations; 00671 } 00672 00673 00674 void 00675 EngngModel :: solveYourself() 00676 { 00677 int nTimeSteps; 00678 int smstep = 1, sjstep = 1; 00679 MetaStep *activeMStep; 00680 FILE *out = this->giveOutputStream(); 00681 00682 this->timer.startTimer(EngngModelTimer :: EMTT_AnalysisTimer); 00683 00684 if ( this->currentStep ) { 00685 smstep = this->currentStep->giveMetaStepNumber(); 00686 sjstep = this->giveMetaStep(smstep)->giveStepRelativeNumber( this->currentStep->giveNumber() ) + 1; 00687 } 00688 00689 for ( int imstep = smstep; imstep <= nMetaSteps; imstep++, sjstep = 1 ) { //loop over meta steps 00690 activeMStep = this->giveMetaStep(imstep); 00691 // update state according to new meta step 00692 this->initMetaStepAttributes(activeMStep); 00693 00694 nTimeSteps = activeMStep->giveNumberOfSteps(); 00695 for ( int jstep = sjstep; jstep <= nTimeSteps; jstep++ ) { //loop over time steps 00696 this->timer.startTimer(EngngModelTimer :: EMTT_SolutionStepTimer); 00697 this->timer.initTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 00698 00699 this->giveNextStep(); 00700 00701 // renumber equations if necessary. Ensure to call forceEquationNumbering() for staggered problems 00702 if ( this->requiresEquationRenumbering( this->giveCurrentStep() ) ) { 00703 this->forceEquationNumbering(); 00704 } 00705 00706 this->solveYourselfAt( this->giveCurrentStep() ); 00707 this->updateYourself( this->giveCurrentStep() ); 00708 this->terminate( this->giveCurrentStep() ); 00709 00710 00711 this->timer.stopTimer(EngngModelTimer :: EMTT_SolutionStepTimer); 00712 00713 double _steptime = this->timer.getUtime(EngngModelTimer :: EMTT_SolutionStepTimer); 00714 OOFEM_LOG_INFO("EngngModel info: user time consumed by solution step %d: %.2fs\n", 00715 this->giveCurrentStep()->giveNumber(), _steptime); 00716 00717 fprintf(out, "\nUser time consumed by solution step %d: %.3f [s]\n\n", 00718 this->giveCurrentStep()->giveNumber(), _steptime); 00719 00720 #ifdef __PARALLEL_MODE 00721 if ( loadBalancingFlag ) { 00722 this->balanceLoad( this->giveCurrentStep() ); 00723 } 00724 00725 #endif 00726 } 00727 } 00728 } 00729 00730 void 00731 EngngModel :: initMetaStepAttributes(MetaStep *mStep) 00732 { 00733 // update attributes 00734 this->updateAttributes(mStep); // virtual function 00735 // finish data acquiring 00736 mStep->giveAttributesRecord()->finish(); 00737 } 00738 00739 void 00740 EngngModel :: updateAttributes(MetaStep *mStep) 00741 { 00742 InputRecord *ir = mStep->giveAttributesRecord(); 00743 00744 if ( this->giveNumericalMethod(mStep) ) { 00745 this->giveNumericalMethod(mStep)->initializeFrom(ir); 00746 } 00747 00748 #ifdef __PARALLEL_MODE 00749 if ( this->giveLoadBalancer() ) { 00750 this->giveLoadBalancer()->initializeFrom(ir); 00751 } 00752 00753 if ( this->giveLoadBalancerMonitor() ) { 00754 this->giveLoadBalancerMonitor()->initializeFrom(ir); 00755 } 00756 00757 #endif 00758 } 00759 00760 00761 void 00762 EngngModel :: updateYourself(TimeStep *stepN) 00763 { 00764 int ndomains = this->giveNumberOfDomains(); 00765 int nnodes; 00766 Domain *domain; 00767 00768 for ( int idomain = 1; idomain <= ndomains; idomain++ ) { 00769 domain = this->giveDomain(idomain); 00770 00771 # ifdef VERBOSE 00772 VERBOSE_PRINT0( "Updating domain ", domain->giveNumber() ) 00773 # endif 00774 00775 nnodes = domain->giveNumberOfDofManagers(); 00776 for ( int j = 1; j <= nnodes; j++ ) { 00777 domain->giveDofManager(j)->updateYourself(stepN); 00778 } 00779 00780 # ifdef VERBOSE 00781 VERBOSE_PRINT0("Updated nodes ", nnodes) 00782 # endif 00783 00784 00785 int nelem = domain->giveNumberOfElements(); 00786 for ( int j = 1; j <= nelem; j++ ) { 00787 Element *elem = domain->giveElement(j); 00788 #ifdef __PARALLEL_MODE 00789 // skip remote elements (these are used as mirrors of remote elements on other domains 00790 // when nonlocal constitutive models are used. They introduction is necessary to 00791 // allow local averaging on domains without fine grain communication between domains). 00792 if ( elem->giveParallelMode() == Element_remote ) { 00793 continue; 00794 } 00795 00796 #endif 00797 elem->updateYourself(stepN); 00798 } 00799 00800 # ifdef VERBOSE 00801 VERBOSE_PRINT0("Updated Elements ", nelem) 00802 # endif 00803 00804 } 00805 00806 // if there is an error estimator, it should be updated so that values can be exported. 00807 if ( this->defaultErrEstimator ) { 00808 this->defaultErrEstimator->estimateError(equilibratedEM, stepN); 00809 } 00810 } 00811 00812 void 00813 EngngModel :: terminate(TimeStep *stepN) 00814 { 00815 this->doStepOutput(stepN); 00816 fflush( this->giveOutputStream() ); 00817 this->saveStepContext(stepN); 00818 } 00819 00820 00821 void 00822 EngngModel :: doStepOutput(TimeStep *stepN) 00823 { 00824 FILE *File = this->giveOutputStream(); 00825 00826 // print output 00827 this->printOutputAt(File, stepN); 00828 // export using export manager 00829 exportModuleManager->doOutput(stepN); 00830 } 00831 00832 void 00833 EngngModel :: saveStepContext(TimeStep *stepN) 00834 { 00835 // save context if required 00836 // default - save only if ALWAYS is set ( see cltypes.h ) 00837 00838 if ( ( this->giveContextOutputMode() == COM_Always ) || 00839 ( this->giveContextOutputMode() == COM_Required ) ) { 00840 this->saveContext(NULL, CM_State); 00841 } else if ( this->giveContextOutputMode() == COM_UserDefined ) { 00842 if ( stepN->giveNumber() % this->giveContextOutputStep() == 0 ) { 00843 this->saveContext(NULL, CM_State); 00844 } 00845 } 00846 } 00847 00848 00849 void 00850 EngngModel :: printOutputAt(FILE *File, TimeStep *stepN) 00851 { 00852 //FILE* File = this -> giveDomain() -> giveOutputStream() ; 00853 int domCount = 0; 00854 Domain *domain; 00855 00856 // fprintf (File,"\nOutput for time step number %d \n\n",stepN->giveNumber()); 00857 for ( int idomain = 1; idomain <= this->ndomains; idomain++ ) { 00858 domain = this->giveDomain(idomain); 00859 domCount += domain->giveOutputManager()->testTimeStepOutput(stepN); 00860 } 00861 00862 if ( domCount == 0 ) { 00863 return; // do not print even Solution step header 00864 } 00865 00866 fprintf(File, "\n=============================================================="); 00867 fprintf( File, "\nOutput for time % .8e ", stepN->giveTargetTime() * this->giveVariableScale(VST_Time) ); 00868 fprintf(File, "\n==============================================================\n"); 00869 for ( int idomain = 1; idomain <= this->ndomains; idomain++ ) { 00870 domain = this->giveDomain(idomain); 00871 fprintf( File, "Output for domain %3d\n", domain->giveNumber() ); 00872 00873 domain->giveOutputManager()->doDofManOutput(File, stepN); 00874 domain->giveOutputManager()->doElementOutput(File, stepN); 00875 } 00876 } 00877 00878 void EngngModel :: printYourself() 00879 { 00880 printf( "\nEngineeringModel: instance %s\n", this->giveClassName() ); 00881 printf( "number of steps: %d\n", this->giveNumberOfSteps() ); 00882 printf("number of eq's : %d\n", numberOfEquations); 00883 } 00884 00885 void EngngModel :: assemble(SparseMtrx *answer, TimeStep *tStep, EquationID eid, 00886 CharType type, const UnknownNumberingScheme &s, Domain *domain) 00887 // 00888 // assembles matrix 00889 // 00890 { 00891 IntArray loc; 00892 FloatMatrix mat, R; 00893 Element *element; 00894 00895 if ( answer == NULL ) { 00896 _error("assemble: NULL pointer encountered."); 00897 } 00898 00899 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 00900 int nelem = domain->giveNumberOfElements(); 00901 #ifdef _OPENMP 00902 #pragma omp parallel for private(element, mat, R, loc) 00903 #endif 00904 for ( int ielem = 1; ielem <= nelem; ielem++ ) { 00905 element = domain->giveElement(ielem); 00906 #ifdef __PARALLEL_MODE 00907 // skip remote elements (these are used as mirrors of remote elements on other domains 00908 // when nonlocal constitutive models are used. They introduction is necessary to 00909 // allow local averaging on domains without fine grain communication between domains). 00910 if ( element->giveParallelMode() == Element_remote ) { 00911 continue; 00912 } 00913 00914 #endif 00915 if ( !element->isActivated(tStep) ) { 00916 continue; 00917 } 00918 00919 this->giveElementCharacteristicMatrix(mat, ielem, type, tStep, domain); 00920 00921 if ( mat.isNotEmpty() ) { 00922 element->giveLocationArray(loc, eid, s); 00923 if ( element->giveRotationMatrix(R, eid) ) { 00924 mat.rotatedWith(R); 00925 } 00926 00927 #ifdef _OPENMP 00928 #pragma omp critical 00929 #endif 00930 if ( answer->assemble(loc, mat) == 0 ) { 00931 _error("assemble: sparse matrix assemble error"); 00932 } 00933 } 00934 } 00935 00936 int nbc = domain->giveNumberOfBoundaryConditions(); 00937 for ( int i = 1; i <= nbc; ++i ) { 00938 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) ); 00939 if ( bc != NULL ) { 00940 bc->assemble(answer, tStep, eid, type, s, s, domain); 00941 } 00942 } 00943 00944 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 00945 00946 answer->assembleBegin(); 00947 answer->assembleEnd(); 00948 } 00949 00950 void EngngModel :: assemble(SparseMtrx *answer, TimeStep *tStep, EquationID r_id, EquationID c_id, 00951 CharType type, const UnknownNumberingScheme &ns, 00952 Domain *domain) 00953 // 00954 // assembles matrix 00955 // 00956 { 00957 IntArray r_loc, c_loc; 00958 FloatMatrix mat, Rr, Rc; 00959 Element *element; 00960 00961 if ( answer == NULL ) { 00962 _error("assemble: NULL pointer encountered."); 00963 } 00964 00965 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 00966 int nelem = domain->giveNumberOfElements(); 00967 #ifdef _OPENMP 00968 #pragma omp parallel for private(element, mat, Rr, Rc, r_loc, c_loc) 00969 #endif 00970 for ( int ielem = 1; ielem <= nelem; ielem++ ) { 00971 element = domain->giveElement(ielem); 00972 #ifdef __PARALLEL_MODE 00973 // skip remote elements (these are used as mirrors of remote elements on other domains 00974 // when nonlocal constitutive models are used. They introduction is necessary to 00975 // allow local averaging on domains without fine grain communication between domains). 00976 if ( element->giveParallelMode() == Element_remote ) { 00977 continue; 00978 } 00979 00980 #endif 00981 if ( !element->isActivated(tStep) ) { 00982 continue; 00983 } 00984 00985 this->giveElementCharacteristicMatrix(mat, ielem, type, tStep, domain); 00986 00987 if ( mat.isNotEmpty() ) { 00988 element->giveLocationArray(r_loc, r_id, ns); 00989 element->giveLocationArray(c_loc, c_id, ns); 00990 // Rotate it 00991 if ( element->giveRotationMatrix(Rr, r_id) ) { 00992 FloatMatrix tmpMat; 00993 tmpMat.beTProductOf(Rr, mat); 00994 mat = tmpMat; 00995 } 00996 00997 if ( element->giveRotationMatrix(Rc, c_id) ) { 00998 FloatMatrix tmpMat; 00999 tmpMat.beProductOf(mat, Rc); 01000 mat = tmpMat; 01001 } 01002 01003 #ifdef _OPENMP 01004 #pragma omp critical 01005 #endif 01006 if ( answer->assemble(r_loc, c_loc, mat) == 0 ) { 01007 _error("assemble: sparse matrix assemble error"); 01008 } 01009 } 01010 } 01011 01013 01014 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01015 01016 answer->assembleBegin(); 01017 answer->assembleEnd(); 01018 } 01019 01020 void EngngModel :: assemble(SparseMtrx *answer, TimeStep *tStep, EquationID eid, 01021 CharType type, const UnknownNumberingScheme &rs, const UnknownNumberingScheme &cs, 01022 Domain *domain) 01023 // Same as assemble, but with different numbering for rows and columns 01024 { 01025 IntArray r_loc, c_loc; 01026 FloatMatrix mat, R; 01027 Element *element; 01028 if ( answer == NULL ) { 01029 OOFEM_ERROR("EngngModel :: assemble: NULL pointer encountered."); 01030 } 01031 01032 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01033 int nelem = domain->giveNumberOfElements(); 01034 #ifdef _OPENMP 01035 #pragma omp parallel for private(element, mat, R, r_loc, c_loc) 01036 #endif 01037 for ( int ielem = 1; ielem <= nelem; ielem++ ) { 01038 element = domain->giveElement(ielem); 01039 #ifdef __PARALLEL_MODE 01040 if ( element->giveParallelMode() == Element_remote ) { 01041 continue; 01042 } 01043 01044 #endif 01045 if ( !element->isActivated(tStep) ) { 01046 continue; 01047 } 01048 01049 this->giveElementCharacteristicMatrix(mat, ielem, type, tStep, domain); 01050 if ( mat.isNotEmpty() ) { 01051 element->giveLocationArray(r_loc, eid, rs); 01052 element->giveLocationArray(c_loc, eid, cs); 01053 // Rotate it 01054 if ( element->giveRotationMatrix(R, eid) ) { 01055 mat.rotatedWith(R); 01056 } 01057 01058 #ifdef _OPENMP 01059 #pragma omp critical 01060 #endif 01061 if ( answer->assemble(r_loc, c_loc, mat) == 0 ) { 01062 OOFEM_ERROR("EngngModel :: assemble: sparse matrix assemble error"); 01063 } 01064 } 01065 } 01066 01067 int nbc = domain->giveNumberOfBoundaryConditions(); 01068 for ( int i = 1; i <= nbc; ++i ) { 01069 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) ); 01070 if ( bc != NULL ) { 01071 bc->assemble(answer, tStep, eid, type, rs, cs, domain); 01072 } 01073 } 01074 01075 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01076 01077 answer->assembleBegin(); 01078 answer->assembleEnd(); 01079 } 01080 01081 01082 double EngngModel :: assembleVector(FloatArray &answer, TimeStep *tStep, EquationID eid, 01083 CharType type, ValueModeType mode, 01084 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) 01085 { 01086 double norm = 0.0; 01087 if ( eNorms ) { 01088 eNorms->resize( domain->giveMaxDofID() ); 01089 eNorms->zero(); 01090 } 01091 01092 norm += this->assembleVectorFromDofManagers(answer, tStep, eid, type, mode, s, domain, eNorms); 01093 norm += this->assembleVectorFromElements(answer, tStep, eid, type, mode, s, domain, eNorms); 01094 norm += this->assembleVectorFromActiveBC(answer, tStep, eid, type, mode, s, domain, eNorms); 01095 01096 // Collect over mpi; 01097 #ifdef __PARALLEL_MODE 01098 if ( this->isParallel() ) { 01099 #ifdef __PETSC_MODULE 01100 norm = this->givePetscContext(domain->giveNumber(), eid)->accumulate(norm); 01101 #else 01102 double localNorm = norm; 01103 MPI_Allreduce(& localNorm, & norm, 1, MPI_DOUBLE, MPI_SUM, comm); 01104 #endif 01105 if ( eNorms ) { 01106 FloatArray localENorms = *eNorms; 01107 #ifdef __PETSC_MODULE 01108 this->givePetscContext(domain->giveNumber(), eid)->accumulate(localENorms, *eNorms); 01109 #else 01110 MPI_Allreduce(localENorms.givePointer(), eNorms.givePointer(), eNorms.giveSize(), MPI_DOUBLE, MPI_SUM, comm); 01111 #endif 01112 } 01113 } 01114 #endif 01115 return norm; 01116 } 01117 01118 01119 double EngngModel :: assembleVectorFromDofManagers(FloatArray &answer, TimeStep *tStep, EquationID eid, 01120 CharType type, ValueModeType mode, 01121 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) 01122 // 01123 // assembles matrix answer by calling 01124 // node(i) -> computeLoadVectorAt (tStep); 01125 // for each dof manager in domain 01126 // and assembling every contribution to answer 01127 // 01128 { 01129 if ( type != ExternalForcesVector ) { // Dof managers can only have external loads. 01130 return 0.0; 01131 } 01132 01133 IntArray loc, dofids; 01134 FloatArray charVec; 01135 FloatMatrix R; 01136 IntArray dofIDarry(0); 01137 DofManager *node; 01138 double norm = 0.0; 01139 int nnode = domain->giveNumberOfDofManagers(); 01140 01141 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01142 // Note! For normal master dofs, loc is unique to each node, but there can be slave dofs, so we must keep it shared, unfortunately. 01143 #ifdef _OPENMP 01144 #pragma omp parallel for shared(answer, eNorms) private(node, R, charVec, loc, dofids) reduction(+:norm) 01145 #endif 01146 for ( int i = 1; i <= nnode; i++ ) { 01147 node = domain->giveDofManager(i); 01148 node->computeLoadVectorAt(charVec, tStep, mode); 01149 #ifdef __PARALLEL_MODE 01150 if ( node->giveParallelMode() == DofManager_shared ) { 01151 charVec.times( 1. / ( node->givePartitionsConnectivitySize() ) ); 01152 } 01153 01154 #endif 01155 if ( charVec.isNotEmpty() ) { 01156 node->giveCompleteLocationArray(loc, s); 01157 if ( node->computeM2LTransformation(R, dofIDarry) ) { 01158 charVec.rotatedWith(R, 't'); 01159 } 01160 01161 answer.assemble(charVec, loc); 01162 01163 if ( eNorms ) { 01164 node->giveCompleteMasterDofIDArray(dofids); 01165 for ( int i = 1; i <= dofids.giveSize(); ++i ) { 01166 eNorms->at(dofids.at(i)) += charVec.at(i) * charVec.at(i); 01167 } 01168 } 01169 norm += charVec.computeSquaredNorm(); 01170 } 01171 } 01172 01173 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01174 return norm; 01175 } 01176 01177 01178 double EngngModel :: assembleVectorFromActiveBC(FloatArray &answer, TimeStep *tStep, EquationID eid, 01179 CharType type, ValueModeType mode, 01180 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) 01181 { 01182 double norm = 0.0; 01183 int nbc = domain->giveNumberOfBoundaryConditions(); 01184 01185 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01186 for ( int i = 1; i <= nbc; ++i ) { 01187 ActiveBoundaryCondition *bc = dynamic_cast< ActiveBoundaryCondition * >( domain->giveBc(i) ); 01188 if ( bc != NULL ) { 01189 norm += bc->assembleVector(answer, tStep, eid, type, mode, s, domain, eNorms); 01190 } 01191 } 01192 01193 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01194 return norm; 01195 } 01196 01197 01198 double EngngModel :: assembleVectorFromElements(FloatArray &answer, TimeStep *tStep, EquationID eid, 01199 CharType type, ValueModeType mode, 01200 const UnknownNumberingScheme &s, Domain *domain, FloatArray *eNorms) 01201 // 01202 // for each element in domain 01203 // and assembling every contribution to answer 01204 // 01205 { 01206 IntArray loc, dofids; 01207 FloatMatrix R; 01208 FloatArray charVec; 01209 Element *element; 01210 double norm = 0.0; 01211 int nelem = domain->giveNumberOfElements(); 01212 01213 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01215 #ifdef _OPENMP 01216 #pragma omp parallel for shared(answer, eNorms) private(element, R, charVec, loc, dofids) reduction(+:norm) 01217 #endif 01218 for ( int i = 1; i <= nelem; i++ ) { 01219 element = domain->giveElement(i); 01220 #ifdef __PARALLEL_MODE 01221 // skip remote elements (these are used as mirrors of remote elements on other domains 01222 // when nonlocal constitutive models are used. They introduction is necessary to 01223 // allow local averaging on domains without fine grain communication between domains). 01224 if ( element->giveParallelMode() == Element_remote ) { 01225 continue; 01226 } 01227 01228 #endif 01229 if ( !element->isActivated(tStep) ) { 01230 continue; 01231 } 01232 01233 element->giveLocationArray(loc, eid, s, &dofids); 01234 this->giveElementCharacteristicVector(charVec, i, type, mode, tStep, domain); 01235 if ( charVec.isNotEmpty() ) { 01236 if ( element->giveRotationMatrix(R, eid) ) { 01237 charVec.rotatedWith(R, 't'); 01238 } 01239 01240 answer.assemble(charVec, loc); 01241 01242 if ( eNorms ) { 01243 for ( int i = 1; i <= dofids.giveSize(); ++i ) { 01244 eNorms->at(dofids.at(i)) += charVec.at(i) * charVec.at(i); 01245 } 01246 } 01247 norm += charVec.computeSquaredNorm(); 01248 } 01249 } 01250 01251 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01252 return norm; 01253 } 01254 01255 01256 void 01257 EngngModel :: assembleExtrapolatedForces(FloatArray &answer, TimeStep *tStep, EquationID eid, CharType type, Domain *domain) 01258 { 01259 // Simply assembles contributions from each element in domain 01260 Element *element; 01261 IntArray loc; 01262 FloatArray charVec, delta_u; 01263 FloatMatrix charMatrix; 01264 int nelems; 01265 EModelDefaultEquationNumbering dn; 01266 01267 answer.resize( this->giveNumberOfEquations(eid) ); 01268 answer.zero(); 01269 01270 nelems = domain->giveNumberOfElements(); 01271 this->timer.resumeTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01272 01273 for ( int i = 1; i <= nelems; i++ ) { 01274 element = domain->giveElement(i); 01275 #ifdef __PARALLEL_MODE 01276 // Skip remote elements (these are used as mirrors of remote elements on other domains 01277 // when nonlocal constitutive models are used. Their introduction is necessary to 01278 // allow local averaging on domains without fine grain communication between domains). 01279 if ( element->giveParallelMode() == Element_remote ) { 01280 continue; 01281 } 01282 01283 #endif 01284 if ( !element->isActivated(tStep) ) { 01285 continue; 01286 } 01287 01288 element->giveLocationArray(loc, eid, dn); 01289 01290 // Take the tangent from the previous step 01293 element->giveCharacteristicMatrix(charMatrix, type, tStep); 01294 element->computeVectorOf(eid, VM_Incremental, tStep, delta_u); 01295 charVec.beProductOf(charMatrix, delta_u); 01296 01298 01299 answer.assemble(charVec, loc); 01300 } 01301 01302 this->timer.pauseTimer(EngngModelTimer :: EMTT_NetComputationalStepTimer); 01303 } 01304 01305 01306 void 01307 EngngModel :: giveElementCharacteristicMatrix(FloatMatrix &answer, int num, CharType type, TimeStep *tStep, Domain *domain) 01308 { 01309 domain->giveElement(num)->giveCharacteristicMatrix(answer, type, tStep); 01310 } 01311 01312 01313 void 01314 EngngModel :: giveElementCharacteristicVector(FloatArray &answer, int num, CharType type, ValueModeType mode, TimeStep *tStep, Domain *domain) 01315 { 01316 domain->giveElement(num)->giveCharacteristicVector(answer, type, mode, tStep); 01317 } 01318 01319 01320 void 01321 EngngModel :: updateComponent(TimeStep *tStep, NumericalCmpn cmpn, Domain *d) 01322 // 01323 // updates some component, which is used by numerical method 01324 // to newly reached state 01325 // 01326 { 01327 _error("updateComponent: Unknown Type of component."); 01328 } 01329 01330 01331 void 01332 EngngModel :: initStepIncrements() 01333 // 01334 // resets all temp data in elements and their gps so only 01335 // non temp variables remain. 01336 // this function can be used if called before this->terminate() 01337 // for current step restart, because it causes complete reset 01338 // of temp variables. 01339 // 01340 { 01341 Element *elem; 01342 Domain *domain; 01343 01344 for ( int idomain = 1; idomain <= this->ndomains; idomain++ ) { 01345 domain = this->giveDomain(idomain); 01346 01347 int nelem = domain->giveNumberOfElements(); 01348 for ( int j = 1; j <= nelem; j++ ) { 01349 elem = domain->giveElement(j); 01350 #ifdef __PARALLEL_MODE 01351 // skip remote elements (these are used as mirrors of remote elements on other domains 01352 // when nonlocal constitutive models are used. They introduction is necessary to 01353 // allow local averaging on domains without fine grain communication between domains). 01354 if ( elem->giveParallelMode() == Element_remote ) { 01355 continue; 01356 } 01357 01358 #endif 01359 elem->initForNewStep(); 01360 } 01361 } 01362 } 01363 01364 01365 void 01366 EngngModel :: updateDomainLinks() 01367 { 01368 this->giveExportModuleManager()->initialize(); 01369 }; 01370 01371 01372 contextIOResultType EngngModel :: saveContext(DataStream *stream, ContextMode mode, void *obj) 01373 // 01374 // this procedure is used mainly for two reasons: 01375 // 01376 // - to save context of current model in order to be able to backtrace 01377 // computational history (useful in nonlinear analysis, when you want 01378 // explore another, previously detected load path 01379 // 01380 // - to save context of current model in order to enable 01381 // possibility of post-processing. 01382 // 01383 // saving context means: (if needed may be enhanced) 01384 // 01385 // - save EngngModel state varialbles as displacement, velocity, .. vectors 01386 // - save Elements stress, strain and material history. 01387 // 01388 // This version saves only Element and Material properties. 01389 // 01390 { 01391 contextIOResultType iores; 01392 int closeFlag = 0; 01393 FILE *file; 01394 01395 01396 OOFEM_LOG_INFO("Storing context\n"); 01397 if ( stream == NULL ) { 01398 if ( !this->giveContextFile(& file, this->giveCurrentStep()->giveNumber(), 01399 this->giveCurrentStep()->giveVersion(), contextMode_write) ) { 01400 THROW_CIOERR(CIO_IOERR); // override 01401 } 01402 01403 stream = new FileDataStream(file); 01404 closeFlag = 1; 01405 } 01406 01407 // store solution step 01408 if ( ( iores = giveCurrentStep()->saveContext(stream, mode) ) != CIO_OK ) { 01409 THROW_CIOERR(iores); 01410 } 01411 01412 // store numberOfEquations and domainNeqs array 01413 if ( !stream->write(& numberOfEquations, 1) ) { 01414 THROW_CIOERR(CIO_IOERR); 01415 } 01416 01417 if ( ( iores = domainNeqs.storeYourself(stream, mode) ) != CIO_OK ) { 01418 THROW_CIOERR(iores); 01419 } 01420 01421 // store numberOfPrescribedEquations and domainNeqs array 01422 if ( !stream->write(& numberOfPrescribedEquations, 1) ) { 01423 THROW_CIOERR(CIO_IOERR); 01424 } 01425 01426 if ( ( iores = domainPrescribedNeqs.storeYourself(stream, mode) ) != CIO_OK ) { 01427 THROW_CIOERR(iores); 01428 } 01429 01430 // store renumber flag 01431 if ( !stream->write(& renumberFlag, 1) ) { 01432 THROW_CIOERR(CIO_IOERR); 01433 } 01434 01435 01436 for ( int idomain = 1; idomain <= this->ndomains; idomain++ ) { 01437 this->giveDomain(idomain)->saveContext(stream, mode, obj); 01438 } 01439 01440 01441 // store nMethod 01442 NumericalMethod *nmethod = this->giveNumericalMethod( this->giveMetaStep( giveCurrentStep()->giveMetaStepNumber() ) ); 01443 if ( nmethod ) { 01444 if ( ( iores = nmethod->saveContext(stream, mode) ) != CIO_OK ) { 01445 THROW_CIOERR(iores); 01446 } 01447 } 01448 01449 01450 if ( closeFlag ) { 01451 fclose(file); 01452 delete(stream); 01453 stream = NULL; 01454 } // ensure consistent records 01455 01456 return CIO_OK; 01457 } 01458 01459 01460 contextIOResultType EngngModel :: restoreContext(DataStream *stream, ContextMode mode, void *obj) 01461 // 01462 // this procedure is used mainly for two reasons: 01463 // 01464 // - to restore context of current model in order to be able to backtrace 01465 // computational history (useful in nonlinear analysis, when you want 01466 // explore another, previously detected load path 01467 // 01468 // - to restore context of current model in order to enable 01469 // possibility of post-processing. 01470 // 01471 // restoring context means: (if needed may be enhanced) 01472 // 01473 // - rest. EngngModel state varialbles as displacement, velocity, .. vectors 01474 // - rest. Elements stress, strain and material history. 01475 // 01476 // This version loads only Element and Material properties. 01477 // 01478 // This function is inverse to the saveContext() member function 01479 // 01480 // WARNING obj is cast into int pointer to time step for which to seek Context. 01481 // 01482 { 01483 contextIOResultType iores; 01484 int closeFlag = 0, istep, iversion; 01485 Domain *domain; 01486 FILE *file; 01487 01488 this->resolveCorrespondingStepNumber(istep, iversion, obj); 01489 OOFEM_LOG_RELEVANT("Restoring context for time step %d.%d\n", istep, iversion); 01490 01491 if ( stream == NULL ) { 01492 if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { 01493 THROW_CIOERR(CIO_IOERR); // override 01494 } 01495 01496 stream = new FileDataStream(file); 01497 closeFlag = 1; 01498 } 01499 01500 // restore solution step 01501 if ( currentStep == NULL ) { 01502 currentStep = new TimeStep(istep, this, 0, 0., 0., 0); 01503 } 01504 01505 if ( ( iores = currentStep->restoreContext(stream, mode) ) != CIO_OK ) { 01506 THROW_CIOERR(iores); 01507 } 01508 01509 // this->updateAttributes (currentStep); 01510 01511 int pmstep = currentStep->giveMetaStepNumber(); 01512 if ( nMetaSteps ) { 01513 if ( !this->giveMetaStep(pmstep)->isStepValid(istep - 1) ) { 01514 pmstep--; 01515 } 01516 } 01517 01518 if ( previousStep ) { 01519 delete previousStep; 01520 } 01521 01522 previousStep = new TimeStep(istep - 1, this, pmstep, currentStep->giveTargetTime() - currentStep->giveTimeIncrement(), 01523 currentStep->giveTimeIncrement(), currentStep->giveSolutionStateCounter() - 1); 01524 01525 // restore numberOfEquations and domainNeqs array 01526 if ( !stream->read(& numberOfEquations, 1) ) { 01527 THROW_CIOERR(CIO_IOERR); 01528 } 01529 01530 if ( ( iores = domainNeqs.restoreYourself(stream, mode) ) != CIO_OK ) { 01531 THROW_CIOERR(iores); 01532 } 01533 01534 // restore numberOfPrescribedEquations and domainNeqs array 01535 if ( !stream->read(& numberOfPrescribedEquations, 1) ) { 01536 THROW_CIOERR(CIO_IOERR); 01537 } 01538 01539 if ( ( iores = domainPrescribedNeqs.restoreYourself(stream, mode) ) != CIO_OK ) { 01540 THROW_CIOERR(iores); 01541 } 01542 01543 // restore renumber flag 01544 if ( !stream->read(& renumberFlag, 1) ) { 01545 THROW_CIOERR(CIO_IOERR); 01546 } 01547 01548 for ( int idomain = 1; idomain <= this->ndomains; idomain++ ) { 01549 domain = this->giveDomain(idomain); 01550 domain->restoreContext(stream, mode, obj); 01551 } 01552 01553 // restore nMethod 01554 NumericalMethod *nmethod = this->giveNumericalMethod( this->giveCurrentMetaStep() ); 01555 if ( nmethod ) { 01556 if ( ( iores = nmethod->restoreContext(stream, mode) ) != CIO_OK ) { 01557 THROW_CIOERR(iores); 01558 } 01559 } 01560 01561 this->updateDomainLinks(); 01562 this->updateAttributes( this->giveCurrentMetaStep() ); 01563 this->initStepIncrements(); 01564 01565 if ( closeFlag ) { 01566 fclose(file); 01567 delete stream; 01568 stream = NULL; 01569 } // ensure consistent records 01570 01571 return CIO_OK; 01572 } 01573 01574 01575 void 01576 EngngModel :: resolveCorrespondingStepNumber(int &istep, int &iversion, void *obj) 01577 { 01578 // 01579 // returns corresponding step number 01580 // 01581 if ( obj == NULL ) { 01582 istep = 1; 01583 iversion = 0; 01584 return; 01585 } 01586 01587 istep = * ( int * ) obj; 01588 iversion = * ( ( ( int * ) obj ) + 1 ); 01589 01590 if ( istep > this->giveNumberOfSteps() ) { 01591 istep = this->giveNumberOfSteps(); 01592 } 01593 01594 if ( istep <= 0 ) { 01595 istep = 1; 01596 } 01597 } 01598 01599 01600 MetaStep * 01601 EngngModel :: giveCurrentMetaStep() 01602 { 01603 return this->giveMetaStep( this->giveCurrentStep()->giveMetaStepNumber() ); 01604 } 01605 01606 01607 int 01608 EngngModel :: giveContextFile(FILE **contextFile, int stepNumber, int stepVersion, ContextFileMode cmode, int errLevel) 01609 // 01610 // 01611 // assigns context file of given step number to stream 01612 // returns nonzero on success 01613 // 01614 { 01615 std :: string fname = this->coreOutputFileName; 01616 char fext [ 100 ]; 01617 sprintf(fext, ".%d.%d.osf", stepNumber, stepVersion); 01618 fname += fext; 01619 01620 if ( cmode == contextMode_read ) { 01621 * contextFile = fopen(fname.c_str(), "rb"); // open for reading 01622 } else { 01623 * contextFile = fopen(fname.c_str(), "wb"); // open for writing, 01624 } 01625 01626 // rewind (*contextFile); // seek the beginning 01627 // // overwrite if exist 01628 // else *contextFile = fopen(fname,"r+"); // open for reading and writing 01629 01630 if ( ( * contextFile == NULL ) && errLevel > 0 ) { 01631 _error2( "giveContextFile : can't open %s", fname.c_str() ); 01632 } 01633 01634 return 1; 01635 } 01636 01637 bool 01638 EngngModel :: testContextFile(int stepNumber, int stepVersion) 01639 { 01640 std :: string fname = this->coreOutputFileName; 01641 char fext [ 100 ]; 01642 sprintf(fext, ".%d.%d.osf", stepNumber, stepVersion); 01643 fname.append(fext); 01644 01645 #ifdef HAVE_ACCESS 01646 return access(fname.c_str(), R_OK) == 0; 01647 01648 #elif _MSC_VER 01649 return _access(fname.c_str(), 4) == 0; 01650 01651 #else 01652 return true; 01653 01654 #endif 01655 } 01656 01657 DataReader * 01658 EngngModel :: GiveDomainDataReader(int domainNum, int domainSerNum, ContextFileMode cmode) 01659 // 01660 // 01661 // returns domain i/o file 01662 // returns nonzero on success 01663 // 01664 { 01665 std :: string fname = this->coreOutputFileName; 01666 char fext [ 100 ]; 01667 sprintf(fext, ".domain.%d.%d.din", domainNum, domainSerNum); 01668 fname += fext; 01669 01670 DataReader *dr; 01671 01672 if ( ( dr = new OOFEMTXTDataReader( fname.c_str() ) ) == NULL ) { 01673 _error("Creation of DataReader failed"); 01674 } 01675 01676 return dr; 01677 } 01678 01679 void 01680 EngngModel :: error(const char *file, int line, const char *format, ...) const 01681 { 01682 char buffer [ MAX_ERROR_MSG_LENGTH ]; 01683 va_list args; 01684 01685 va_start(args, format); 01686 vsprintf(buffer, format, args); 01687 va_end(args); 01688 #ifdef __PARALLEL_MODE 01689 __OOFEM_ERROR4(file, line, "Class: %s, Rank: %d\n%s", giveClassName(), rank, buffer); 01690 #else 01691 __OOFEM_ERROR3(file, line, "Class: %s\n%s", giveClassName(), buffer); 01692 #endif 01693 } 01694 01695 01696 void EngngModel :: warning(const char *file, int line, const char *format, ...) const 01697 // 01698 // this function handles error reporting 01699 // prints errorMsg enriched by ClasName and Number 01700 // to the standard error stream 01701 { 01702 char buffer [ MAX_ERROR_MSG_LENGTH ]; 01703 va_list args; 01704 01705 va_start(args, format); 01706 vsprintf(buffer, format, args); 01707 va_end(args); 01708 #ifdef __PARALLEL_MODE 01709 __OOFEM_WARNING4(file, line, "Class: %s, Rank: %d\n%s", giveClassName(), rank, buffer); 01710 #else 01711 __OOFEM_WARNING3(file, line, "Class: %s\n%s", giveClassName(), buffer); 01712 #endif 01713 } 01714 01715 Domain * 01716 EngngModel :: giveDomain(int i) 01717 { 01718 if ( ( i > 0 ) && ( i <= this->ndomains ) ) { 01719 return this->domainList->at(i); 01720 } else { 01721 _error("giveDomain: Undefined domain"); 01722 } 01723 01724 return NULL; 01725 } 01726 01727 void 01728 EngngModel :: setDomain(int i, Domain *ptr) 01729 { 01730 if ( ( i > 0 ) && ( i <= this->ndomains ) ) { 01731 this->domainList->put(i, ptr); 01732 } else { 01733 _error3("setDomain: Domain index %d out of range [1,%d]", i, this->ndomains); 01734 } 01735 } 01736 01737 01738 01739 XfemManager * 01740 EngngModel :: giveXfemManager(int i) 01741 { 01742 if ( xfemManagerList->includes(i) ) { 01743 return this->xfemManagerList->at(i); 01744 } else { 01745 _error2("giveXfemManager: undefined xfem manager (%d)", i); 01746 return NULL; // return NULL to prevent compiler warnings 01747 } 01748 } 01749 01750 bool 01751 EngngModel :: hasXfemManager(int i) 01752 { 01753 return xfemManagerList->includes(i); 01754 } 01755 01756 01757 #ifdef __PETSC_MODULE 01758 PetscContext * 01759 EngngModel :: givePetscContext(int i, EquationID eid) 01760 { 01761 if ( ( i > 0 ) && ( i <= this->ndomains ) ) { 01762 if ( i > petscContextList->giveSize() ) { 01763 _error("givePetscContext: petsc context not initialized for this problem"); 01764 } 01765 01766 return this->petscContextList->at(i); 01767 } else { 01768 _error2("givePetscContext: Undefined domain index %d ", i); 01769 } 01770 01771 return NULL; 01772 } 01773 01774 void 01775 EngngModel :: initPetscContexts() { } 01776 #endif 01777 01778 01779 01780 MetaStep * 01781 EngngModel :: giveMetaStep(int i) 01782 { 01783 if ( ( i > 0 ) && ( i <= this->nMetaSteps ) ) { 01784 return this->metaStepList->at(i); 01785 } else { 01786 _error2("giveMetaStep: undefined metaStep (%d)", i); 01787 } 01788 01789 return NULL; 01790 } 01791 01792 FILE * 01793 EngngModel :: giveOutputStream() 01794 // Returns an output stream on the data file of the receiver. 01795 { 01796 if ( !outputStream ) { 01797 #ifdef _WIN32 //_MSC_VER and __MINGW32__ included 01798 char *tmp = tmpnam(NULL); 01799 _warning2("giveOutputStream: using default output stream %s", tmp); 01800 outputStream = fopen(tmp, "w"); 01801 #else 01802 char sfn[] = "oofem.out.XXXXXX"; 01803 int fd = -1; 01804 FILE *sfp; 01805 01806 if ( ( fd = mkstemp(sfn) ) == -1 || 01807 ( sfp = fdopen(fd, "w+") ) == NULL ) { 01808 if ( fd != -1 ) { 01809 unlink(sfn); 01810 close(fd); 01811 } 01812 01813 OOFEM_ERROR2("Failed to create temporary file %s\n", sfn); 01814 return ( NULL ); 01815 } 01816 01817 outputStream = sfp; 01818 #endif 01819 } 01820 01821 return outputStream; 01822 } 01823 01824 void 01825 EngngModel :: terminateAnalysis() 01826 { 01827 double tsec; 01828 int nsec = 0, nmin = 0, nhrs = 0; 01829 FILE *out = this->giveOutputStream(); 01830 time_t endTime = time(NULL); 01831 this->timer.stopTimer(EngngModelTimer :: EMTT_AnalysisTimer); 01832 01833 01834 fprintf( out, "\nFinishing analysis on: %s\n", ctime(& endTime) ); 01835 // compute real time consumed 01836 tsec = this->timer.getWtime(EngngModelTimer :: EMTT_AnalysisTimer); 01837 this->timer.convert2HMS(nhrs, nmin, nsec, tsec); 01838 fprintf(out, "Real time consumed: %03dh:%02dm:%02ds\n", nhrs, nmin, nsec); 01839 LOG_FORCED_MSG(oofem_logger, "\n\nANALYSIS FINISHED\n\n\n"); 01840 LOG_FORCED_MSG(oofem_logger, "Real time consumed: %03dh:%02dm:%02ds\n", nhrs, nmin, nsec); 01841 // compute processor time used by the program 01842 // nsec = (endClock - startClock) / CLOCKS_PER_SEC; 01843 tsec = this->timer.getUtime(EngngModelTimer :: EMTT_AnalysisTimer); 01844 this->timer.convert2HMS(nhrs, nmin, nsec, tsec); 01845 fprintf(out, "User time consumed: %03dh:%02dm:%02ds\n\n\n", nhrs, nmin, nsec); 01846 LOG_FORCED_MSG(oofem_logger, "User time consumed: %03dh:%02dm:%02ds\n", nhrs, nmin, nsec); 01847 exportModuleManager->terminate(); 01848 } 01849 01850 int 01851 EngngModel :: checkProblemConsistency() 01852 { 01853 int result = 1; 01854 01855 result &= this->checkConsistency(); 01856 01857 int ndomains = this->giveNumberOfDomains(); 01858 for ( int i = 1; i <= ndomains; i++ ) { 01859 result &= this->giveDomain(i)->checkConsistency(); 01860 } 01861 01862 # ifdef VERBOSE 01863 if ( result ) { 01864 OOFEM_LOG_DEBUG("Consistency check: OK\n"); 01865 } else { 01866 VERBOSE_PRINTS("Consistency check", "failed") 01867 exit(1); 01868 } 01869 01870 # endif 01871 01872 return result; 01873 } 01874 01875 01876 void 01877 EngngModel :: init() 01878 { 01879 initModuleManager->doInit(); 01880 } 01881 01882 01883 #ifdef __PARALLEL_MODE 01884 void 01885 EngngModel :: initParallel() 01886 { 01887 #ifdef __USE_MPI 01888 int len; 01889 MPI_Get_processor_name(processor_name, & len); 01890 MPI_Comm_rank(MPI_COMM_WORLD, & this->rank); 01891 MPI_Comm_size(MPI_COMM_WORLD, & numProcs); 01892 #endif 01893 #ifdef __VERBOSE_PARALLEL 01894 OOFEM_LOG_RELEVANT("[%d/%d] Running on %s\n", rank, numProcs, processor_name); 01895 #endif 01896 } 01897 01898 #endif 01899 01900 #ifdef __OOFEG 01901 void EngngModel :: drawYourself(oofegGraphicContext &context) { 01902 this->giveDomain( context.getActiveDomain() )->drawYourself(context); 01903 } 01904 01905 void EngngModel :: drawElements(oofegGraphicContext &context) { 01906 this->giveDomain( context.getActiveDomain() )->drawElements(context); 01907 } 01908 01909 void EngngModel :: drawNodes(oofegGraphicContext &context) { 01910 this->giveDomain( context.getActiveDomain() )->drawNodes(context); 01911 } 01912 01913 #endif 01914 01915 01916 #ifdef __PARALLEL_MODE 01917 void 01918 EngngModel :: balanceLoad(TimeStep *atTime) 01919 { 01920 LoadBalancerMonitor :: LoadBalancerDecisionType _d; 01921 this->giveLoadBalancerMonitor(); 01922 this->giveLoadBalancer(); 01923 EModelDefaultEquationNumbering dn; 01924 01925 //print statistics for current step 01926 lb->printStatistics(); 01927 01928 if ( atTime->isNotTheLastStep() ) { 01929 _d = lbm->decide(atTime); 01930 if ( ( _d == LoadBalancerMonitor :: LBD_RECOVER ) || 01931 ( ( atTime->isTheFirstStep() ) && force_load_rebalance_in_first_step ) ) { 01932 this->timer.startTimer(EngngModelTimer :: EMTT_LoadBalancingTimer); 01933 01934 // determine nwe partitioning 01935 lb->calculateLoadTransfer(); 01936 // pack e-model solution data into dof dictionaries 01937 this->packMigratingData(atTime); 01938 // migrate data 01939 lb->migrateLoad( this->giveDomain(1) ); 01940 // renumber itself 01941 this->forceEquationNumbering(); 01942 #ifdef __VERBOSE_PARALLEL 01943 // debug print 01944 int nnodes = giveDomain(1)->giveNumberOfDofManagers(); 01945 int myrank = this->giveRank(); 01946 fprintf(stderr, "\n[%d] Nodal Table\n", myrank); 01947 for ( int i = 1; i <= nnodes; i++ ) { 01948 if ( giveDomain(1)->giveDofManager(i)->giveParallelMode() == DofManager_local ) { 01949 fprintf( stderr, "[%d]: %5d[%d] local ", myrank, i, giveDomain(1)->giveDofManager(i)->giveGlobalNumber() ); 01950 } else if ( giveDomain(1)->giveDofManager(i)->giveParallelMode() == DofManager_shared ) { 01951 fprintf( stderr, "[%d]: %5d[%d] shared ", myrank, i, giveDomain(1)->giveDofManager(i)->giveGlobalNumber() ); 01952 } 01953 01954 for ( int j = 1; j <= giveDomain(1)->giveDofManager(i)->giveNumberOfDofs(); j++ ) { 01955 fprintf( stderr, "(%d)", giveDomain(1)->giveDofManager(i)->giveDof(j)->giveEquationNumber(dn) ); 01956 } 01957 01958 fprintf(stderr, "\n"); 01959 } 01960 01961 #endif 01962 // unpack (restore) e-model solution data from dof dictionaries 01963 this->unpackMigratingData(atTime); 01964 01965 this->timer.stopTimer(EngngModelTimer :: EMTT_LoadBalancingTimer); 01966 double _steptime = this->timer.getUtime(EngngModelTimer :: EMTT_LoadBalancingTimer); 01967 OOFEM_LOG_INFO("[%d] EngngModel info: user time consumed by load rebalancing %.2fs\n", 01968 this->giveRank(), _steptime); 01969 } 01970 } 01971 } 01972 01973 01974 int 01975 EngngModel :: updateSharedDofManagers(FloatArray &answer, int ExchangeTag) 01976 { 01977 int result = 1; 01978 01979 01980 if ( isParallel() ) { 01981 #ifdef __VERBOSE_PARALLEL 01982 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Packing data", this->giveRank() ); 01983 #endif 01984 01985 result &= communicator->packAllData( this, & answer, & EngngModel :: packDofManagers ); 01986 01987 #ifdef __VERBOSE_PARALLEL 01988 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Exchange started", this->giveRank() ); 01989 #endif 01990 01991 result &= communicator->initExchange(ExchangeTag); 01992 01993 #ifdef __VERBOSE_PARALLEL 01994 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Receiving and unpacking", this->giveRank() ); 01995 #endif 01996 01997 result &= communicator->unpackAllData( this, & answer, & EngngModel :: unpackDofManagers ); 01998 result &= communicator->finishExchange(); 01999 } 02000 02001 return result; 02002 } 02003 02004 int 02005 EngngModel :: updateSharedPrescribedDofManagers(FloatArray &answer, int ExchangeTag) 02006 { 02007 int result = 1; 02008 02009 if ( isParallel() ) { 02010 #ifdef __VERBOSE_PARALLEL 02011 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedPrescribedDofManagers", "Packing data", this->giveRank() ); 02012 #endif 02013 02014 result &= communicator->packAllData( this, & answer, & EngngModel :: packPrescribedDofManagers ); 02015 02016 #ifdef __VERBOSE_PARALLEL 02017 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedPrescribedDofManagers", "Exchange started", this->giveRank() ); 02018 #endif 02019 02020 result &= communicator->initExchange(ExchangeTag); 02021 02022 #ifdef __VERBOSE_PARALLEL 02023 VERBOSEPARALLEL_PRINT( "EngngModel :: updateSharedDofManagers", "Receiving and unpacking", this->giveRank() ); 02024 #endif 02025 02026 result &= communicator->unpackAllData( this, & answer, & EngngModel :: unpackPrescribedDofManagers ); 02027 result &= communicator->finishExchange(); 02028 } 02029 02030 return result; 02031 } 02032 02033 02034 void 02035 EngngModel :: initializeCommMaps(bool forceInit) 02036 { 02037 // Set up communication patterns. 02038 communicator->setUpCommunicationMaps(this, true, forceInit); 02039 if ( nonlocalExt ) { 02040 nonlocCommunicator->setUpCommunicationMaps(this, true, forceInit); 02041 } 02042 } 02043 02044 02045 int 02046 EngngModel :: exchangeRemoteElementData(int ExchangeTag) 02047 { 02048 int result = 1; 02049 02050 if ( isParallel() && nonlocalExt ) { 02051 #ifdef __VERBOSE_PARALLEL 02052 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Packing remote element data", this->giveRank() ); 02053 #endif 02054 02055 result &= nonlocCommunicator->packAllData( this, & EngngModel :: packRemoteElementData ); 02056 02057 #ifdef __VERBOSE_PARALLEL 02058 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Remote element data exchange started", this->giveRank() ); 02059 #endif 02060 02061 result &= nonlocCommunicator->initExchange(ExchangeTag); 02062 02063 #ifdef __VERBOSE_PARALLEL 02064 VERBOSEPARALLEL_PRINT( "EngngModel :: exchangeRemoteElementData", "Receiveng and Unpacking remote element data", this->giveRank() ); 02065 #endif 02066 02067 if ( !( result &= nonlocCommunicator->unpackAllData( this, & EngngModel :: unpackRemoteElementData ) ) ) { 02068 _error("EngngModel :: exchangeRemoteElementData: Receiveng and Unpacking remote element data"); 02069 } 02070 02071 result &= nonlocCommunicator->finishExchange(); 02072 } 02073 02074 return result; 02075 } 02076 02077 02078 int 02079 EngngModel :: packRemoteElementData(ProcessCommunicator &processComm) 02080 { 02081 int result = 1; 02082 IntArray const *toSendMap = processComm.giveToSendMap(); 02083 CommunicationBuffer *send_buff = processComm.giveProcessCommunicatorBuff()->giveSendBuff(); 02084 Domain *domain = this->giveDomain(1); 02085 02086 02087 for ( int i = 1; i <= toSendMap->giveSize(); i++ ) { 02088 result &= domain->giveElement( toSendMap->at(i) )->packUnknowns( * send_buff, this->giveCurrentStep() ); 02089 } 02090 02091 return result; 02092 } 02093 02094 02095 int 02096 EngngModel :: unpackRemoteElementData(ProcessCommunicator &processComm) 02097 { 02098 int result = 1; 02099 IntArray const *toRecvMap = processComm.giveToRecvMap(); 02100 CommunicationBuffer *recv_buff = processComm.giveProcessCommunicatorBuff()->giveRecvBuff(); 02101 Element *element; 02102 Domain *domain = this->giveDomain(1); 02103 02104 02105 for ( int i = 1; i <= toRecvMap->giveSize(); i++ ) { 02106 element = domain->giveElement( toRecvMap->at(i) ); 02107 if ( element->giveParallelMode() == Element_remote ) { 02108 result &= element->unpackAndUpdateUnknowns( * recv_buff, this->giveCurrentStep() ); 02109 } else { 02110 _error("unpackRemoteElementData: element is not remote"); 02111 } 02112 } 02113 02114 return result; 02115 } 02116 02117 02118 int 02119 EngngModel :: packDofManagers(FloatArray *src, ProcessCommunicator &processComm) 02120 { 02121 return this->packDofManagers(src, processComm, false); 02122 } 02123 02124 02125 int 02126 EngngModel :: packPrescribedDofManagers(FloatArray *src, ProcessCommunicator &processComm) 02127 { 02128 return this->packDofManagers(src, processComm, true); 02129 } 02130 02131 02132 int 02133 EngngModel :: packDofManagers(FloatArray *src, ProcessCommunicator &processComm, bool prescribedEquations) 02134 { 02136 int result = 1; 02137 Domain *domain = this->giveDomain(1); 02138 IntArray const *toSendMap = processComm.giveToSendMap(); 02139 ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); 02140 02141 for ( int i = 1; i <= toSendMap->giveSize(); i++ ) { 02142 DofManager *dman = domain->giveDofManager( toSendMap->at(i) ); 02143 int ndofs = dman->giveNumberOfDofs(); 02144 for ( int j = 1; j <= ndofs; j++ ) { 02145 Dof *jdof = dman->giveDof(j); 02146 if ( jdof->isPrimaryDof() ) { 02147 int eqNum; 02148 if ( prescribedEquations ) { 02149 eqNum = jdof->__givePrescribedEquationNumber(); 02150 } else { 02151 eqNum = jdof->__giveEquationNumber(); 02152 } 02153 if ( eqNum ) { 02154 result &= pcbuff->packDouble( src->at(eqNum) ); 02155 } 02156 } 02157 } 02158 } 02159 02160 return result; 02161 } 02162 02163 02164 int 02165 EngngModel :: unpackDofManagers(FloatArray *src, ProcessCommunicator &processComm) 02166 { 02167 return this->unpackDofManagers(src, processComm, false); 02168 } 02169 02170 02171 int 02172 EngngModel :: unpackPrescribedDofManagers(FloatArray *src, ProcessCommunicator &processComm) 02173 { 02174 return this->unpackDofManagers(src, processComm, true); 02175 } 02176 02177 02178 int 02179 EngngModel :: unpackDofManagers(FloatArray *dest, ProcessCommunicator &processComm, bool prescribedEquations) 02180 { 02181 int result = 1; 02182 int size; 02183 int ndofs, eqNum; 02184 Domain *domain = this->giveDomain(1); 02185 dofManagerParallelMode dofmanmode; 02186 IntArray const *toRecvMap = processComm.giveToRecvMap(); 02187 ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); 02188 DofManager *dman; 02189 Dof *jdof; 02190 double value; 02191 02192 02193 size = toRecvMap->giveSize(); 02194 for ( int i = 1; i <= size; i++ ) { 02195 dman = domain->giveDofManager( toRecvMap->at(i) ); 02196 ndofs = dman->giveNumberOfDofs(); 02197 dofmanmode = dman->giveParallelMode(); 02198 for ( int j = 1; j <= ndofs; j++ ) { 02199 jdof = dman->giveDof(j); 02200 if ( prescribedEquations ) { 02201 eqNum = jdof->__givePrescribedEquationNumber(); 02202 } else { 02203 eqNum = jdof->__giveEquationNumber(); 02204 } 02205 if ( jdof->isPrimaryDof() && eqNum ) { 02206 result &= pcbuff->unpackDouble(value); 02207 if ( dofmanmode == DofManager_shared ) { 02208 dest->at(eqNum) += value; 02209 } else if ( dofmanmode == DofManager_remote ) { 02210 dest->at(eqNum) = value; 02211 } else { 02212 _error("unpackReactions: unknown dof namager parallel mode"); 02213 } 02214 } 02215 } 02216 } 02217 02218 return result; 02219 } 02220 02221 #endif 02222 } // end namespace oofem