00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <fstream>
00018 #include <stdlib.h>
00019
00020 #include <SymSparseLinSOE.h>
00021 #include <SymSparseLinSolver.h>
00022 #include <Matrix.h>
00023 #include <Graph.h>
00024 #include <Vertex.h>
00025 #include <VertexIter.h>
00026 #include <math.h>
00027 #include <Channel.h>
00028 #include <FEM_ObjectBroker.h>
00029
00030
00031 SymSparseLinSOE::SymSparseLinSOE(SymSparseLinSolver &the_Solver, int lSparse)
00032 :LinearSOE(the_Solver, LinSOE_TAGS_SymSparseLinSOE),
00033 size(0), nnz(0), B(0), X(0), colA(0), rowStartA(0),
00034 vectX(0), vectB(0),
00035 Bsize(0), factored(false),
00036 nblks(0), xblk(0), invp(0), diag(0), penv(0), rowblks(0),
00037 begblk(0), first(0)
00038 {
00039 the_Solver.setLinearSOE(*this);
00040 this->LSPARSE = lSparse;
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 SymSparseLinSOE::~SymSparseLinSOE()
00050 {
00051
00052 if (diag != NULL) free(diag);
00053
00054
00055 if (penv != NULL) {
00056 if (penv[0] != NULL) {
00057 free(penv[0]);
00058 }
00059 free(penv);
00060 }
00061
00062
00063 OFFDBLK *blkPtr = first;
00064 OFFDBLK *tempBlk;
00065 int curRow = -1;
00066
00067 while (1) {
00068 if (blkPtr->next == blkPtr) {
00069 if (blkPtr != NULL) {
00070 free(blkPtr);
00071 }
00072 break;
00073 }
00074
00075 tempBlk = blkPtr->next;
00076 if (blkPtr->row != curRow) {
00077 if (blkPtr->nz != NULL) {
00078 free(blkPtr->nz);
00079 }
00080 curRow = blkPtr->row;
00081 }
00082
00083 free(blkPtr);
00084
00085 blkPtr = tempBlk;
00086 }
00087
00088
00089 if (xblk != 0) free(xblk);
00090 if (rowblks != 0) free(rowblks);
00091 if (invp != 0) free(invp);
00092
00093
00094 if (B != 0) delete [] B;
00095 if (X != 0) delete [] X;
00096 if (vectX != 0) delete vectX;
00097 if (vectB != 0) delete vectB;
00098 if (rowStartA != 0) delete [] rowStartA;
00099 if (colA != 0) delete [] colA;
00100 }
00101
00102
00103 int SymSparseLinSOE::getNumEqn(void) const
00104 {
00105 return size;
00106 }
00107
00108
00109
00110
00111 extern "C" int symFactorization(int *fxadj, int *adjncy, int neq, int LSPARSE,
00112 int **xblkMY, int **invpMY, int **rowblksMY,
00113 OFFDBLK ***begblkMY, OFFDBLK **firstMY,
00114 double ***penvMY, double **diagMY);
00115
00116
00117
00118
00119
00120
00121 int SymSparseLinSOE::setSize(Graph &theGraph)
00122 {
00123
00124 int result = 0;
00125 int oldSize = size;
00126 size = theGraph.getNumVertex();
00127
00128
00129 Vertex *theVertex;
00130 int newNNZ = 0;
00131 VertexIter &theVertices = theGraph.getVertices();
00132 while ((theVertex = theVertices()) != 0) {
00133 const ID &theAdjacency = theVertex->getAdjacency();
00134 newNNZ += theAdjacency.Size();
00135 }
00136 nnz = newNNZ;
00137
00138 colA = new int[newNNZ];
00139 if (colA == 0) {
00140 opserr << "WARNING SymSparseLinSOE::SymSparseLinSOE :";
00141 opserr << " ran out of memory for colA with nnz = ";
00142 opserr << newNNZ << " \n";
00143 size = 0; nnz = 0;
00144 result = -1;
00145 }
00146
00147 factored = false;
00148
00149 if (size > Bsize) {
00150
00151
00152 if (B != 0) delete [] B;
00153 if (X != 0) delete [] X;
00154 if (rowStartA != 0) delete [] rowStartA;
00155
00156
00157 B = new double[size];
00158 X = new double[size];
00159 rowStartA = new int[size+1];
00160
00161 if (B == 0 || X == 0 || rowStartA == 0) {
00162 opserr << "WARNING SymSparseLinSOE::SymSparseLinSOE :";
00163 opserr << " ran out of memory for vectors (size) (";
00164 opserr << size << ") \n";
00165 size = 0; Bsize = 0;
00166 result = -1;
00167 } else {
00168 Bsize = size;
00169 }
00170 }
00171
00172
00173 for (int j=0; j<size; j++) {
00174 B[j] = 0;
00175 X[j] = 0;
00176 }
00177
00178
00179 if (size != oldSize) {
00180 if (vectX != 0)
00181 delete vectX;
00182
00183 if (vectB != 0)
00184 delete vectB;
00185
00186 vectX = new Vector(X,size);
00187 vectB = new Vector(B,size);
00188 }
00189
00190
00191 if (size != 0) {
00192 rowStartA[0] = 0;
00193 int startLoc = 0;
00194 int lastLoc = 0;
00195
00196 for (int a=0; a<size; a++) {
00197 theVertex = theGraph.getVertexPtr(a);
00198 if (theVertex == 0) {
00199 opserr << "WARNING:SymSparseLinSOE::setSize :";
00200 opserr << " vertex " << a << " not in graph! - size set to 0\n";
00201 size = 0;
00202 return -1;
00203 }
00204
00205 const ID &theAdjacency = theVertex->getAdjacency();
00206 int idSize = theAdjacency.Size();
00207
00208
00209 for (int i=0; i<idSize; i++) {
00210 int row = theAdjacency(i);
00211 bool foundPlace = false;
00212
00213 for (int j=startLoc; j<lastLoc; j++)
00214 if (colA[j] > row) {
00215
00216
00217 for (int k=lastLoc; k>j; k--)
00218 colA[k] = colA[k-1];
00219 colA[j] = row;
00220 foundPlace = true;
00221 j = lastLoc;
00222 }
00223
00224 if (foundPlace == false)
00225 colA[lastLoc] = row;
00226
00227 lastLoc++;
00228 }
00229 rowStartA[a+1] = lastLoc;;
00230 startLoc = lastLoc;
00231 }
00232 }
00233
00234
00235 nblks = symFactorization(rowStartA, colA, size, this->LSPARSE,
00236 &xblk, &invp, &rowblks, &begblk, &first, &penv, &diag);
00237
00238 return result;
00239 }
00240
00241
00242
00243
00244 int SymSparseLinSOE::addA(const Matrix &in_m, const ID &in_id, double fact)
00245 {
00246
00247 if (fact == 0.0)
00248 return 0;
00249
00250 int idSize = in_id.Size();
00251 if (idSize == 0) return 0;
00252
00253
00254 if (idSize != in_m.noRows() && idSize != in_m.noCols()) {
00255 opserr << "SymSparseLinSOE::addA() ";
00256 opserr << " - Matrix and ID not of similiar sizes\n";
00257 return -1;
00258 }
00259
00260
00261 int newPt = 0;
00262 int *id = new int[idSize];
00263
00264 for (int jj = 0; jj < idSize; jj++) {
00265 if (in_id(jj) >= 0 && in_id(jj) < size) {
00266 id[newPt] = in_id(jj);
00267 newPt++;
00268 }
00269 }
00270
00271 idSize = newPt;
00272 if (idSize == 0) return 0;
00273 double *m = new double[idSize*idSize];
00274
00275 int newII = 0;
00276 for (int ii = 0; ii < in_id.Size(); ii++) {
00277 if (in_id(ii) >= 0 && in_id(ii) < size) {
00278
00279 int newJJ = 0;
00280 for (int jj = 0; jj < in_id.Size(); jj++) {
00281 if (in_id(jj) >= 0 && in_id(jj) < size) {
00282 m[newII*idSize + newJJ] = in_m(ii, jj);
00283 newJJ++;
00284 }
00285 }
00286 newII++;
00287 }
00288 }
00289
00290
00291
00292 int *newID = new int[idSize];
00293 int *isort = new int[idSize];
00294 if (newID == 0 || isort ==0) {
00295 opserr << "WARNING SymSparseLinSOE::SymSparseLinSOE :";
00296 opserr << " ran out of memory for vectors (newID, isort)";
00297 return -1;
00298 }
00299
00300 for (int kk=0; kk<idSize; kk++) {
00301 newID[kk] = id[kk];
00302 if (newID[kk] >= 0)
00303 newID[kk] = invp[newID[kk]];
00304 }
00305
00306 long int i_eq, j_eq;
00307 int i, j, nee, lnee;
00308 int k, ipos, jpos;
00309 int it, jt;
00310 int iblk;
00311 OFFDBLK *ptr;
00312 OFFDBLK *saveblk;
00313 double *fpt, *iloc, *loc;
00314
00315 nee = idSize;
00316 lnee = nee;
00317
00318
00319 for( i = 0, k = 0; i < lnee ; i++ )
00320 {
00321 if( newID[i] >= 0 ) {
00322 isort[k] = i;
00323 k++;
00324 }
00325 }
00326
00327 lnee = k;
00328
00329
00330 i = k - 1;
00331 do
00332 {
00333 k = 0 ;
00334 for (j = 0 ; j < i ; j++)
00335 {
00336 if ( newID[isort[j]] > newID[isort[j+1]]) {
00337 isort[j] ^= isort[j+1] ;
00338 isort[j+1] ^= isort[j] ;
00339 isort[j] ^= isort[j+1] ;
00340 k = j ;
00341 }
00342 }
00343 i = k ;
00344 } while ( k > 0) ;
00345
00346 i = 0 ;
00347 ipos = isort[i] ;
00348 k = rowblks[newID[ipos]] ;
00349 saveblk = begblk[k] ;
00350
00351
00352 for (i=0; i<lnee; i++)
00353 {
00354 ipos = isort[i] ;
00355 i_eq = newID[ipos] ;
00356 iblk = rowblks[i_eq] ;
00357 iloc = penv[i_eq +1] - i_eq ;
00358 if (k < iblk)
00359 while (saveblk->row != i_eq) saveblk = saveblk->bnext ;
00360
00361 ptr = saveblk ;
00362 for (j=0; j< i ; j++)
00363 {
00364 jpos = isort[j] ;
00365 j_eq = newID[jpos] ;
00366
00367 if (ipos > jpos) {
00368 jt = ipos;
00369 it = jpos;
00370 } else {
00371 it = ipos;
00372 jt = jpos;
00373 }
00374
00375 if (j_eq >= xblk[iblk])
00376 {
00377 loc = iloc + j_eq ;
00378 *loc += m[it*idSize + jt] * fact;
00379 }
00380 else
00381 {
00382 while((j_eq >= (ptr->next)->beg) && ((ptr->next)->row == i_eq))
00383 ptr = ptr->next ;
00384 fpt = ptr->nz ;
00385 fpt[j_eq - ptr->beg] += m[it*idSize + jt] * fact;
00386 }
00387 }
00388 diag[i_eq] += m[ipos*idSize + ipos] * fact;
00389 }
00390
00391 delete [] newID;
00392 delete [] isort;
00393 delete [] m;
00394 delete [] id;
00395
00396 return 0;
00397 }
00398
00399
00400
00401
00402 int SymSparseLinSOE::addB(const Vector &in_v, const ID &in_id, double fact)
00403 {
00404
00405 if (fact == 0.0) return 0;
00406
00407 int idSize = in_id.Size();
00408
00409 if (idSize != in_v.Size() ) {
00410 opserr << "SymSparseLinSOE::addB() ";
00411 opserr << " - Vector and ID not of similar sizes\n";
00412 return -1;
00413 }
00414
00415
00416 int newPt = 0;
00417 int *id = new int[idSize];
00418 double *v = new double[idSize];
00419
00420 for (int ii = 0; ii < idSize; ii++) {
00421 if (in_id(ii) >= 0 && in_id(ii) < size) {
00422 id[newPt] = in_id(ii);
00423 v[newPt] = in_v(ii);
00424 newPt++;
00425 }
00426 }
00427
00428 idSize = newPt;
00429 if (idSize == 0) {
00430 delete [] id;
00431 delete [] v;
00432 return 0;
00433 }
00434 int *newID = new int[idSize];
00435 if (newID == 0) {
00436 opserr << "WARNING SymSparseLinSOE::SymSparseLinSOE :";
00437 opserr << " ran out of memory for vectors (newID)";
00438 return -1;
00439 }
00440
00441 for (int i=0; i<idSize; i++) {
00442 newID[i] = id[i];
00443 if (newID[i] >= 0)
00444 newID[i] = invp[newID[i]];
00445 }
00446
00447 if (fact == 1.0) {
00448 for (int i=0; i<idSize; i++) {
00449 int pos = newID[i];
00450 if (pos <size && pos >= 0)
00451 B[pos] += v[i];
00452 }
00453 } else if (fact == -1.0) {
00454 for (int i=0; i<idSize; i++) {
00455 int pos = newID[i];
00456 if (pos <size && pos >= 0)
00457 B[pos] -= v[i];
00458 }
00459 } else {
00460 for (int i=0; i<idSize; i++) {
00461 int pos = newID[i];
00462 if (pos <size && pos >= 0)
00463 B[pos] += v[i] * fact;
00464 }
00465 }
00466
00467 delete [] newID;
00468 delete [] v;
00469 delete [] id;
00470
00471 return 0;
00472 }
00473
00474
00475 int
00476 SymSparseLinSOE::setB(const Vector &v, double fact)
00477 {
00478
00479 if (fact == 0.0) return 0;
00480
00481 if (v.Size() != size) {
00482 opserr << "WARNING SymSparseLinSOE::setB() -";
00483 opserr << " incomptable sizes " << size << " and " << v.Size() << endln;
00484 return -1;
00485 }
00486
00487 if (fact == 1.0) {
00488 for (int i=0; i<size; i++) {
00489 B[i] = v(i);
00490 }
00491 } else if (fact == -1.0) {
00492 for (int i=0; i<size; i++) {
00493 B[i] = -v(i);
00494 }
00495 } else {
00496 for (int i=0; i<size; i++) {
00497 B[i] = v(i) * fact;
00498 }
00499 }
00500 return 0;
00501 }
00502
00503
00504
00505
00506
00507
00508
00509 void SymSparseLinSOE::zeroA(void)
00510 {
00511 memset(diag, 0, size*sizeof(double));
00512
00513 int profileSize = penv[size] - penv[0];
00514 memset(penv[0], 0, profileSize*sizeof(double));
00515
00516 OFFDBLK *blkPtr = first;
00517 int rLen = 0;
00518 while (1) {
00519 if (blkPtr->beg == size) break;
00520 rLen = xblk[rowblks[blkPtr->beg]+1] - blkPtr->beg;
00521 memset(blkPtr->nz, 0, rLen*sizeof(double));
00522
00523 blkPtr = blkPtr->next;
00524 }
00525
00526 factored = false;
00527 }
00528
00529 void
00530 SymSparseLinSOE::zeroB(void)
00531 {
00532 double *Bptr = B;
00533 for (int i=0; i<size; i++)
00534 *Bptr++ = 0;
00535 }
00536
00537 void
00538 SymSparseLinSOE::setX(int loc, double value)
00539 {
00540 if (loc < size && loc >=0)
00541 X[loc] = value;
00542 }
00543
00544 void
00545 SymSparseLinSOE::setX(const Vector &x)
00546 {
00547 if (x.Size() == size && vectX != 0)
00548 *vectX = x;
00549 }
00550
00551
00552 const Vector &
00553 SymSparseLinSOE::getX(void)
00554 {
00555 if (vectX == 0) {
00556 opserr << "FATAL SymSparseLinSOE::getX - vectX == 0";
00557 exit(-1);
00558 }
00559 return *vectX;
00560 }
00561
00562 const Vector &
00563 SymSparseLinSOE::getB(void)
00564 {
00565 if (vectB == 0) {
00566 opserr << "FATAL SymSparseLinSOE::getB - vectB == 0";
00567 exit(-1);
00568 }
00569 return *vectB;
00570 }
00571
00572 double
00573 SymSparseLinSOE::normRHS(void)
00574 {
00575 double norm =0.0;
00576 for (int i=0; i<size; i++) {
00577 double Yi = B[i];
00578 norm += Yi*Yi;
00579 }
00580 return sqrt(norm);
00581 }
00582
00583
00584
00585
00586 int SymSparseLinSOE::setSymSparseLinSolver(SymSparseLinSolver &newSolver)
00587 {
00588 newSolver.setLinearSOE(*this);
00589
00590 if (size != 0) {
00591 int solverOK = newSolver.setSize();
00592 if (solverOK < 0) {
00593 opserr << "WARNING:SymSparseLinSOE::setSolver :";
00594 opserr << "the new solver could not setSeize() - staying with old\n";
00595 return -1;
00596 }
00597 }
00598
00599 return this->LinearSOE::setSolver(newSolver);
00600 }
00601
00602
00603 int
00604 SymSparseLinSOE::sendSelf(int cTag, Channel &theChannel)
00605 {
00606
00607 return 0;
00608 }
00609
00610
00611 int
00612 SymSparseLinSOE::recvSelf(int cTag,
00613 Channel &theChannel, FEM_ObjectBroker &theBroker)
00614 {
00615
00616 return 0;
00617 }
00618