OOFEM  2.1
directerrorindicatorrc.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 #include "errorestimator.h"
00036 #include "directerrorindicatorrc.h"
00037 #include "domain.h"
00038 #include "element.h"
00039 #include "conTable.h"
00040 #include "mathfem.h"
00041 #include "timestep.h"
00042 
00043 namespace oofem {
00044 DirectErrorIndicatorRC :: DirectErrorIndicatorRC(int n, ErrorEstimator *e) : RemeshingCriteria(n, e)
00045 {
00046     stateCounter = -1;
00047 #ifdef __PARALLEL_MODE
00048     dofManDensityExchangeFlag = true;
00049 #endif
00050 }
00051 
00052 DirectErrorIndicatorRC :: ~DirectErrorIndicatorRC()
00053 {
00054 #ifdef __PARALLEL_MODE
00055 #endif
00056 }
00057 
00058 void
00059 DirectErrorIndicatorRC :: giveNodeChar(int inode, TimeStep *tStep, double &indicatorVal, double &currDensity)
00060 {
00061     currDensity = this->giveDofManDensity(inode);
00062     indicatorVal =  this->giveDofManIndicator(inode, tStep);
00063 }
00064 
00065 
00066 double
00067 DirectErrorIndicatorRC :: giveDofManDensity(int num)
00068 {
00069 #ifdef __PARALLEL_MODE
00070     Domain *d = this->giveDomain();
00071     if ( d->giveDofManager(num)->isShared() ) {
00072         return this->sharedDofManDensities [ num ];
00073     } else {
00074         return this->giveLocalDofManDensity(num);
00075     }
00076 
00077 #else
00078     return this->giveLocalDofManDensity(num);
00079 
00080 #endif
00081 }
00082 
00083 double
00084 DirectErrorIndicatorRC :: giveLocalDofManDensity(int num)
00085 {
00086     int isize;
00087     double currDensity = 0.0;
00088     const IntArray *con;
00089     Domain *d = this->giveDomain();
00090     ConnectivityTable *ct = d->giveConnectivityTable();
00091     DirectErrorIndicatorRCInterface *interface;
00092 
00093     con = ct->giveDofManConnectivityArray(num);
00094     isize = con->giveSize();
00095 
00096     for ( int i = 1; i <= isize; i++ ) {
00097         // ask for indicator variable value and determine current mesh density
00098         interface = static_cast< DirectErrorIndicatorRCInterface * >
00099                     ( d->giveElement( con->at(i) )->giveInterface(DirectErrorIndicatorRCInterfaceType) );
00100         if ( !interface ) {
00101             OOFEM_WARNING2( "DirectErrorIndicatorRC::giveRequiredDofManDensity: elem %d does not support DirectErrorIndicatorRCInterface", con->at(i) );
00102         }
00103 
00104         if ( i == 1 ) {
00105             currDensity = interface->DirectErrorIndicatorRCI_giveCharacteristicSize();
00106         } else {
00107             currDensity =  max( currDensity, interface->DirectErrorIndicatorRCI_giveCharacteristicSize() );
00108         }
00109     }
00110 
00111     return currDensity;
00112 }
00113 
00114 
00115 double
00116 DirectErrorIndicatorRC :: giveDofManIndicator(int num, TimeStep *tStep)
00117 {
00118 #ifdef __PARALLEL_MODE
00119     Domain *d = this->giveDomain();
00120     if ( d->giveDofManager(num)->isShared() ) {
00121         return this->sharedDofManIndicatorVals [ num ];
00122     } else {
00123         return this->giveLocalDofManIndicator(num, tStep);
00124     }
00125 
00126 #else
00127     return this->giveLocalDofManIndicator(num, tStep);
00128 
00129 #endif
00130 }
00131 
00132 double
00133 DirectErrorIndicatorRC :: giveLocalDofManIndicator(int inode, TimeStep *tStep)
00134 {
00135     int isize;
00136     const IntArray *con;
00137     Domain *d = this->giveDomain();
00138     ConnectivityTable *ct = d->giveConnectivityTable();
00139     DirectErrorIndicatorRCInterface *interface;
00140     double indicatorVal = 0.0;
00141 
00142     con = ct->giveDofManConnectivityArray(inode);
00143     isize = con->giveSize();
00144 
00145     for ( int i = 1; i <= isize; i++ ) {
00146         // ask for indicator variable value and determine current mesh density
00147         interface = static_cast< DirectErrorIndicatorRCInterface * >
00148                     ( d->giveElement( con->at(i) )->giveInterface(DirectErrorIndicatorRCInterfaceType) );
00149         if ( !interface ) {
00150             OOFEM_WARNING2( "DirectErrorIndicatorRC::giveRequiredDofManDensity: element %d does not support DirectErrorIndicatorRCInterface", con->at(i) );
00151         }
00152 
00153         if ( i == 1 ) {
00154             indicatorVal = ee->giveElementError(indicatorET, d->giveElement( con->at(i) ), tStep);
00155         } else {
00156             indicatorVal = max( indicatorVal, ee->giveElementError(indicatorET, d->giveElement( con->at(i) ), tStep) );
00157         }
00158     }
00159 
00160     return indicatorVal;
00161 }
00162 
00163 
00164 
00165 int
00166 DirectErrorIndicatorRC :: estimateMeshDensities(TimeStep *tStep)
00167 {
00168     Domain *d = this->giveDomain();
00169     int inode, nnodes = d->giveNumberOfDofManagers();
00170     double indicatorVal, currDensity, proposedDensity;
00171 
00172     if ( stateCounter == tStep->giveSolutionStateCounter() ) {
00173         return 1;
00174     }
00175 
00176 #ifdef __PARALLEL_MODE
00177     if ( initCommMap ) {
00178         communicator->setUpCommunicationMaps(d->giveEngngModel(), true, true);
00179         OOFEM_LOG_INFO("DirectErrorIndicatorRC :: estimateMeshDensities: initialized comm maps\n");
00180         initCommMap = false;
00181     }
00182 
00183 
00184     this->exchangeDofManDensities();
00185     this->exchangeDofManIndicatorVals(tStep);
00186 #endif
00187 
00188     this->currStrategy  = NoRemeshing_RS;
00189     this->nodalDensities.resize(nnodes);
00190 
00191     for ( inode = 1; inode <= nnodes; inode++ ) {
00192         this->giveNodeChar(inode, tStep, indicatorVal, currDensity);
00193 
00194         if ( indicatorVal < minIndicatorLimit ) {
00195             this->nodalDensities.at(inode) = zeroIndicatorDensity; //currDensity;
00196         } else if ( indicatorVal >= maxIndicatorLimit ) {
00197             this->nodalDensities.at(inode) = proposedDensity = maxIndicatorDensity;
00198 
00199             if ( proposedDensity < ( currDensity * this->remeshingDensityRatioToggle ) ) {
00200                 this->currStrategy  = RemeshingFromCurrentState_RS;
00201             }
00202         } else {
00203             // evaluate the required size
00204             proposedDensity = minIndicatorDensity +
00205                               ( indicatorVal - minIndicatorLimit ) * ( maxIndicatorDensity - minIndicatorDensity ) / ( maxIndicatorLimit - minIndicatorLimit );
00206             //proposedDensity = min (currDensity, proposedDensity);
00207             this->nodalDensities.at(inode) = proposedDensity;
00208 
00209             if ( proposedDensity < ( currDensity * this->remeshingDensityRatioToggle ) ) {
00210                 this->currStrategy  = RemeshingFromCurrentState_RS;
00211             }
00212         }
00213     }
00214 
00215 #ifdef __PARALLEL_MODE
00216     // exchange strategies between nodes to ensure consistency
00217     int myStrategy = this->currStrategy, globalStrategy;
00218     MPI_Allreduce(& myStrategy, & globalStrategy, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
00219     this->currStrategy = ( RemeshingStrategy ) globalStrategy;
00220 #endif
00221 
00222     // remember time stamp
00223     stateCounter = tStep->giveSolutionStateCounter();
00224     return 1;
00225 }
00226 
00227 
00228 double
00229 DirectErrorIndicatorRC :: giveRequiredDofManDensity(int num, TimeStep *tStep, int relative)
00230 {
00231     this->estimateMeshDensities(tStep);
00232     if ( relative ) {
00233         double currDens;
00234         currDens = this->giveDofManDensity(num);
00235         return this->nodalDensities.at(num) / currDens;
00236     } else {
00237         return this->nodalDensities.at(num);
00238     }
00239 }
00240 
00241 
00242 IRResultType
00243 DirectErrorIndicatorRC :: initializeFrom(InputRecord *ir)
00244 {
00245     const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro
00246     IRResultType result;                // Required by IR_GIVE_FIELD macro
00247 
00248     IR_GIVE_FIELD(ir, minIndicatorLimit, IFT_DirectErrorIndicatorRC_minlim, "minlim"); // Macro
00249     IR_GIVE_FIELD(ir, maxIndicatorLimit, IFT_DirectErrorIndicatorRC_maxlim, "maxlim"); // Macro
00250     IR_GIVE_FIELD(ir, minIndicatorDensity, IFT_DirectErrorIndicatorRC_mindens, "mindens"); // Macro
00251     IR_GIVE_FIELD(ir, maxIndicatorDensity, IFT_DirectErrorIndicatorRC_maxdens, "maxdens"); // Macro
00252     IR_GIVE_FIELD(ir, zeroIndicatorDensity, IFT_DirectErrorIndicatorRC_defdens, "defdens"); // Macro
00253 
00254     remeshingDensityRatioToggle = 0.80;
00255     IR_GIVE_OPTIONAL_FIELD(ir, remeshingDensityRatioToggle, IFT_DirectErrorIndicatorRC_remeshingdensityratio, "remeshingdensityratio"); // Macro
00256 
00257 #ifdef __PARALLEL_MODE
00258     EngngModel *emodel = domain->giveEngngModel();
00259     ProblemCommunicatorMode commMode = emodel->giveProblemCommMode();
00260     if ( commMode == ProblemCommMode__NODE_CUT ) {
00261         commBuff = new CommunicatorBuff(emodel->giveNumberOfProcesses(), CBT_dynamic);
00262         communicator = new ProblemCommunicator(emodel, commBuff, emodel->giveRank(),
00263                                                emodel->giveNumberOfProcesses(),
00264                                                commMode);
00265     }
00266 
00267 #endif
00268     return IRRT_OK;
00269 }
00270 
00271 RemeshingStrategy
00272 DirectErrorIndicatorRC :: giveRemeshingStrategy(TimeStep *tStep)
00273 {
00274     this->estimateMeshDensities(tStep);
00275     return this->currStrategy;
00276 }
00277 
00278 void
00279 DirectErrorIndicatorRC :: reinitialize()
00280 {
00281     stateCounter = -1;
00282 #ifdef __PARALLEL_MODE
00283     dofManDensityExchangeFlag  = true;
00284     initCommMap = true;
00285 #endif
00286 }
00287 
00288 
00289 void
00290 DirectErrorIndicatorRC :: setDomain(Domain *d)
00291 {
00292     RemeshingCriteria :: setDomain(d);
00293 #ifdef __PARALLEL_MODE
00294     dofManDensityExchangeFlag = true;
00295     initCommMap = true;
00296 #endif
00297 }
00298 
00299 
00300 #ifdef __PARALLEL_MODE
00301 void
00302 DirectErrorIndicatorRC :: exchangeDofManDensities()
00303 {
00304     Domain *domain = this->giveDomain();
00305     EngngModel *emodel = domain->giveEngngModel();
00306     ProblemCommunicatorMode commMode = emodel->giveProblemCommMode();
00307 
00308     if ( this->dofManDensityExchangeFlag ) {
00309         if ( commMode == ProblemCommMode__NODE_CUT ) {
00311             sharedDofManDensities.clear();
00312             int i, size = domain->giveNumberOfDofManagers();
00313             for ( i = 1; i <= size; i++ ) {
00314                 if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
00315                     sharedDofManDensities [ i ] = this->giveLocalDofManDensity(i);
00316                 }
00317             }
00318 
00319             // exchange them
00320             communicator->packAllData(this, & DirectErrorIndicatorRC :: packSharedDofManLocalDensities);
00321             communicator->initExchange(999);
00322             communicator->unpackAllData(this, & DirectErrorIndicatorRC :: unpackSharedDofManLocalDensities);
00323             communicator->finishExchange();
00324         }
00325 
00326         this->dofManDensityExchangeFlag = false;
00327     } // if (this->dofManDensityExchangeFlag)
00328 
00329 }
00330 
00331 int
00332 DirectErrorIndicatorRC :: packSharedDofManLocalDensities(ProcessCommunicator &processComm)
00333 {
00334     int result = 1, i, size;
00335     ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff();
00336     IntArray const *toSendMap = processComm.giveToSendMap();
00337 
00338     size = toSendMap->giveSize();
00339     for ( i = 1; i <= size; i++ ) {
00340         result &= pcbuff->packDouble(this->sharedDofManDensities [ toSendMap->at(i) ]);
00341     }
00342 
00343     return result;
00344 }
00345 
00346 int
00347 DirectErrorIndicatorRC :: unpackSharedDofManLocalDensities(ProcessCommunicator &processComm)
00348 {
00349     int result = 1;
00350     int i, size;
00351     IntArray const *toRecvMap = processComm.giveToRecvMap();
00352     ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff();
00353     double value;
00354 
00355     size = toRecvMap->giveSize();
00356     for ( i = 1; i <= size; i++ ) {
00357         result &= pcbuff->unpackDouble(value);
00358         this->sharedDofManDensities [ toRecvMap->at(i) ] = max(value, this->sharedDofManDensities [ toRecvMap->at(i) ]);
00359  #ifdef __VERBOSE_PARALLEL
00360         OOFEM_LOG_INFO("unpackSharedDofManLocalDensities: node %d[%d], value %f\n", toRecvMap->at(i), domain->giveDofManager( toRecvMap->at(i) )->giveGlobalNumber(), this->sharedDofManDensities [ toRecvMap->at(i) ]);
00361  #endif
00362     }
00363 
00364     return result;
00365 }
00366 
00367 
00368 
00369 
00370 void
00371 DirectErrorIndicatorRC :: exchangeDofManIndicatorVals(TimeStep *tStep)
00372 {
00373     Domain *domain = this->giveDomain();
00374     EngngModel *emodel = domain->giveEngngModel();
00375     ProblemCommunicatorMode commMode = emodel->giveProblemCommMode();
00376 
00377     if ( commMode == ProblemCommMode__NODE_CUT ) {
00379         sharedDofManIndicatorVals.clear();
00380         int i, size = domain->giveNumberOfDofManagers();
00381         for ( i = 1; i <= size; i++ ) {
00382             if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
00383                 sharedDofManIndicatorVals [ i ] = this->giveLocalDofManIndicator(i, tStep);
00384             }
00385         }
00386 
00387         // exchange them
00388         communicator->packAllData(this, & DirectErrorIndicatorRC :: packSharedDofManLocalIndicatorVals);
00389         communicator->initExchange(999);
00390         communicator->unpackAllData(this, & DirectErrorIndicatorRC :: unpackSharedDofManLocalIndicatorVals);
00391         communicator->finishExchange();
00392     }
00393 }
00394 
00395 int
00396 DirectErrorIndicatorRC :: packSharedDofManLocalIndicatorVals(ProcessCommunicator &processComm)
00397 {
00398     int result = 1, i, size;
00399     //Domain *d = this->giveDomain();
00400     ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff();
00401     IntArray const *toSendMap = processComm.giveToSendMap();
00402 
00403     size = toSendMap->giveSize();
00404     for ( i = 1; i <= size; i++ ) {
00405         result &= pcbuff->packDouble(this->sharedDofManIndicatorVals [ toSendMap->at(i) ]);
00406     }
00407 
00408     return result;
00409 }
00410 
00411 int
00412 DirectErrorIndicatorRC :: unpackSharedDofManLocalIndicatorVals(ProcessCommunicator &processComm)
00413 {
00414     int result = 1;
00415     int i, size;
00416     IntArray const *toRecvMap = processComm.giveToRecvMap();
00417     ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff();
00418     double value;
00419 
00420     size = toRecvMap->giveSize();
00421     for ( i = 1; i <= size; i++ ) {
00422         result &= pcbuff->unpackDouble(value);
00423         this->sharedDofManIndicatorVals [ toRecvMap->at(i) ] = max(value, this->sharedDofManIndicatorVals [ toRecvMap->at(i) ]);
00424  #ifdef __VERBOSE_PARALLEL
00425         OOFEM_LOG_INFO("unpackSharedDofManLocalIndicatorVals: node %d[%d], value %f\n", toRecvMap->at(i), domain->giveDofManager( toRecvMap->at(i) )->giveGlobalNumber(), this->sharedDofManIndicatorVals [ toRecvMap->at(i) ]);
00426  #endif
00427     }
00428 
00429     return result;
00430 }
00431 
00432 
00433 #endif
00434 } // 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