OOFEM  2.1
linearstatic.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 "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

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:55 for OOFEM by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2011