|
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 "linearstatic.h" 00036 #include "nummet.h" 00037 #include "timestep.h" 00038 #include "element.h" 00039 #include "sparsemtrx.h" 00040 #include "verbose.h" 00041 #include "structuralelement.h" 00042 #include "structuralelementevaluator.h" 00043 #include "usrdefsub.h" 00044 #include "datastream.h" 00045 #include "contextioerr.h" 00046 00047 #ifdef __PARALLEL_MODE 00048 #include "fetisolver.h" 00049 #endif 00050 00051 namespace oofem { 00052 LinearStatic :: LinearStatic(int i, EngngModel *_master) : StructuralEngngModel(i, _master), loadVector(), displacementVector() 00053 { 00054 stiffnessMatrix = NULL; 00055 ndomains = 1; 00056 nMethod = NULL; 00057 initFlag = 1; 00058 00059 #ifdef __PARALLEL_MODE 00060 commMode = ProblemCommMode__NODE_CUT; 00061 nonlocalExt = 0; 00062 communicator = nonlocCommunicator = NULL; 00063 commBuff = NULL; 00064 #endif 00065 } 00066 00067 00068 LinearStatic :: ~LinearStatic() 00069 { 00070 if (stiffnessMatrix) { 00071 delete stiffnessMatrix; 00072 } 00073 if ( nMethod ) { 00074 delete nMethod; 00075 } 00076 } 00077 00078 00079 NumericalMethod *LinearStatic :: giveNumericalMethod(MetaStep *mStep) 00080 { 00081 if ( nMethod ) { 00082 return nMethod; 00083 } 00084 00085 if ( isParallel() ) { 00086 if ( ( solverType == ST_Petsc ) || ( solverType == ST_Feti ) ) { 00087 nMethod = CreateUsrDefSparseLinSolver(solverType, 1, this->giveDomain(1), this); 00088 } 00089 } else { 00090 nMethod = CreateUsrDefSparseLinSolver(solverType, 1, this->giveDomain(1), this); 00091 } 00092 00093 if ( nMethod == NULL ) { 00094 _error("giveNumericalMethod: linear solver creation failed"); 00095 } 00096 00097 return nMethod; 00098 } 00099 00100 IRResultType 00101 LinearStatic :: initializeFrom(InputRecord *ir) 00102 { 00103 const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro 00104 IRResultType result; // Required by IR_GIVE_FIELD macro 00105 00106 StructuralEngngModel :: initializeFrom(ir); 00107 int val = 0; 00108 IR_GIVE_OPTIONAL_FIELD(ir, val, IFT_LinearStatic_lstype, "lstype"); // Macro 00109 solverType = ( LinSystSolverType ) val; 00110 00111 val = 0; 00112 IR_GIVE_OPTIONAL_FIELD(ir, val, IFT_LinearStatic_smtype, "smtype"); // Macro 00113 sparseMtrxType = ( SparseMtrxType ) val; 00114 00115 #ifdef __PARALLEL_MODE 00116 if ( isParallel() ) { 00117 commBuff = new CommunicatorBuff( this->giveNumberOfProcesses() ); 00118 communicator = new ProblemCommunicator(this, commBuff, this->giveRank(), 00119 this->giveNumberOfProcesses(), 00120 this->commMode); 00121 } 00122 00123 #endif 00124 00125 00126 return IRRT_OK; 00127 } 00128 00129 00130 double LinearStatic :: giveUnknownComponent(EquationID chc, ValueModeType mode, 00131 TimeStep *tStep, Domain *d, Dof *dof) 00132 // returns unknown quantity like displacement, velocity of equation eq 00133 // This function translates this request to numerical method language 00134 { 00135 int eq = dof->__giveEquationNumber(); 00136 if ( eq == 0 ) { 00137 _error("giveUnknownComponent: invalid equation number"); 00138 } 00139 00140 if ( tStep != this->giveCurrentStep() ) { 00141 _error("giveUnknownComponent: unknown time step encountered"); 00142 return 0.; 00143 } 00144 00145 if ( chc != EID_MomentumBalance ) { 00146 _error("giveUnknownComponent: Unknown is of undefined CharType for this problem"); 00147 return 0.; 00148 } 00149 00150 switch ( mode ) { 00151 case VM_Total: 00152 case VM_Incremental: 00153 if ( displacementVector.isNotEmpty() ) { 00154 return displacementVector.at(eq); 00155 } else { 00156 return 0.; 00157 } 00158 00159 default: 00160 _error("giveUnknownComponent: Unknown is of undefined type for this problem"); 00161 } 00162 00163 return 0.; 00164 } 00165 00166 00167 TimeStep *LinearStatic :: giveNextStep() 00168 { 00169 int istep = this->giveNumberOfFirstStep(); 00170 //int mstep = 1; 00171 StateCounterType counter = 1; 00172 00173 if (previousStep != NULL){ 00174 delete previousStep; 00175 } 00176 00177 if ( currentStep != NULL ) { 00178 istep = currentStep->giveNumber() + 1; 00179 counter = currentStep->giveSolutionStateCounter() + 1; 00180 } 00181 00182 previousStep = currentStep; 00183 currentStep = new TimeStep(istep, this, 1, ( double ) istep, 0., counter); 00184 // time and dt variables are set eq to 0 for staics - has no meaning 00185 return currentStep; 00186 } 00187 00188 00189 void LinearStatic :: solveYourself() 00190 { 00191 #ifdef __PARALLEL_MODE 00192 if (this->isParallel()) { 00193 #ifdef __VERBOSE_PARALLEL 00194 // force equation numbering before setting up comm maps 00195 int neq = this->giveNumberOfEquations(EID_MomentumBalance); 00196 OOFEM_LOG_INFO("[process rank %d] neq is %d\n", this->giveRank(), neq); 00197 #endif 00198 00199 // set up communication patterns 00200 // needed only for correct shared rection computation 00201 communicator->setUpCommunicationMaps(this, true); 00202 if ( nonlocalExt ) { 00203 nonlocCommunicator->setUpCommunicationMaps(this, true); 00204 } 00205 } 00206 #endif 00207 00208 StructuralEngngModel :: solveYourself(); 00209 } 00210 00211 00212 00213 void LinearStatic :: solveYourselfAt(TimeStep *tStep) 00214 { 00215 // 00216 // creates system of governing eq's and solves them at given time step 00217 // 00218 // first assemble problem at current time step 00219 00220 if ( initFlag ) { 00221 #ifdef VERBOSE 00222 OOFEM_LOG_DEBUG("Assembling stiffness matrix\n"); 00223 #endif 00224 00225 // 00226 // first step assemble stiffness Matrix 00227 // 00228 stiffnessMatrix = CreateUsrDefSparseMtrx(sparseMtrxType); 00229 if ( stiffnessMatrix == NULL ) { 00230 _error("solveYourselfAt: sparse matrix creation failed"); 00231 } 00232 00233 stiffnessMatrix->buildInternalStructure( this, 1, EID_MomentumBalance, EModelDefaultEquationNumbering() ); 00234 00235 this->assemble( stiffnessMatrix, tStep, EID_MomentumBalance, StiffnessMatrix, 00236 EModelDefaultEquationNumbering(), this->giveDomain(1) ); 00237 00238 initFlag = 0; 00239 } 00240 00241 #ifdef VERBOSE 00242 OOFEM_LOG_DEBUG("Assembling load\n"); 00243 #endif 00244 00245 // 00246 // allocate space for displacementVector 00247 // 00248 displacementVector.resize( this->giveNumberOfEquations(EID_MomentumBalance) ); 00249 displacementVector.zero(); 00250 00251 // 00252 // assembling the load vector 00253 // 00254 loadVector.resize( this->giveNumberOfEquations(EID_MomentumBalance) ); 00255 loadVector.zero(); 00256 this->assembleVector( loadVector, tStep, EID_MomentumBalance, ExternalForcesVector, VM_Total, 00257 EModelDefaultEquationNumbering(), this->giveDomain(1) ); 00258 00259 // 00260 // internal forces (from Dirichlet b.c's, or thermal expansion, etc.) 00261 // 00262 FloatArray internalForces( this->giveNumberOfEquations(EID_MomentumBalance) ); 00263 internalForces.zero(); 00264 this->assembleVector( internalForces, tStep, EID_MomentumBalance, InternalForcesVector, VM_Total, 00265 EModelDefaultEquationNumbering(), this->giveDomain(1) ); 00266 00267 loadVector.subtract(internalForces); 00268 00269 // 00270 // set-up numerical model 00271 // 00272 this->giveNumericalMethod( this->giveMetaStep( tStep->giveMetaStepNumber() ) ); 00273 00274 // 00275 // call numerical model to solve arose problem 00276 // 00277 #ifdef VERBOSE 00278 OOFEM_LOG_INFO("\n\nSolving ...\n\n"); 00279 #endif 00280 NM_Status s = nMethod->solve(stiffnessMatrix, & loadVector, & displacementVector); 00281 if ( !(s & NM_Success) ) { 00282 OOFEM_ERROR("LinearStatic :: solverYourselfAt - No success in solving system."); 00283 } 00284 00285 tStep->incrementStateCounter(); // update solution state counter 00286 } 00287 00288 00289 contextIOResultType LinearStatic :: saveContext(DataStream *stream, ContextMode mode, void *obj) 00290 // 00291 // saves state variable - displacement vector 00292 // 00293 { 00294 contextIOResultType iores; 00295 int closeFlag = 0; 00296 FILE *file; 00297 00298 if ( stream == NULL ) { 00299 if ( !this->giveContextFile(& file, this->giveCurrentStep()->giveNumber(), 00300 this->giveCurrentStep()->giveVersion(), contextMode_write) ) { 00301 THROW_CIOERR(CIO_IOERR); // override 00302 } 00303 00304 stream = new FileDataStream(file); 00305 closeFlag = 1; 00306 } 00307 00308 if ( ( iores = StructuralEngngModel :: saveContext(stream, mode) ) != CIO_OK ) { 00309 THROW_CIOERR(iores); 00310 } 00311 00312 if ( ( iores = displacementVector.storeYourself(stream, mode) ) != CIO_OK ) { 00313 THROW_CIOERR(iores); 00314 } 00315 00316 if ( closeFlag ) { 00317 fclose(file); 00318 delete stream; 00319 stream = NULL; 00320 } 00321 00322 return CIO_OK; 00323 } 00324 00325 00326 contextIOResultType LinearStatic :: restoreContext(DataStream *stream, ContextMode mode, void *obj) 00327 // 00328 // restore state variable - displacement vector 00329 // 00330 { 00331 contextIOResultType iores; 00332 int closeFlag = 0; 00333 int istep, iversion; 00334 FILE *file; 00335 00336 this->resolveCorrespondingStepNumber(istep, iversion, obj); 00337 00338 if ( stream == NULL ) { 00339 if ( !this->giveContextFile(& file, istep, iversion, contextMode_read) ) { 00340 THROW_CIOERR(CIO_IOERR); // override 00341 } 00342 00343 stream = new FileDataStream(file); 00344 closeFlag = 1; 00345 } 00346 00347 if ( ( iores = StructuralEngngModel :: restoreContext(stream, mode, obj) ) != CIO_OK ) { 00348 THROW_CIOERR(iores); 00349 } 00350 00351 if ( ( iores = displacementVector.restoreYourself(stream, mode) ) != CIO_OK ) { 00352 THROW_CIOERR(iores); 00353 } 00354 00355 00356 if ( closeFlag ) { 00357 fclose(file); 00358 delete stream; 00359 stream = NULL; 00360 } 00361 00362 return CIO_OK; 00363 } 00364 00365 00366 void 00367 LinearStatic :: terminate(TimeStep *tStep) 00368 { 00369 StructuralEngngModel :: terminate(tStep); 00370 this->printReactionForces(tStep, 1); 00371 fflush(this->giveOutputStream()); 00372 } 00373 00374 00375 int 00376 LinearStatic :: checkConsistency() 00377 { 00378 // check internal consistency 00379 // if success returns nonzero 00380 int i, nelem; 00381 Element *ePtr; 00382 StructuralElement *sePtr; 00383 StructuralElementEvaluator *see; 00384 Domain *domain = this->giveDomain(1); 00385 00386 nelem = domain->giveNumberOfElements(); 00387 // check for proper element type 00388 00389 for ( i = 1; i <= nelem; i++ ) { 00390 ePtr = domain->giveElement(i); 00391 sePtr = dynamic_cast< StructuralElement * >(ePtr); 00392 see = dynamic_cast< StructuralElementEvaluator * >(ePtr); 00393 00394 if ( ( sePtr == NULL ) && ( see == NULL ) ) { 00395 _warning2("checkConsistency: element %d has no Structural support", i); 00396 return 0; 00397 } 00398 } 00399 00400 EngngModel :: checkConsistency(); 00401 00402 return 1; 00403 } 00404 00405 00406 void 00407 LinearStatic :: updateDomainLinks() 00408 { 00409 EngngModel :: updateDomainLinks(); 00410 this->giveNumericalMethod( this->giveCurrentMetaStep() )->setDomain( this->giveDomain(1) ); 00411 } 00412 00413 00414 00415 void 00416 LinearStatic :: printDofOutputAt(FILE *stream, Dof *iDof, TimeStep *atTime) 00417 { 00418 iDof->printSingleOutputAt(stream, atTime, 'd', EID_MomentumBalance, VM_Total); 00419 } 00420 00421 00422 #ifdef __PARALLEL_MODE 00423 int 00424 LinearStatic :: estimateMaxPackSize(IntArray &commMap, CommunicationBuffer &buff, int packUnpackType) 00425 { 00426 int mapSize = commMap.giveSize(); 00427 int i, j, ndofs, count = 0, pcount = 0; 00428 IntArray locationArray; 00429 Domain *domain = this->giveDomain(1); 00430 DofManager *dman; 00431 Dof *jdof; 00432 00433 if ( packUnpackType == ProblemCommMode__ELEMENT_CUT ) { 00434 for ( i = 1; i <= mapSize; i++ ) { 00435 count += domain->giveDofManager( commMap.at(i) )->giveNumberOfDofs(); 00436 } 00437 00438 return ( buff.givePackSize(MPI_DOUBLE, 1) * count ); 00439 } else if ( packUnpackType == ProblemCommMode__NODE_CUT ) { 00440 for ( i = 1; i <= mapSize; i++ ) { 00441 ndofs = ( dman = domain->giveDofManager( commMap.at(i) ) )->giveNumberOfDofs(); 00442 for ( j = 1; j <= ndofs; j++ ) { 00443 jdof = dman->giveDof(j); 00444 if ( jdof->isPrimaryDof() && ( jdof->__giveEquationNumber() ) ) { 00445 count++; 00446 } else { 00447 pcount++; 00448 } 00449 } 00450 } 00451 00452 // -------------------------------------------------------------------------------- 00453 // only pcount is relevant here, since only prescribed components are exchanged !!!! 00454 // -------------------------------------------------------------------------------- 00455 00456 return ( buff.givePackSize(MPI_DOUBLE, 1) * pcount ); 00457 } else if ( packUnpackType == ProblemCommMode__REMOTE_ELEMENT_MODE ) { 00458 for ( i = 1; i <= mapSize; i++ ) { 00459 count += domain->giveElement( commMap.at(i) )->estimatePackSize(buff); 00460 } 00461 00462 return count; 00463 } 00464 00465 return 0; 00466 } 00467 #endif 00468 } // end namespace oofem