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