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 #ifndef MECHSYS_LINALG_LAWRAP_H
00035 #define MECHSYS_LINALG_LAWRAP_H
00036
00037
00038 #include <cassert>
00039 #include <map>
00040
00041
00042 #ifdef USE_UMFPACK
00043 #include <umfpack.h>
00044 #endif
00045
00046
00047 #ifdef USE_SCALAPACK
00048 #include <mpi.h>
00049 #endif
00050
00051
00052
00053
00054 #ifdef HAVE_CONFIG_H
00055 #include "config.h"
00056 #else
00057 #ifndef REAL
00058 #define REAL double
00059 #endif
00060 #endif
00061
00062
00063 #include "linalg/matrix.h"
00064 #include "linalg/vector.h"
00065 #include "util/exception.h"
00066 #include "util/util.h"
00067
00068 #ifdef USE_SCALAPACK
00069 #include "linalg/scalpk.h"
00070 #endif
00071
00072 extern "C"
00073 {
00074
00075 void dscal_(int const *N, double const *alpha, double *X, int const *incX);
00076
00077 void dcopy_(int const *N, double const *X, int const *incX, double *Y, int const *incY);
00078
00079 void daxpy_(int const *N, double const *alpha, double const *X, int const *incX, double *Y, int const *incY);
00080
00081 double ddot_(int const *N, double const *X, int const *incX, double const *Y, int const *incY);
00082
00083 void dsymv_(char const *Uplo, int const *N, double const *alpha, double const *A,
00084 int const *lda , double const *X, int const *incX , double const *beta,
00085 double *Y , int const *incY);
00086
00087 void dgemv_(char const *TransA , int const *M , int const *N , double const *alpha ,
00088 double const *A , int const *lda , double const *X , int const *incX ,
00089 double const *beta , double *Y , int const *incY);
00090
00091 void dgemm_(char const *TransA , char const *TransB , int const *M , int const *N ,
00092 int const *K , double const *alpha , double const *A , int const *lda ,
00093 double const *B , int const *ldb , double const *beta , double *C , int const *ldc);
00094
00095 void dger_(int const *M , int const *N, double const *alpha, double const *X,
00096 int const *incX, double const *Y, int const *incY , double *A, int const *lda);
00097
00098
00099 #if defined (USE_LAPACK) || defined (USE_GOTOBLAS)
00100 #ifdef USE_FLOAT
00101 void sgesv_(int *Np, int *NRHSp,
00102 float *A, int *LDAp, int *IPIVp,
00103 float *B, int *LDBp, int *INFOp);
00104 #else
00105 void dgesv_(int *Np, int *NRHSp,
00106 double *A, int *LDAp, int *IPIVp,
00107 double *B, int *LDBp, int *INFOp);
00108 #endif // #ifdef USE_FLOAT
00109 #endif // #if defined (USE_LAPACK) || defined (USE_GOTOBLAS)
00110
00111
00112 #ifdef USE_LAPACK
00113 #ifdef USE_FLOAT
00114 float slamch_ (char *CMACHp);
00115 void sgtsv_ (int *Np, int *NRHSp, float *DL, float *D, float *DU, float *B, int *LDBp, int *INFOp);
00116 void ssyevr_ (char *JOBZp, char *RANGEp, char *UPLOp, int *Np, float *A, int *LDAp, float *VLp, float *VUp,
00117 int *ILp, int *IUp, float *ABSTOLp, int *Mp, float *W, float *Z, int *LDZp, int *ISUPPZ,
00118 float *WORK, int *LWORKp, int *IWORK, int *LIWORKp, int *INFOp);
00119 #else
00120 double dlamch_ (char *CMACHp);
00121 void dgtsv_ (int *Np, int *NRHSp, double *DL, double *D, double *DU, double *B, int *LDBp, int *INFOp);
00122 void dsyevr_ (char *JOBZp, char *RANGEp, char *UPLOp, int *Np, double *A, int *LDAp, double *VLp, double *VUp,
00123 int *ILp, int *IUp, double *ABSTOLp, int *Mp, double *W, double *Z, int *LDZp, int *ISUPPZ,
00124 double *WORK, int *LWORKp, int *IWORK, int *LIWORKp, int *INFOp);
00125 #endif // #ifdef USE_FLOAT
00126 #endif // #ifdef USE_LAPACK
00127
00128 }
00129
00130 namespace LinAlg
00131 {
00132
00194
00200
00201
00202
00208
00209
00210
00212 inline void Scal(REAL const a,
00213 Vector<REAL> & X)
00214 {
00215 int N = X.Size();
00216 #ifdef USE_FLOAT
00217 throw new Fatal(_("LinAlg::Scal not yet."));
00218
00219 #else
00220 int incX = 1;
00221 dscal_(&N,&a,X.GetPtr(),&incX);
00222 #endif // #ifdef USE_FLOAT
00223 }
00224
00225
00227 inline void Copy(Vector<REAL> const & X,
00228 Vector<REAL> & Y)
00229 {
00230 int N = X.Size();
00231 assert(Y.Size()==N);
00232 #ifdef USE_FLOAT
00233 throw new Fatal(_("LinAlg::Copy not yet."));
00234
00235 #else
00236 int incX = 1;
00237 int incY = 1;
00238 dcopy_(&N,X.GetPtr(),&incX,Y.GetPtr(),&incY);
00239 #endif // #ifdef USE_FLOAT
00240 }
00241
00242
00244 inline void Axpy(REAL const a,
00245 Vector<REAL> const & X,
00246 Vector<REAL> & Y)
00247 {
00248 int N = X.Size();
00249 assert(Y.Size()==N);
00250 #ifdef USE_FLOAT
00251 throw new Fatal(_("LinAlg::Axpy not yet."));
00252
00253 #else
00254 int incX = 1;
00255 int incY = 1;
00256 daxpy_(&N,&a,X.GetPtr(),&incX,Y.GetPtr(),&incY);
00257 #endif // #ifdef USE_FLOAT
00258 }
00259
00260
00262
00263 #ifdef USE_FLOAT
00264 inline float Dot(Vector<REAL> const & X,
00265 Vector<REAL> const & Y)
00266 #else
00267 inline double Dot(Vector<REAL> const & X,
00268 Vector<REAL> const & Y)
00269 #endif // #ifdef USE_FLOAT
00270 {
00271 int N = X.Size();
00272 assert(Y.Size()==N);
00273 #ifdef USE_FLOAT
00274 throw new Fatal(_("LinAlg::Dot not yet."));
00275
00276 #else
00277 int incX = 1;
00278 int incY = 1;
00279 return ddot_(&N,X.GetPtr(),&incX,Y.GetPtr(),&incY);
00280 #endif // #ifdef USE_FLOAT
00281 }
00282
00283
00285 inline REAL Norm(Vector<REAL> const & X)
00286 {
00287 return sqrt(LinAlg::Dot(X,X));
00288 }
00289
00290
00292 inline void CopyScal(REAL const a,
00293 Vector<REAL> const & X,
00294 Vector<REAL> & Y)
00295 {
00296 assert(Y.Size()==X.Size());
00297 Copy(X,Y);
00298 Scal(a,Y);
00299 }
00300
00301
00303 inline void AddScaled(REAL const a,
00304 Vector<REAL> const & X,
00305 REAL const b,
00306 Vector<REAL> const & Y,
00307 Vector<REAL> & Z)
00308 {
00309 assert(Y.Size()==X.Size());
00310 Z.SetValues(0.0);
00311 Axpy(a,X,Z);
00312 Axpy(b,Y,Z);
00313 }
00314
00316
00317
00318
00324
00325
00326
00328
00343 inline void Symv(REAL const a,
00344 Matrix<REAL> const & A,
00345 Vector<REAL> const & X,
00346 REAL const b,
00347 Vector<REAL> & Y)
00348 {
00349 int N = A.Rows();
00350 assert(A.Cols()==N);
00351 assert(X.Size()==N);
00352 assert(Y.Size()==N);
00353 #ifdef USE_FLOAT
00354 throw new Fatal(_("LinAlg::Symv not yet."));
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 #else
00367 char Uplo = 'U';
00368 int incX = 1;
00369 int incY = 1;
00370 dsymv_(&Uplo,
00371 &N,
00372 &a,
00373 A.GetPtr(),
00374 &N,
00375 X.GetPtr(),
00376 &incX,
00377 &b,
00378 Y.GetPtr(),
00379 &incY);
00380 #endif // #ifdef USE_FLOAT
00381 }
00382
00383
00385
00401 inline void Gemv(REAL const a,
00402 Matrix<REAL> const & A,
00403 Vector<REAL> const & X,
00404 REAL const b,
00405 Vector<REAL> & Y)
00406 {
00407 int M = A.Rows();
00408 int N = A.Cols();
00409 assert(X.Size()==N);
00410 assert(Y.Size()==M);
00411 #ifdef USE_FLOAT
00412 throw new Fatal(_("LinAlg::Gemv not yet."));
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 #else
00426 char TransA = 'N';
00427 int incX = 1;
00428 int incY = 1;
00429 dgemv_(&TransA,
00430 &M,
00431 &N,
00432 &a,
00433 A.GetPtr(),
00434 &M,
00435 X.GetPtr(),
00436 &incX,
00437 &b,
00438 Y.GetPtr(),
00439 &incY);
00440 #endif // #ifdef USE_FLOAT
00441 }
00442
00443
00445 inline void Gemtv(REAL const a,
00446 Matrix<REAL> const & A,
00447 Vector<REAL> const & X,
00448 REAL const b,
00449 Vector<REAL> & Y)
00450 {
00451 int M = A.Rows();
00452 int N = A.Cols();
00453 assert(X.Size()==N);
00454 assert(Y.Size()==M);
00455 #ifdef USE_FLOAT
00456 throw new Fatal(_("LinAlg::Gemtv not yet."));
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 #else
00470 char TransA = 'T';
00471 int incX = 1;
00472 int incY = 1;
00473 dgemv_(&TransA,
00474 &M,
00475 &N,
00476 &a,
00477 A.GetPtr(),
00478 &M,
00479 X.GetPtr(),
00480 &incX,
00481 &b,
00482 Y.GetPtr(),
00483 &incY);
00484 #endif // #ifdef USE_FLOAT
00485 }
00486
00487
00489
00502 inline void Ger(REAL const a,
00503 Vector<REAL> const & X,
00504 Vector<REAL> const & Y,
00505 Matrix<REAL> & A)
00506 {
00507 int M = A.Rows();
00508 int N = A.Cols();
00509 assert(X.Size()==M);
00510 assert(Y.Size()==N);
00511 #ifdef USE_FLOAT
00512 throw new Fatal(_("LinAlg::Ger not yet."));
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 #else
00524 int incX = 1;
00525 int incY = 1;
00526 dger_(&M,
00527 &N,
00528 &a,
00529 X.GetPtr(),
00530 &incX,
00531 Y.GetPtr(),
00532 &incY,
00533 A.GetPtr(),
00534 &M);
00535 #endif // #ifdef USE_FLOAT
00536 }
00537
00538
00539
00540
00542
00549 inline void Gemvpmv(REAL const a,
00550 Matrix<REAL> const & A,
00551 Vector<REAL> const & X,
00552 REAL const b,
00553 Matrix<REAL> const & B,
00554 Vector<REAL> const & Y,
00555 Vector<REAL> & Z)
00556 {
00557 #ifndef NDEBUG
00558 int M = A.Rows();
00559 int N = A.Cols();
00560 int P = B.Cols();
00561 assert(B.Rows()==M);
00562 assert(X.Size()==N);
00563 assert(Y.Size()==P);
00564 assert(Z.Size()==M);
00565 #endif
00566 Gemv(a,A,X, 0.0,Z);
00567 Gemv(b,B,Y, 1.0,Z);
00568 }
00569
00570
00571
00573
00574
00575
00581
00582
00583
00585
00599 inline void Gemm(REAL const a,
00600 Matrix<REAL> const & A,
00601 Matrix<REAL> const & B,
00602 REAL const b,
00603 Matrix<REAL> & C)
00604 {
00605 int M = A.Rows();
00606 int K = A.Cols();
00607 int N = B.Cols();
00608 assert(B.Rows()==K);
00609 assert(C.Rows()==M); assert(C.Cols()==N);
00610 #ifdef USE_FLOAT
00611 throw new Fatal(_("LinAlg::Gemm not yet."));
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 #else
00627 char TransA='N';
00628 char TransB='N';
00629 dgemm_(&TransA,
00630 &TransB,
00631 &M,
00632 &N,
00633 &K,
00634 &a,
00635 A.GetPtr(),
00636 &M,
00637 B.GetPtr(),
00638 &K,
00639 &b,
00640 C.GetPtr(),
00641 &M);
00642 #endif // #ifdef USE_FLOAT
00643 }
00644
00645
00647 inline void Gemtm(REAL const a,
00648 Matrix<REAL> const & A,
00649 Matrix<REAL> const & B,
00650 REAL const b,
00651 Matrix<REAL> & C)
00652 {
00653 int K = A.Rows();
00654 int M = A.Cols();
00655 int N = B.Cols();
00656 assert(B.Rows()==K);
00657 assert(C.Rows()==M); assert(C.Cols()==N);
00658 #ifdef USE_FLOAT
00659 throw new Fatal(_("LinAlg::Gemtm not yet."));
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674 #else
00675 char TransA='T';
00676 char TransB='N';
00677 dgemm_(&TransA,
00678 &TransB,
00679 &M,
00680 &N,
00681 &K,
00682 &a,
00683 A.GetPtr(),
00684 &K,
00685 B.GetPtr(),
00686 &K,
00687 &b,
00688 C.GetPtr(),
00689 &M);
00690 #endif // #ifdef USE_FLOAT
00691 }
00692
00693
00695 inline void Gemmt(REAL const a,
00696 Matrix<REAL> const & A,
00697 Matrix<REAL> const & B,
00698 REAL const b,
00699 Matrix<REAL> & C)
00700 {
00701 int M = A.Rows();
00702 int K = A.Cols();
00703 int N = B.Rows();
00704 assert(B.Cols()==K);
00705 assert(C.Rows()==M); assert(C.Cols()==N);
00706 #ifdef USE_FLOAT
00707 throw new Fatal(_("LinAlg::Gemmt not yet."));
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722 #else
00723 char TransA='N';
00724 char TransB='T';
00725 dgemm_(&TransA,
00726 &TransB,
00727 &M,
00728 &N,
00729 &K,
00730 &a,
00731 A.GetPtr(),
00732 &M,
00733 B.GetPtr(),
00734 &N,
00735 &b,
00736 C.GetPtr(),
00737 &M);
00738 #endif // #ifdef USE_FLOAT
00739 }
00740
00741
00743 inline void Gemtmt(REAL const a,
00744 Matrix<REAL> const & A,
00745 Matrix<REAL> const & B,
00746 REAL const b,
00747 Matrix<REAL> & C)
00748 {
00749 int K = A.Rows();
00750 int M = A.Cols();
00751 int N = B.Rows();
00752 assert(B.Cols()==K);
00753 assert(C.Rows()==M); assert(C.Cols()==N);
00754 #ifdef USE_FLOAT
00755 throw new Fatal(_("LinAlg::Gemtmt not yet."));
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 #else
00771 char TransA='T';
00772 char TransB='T';
00773 dgemm_(&TransA,
00774 &TransB,
00775 &M,
00776 &N,
00777 &K,
00778 &a,
00779 A.GetPtr(),
00780 &K,
00781 B.GetPtr(),
00782 &N,
00783 &b,
00784 C.GetPtr(),
00785 &M);
00786 #endif // #ifdef USE_FLOAT
00787 }
00788
00790
00791
00793
00794
00795
00796
00797
00799
00808 inline int Gesv(Matrix<REAL> & A,
00809 Vector<REAL> & Y,
00810 bool DoPreserveA=false)
00811 {
00812 int info = 0;
00813
00814 #if (defined (USE_LAPACK) || defined (USE_GOTOBLAS))
00815
00816
00817
00818
00819 Matrix<REAL> * tmp_A;
00820
00821
00822 if (DoPreserveA==true) tmp_A = new Matrix<REAL> (A);
00823 else tmp_A = &A;
00824
00825
00826 int N = tmp_A->Rows();
00827 int NRHS = 1;
00828 assert(tmp_A->Cols()==N);
00829 assert(Y.Size()==N);
00830 int * ipiv = new int [N];
00831
00832 #ifdef USE_FLOAT
00833 sgesv_(&N,
00834 &NRHS,
00835 tmp_A->GetPtr(),
00836 &N,
00837 ipiv,
00838 Y.GetPtr(),
00839 &N,
00840 &info);
00841 #else
00842 dgesv_(&N,
00843 &NRHS,
00844 tmp_A->GetPtr(),
00845 &N,
00846 ipiv,
00847 Y.GetPtr(),
00848 &N,
00849 &info);
00850 #endif // #ifdef USE_FLOAT
00851
00852
00853 delete [] ipiv;
00854 if (DoPreserveA==true) delete tmp_A;
00855
00856
00857
00858 #elif (defined (USE_UMFPACK))
00859
00860
00861
00862
00863
00864
00865 const double ZEROELEM = 1.0e-9;
00866
00867
00868 int m = A.Rows();
00869 int n = A.Cols();
00870
00871
00872 int num_nonzero=0;
00873 for (int j=0; j<n; ++j)
00874 for (int i=0; i<m; ++i)
00875 if (fabs(A(i,j))>ZEROELEM) num_nonzero++;
00876
00877
00878 int * Ap = new int [n+1];
00879 int * Ai = new int [num_nonzero];
00880 double * Ax = new double [num_nonzero];
00881 for (int j=0; j<n; ++j) Ap[j]=-1;
00882
00883
00884 int k=0;
00885 for (int j=0; j<n; ++j)
00886 for (int i=0; i<m; ++i)
00887 {
00888 if (fabs(A(i,j))>ZEROELEM)
00889 {
00890 if (Ap[j]==-1)
00891 Ap[j]=k;
00892 Ai[k] = i;
00893 Ax[k] = A(i,j);
00894 k++;
00895 }
00896 }
00897 Ap[n] = num_nonzero;
00898
00899 #ifdef UMFPACK_DEBUG
00900
00901 cout << "num_nonzero = " << num_nonzero << endl;
00902 cout << "Ap = "; for (int j=0; j<n+1; ++j) cout<<Ap[j]<<" "; cout << endl;
00903 cout << "Ai = "; for (int i=0; i<k; ++i) cout<<Ai[i]<<" "; cout << endl;
00904 cout << "Ax = "; for (int i=0; i<k; ++i) cout<<Ax[i]<<" "; cout << endl;
00905 #endif
00906
00907
00908 Vector<REAL> b(Y);
00909 double *null = (double *)NULL;
00910 void *Symbolic, *Numeric;
00911 info = umfpack_di_symbolic (n, n, Ap, Ai, Ax, &Symbolic, null, null);
00912 info += umfpack_di_numeric (Ap, Ai, Ax, Symbolic, &Numeric, null, null);
00913 umfpack_di_free_symbolic (&Symbolic);
00914 info += umfpack_di_solve (UMFPACK_A, Ap, Ai, Ax, Y.GetPtr(), b.GetPtr(), Numeric, null, null);
00915 umfpack_di_free_numeric (&Numeric);
00916
00917
00918 delete [] Ap;
00919 delete [] Ai;
00920 delete [] Ax;
00921
00922
00923
00924 #elif (defined (USE_SCALAPACK))
00925
00926
00927
00928
00929
00930
00931 int size = MPI::COMM_WORLD.Get_size();
00932
00933
00934 int nprow = -1;
00935 int npcol = -1;
00936 Util::FindBestSquare(size, nprow,npcol);
00937 if ((nprow<1) || (npcol<1))
00938 {
00939 MPI::Finalize();
00940 throw new Fatal(_("LinAlg::Gesv::ScaLAPACK: Could not find nprow=%d and npcol=%d"),nprow,npcol);
00941 }
00942
00943
00944 int N = A.Rows();
00945 int NRHS = 1;
00946 int nb = 2;
00947 if ((N/nprow)<(N/npcol)) nb=(N/nprow);
00948 else nb=(N/npcol);
00949 if (nb<1) nb=1;
00950 if (nb>64) nb=64;
00951
00952
00953 #ifdef SCALAPACK_DEBUG
00954 nprow=2;
00955 npcol=3;
00956 nb =2;
00957 if (size!=6)
00958 {
00959 MPI::Finalize();
00960 throw new Fatal(_("LinAlg::Gesv::ScaLAPACK: The number of process for DEBUG must be equal to 6"));
00961 }
00962 #endif
00963
00964
00965 if (nb>N) nb=N;
00966 if (nprow*npcol>size)
00967 {
00968 MPI::Finalize();
00969 throw new Fatal(_("LinAlg::Gesv::ScaLAPACK: There is not enough processes (%d<%d) to make a %d-by-%d process grid"),size,nprow*npcol,nprow,npcol);
00970 }
00971
00972
00973 int iam, nprocs, ictxt;
00974 int myrow, mycol;
00975 Cblacs_pinfo (&iam, &nprocs);
00976 Cblacs_get (-1, 0, &ictxt);
00977 Cblacs_gridinit (&ictxt, "Col-major", nprow, npcol);
00978 Cblacs_gridinfo (ictxt, &nprow, &npcol, &myrow, &mycol);
00979
00980 #ifdef SCALAPACK_DEBUG
00981
00982 String msg, buf;
00983 msg.Printf("Hi, I'am {%d,%d}: nprow=%d, npcol=%d, nb=%d",myrow,mycol,nprow,npcol,nb);
00984 std::map<int,String> letters;
00985 letters[19]="S"; letters[-19]="-S";
00986 letters[ 3]="C"; letters[ -3]="-C";
00987 letters[ 1]="A"; letters[ -1]="-A";
00988 letters[12]="L"; letters[-12]="-L";
00989 letters[16]="P"; letters[-16]="-P";
00990 letters[11]="K"; letters[-11]="-K";
00991 msg.append(" A =\n");
00992 int rank = MPI::COMM_WORLD.Get_rank();
00993 if (rank==0)
00994 {
00995 for (int i=0; i<A.Rows(); ++i)
00996 {
00997 for (int j=0; j<A.Rows(); ++j)
00998 {
00999 buf.Printf(" %2s",letters[static_cast<int>(A(i,j))].GetSTL().c_str());
01000 msg.append(buf);
01001 }
01002 msg.append("\n");
01003 }
01004 }
01005 #endif
01006
01007
01008 if ((myrow>-1)&&(mycol>-1)&&(myrow<nprow)&&(mycol<npcol))
01009 {
01010
01011 int isrc = 0;
01012 int m_loc_A = numroc_(&N , &nb, &myrow, &isrc, &nprow);
01013 int n_loc_A = numroc_(&N , &nb, &mycol, &isrc, &npcol);
01014 int n_loc_b = numroc_(&NRHS, &nb, &mycol, &isrc, &npcol);
01015
01016
01017
01018 #ifdef SCALAPACK_DEBUG
01019
01020 buf.Printf(" m_loc_A=%d, n_loc_A=%d, n_loc_b=%d\n", m_loc_A,n_loc_A,n_loc_b);
01021 msg.append(buf);
01022 #endif
01023
01024
01025 double * loc_A = new double [m_loc_A*n_loc_A];
01026 double * loc_b = NULL;
01027 if (n_loc_b>0)
01028 loc_b = new double [m_loc_A*n_loc_b];
01029
01030
01031 int loc_ld_A = Util::Max(1,m_loc_A);
01032 int loc_ld_b = loc_ld_A;
01033 int desc_A[9];
01034 int desc_b[9];
01035 descinit_(desc_A, &N, &N , &nb, &nb, &isrc, &isrc, &ictxt, &loc_ld_A, &info);
01036 descinit_(desc_b, &N, &NRHS, &nb, &nb, &isrc, &isrc, &ictxt, &loc_ld_b, &info);
01037
01038
01039 for (int i_loc=0; i_loc<m_loc_A; i_loc++)
01040 {
01041 int i_glob = IndxL2G(i_loc, nb, myrow, isrc, nprow);
01042 for (int j_loc=0; j_loc<n_loc_A; j_loc++)
01043 {
01044 int j_glob = IndxL2G(j_loc, nb, mycol, isrc, npcol);
01045 #ifdef SCALAPACK_DEBUG
01046
01047 buf.Printf(" [%d,%d]=A(%d,%d)=%2s",i_loc,j_loc,i_glob,j_glob,letters[static_cast<int>(A(i_glob,j_glob))].GetSTL().c_str());
01048 msg.append(buf);
01049 #endif
01050
01051 loc_A[j_loc*m_loc_A+i_loc] = A(i_glob,j_glob);
01052 }
01053 #ifdef SCALAPACK_DEBUG
01054
01055 msg.append("\n");
01056 #endif
01057
01058 if (n_loc_b>0) loc_b[i_loc] = Y(i_glob);
01059 }
01060
01061
01062 int * ippiv = new int [m_loc_A+nb];
01063
01064
01065 int ione = 1;
01066 #ifdef SCALAPACK_DEBUG
01067 double tini = MPI::Wtime();
01068 #endif
01069
01070 pdgesv_(&N, &NRHS, loc_A, &ione, &ione, desc_A, ippiv, loc_b, &ione, &ione, desc_b, &info);
01071
01072 #ifdef SCALAPACK_DEBUG
01073
01074 double tfin = MPI::Wtime();
01075 if (n_loc_b>0)
01076 {
01077 msg.append("\n loc_b = ");
01078 for (int i_loc=0; i_loc<m_loc_A; i_loc++)
01079 {
01080 buf.Printf("%12f ",loc_b[i_loc]);
01081 msg.append(buf);
01082 }
01083 msg.append("\n\n");
01084 }
01085 buf.Printf(" Elapsed time = %f\n",tfin-tini);
01086 msg.append(buf);
01087 #endif
01088
01089
01090 int lld_Y = N;
01091 int desc_Y[9];
01092 int my = N*nprow;
01093 int ny = NRHS*npcol;
01094 descinit_(desc_Y, &my, &ny, &N, &NRHS, &isrc, &isrc, &ictxt, &lld_Y, &info);
01095 for (int i=0; i<nprow; ++i)
01096 {
01097 int istart = i*N+1;
01098 for (int j=0; j<npcol; ++j)
01099 {
01100 int jstart = j*NRHS+1;
01101 Cpdgemr2d(N,NRHS,loc_b,1,1,desc_b, Y.GetPtr(),istart,jstart,desc_Y,ictxt);
01102 }
01103 }
01104
01105
01106 Cblacs_barrier(ictxt, "All");
01107
01108 #ifdef SCALAPACK_DEBUG
01109
01110 msg.append("\n\n Solution: Y = ");
01111 for (int i=0; i<Y.Size(); ++i)
01112 {
01113 buf.Printf("%e ",Y(i));
01114 msg.append(buf);
01115 }
01116 msg.append("\n\n");
01117 std::cout<<msg<<std::endl;
01118 #endif
01119
01120
01121 delete [] loc_A;
01122 if (n_loc_b>0)
01123 delete [] loc_b;
01124 delete [] ippiv;
01125
01126
01127 Cblacs_gridexit(0);
01128 }
01129
01130
01131
01132 #else
01133 throw new Fatal(_("LinAlg::Gesv: Low level solver {dgesv_, pdgesv_, ...} is not available"));
01134 #endif
01135
01136 if (info!=0)
01137 {
01138 #ifdef USE_SCALAPACK
01139 MPI::Finalize();
01140 #endif
01141 throw new Fatal(_("LinAlg::Gesv: info=%d means that dgesv routine failed"),info);
01142 }
01143 return info;
01144 }
01145
01146
01147
01148 #ifdef USE_LAPACK
01149
01150
01151
01152
01154
01173 inline int Gtsv(Vector<REAL> & DL,
01174 Vector<REAL> & D,
01175 Vector<REAL> & DU,
01176 Vector<REAL> & Y)
01177 {
01178 int N = D.Size();
01179 int NRHS = 1;
01180 assert(Y.Size()==N);
01181 assert(DL.Size()==N-1);
01182 assert(DU.Size()==N-1);
01183 int info;
01184 #ifdef USE_FLOAT
01185 sgtsv_(&N,
01186 &NRHS,
01187 DL.GetPtr(),
01188 D.GetPtr(),
01189 DU.GetPtr(),
01190 Y.GetPtr(),
01191 &N,
01192 &info);
01193 #else
01194 dgtsv_(&N,
01195 &NRHS,
01196 DL.GetPtr(),
01197 D.GetPtr(),
01198 DU.GetPtr(),
01199 Y.GetPtr(),
01200 &N,
01201 &info);
01202 #endif // #ifdef USE_FLOAT
01203 return info;
01204 }
01205
01206
01207
01208 #endif
01209
01210
01211
01212 #ifdef USE_LAPACK
01213
01214
01215
01216
01218 inline int Syevr(Matrix<REAL> & A,
01219 Vector<REAL> & L,
01220 Matrix<REAL> & Q)
01221 {
01222 int N = A.Rows();
01223 assert(A.Cols()==N);
01224 assert(L.Size()==N);
01225 assert(Q.Rows()==N); assert(Q.Cols()==N);
01226 char jobz = 'V';
01227 char range = 'A';
01228 char uplo = 'L';
01229 REAL vl,vu;
01230 int il,iu;
01231 char cmach = 'S';
01232 #ifdef USE_FLOAT
01233 REAL abstol = slamch_(&cmach);
01234 #else
01235 REAL abstol = dlamch_(&cmach);
01236 #endif
01237 int m;
01238 int * isuppz = new int [2*N];
01239 int lwork = 26*N;
01240 REAL * work = new REAL [lwork];
01241 int liwork = 10*N;
01242 int * iwork = new int [liwork];
01243 int info;
01244 #ifdef USE_FLOAT
01245 ssyevr_(&jobz,
01246 &range,
01247 &uplo,
01248 &N,
01249 A.GetPtr(),
01250 &N,
01251 &vl,
01252 &vu,
01253 &il,
01254 &iu,
01255 &abstol,
01256 &m,
01257 L.GetPtr(),
01258 Q.GetPtr(),
01259 &N,
01260 isuppz,
01261 work,
01262 &lwork,
01263 iwork,
01264 &liwork,
01265 &info);
01266 #else
01267 dsyevr_(&jobz,
01268 &range,
01269 &uplo,
01270 &N,
01271 A.GetPtr(),
01272 &N,
01273 &vl,
01274 &vu,
01275 &il,
01276 &iu,
01277 &abstol,
01278 &m,
01279 L.GetPtr(),
01280 Q.GetPtr(),
01281 &N,
01282 isuppz,
01283 work,
01284 &lwork,
01285 iwork,
01286 &liwork,
01287 &info);
01288 #endif // #ifdef USE_FLOAT
01289 delete [] iwork;
01290 delete [] work;
01291 delete [] isuppz;
01292 return info;
01293 }
01294
01295
01296
01297
01303
01304
01305
01307 inline int Syep(Matrix<REAL> & A,
01308 Vector<REAL> & L,
01309 Matrix<REAL> P[])
01310 {
01311 int N = A.Rows();
01312 assert(A.Cols()==N);
01313 assert(L.Size()==N);
01314 int info;
01315 Matrix<REAL> Q(N,N);
01316 info = Syevr(A,L,Q);
01317 if (info==0)
01318 {
01319 for (int i=0; i<N; ++i)
01320 {
01321 assert(P[i].Rows()==N); assert(P[i].Cols()==N);
01322 P[i].SetValues(0.0);
01323 #ifdef USE_FLOAT
01324 throw new Fatal(_("LinAlg::Syep not yet."));
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335 #else
01336 throw new Fatal(_("LinAlg::Syep not yet."));
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 #endif // #ifdef USE_FLOAT
01348 }
01349 }
01350 return info;
01351 }
01352
01353
01355 inline int Syif(Matrix<REAL> & A ,
01356 Matrix<REAL> & IF ,
01357 REAL (*func) (REAL))
01358 {
01359 int N = A.Rows();
01360 assert(A.Cols()==N);
01361 assert(IF.Rows()==N); assert(IF.Cols()==N);
01362 int info;
01363 REAL alpha;
01364 Matrix<REAL> Q(N,N);
01365 Vector<REAL> L(N);
01366 info = Syevr(A,L,Q);
01367 if (info==0)
01368 {
01369 IF.SetValues(0.0);
01370 for (int i=0; i<N; ++i)
01371 {
01372 alpha = (*func) (L(i));
01373 #ifdef USE_FLOAT
01374 throw new Fatal(_("LinAlg::Syif not yet."));
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 #else
01386 throw new Fatal(_("LinAlg::Syif not yet."));
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 #endif // #ifdef USE_FLOAT
01398 }
01399 }
01400 return info;
01401 }
01402
01404
01405
01406 #endif
01407
01409
01410 };
01411
01412 #endif //#define MECHSYS_LINALG_LAWRAP_H
01413
01414