00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <SymBandEigenSOE.h>
00033 #include <SymBandEigenSolver.h>
00034 #include <Matrix.h>
00035 #include <Graph.h>
00036 #include <Vertex.h>
00037 #include <VertexIter.h>
00038 #include <f2c.h>
00039 #include <math.h>
00040 #include <Channel.h>
00041 #include <FEM_ObjectBroker.h>
00042 #include <AnalysisModel.h>
00043
00044 SymBandEigenSOE::SymBandEigenSOE(SymBandEigenSolver &theSolvr,
00045 AnalysisModel &aModel)
00046 :EigenSOE(theSolvr, EigenSOE_TAGS_SymBandEigenSOE),
00047 size(0), numSuperD(0), A(0),
00048 Asize(0), factored(false), theModel(&aModel), M(0), Msize(0)
00049 {
00050 theSolvr.setEigenSOE(*this);
00051 }
00052
00053 int
00054 SymBandEigenSOE::getNumEqn(void) const
00055 {
00056 return size;
00057 }
00058
00059 SymBandEigenSOE::~SymBandEigenSOE()
00060 {
00061 if (A != 0)
00062 delete [] A;
00063 if (M != 0)
00064 delete [] M;
00065 }
00066
00067 int
00068 SymBandEigenSOE::setSize(Graph &theGraph)
00069 {
00070 int result = 0;
00071 size = theGraph.getNumVertex();
00072
00073
00074
00075 numSuperD = 0;
00076
00077 Vertex *vertexPtr;
00078 VertexIter &theVertices = theGraph.getVertices();
00079
00080 while ((vertexPtr = theVertices()) != 0) {
00081 int vertexNum = vertexPtr->getTag();
00082 const ID &theAdjacency = vertexPtr->getAdjacency();
00083 for (int i=0; i<theAdjacency.Size(); i++) {
00084 int otherNum = theAdjacency(i);
00085 int diff = vertexNum - otherNum;
00086 if (diff > 0) {
00087 if (diff > numSuperD)
00088 numSuperD = diff;
00089 } else
00090 if (diff < -numSuperD)
00091 numSuperD = -diff;
00092 }
00093 }
00094
00095 int newSize = size*(numSuperD+1);
00096 if (newSize > Asize) {
00097
00098 if (A != 0)
00099 delete [] A;
00100
00101 A = new double[newSize];
00102
00103 if (A == 0) {
00104 opserr << "SymBandEigenSOE::setSize() -- ran out of memory for A, size = " <<
00105 size << " and numSuperD = : " << numSuperD << endln;
00106
00107 Asize = 0; size = 0; numSuperD = 0;
00108 result= -1;
00109 }
00110 else
00111 Asize = newSize;
00112 }
00113
00114
00115 for (int i = 0; i < Asize; i++)
00116 A[i] = 0.0;
00117
00118 factored = false;
00119
00120
00121 EigenSolver *theSolvr = this->getSolver();
00122 int solverOK = theSolvr->setSize();
00123 if (solverOK < 0) {
00124 opserr << "SymBandEigenSOE::setSize() -- solver failed in setSize()\n";
00125
00126 return solverOK;
00127 }
00128
00129 return result;
00130 }
00131
00132 int
00133 SymBandEigenSOE::addA(const Matrix &m, const ID &id, double fact)
00134 {
00135
00136 if (fact == 0.0)
00137 return 0;
00138
00139
00140 int idSize = id.Size();
00141 if (idSize != m.noRows() && idSize != m.noCols()) {
00142 opserr << "SymBandEigenSOE::addA() -- Matrix and ID not of similar sizes,\n";
00143 return -1;
00144 }
00145
00146 if (fact == 1.0) {
00147 for (int i = 0; i < idSize; i++) {
00148 int col = id(i);
00149 if (col < size && col >= 0) {
00150 double *coliiPtr = A +(col+1)*(numSuperD+1) - 1;
00151 int minColRow = col - (numSuperD+1) + 1;
00152 for (int j = 0; j < idSize; j++) {
00153 int row = id(j);
00154 if (row <size && row >= 0 &&
00155 row <= col && row >= minColRow) {
00156 double *APtr = coliiPtr + (row-col);
00157 *APtr += m(j,i);
00158 }
00159 }
00160 }
00161 }
00162 } else {
00163 for (int i = 0; i < idSize; i++) {
00164 int col = id(i);
00165 if (col < size && col >= 0) {
00166 double *coliiPtr = A +(col+1)*(numSuperD+1) - 1;
00167 int minColRow = col - (numSuperD+1) +1;
00168 for (int j = 0; j < idSize; j++) {
00169 int row = id(j);
00170 if (row < size && row >= 0 &&
00171 row <= col && row >= minColRow) {
00172 double *APtr = coliiPtr + (row-col);
00173 *APtr += m(j,i)*fact;
00174 }
00175 }
00176 }
00177 }
00178 }
00179
00180 return 0;
00181 }
00182
00183 void
00184 SymBandEigenSOE::zeroA(void)
00185 {
00186 double *Aptr = A;
00187
00188 for (int i = 0; i < Asize; i++)
00189 *Aptr++ = 0;
00190
00191 factored = false;
00192 }
00193
00194 int
00195 SymBandEigenSOE::addM(const Matrix &m, const ID &id, double fact)
00196 {
00197
00198 if (fact == 0.0)
00199 return 0;
00200
00201
00202 if (M == 0 || Msize != size) {
00203 if (M != 0)
00204 delete [] M;
00205 M = new double[size];
00206 Msize = size;
00207 if (M == 0) {
00208 opserr << "WARNING SymBandEigenSOE::addM() - out of memory creating M for size: " << size << endln;
00209 return -1;
00210 }
00211 for (int i=0; i<size; i++)
00212 M[i] = 0.0;
00213 }
00214
00215
00216 int idSize = id.Size();
00217 if (idSize != m.noRows() && idSize != m.noCols()) {
00218 opserr << "WARING: SymBandEigenSOE::addM() -- Matrix and ID not of similar sizes!!\n";
00219 return -1;
00220 }
00221
00222 for (int i = 0; i <idSize; i++) {
00223 int loc = id(i);
00224 if (loc >= 0)
00225 M[loc] += fact * m(i,i);
00226 }
00227
00228
00229 bool issueWarning = false;
00230 for (int ii=0; ii<idSize; ii++)
00231 for (int jj=0; jj<idSize; jj++)
00232 if (ii!=jj)
00233 if (m(ii,jj) != 0.0)
00234 issueWarning = true;
00235 if (issueWarning == true) {
00236 opserr << "WARNING SymBandEigenSOE::addM() - m passed was not diagonal, only diagonal entries added\n";
00237 }
00238
00239 return 0;
00240 }
00241
00242 void
00243 SymBandEigenSOE::zeroM(void)
00244 {
00245 if (M != 0)
00246 for (int i=0; i<size; i++)
00247 M[i] = 0.0;
00248
00249 return;
00250 }
00251
00252 int
00253 SymBandEigenSOE::sendSelf(int commitTag, Channel &theChannel)
00254 {
00255 return 0;
00256 }
00257
00258 int
00259 SymBandEigenSOE::recvSelf(int commitTag, Channel &theChannel,
00260 FEM_ObjectBroker &theBroker)
00261 {
00262 return 0;
00263 }