/* $Id: sysmatma28.cc,v 1.4 1996/10/11 09:10:09 roitzsch Exp $ (C)opyright 1996 by Konrad-Zuse-Center, Berlin All rights reserved. Part of the Kaskade distribution */ #include "sysmatma28.h" #include "utils.h" #include "numerics.h" #include "cmdpars.h" extern CmdPars Cmd; //------------------------------------------------------------------------- extern "C" { void F77NAME(ma28adint,MA28ADINT)(int* N, int* NZ, double* A, int* LICN, int* IRN, int* LIRN, int* ICN, double* U, int* IKEEP, int* IW, double* W, int* FLAG, int* nsearch, int* rncp, int* cncp, int* iMinIRN, int* iMinICN, double* TOL, int* NDROP); void F77NAME(ma28cdint,MA28CDINT)(int* N, double* A, int* LICN, int* ICN, int* IKEEP, double* rhs, double* W, int* MTYPE); void F77NAME(madc28adint,MAC28ADINT)(int* N, int* NZ, Complex* A, int* LICN, int* IRN, int* LIRN, int* ICN, double* U, int* IKEEP, int* IW, Complex* W, int* FLAG, int* nsearch, int* rncp, int* cncp, int* iMinIRN, int* iMinICN, double* TOL, int* NDROP); void F77NAME(madc28cdint,MADC28CDINT)(int* N, Complex* A, int* LICN, int* ICN, int* IKEEP, Complex* rhs, Complex* W, int* MTYPE); }; //------------------------------------------------------------------------- //------------------------------------------------------------------------- MA28Matrix:: MA28Matrix(int spaceDim0) : spaceDim(spaceDim0), A(0,0), W(0,0), IRN(0,0), ICN(0,0), IKEEP(0,0), IW(0,0) { NZ = LICN = LIRN = 0; defDropTol = 1e-8; Cmd.get("defDropTol", &defDropTol); UPivot = 0.1; Cmd.get("UPivot", &UPivot); ICNFactor = 1.0; Cmd.get("ICNFactor", &ICNFactor); IRNFactor = 1.0; Cmd.get("IRNFactor", &IRNFactor); NSearch = 1; Cmd.get("nsearch", &NSearch); infoLinSystem = 0; Cmd.get("infoLinSystem", &infoLinSystem); } //------------------------------------------------------------------------- void MA28Matrix:: MA28RemoveLUFactorization() { A.resize(0,0); W.resize(0,0); IW.resize(0,0); IRN.resize(0,0); ICN.resize(0,0); IKEEP.resize(0,0); } //------------------------------------------------------------------------- void MA28Matrix:: MA28Decompose(Real dropTol) { int rncp, cncp, MINIRN, MINICN, NDROP, FLAG, extend, maxExtend = 3; countEntries(&N, &NZ); MA28ResizeArrays(dropTol); fillMA28Vectors(); if (equal(dropTol, 0.0)) dropTol = defDropTol; Real absTol = dropTol * minDiag(); for (extend=0; extend<=maxExtend; ++extend) { #if (ComplexVersion) F77NAME(madc28adint,MADC28ADINT)(&N, &NZ, A.v, &LICN, IRN.v, &LIRN, ICN.v, &UPivot, IKEEP.v, IW.v, W.v, &FLAG, &NSearch, &rncp, &cncp, &MINIRN, &MINICN, &absTol, &NDROP); #else F77NAME(ma28adint,MA28ADINT)(&N, &NZ, A.v, &LICN, IRN.v, &LIRN, ICN.v, &UPivot, IKEEP.v, IW.v, W.v, &FLAG, &NSearch, &rncp, &cncp, &MINIRN, &MINICN, &absTol, &NDROP); #endif if (infoLinSystem) { double space = double(MA28MemSpace())/1e6; cout << Form("\n MA28 Decomposition: FLAG = %1d", FLAG); cout << Form(" N = %1d Entries = %1d (%1.6f MB)", N, NZ, space); } if (FLAG == 0) break; // successful decomposition else if (FLAG <= -3 && FLAG >= -6) // space in IRN/ICN not sufficient { MA28ExtendArrays(FLAG); fillMA28Vectors(); } else { cout << "\n*** MA28Decompose failed: FLAG = " << FLAG << "\n"; cout.flush(); abort(); } } if (extend > maxExtend) { cout << "\n*** MA28Decompose failed. Increase ICNFact and/or IRNFact!\n"; cout.flush(); abort(); } IRN.resize(0,0); if (infoLinSystem) { cout << Form("\n U = %1.2f NSearch = %1d", UPivot, NSearch); cout << Form(" irncp=%1d icncp=%1d fill-in: %1d (f=%1.2f)", rncp, cncp, MINICN-NZ, Real(MINICN-NZ)/Real(NZ)); cout << Form("\n MINICN=%1d (%1.2f LICN=%1d)", MINICN, Real(MINICN)/LICN, LICN); cout << Form(" MINIRN=%1d (%1.2f LIRN=%1d)\n", MINIRN, Real(MINIRN)/LIRN, LIRN); cout << Form(" dropTol = %5.3g (absTol = %5.3g) NDROP = %1d\n", dropTol, absTol, NDROP); } } //------------------------------------------------------------------------- void MA28Matrix:: MA28ResizeArrays(Real dropTol) { W.resize(0,N); IKEEP.resize(0,5*N); if (NSearch <= N) IW.resize(0,7*N); else IW.resize(0,8*N); Real fact = 0.05; if (spaceDim > 1) { if (dropTol > 1e-1) fact *= 0.1; else if (dropTol > 1e-2) fact *= 0.2; else if (dropTol > 1e-3) fact *= 0.3; else if (dropTol > 1e-4) fact *= 0.4; else if (dropTol > 1e-5) fact *= 0.5; else if (dropTol > 1e-6) fact *= 0.6; else if (dropTol > 1e-7) fact *= 0.7; } if (spaceDim == 1) { LICN = int(ICNFactor * NZ * 1.5); LIRN = int(IRNFactor * NZ * 1.2); } else if (spaceDim == 2) { LICN = int(ICNFactor * NZ * (4.0 + fact*int(pow(double(N),0.50)))); LIRN = int(IRNFactor * NZ * (2.0 + fact*int(pow(double(N),0.25)))); } else if (spaceDim == 3) { LICN = int(ICNFactor * NZ * (6.0 + fact*int(pow(double(N),0.66)))); LIRN = int(IRNFactor * NZ * (3.0 + fact*int(pow(double(N),0.50)))); } A.resize (0,LICN); ICN.resize(0,LICN); IRN.resize(0,LIRN); } //------------------------------------------------------------------------- void MA28Matrix:: MA28ExtendArrays(int FLAG) { if (FLAG == -3 || FLAG == -6) { LIRN = int(1.5*LIRN); IRN.resize(0,LIRN); if (infoLinSystem) cout << "\n\t * MA28 FLAG " << FLAG << ": IRN Working Space extended\n"; } if (FLAG == -5 || FLAG == -6) { LICN = int(1.5*LICN); ICN.resize(0,LICN); A.resize (0,LICN); if (infoLinSystem) cout << "\n\t * MA28 FLAG " << FLAG << ": ICN Working Space extended\n"; } if (FLAG == -4) { LICN = int(3*LICN); ICN.resize(0,LICN); A.resize (0,LICN); if (infoLinSystem) cout << "\n\t * MA28 FLAG " << FLAG << ": ICN Working Space extended (far too small)\n"; } } //------------------------------------------------------------------------- void MA28Matrix:: MA28FBSubst(Num* rhs) { int MTYPE = 1; #if (ComplexVersion) F77NAME(madc28cdint,MADC28CDINT)(&N, A.v, &LICN, ICN.v, IKEEP.v, rhs, W.v, &MTYPE); #else F77NAME(ma28cdint,MA28CDINT) (&N, A.v, &LICN, ICN.v, IKEEP.v, rhs, W.v, &MTYPE); #endif } //------------------------------------------------------------------------- Real MA28Matrix:: minDiag() { int i; Real minD = Abs(A[0]); for (i=1; iv[k])); } } //------------------------------------------------------------------------- // -- sort by straight insertion; first element in vector is j=1 void MA28Matrix:: sortRow(int n, int* col, Num* L) { int i,j; int a; Num u; for (j=2; j<=n; j++) { a = col[j]; u = L[j]; i = j-1; while (i > 0 && col[i] > a) { col[i+1] = col[i]; L [i+1] = L [i]; --i; } col[i+1] = a; L [i+1] = u; } } */ //-------------------------------------------------------------------------