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
00033
00034
00035
00036
00037
00038 #include <UmfpackGenLinSOE.h>
00039 #include <UmfpackGenLinSolver.h>
00040 #include <Matrix.h>
00041 #include <Graph.h>
00042 #include <Vertex.h>
00043 #include <VertexIter.h>
00044 #include <math.h>
00045
00046 #include <Channel.h>
00047 #include <FEM_ObjectBroker.h>
00048
00049 UmfpackGenLinSOE::UmfpackGenLinSOE(UmfpackGenLinSolver &the_Solver)
00050 :LinearSOE(the_Solver, LinSOE_TAGS_UmfpackGenLinSOE),
00051 size(0), nnz(0), A(0), B(0), X(0), colA(0), rowStartA(0),
00052 lValue(0), index(0),
00053 vectX(0), vectB(0), Asize(0), Bsize(0),
00054 factored(false)
00055 {
00056 the_Solver.setLinearSOE(*this);
00057 }
00058
00059
00060 UmfpackGenLinSOE::~UmfpackGenLinSOE()
00061 {
00062 if (A != 0) delete [] A;
00063 if (B != 0) delete [] B;
00064 if (X != 0) delete [] X;
00065 if (rowStartA != 0) delete [] rowStartA;
00066 if (colA != 0) delete []colA;
00067 if (index != 0) delete []index;
00068 if (vectX != 0) delete vectX;
00069 if (vectB != 0) delete vectB;
00070 }
00071
00072
00073 int
00074 UmfpackGenLinSOE::getNumEqn(void) const
00075 {
00076 return size;
00077 }
00078
00079 int
00080 UmfpackGenLinSOE::setSize(Graph &theGraph)
00081 {
00082
00083 int result = 0;
00084 int oldSize = size;
00085 size = theGraph.getNumVertex();
00086
00087
00088 Vertex *theVertex;
00089 int newNNZ = 0;
00090 VertexIter &theVertices = theGraph.getVertices();
00091 while ((theVertex = theVertices()) != 0) {
00092 const ID &theAdjacency = theVertex->getAdjacency();
00093 newNNZ += theAdjacency.Size() +1;
00094 }
00095 nnz = newNNZ;
00096 lValue = 20*nnz;
00097
00098 opserr << "UmfpackGenLinSOE::setSize - n " << size << " nnz " << nnz << " lVal " << lValue << endln;
00099
00100 if (lValue > Asize) {
00101
00102 if (A != 0)
00103 delete [] A;
00104 if (colA != 0)
00105 delete [] colA;
00106
00107 A = new double[lValue];
00108 colA = new int[newNNZ];
00109
00110 if (A == 0 || colA == 0) {
00111 opserr << "WARNING UmfpackGenLinSOE::UmfpackGenLinSOE :";
00112 opserr << " ran out of memory for A and colA with nnz = ";
00113 opserr << newNNZ << " \n";
00114 size = 0; Asize = 0; nnz = 0;
00115 result = -1;
00116 }
00117
00118 Asize = lValue;
00119
00120
00121 if (index != 0)
00122 delete [] index;
00123
00124 index = new int[2*nnz];
00125 }
00126
00127
00128 for (int i=0; i<Asize; i++)
00129 A[i] = 0;
00130
00131 factored = false;
00132
00133 if (size > Bsize) {
00134
00135
00136 if (B != 0) delete [] B;
00137 if (X != 0) delete [] X;
00138 if (rowStartA != 0) delete [] rowStartA;
00139
00140
00141 B = new double[size];
00142 X = new double[size];
00143 rowStartA = new int[size+1];
00144
00145 if (B == 0 || X == 0 || rowStartA == 0) {
00146 opserr << "WARNING UmfpackGenLinSOE::UmfpackGenLinSOE :";
00147 opserr << " ran out of memory for vectors (size) (";
00148 opserr << size << ") \n";
00149 size = 0; Bsize = 0;
00150 result = -1;
00151 }
00152 else
00153 Bsize = size;
00154 }
00155
00156
00157 for (int j=0; j<size; j++) {
00158 B[j] = 0;
00159 X[j] = 0;
00160 }
00161
00162
00163 if (size != oldSize) {
00164 if (vectX != 0)
00165 delete vectX;
00166
00167 if (vectB != 0)
00168 delete vectB;
00169
00170 vectX = new Vector(X,size);
00171 vectB = new Vector(B,size);
00172 }
00173
00174
00175 if (size != 0) {
00176 rowStartA[0] = 0;
00177 int startLoc = 0;
00178 int lastLoc = 0;
00179 for (int a=0; a<size; a++) {
00180
00181 theVertex = theGraph.getVertexPtr(a);
00182 if (theVertex == 0) {
00183 opserr << "WARNING:UmfpackGenLinSOE::setSize :";
00184 opserr << " vertex " << a << " not in graph! - size set to 0\n";
00185 size = 0;
00186 return -1;
00187 }
00188
00189 colA[lastLoc++] = theVertex->getTag();
00190 const ID &theAdjacency = theVertex->getAdjacency();
00191 int idSize = theAdjacency.Size();
00192
00193
00194 for (int i=0; i<idSize; i++) {
00195
00196 int row = theAdjacency(i);
00197 bool foundPlace = false;
00198
00199 for (int j=startLoc; j<lastLoc; j++)
00200 if (colA[j] > row) {
00201
00202
00203 for (int k=lastLoc; k>j; k--)
00204
00205 colA[k] = colA[k-1];
00206 colA[j] = row;
00207 foundPlace = true;
00208 j = lastLoc;
00209 }
00210 if (foundPlace == false)
00211 colA[lastLoc] = row;
00212
00213 lastLoc++;
00214 }
00215 rowStartA[a+1] = lastLoc;;
00216 startLoc = lastLoc;
00217 }
00218 }
00219
00220
00221
00222 int *indexRowPtr = &index[0];
00223 int *indexColPtr = &index[nnz];
00224 for (int ii=0; ii<size; ii++) {
00225 int rowBegin = rowStartA[ii];
00226 int rowEnd = rowStartA[ii+1] -1;
00227 for (int j=rowBegin; j<=rowEnd; j++) {
00228 int row = ii+1;
00229 int col = colA[j] +1;
00230 *indexRowPtr++ = row;
00231 *indexColPtr++ = col;
00232 }
00233 }
00234
00235
00236 LinearSOESolver *the_Solver = this->getSolver();
00237 int solverOK = the_Solver->setSize();
00238 if (solverOK < 0) {
00239 opserr << "WARNING:UmfpackGenLinSOE::setSize :";
00240 opserr << " solver failed setSize()\n";
00241 return solverOK;
00242 }
00243 return result;
00244 }
00245
00246 int
00247 UmfpackGenLinSOE::addA(const Matrix &m, const ID &id, double fact)
00248 {
00249
00250 if (fact == 0.0)
00251 return 0;
00252
00253 int idSize = id.Size();
00254
00255
00256 if (idSize != m.noRows() && idSize != m.noCols()) {
00257 opserr << "UmfpackGenLinSOE::addA() ";
00258 opserr << " - Matrix and ID not of similar sizes\n";
00259 return -1;
00260 }
00261
00262 if (fact == 1.0) {
00263 for (int i=0; i<idSize; i++) {
00264 int row = id(i);
00265 if (row < size && row >= 0) {
00266 int startRowLoc = rowStartA[row];
00267 int endRowLoc = rowStartA[row+1];
00268 for (int j=0; j<idSize; j++) {
00269 int col = id(j);
00270 if (col <size && col >= 0) {
00271
00272 for (int k=startRowLoc; k<endRowLoc; k++)
00273 if (colA[k] == col) {
00274 A[k] += m(i,j);
00275 k = endRowLoc;
00276 }
00277 }
00278 }
00279 }
00280 }
00281 } else {
00282 for (int i=0; i<idSize; i++) {
00283 int row = id(i);
00284 if (row < size && row >= 0) {
00285 int startRowLoc = rowStartA[row];
00286 int endRowLoc = rowStartA[row+1];
00287 for (int j=0; j<idSize; j++) {
00288 int col = id(j);
00289 if (col <size && col >= 0) {
00290
00291 for (int k=startRowLoc; k<endRowLoc; k++)
00292 if (colA[k] == col) {
00293 A[k] += fact * m(i,j);
00294 k = endRowLoc;
00295 }
00296 }
00297 }
00298 }
00299 }
00300 }
00301
00302 return 0;
00303 }
00304
00305
00306 int
00307 UmfpackGenLinSOE::addB(const Vector &v, const ID &id, double fact)
00308 {
00309
00310
00311 if (fact == 0.0) return 0;
00312
00313 int idSize = id.Size();
00314
00315 if (idSize != v.Size() ) {
00316 opserr << "UmfpackGenLinSOE::addB() ";
00317 opserr << " - Vector and ID not of similar sizes\n";
00318 return -1;
00319 }
00320
00321 if (fact == 1.0) {
00322 for (int i=0; i<idSize; i++) {
00323 int pos = id(i);
00324 if (pos <size && pos >= 0)
00325 B[pos] += v(i);
00326 }
00327 } else if (fact == -1.0) {
00328 for (int i=0; i<idSize; i++) {
00329 int pos = id(i);
00330 if (pos <size && pos >= 0)
00331 B[pos] -= v(i);
00332 }
00333 } else {
00334 for (int i=0; i<idSize; i++) {
00335 int pos = id(i);
00336 if (pos <size && pos >= 0)
00337 B[pos] += v(i) * fact;
00338 }
00339 }
00340
00341 return 0;
00342 }
00343
00344
00345 int
00346 UmfpackGenLinSOE::setB(const Vector &v, double fact)
00347 {
00348
00349 if (fact == 0.0) return 0;
00350
00351
00352 if (v.Size() != size) {
00353 opserr << "WARNING BandGenLinSOE::setB() -";
00354 opserr << " incomptable sizes " << size << " and " << v.Size() << endln;
00355 return -1;
00356 }
00357
00358 if (fact == 1.0) {
00359 for (int i=0; i<size; i++) {
00360 B[i] = v(i);
00361 }
00362 } else if (fact == -1.0) {
00363 for (int i=0; i<size; i++) {
00364 B[i] = -v(i);
00365 }
00366 } else {
00367 for (int i=0; i<size; i++) {
00368 B[i] = v(i) * fact;
00369 }
00370 }
00371 return 0;
00372 }
00373
00374 void
00375 UmfpackGenLinSOE::zeroA(void)
00376 {
00377 double *Aptr = A;
00378 for (int i=0; i<Asize; i++)
00379 *Aptr++ = 0;
00380
00381 factored = false;
00382 }
00383
00384 void
00385 UmfpackGenLinSOE::zeroB(void)
00386 {
00387 double *Bptr = B;
00388 for (int i=0; i<size; i++)
00389 *Bptr++ = 0;
00390 }
00391
00392 void
00393 UmfpackGenLinSOE::setX(int loc, double value)
00394 {
00395 if (loc < size && loc >=0)
00396 X[loc] = value;
00397 }
00398
00399
00400 void
00401 UmfpackGenLinSOE::setX(const Vector &x)
00402 {
00403 if (x.Size() == size && vectX != 0)
00404 *vectX = x;
00405 }
00406
00407
00408 const Vector &
00409 UmfpackGenLinSOE::getX(void)
00410 {
00411 if (vectX == 0) {
00412 opserr << "FATAL UmfpackGenLinSOE::getX - vectX == 0";
00413 exit(-1);
00414 }
00415 return *vectX;
00416 }
00417
00418 const Vector &
00419 UmfpackGenLinSOE::getB(void)
00420 {
00421 if (vectB == 0) {
00422 opserr << "FATAL UmfpackGenLinSOE::getB - vectB == 0";
00423 exit(-1);
00424 }
00425 return *vectB;
00426 }
00427
00428 double
00429 UmfpackGenLinSOE::normRHS(void)
00430 {
00431 double norm =0.0;
00432 for (int i=0; i<size; i++) {
00433 double Yi = B[i];
00434 norm += Yi*Yi;
00435 }
00436 return sqrt(norm);
00437
00438 }
00439
00440
00441 int
00442 UmfpackGenLinSOE::setUmfpackGenLinSolver(UmfpackGenLinSolver &newSolver)
00443 {
00444 newSolver.setLinearSOE(*this);
00445
00446 if (size != 0) {
00447 int solverOK = newSolver.setSize();
00448 if (solverOK < 0) {
00449 opserr << "WARNING:UmfpackGenLinSOE::setSolver :";
00450 opserr << "the new solver could not setSeize() - staying with old\n";
00451 return -1;
00452 }
00453 }
00454
00455 return this->LinearSOE::setSolver(newSolver);
00456 }
00457
00458
00459 int
00460 UmfpackGenLinSOE::sendSelf(int cTag, Channel &theChannel)
00461 {
00462 return 0;
00463 }
00464
00465 int
00466 UmfpackGenLinSOE::recvSelf(int cTag, Channel &theChannel,
00467 FEM_ObjectBroker &theBroker)
00468 {
00469 return 0;
00470 }
00471