|
OOFEM
2.1
|
00001 /* 00002 * 00003 * ##### ##### ###### ###### ### ### 00004 * ## ## ## ## ## ## ## ### ## 00005 * ## ## ## ## #### #### ## # ## 00006 * ## ## ## ## ## ## ## ## 00007 * ## ## ## ## ## ## ## ## 00008 * ##### ##### ## ###### ## ## 00009 * 00010 * 00011 * OOFEM : Object Oriented Finite Element Code 00012 * 00013 * Copyright (C) 1993 - 2013 Borek Patzak 00014 * 00015 * 00016 * 00017 * Czech Technical University, Faculty of Civil Engineering, 00018 * Department of Structural Mechanics, 166 29 Prague, Czech Republic 00019 * 00020 * This program is free software; you can redistribute it and/or modify 00021 * it under the terms of the GNU General Public License as published by 00022 * the Free Software Foundation; either version 2 of the License, or 00023 * (at your option) any later version. 00024 * 00025 * This program is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 * GNU General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU General Public License 00031 * along with this program; if not, write to the Free Software 00032 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00033 */ 00034 00035 #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