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 <DistributedSuperLU.h>
00033 #include <SparseGenColLinSOE.h>
00034 #include <f2c.h>
00035 #include <math.h>
00036 #include <Channel.h>
00037 #include <FEM_ObjectBroker.h>
00038 #include <ID.h>
00039
00040 DistributedSuperLU::DistributedSuperLU(int npR, int npC)
00041 :SparseGenColLinSolver(SOLVER_TAGS_DistributedSuperLU),
00042 gridInit(false), npRow(npR), npCol(npC),
00043 processID(0), numChannels(0), theChannels(0)
00044 {
00045
00046 }
00047
00048
00049 DistributedSuperLU::DistributedSuperLU()
00050 :SparseGenColLinSolver(SOLVER_TAGS_DistributedSuperLU),
00051 gridInit(false), npRow(0), npCol(0),
00052 processID(0), numChannels(0), theChannels(0)
00053 {
00054
00055 }
00056
00057
00058 DistributedSuperLU::~DistributedSuperLU()
00059 {
00060
00061 ScalePermstructFree(&ScalePermstruct);
00062 LUstructFree(&LUstruct);
00063
00064
00065
00066 if (theChannels != 0)
00067 delete [] theChannels;
00068
00069
00070 }
00071
00072 int
00073 DistributedSuperLU::solve(void)
00074 {
00075 if (theSOE == 0) {
00076 opserr << "WARNING DistributedSuperLU::solve(void)- ";
00077 opserr << " No LinearSOE object has been set\n";
00078 return -1;
00079 }
00080
00081
00082 if (theSOE->size == 0)
00083 return 0;
00084
00085
00086 if (processID != 0) {
00087 Channel *theChannel = theChannels[0];
00088 theChannel->recvVector(0, 0, (*theSOE->vectB));
00089 Vector vectA(theSOE->A, theSOE->nnz);
00090 theChannel->recvVector(0, 0, vectA);
00091 }
00092
00093
00094
00095
00096
00097 else {
00098
00099 Vector vectA(theSOE->A, theSOE->nnz);
00100
00101
00102 for (int j=0; j<numChannels; j++) {
00103 Channel *theChannel = theChannels[j];
00104 theChannel->sendVector(0, 0, *(theSOE->vectB));
00105 theChannel->sendVector(0, 0, vectA);
00106 }
00107 }
00108
00109 int info;
00110
00111 int iam = grid.iam;
00112
00113 if (iam < (npRow * npCol)) {
00114 int n = theSOE->size;
00115 int nnz = theSOE->nnz;
00116 int ldb = n;
00117 int nrhs = 1;
00118 static double berr[1];
00119
00120
00121 double *Xptr = theSOE->X;
00122 double *Bptr = theSOE->B;
00123
00124 for (int i=0; i<n; i++)
00125 *(Xptr++) = *(Bptr++);
00126 Xptr = theSOE->X;
00127
00128
00129
00130
00131
00132
00133
00134 if ((options.Fact == FACTORED) && (theSOE->factored == false)) {
00135 options.Fact = SamePattern;
00136 for (int i=0; i<nnz; i++) rowA[i] = theSOE->rowA[i];
00137 }
00138
00139
00140
00141
00142
00143 pdgssvx_ABglobal(&options, &A, &ScalePermstruct, Xptr, ldb, nrhs, &grid,
00144 &LUstruct, berr, &stat, &info);
00145
00146 if (theSOE->factored == false) {
00147 options.Fact = FACTORED;
00148 theSOE->factored = true;
00149 }
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 return 0;
00170 }
00171
00172 int
00173 DistributedSuperLU::setSize()
00174 {
00175 int n = theSOE->size;
00176
00177
00178
00179
00180 if (gridInit == false) {
00181
00182 MPI_Comm comm_world;
00183 MPI_Group group_world;
00184
00185 comm_world = MPI_COMM_WORLD;
00186 MPI_Comm_group(comm_world, &group_world);
00187
00188
00189 MPI_Comm_create(comm_world, group_world, &comm_SuperLU);
00190
00191 superlu_gridinit(comm_SuperLU, npRow, npCol, &grid);
00192
00193
00194 } else {
00195 Destroy_LU(theSOE->size, &grid, &LUstruct);
00196 ScalePermstructFree(&ScalePermstruct);
00197 LUstructFree(&LUstruct);
00198 }
00199
00200
00201
00202
00203 PStatInit(&stat);
00204
00205
00206
00207
00208
00209 if (n > 0) {
00210
00211
00212 int nnz = theSOE->nnz;
00213 rowA = new int[nnz];
00214 for (int i=0; i<nnz; i++) rowA[i] = theSOE->rowA[i];
00215
00216 dCreate_CompCol_Matrix_dist(&A, n, n, nnz, theSOE->A,
00217 rowA, theSOE->colStartA,
00218 SLU_NC, SLU_D, SLU_GE);
00219
00220
00221
00222
00223
00224 ScalePermstructInit(n, n, &ScalePermstruct);
00225 LUstructInit(n, n, &LUstruct);
00226 }
00227
00228
00229
00230
00231
00232 set_default_options_Distributed(&options);
00233
00234
00235
00236
00237 PStatInit(&stat);
00238
00239 return 0;
00240 }
00241
00242
00243 int
00244 DistributedSuperLU::setProcessID(int dTag)
00245 {
00246 processID = dTag;
00247 return 0;
00248 }
00249
00250 int
00251 DistributedSuperLU::setChannels(int nChannels, Channel **theC)
00252 {
00253 numChannels = nChannels;
00254
00255 if (theChannels != 0)
00256 delete [] theChannels;
00257
00258 theChannels = new Channel *[numChannels];
00259 if (theChannels == 0) {
00260 opserr << "DistributedSuperLU::sendSelf() - failed to allocate channel array of size: " <<
00261 numChannels << endln;
00262 return -1;
00263 }
00264
00265 for (int i=0; i<numChannels; i++)
00266 theChannels[i] = theC[i];
00267
00268 return 0;
00269 }
00270
00271 int
00272 DistributedSuperLU::sendSelf(int cTag, Channel &theChannel)
00273 {
00274 int sendID =0;
00275
00276
00277
00278
00279
00280
00281 if (processID == 0) {
00282
00283
00284 bool found = false;
00285 for (int i=0; i<numChannels; i++)
00286 if (theChannels[i] == &theChannel) {
00287 sendID = i+1;
00288 found = true;
00289 }
00290
00291
00292 if (found == false) {
00293 int nextNumChannels = numChannels + 1;
00294 Channel **nextChannels = new Channel *[nextNumChannels];
00295 if (nextNumChannels == 0) {
00296 opserr << "DistributedSuperLU::sendSelf() - failed to allocate channel array of size: " <<
00297 nextNumChannels << endln;
00298 return -1;
00299 }
00300 for (int i=0; i<numChannels; i++)
00301 nextChannels[i] = theChannels[i];
00302 nextChannels[numChannels] = &theChannel;
00303
00304 numChannels = nextNumChannels;
00305
00306 if (theChannels != 0)
00307 delete [] theChannels;
00308
00309 theChannels = nextChannels;
00310
00311
00312 sendID = numChannels;
00313 }
00314
00315 } else
00316 sendID = processID;
00317
00318 static ID idData(3);
00319 idData(0) = sendID;
00320 idData(1) = npRow;
00321 idData(2) = npCol;
00322 int res = theChannel.sendID(0, cTag, idData);
00323 if (res < 0) {
00324 opserr <<"WARNING DistributedSuperLU::sendSelf() - failed to send data\n";
00325 return -1;
00326 }
00327 return 0;
00328 }
00329
00330 int
00331 DistributedSuperLU::recvSelf(int cTag,
00332 Channel &theChannel,
00333 FEM_ObjectBroker &theBroker)
00334 {
00335 static ID idData(3);
00336
00337 int res = theChannel.recvID(0, cTag, idData);
00338 if (res < 0) {
00339 opserr <<"WARNING DistributedSuperLU::recvSelf() - failed to receive data\n";
00340 return -1;
00341 }
00342
00343 processID = idData(0);
00344 npRow = idData(1);
00345 npCol = idData(2);
00346
00347 numChannels = 1;
00348 theChannels = new Channel *[1];
00349 theChannels[0] = &theChannel;
00350
00351 return 0;
00352 }
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363