OOFEM  2.1
engngm.C
Go to the documentation of this file.
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

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Sun Mar 10 2013 18:16:53 for OOFEM by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2011