CTestEnergyIncr.cpp

Go to the documentation of this file.
00001 /* ****************************************************************** **
00002 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00003 **          Pacific Earthquake Engineering Research Center            **
00004 **                                                                    **
00005 **                                                                    **
00006 ** (C) Copyright 1999, The Regents of the University of California    **
00007 ** All Rights Reserved.                                               **
00008 **                                                                    **
00009 ** Commercial use of this program without express permission of the   **
00010 ** University of California, Berkeley, is strictly prohibited.  See   **
00011 ** file 'COPYRIGHT'  in main directory for information on usage and   **
00012 ** redistribution,  and for a DISCLAIMER OF ALL WARRANTIES.           **
00013 **                                                                    **
00014 ** Developed by:                                                      **
00015 **   Frank McKenna (fmckenna@ce.berkeley.edu)                         **
00016 **   Gregory L. Fenves (fenves@ce.berkeley.edu)                       **
00017 **   Filip C. Filippou (filippou@ce.berkeley.edu)                     **
00018 **                                                                    **
00019 ** ****************************************************************** */
00020 
00021 // $Revision: 1.6 $
00022 // $Date: 2005/12/15 00:19:28 $
00023 // $Source: /usr/local/cvs/OpenSees/SRC/convergenceTest/CTestEnergyIncr.cpp,v $
00024 
00025 
00026 // File: ~/convergenceTest/CTestEnergyIncr.C
00027 //
00028 // Written: fmk 
00029 // Date: 09/98
00030 // Revised:
00031 //
00032 // Purpose: This file contains the class implementation for CTestEnergyIncr.
00033 // A CTestEnergyIncr object tests for convergence using the energy increment,
00034 // which is 0.5 times the absolute value of the product of the rhs and 
00035 // the solution vector of the LinearSOE.
00036 
00037 #include <CTestEnergyIncr.h>
00038 #include <Vector.h>
00039 #include <Channel.h>
00040 #include <EquiSolnAlgo.h>
00041 #include <LinearSOE.h>
00042 
00043 
00044 CTestEnergyIncr::CTestEnergyIncr()              
00045     : ConvergenceTest(CONVERGENCE_TEST_CTestEnergyIncr),
00046     theSOE(0), tol(0), maxNumIter(0), currentIter(0), printFlag(0),
00047     norms(1), nType(2)
00048 {
00049     
00050 }
00051 
00052 
00053 CTestEnergyIncr::CTestEnergyIncr(double theTol, int maxIter, int printIt, int normType)
00054     : ConvergenceTest(CONVERGENCE_TEST_CTestEnergyIncr),
00055     theSOE(0), tol(theTol), maxNumIter(maxIter), currentIter(0),printFlag(printIt),
00056     norms(maxNumIter), nType(normType)
00057 {
00058     
00059 }
00060 
00061 
00062 CTestEnergyIncr::~CTestEnergyIncr()
00063 {
00064     
00065 }
00066 
00067 
00068 ConvergenceTest* CTestEnergyIncr::getCopy(int iterations)
00069 {
00070     CTestEnergyIncr *theCopy ;
00071     theCopy = new CTestEnergyIncr(this->tol, iterations, this->printFlag, this->nType);
00072     
00073     theCopy->theSOE = this->theSOE ;
00074     
00075     return theCopy ;
00076 }
00077 
00078 
00079 void CTestEnergyIncr::setTolerance(double newTol)
00080 {
00081     tol = newTol;
00082 }
00083 
00084 
00085 int CTestEnergyIncr::setEquiSolnAlgo(EquiSolnAlgo &theAlgo)
00086 {
00087     theSOE = theAlgo.getLinearSOEptr();
00088     if (theSOE == 0) {
00089         opserr << "WARNING: CTestEnergyIncr::setEquiSolnAlgo - no SOE\n";       
00090         return -1;
00091     }
00092     else
00093         return 0;
00094 }
00095 
00096 
00097 int CTestEnergyIncr::test(void)
00098 {
00099     // check to ensure the SOE has been set - this should not happen if the 
00100     // return from start() is checked
00101     if (theSOE == 0)
00102         return -2;
00103     
00104     // check to ensure the algo does invoke start() - this is needed otherwise
00105     // may never get convergence later on in analysis!
00106     if (currentIter == 0) {
00107         opserr << "WARNING: CTestEnergyIncr::test() - start() was never invoked.\n";    
00108         return -2;
00109     }
00110     
00111     // determine the energy & save value in norms vector
00112     const Vector &b = theSOE->getB();
00113     const Vector &x = theSOE->getX();    
00114     double product = x ^ b;
00115     if (product < 0.0)
00116         product *= -0.5;
00117     else
00118         product *= 0.5;
00119     
00120     if (currentIter <= maxNumIter) 
00121         norms(currentIter-1) = product;
00122     
00123     // print the data if required
00124     if (printFlag == 1) {
00125         opserr << "CTestEnergyIncr::test() - iteration: " << currentIter;
00126         opserr << " current EnergyIncr: " << product << " (max: " << tol << ")\n";
00127     }
00128     if (printFlag == 4) {
00129         opserr << "CTestEnergyIncr::test() - iteration: " << currentIter;
00130         opserr << " current EnergyIncr: " << product << " (max: " << tol << ")\n";
00131         opserr << "\tNorm deltaX: " << x.pNorm(nType) << ", Norm deltaR: " << b.pNorm(nType) << endln;
00132         opserr << "\tdeltaX: " << x << "\tdeltaR: " << b;
00133     }
00134     
00135     //
00136     // check if the algorithm converged
00137     //
00138     
00139     // if converged - print & return ok
00140     if (product <= tol) {
00141         
00142         // do some printing first
00143         if (printFlag != 0) {
00144             if (printFlag == 1 || printFlag == 4) 
00145                 opserr << endln;
00146             else if (printFlag == 2 || printFlag == 6) {
00147                 opserr << "CTestEnergyIncr::test() - iteration: " << currentIter;
00148                 opserr << " last EnergyIncr: " << product << " (max: " << tol << ")\n";
00149             }
00150         }
00151         
00152         // return the number of times test has been called - SUCCESSFULL
00153         return currentIter;
00154     }
00155     
00156     // algo failed to converged after specified number of iterations - but RETURN OK
00157     else if ((printFlag == 5 || printFlag == 6) && currentIter >= maxNumIter) {
00158         opserr << "WARNING: CTestEnergyIncr::test() - failed to converge but goin on -";
00159         opserr << " current EnergyIncr: " << product << " (max: " << tol << ")\n";
00160         opserr << "\tNorm deltaX: " << x.pNorm(nType) << ", Norm deltaR: " << b.pNorm(nType) << endln;
00161         return currentIter;
00162     }
00163     
00164     // algo failed to converged after specified number of iterations - return FAILURE -2
00165     else if (currentIter >= maxNumIter) { // >= in case algorithm does not check
00166         opserr << "WARNING: CTestEnergyIncr::test() - failed to converge \n";
00167         opserr << "after: " << currentIter << " iterations\n";  
00168         currentIter++;    
00169         return -2;
00170     } 
00171     
00172     // algorithm not yet converged - increment counter and return -1
00173     else {
00174         currentIter++;    
00175         return -1;
00176     }
00177 }
00178 
00179 
00180 int CTestEnergyIncr::start(void)
00181 {
00182     if (theSOE == 0) {
00183         opserr << "WARNING: CTestEnergyIncr::test() - no SOE returning true\n";
00184         return -1;
00185     }
00186     
00187     // set iteration count = 1
00188     currentIter = 1;
00189     norms.Zero();
00190     return 0;
00191 }
00192 
00193 
00194 int CTestEnergyIncr::getNumTests(void)
00195 {
00196     return currentIter;
00197 }
00198 
00199 
00200 int CTestEnergyIncr::getMaxNumTests(void)
00201 {
00202     return maxNumIter;
00203 }
00204 
00205 
00206 double CTestEnergyIncr::getRatioNumToMax(void)
00207 {
00208     double div = maxNumIter;
00209     return currentIter/div;
00210 }
00211 
00212 
00213 const Vector& CTestEnergyIncr::getNorms(void) 
00214 {
00215     return norms;
00216 }
00217 
00218 
00219 int CTestEnergyIncr::sendSelf(int cTag, Channel &theChannel)
00220 {
00221     int res = 0;
00222     static Vector x(4);
00223     x(0) = tol;
00224     x(1) = maxNumIter;
00225     x(2) = printFlag;
00226     x(3) = nType;
00227     res = theChannel.sendVector(this->getDbTag(), cTag, x);
00228     if (res < 0) 
00229         opserr << "CTestEnergyIncr::sendSelf() - failed to send data\n";
00230     
00231     return res;
00232 }
00233 
00234 
00235 int CTestEnergyIncr::recvSelf(int cTag, Channel &theChannel, 
00236     FEM_ObjectBroker &theBroker)
00237 {
00238     int res = 0;
00239     static Vector x(4);
00240     res = theChannel.recvVector(this->getDbTag(), cTag, x);    
00241     
00242     if (res < 0) {
00243         opserr << "CTestEnergyIncr::sendSelf() - failed to send data\n";
00244         tol = 1.0e-8;
00245         maxNumIter = 25;
00246         printFlag = 0;
00247         nType = 2;
00248     }
00249     else {
00250         tol = x(0);
00251         maxNumIter = (int) x(1);
00252         printFlag = (int) x(2);
00253         nType = (int) x(3);
00254         norms.resize(maxNumIter);
00255     }
00256     
00257     return res;
00258 }

Generated on Mon Oct 23 15:04:59 2006 for OpenSees by doxygen 1.5.0