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