#define CS 1 /* check subscripts on */ #include "common.h" #include "corefunc.h" #include "_linalg.h" /* for access std vectors */ /* Vector and Matrix are type from _linalg.h */ #include #define Var FloatHi #define VarPtr FloatHiPtr typedef VarPtr VectPtr; #ifdef WIN_MSWIN static FILE *deb=NULL; static void DebOpen(void) { if (!deb) deb=fopen("deb","wt"); } #endif #if CS Local(Boolean) Check(Int2 sub, Int2 lim, Int2 line) { if (sub<0 || sub>=lim) { if (Message(MSG_OKC,"Index is out of range:\n" " %i not in [0,%i)\n" "_linalg.c, line %i", (int)sub,(int)lim,(int)line) == ANS_CANCEL) { abort(); } else return TRUE; } return FALSE; } #endif /***************************************/ /************/ /* Matrixes */ /* Pointer to standard linea algebra's functions */ Local(StdLinAlgDataPtr) stdalg; /* phase dim and number of mesh points */ Local(Int2) nphase,nmesh,nappend; /* Decomp's work stuff */ Local(Matrix) T=NULL,Z1=NULL,Z2=NULL,A0=NULL,ZZ2=NULL,tt=NULL,ttfi=NULL; Local(Vector) t=NULL,ttt=NULL,tttt=NULL,beta=NULL,beta1=NULL,wdet=NULL; /* Package initialization function */ Entry(void) rd_Init(StdLinAlgDataPtr Stdalg, Int2 Nphase, Int2 Nmesh, Int2 Nappend) { /* save global data */ stdalg=Stdalg; nphase=Nphase; nmesh=Nmesh; nappend=Nappend; /* Create Decomp's work matrices and vectors */ if (!T) { T=stdalg->CreateMatrix(nphase,nphase); Z1=stdalg->CreateMatrix(nphase,nphase); Z2=stdalg->CreateMatrix(nphase,nphase); A0=stdalg->CreateMatrix(nphase,nphase); ZZ2=stdalg->CreateMatrix(nphase,nappend+1); tt=stdalg->CreateMatrix(nphase,nappend+1); ttfi=stdalg->CreateMatrix(nappend+1,nappend+1); t=stdalg->CreateVector(nphase); ttt=stdalg->CreateVector(nphase); tttt=stdalg->CreateVector(nphase); beta=stdalg->CreateVector(nappend+1); beta1=stdalg->CreateVector(nappend+1); wdet=stdalg->CreateVector(nphase*nmesh+nappend+1); } } /* Package clean up function */ Entry(void) rd_Term(void) { /* Decomp */ T=stdalg->DestroyMatrix(T); Z1=stdalg->DestroyMatrix(Z1); Z2=stdalg->DestroyMatrix(Z2); A0=stdalg->DestroyMatrix(A0); ZZ2=stdalg->DestroyMatrix(ZZ2); tt=stdalg->DestroyMatrix(tt); ttfi=stdalg->DestroyMatrix(ttfi); t=stdalg->DestroyVector(t); ttt=stdalg->DestroyVector(ttt); tttt=stdalg->DestroyVector(tttt); beta=stdalg->DestroyVector(beta); beta1=stdalg->DestroyVector(beta1); wdet=stdalg->DestroyVector(wdet); } /* A matrix */ /* Logical structure of a matrix (n=nmesh): a[0] b[0] c[0] 0 0 ... 0 0 0 0 0 delta[0] a[1] b[1] c[1] 0 0 ... 0 0 0 0 0 delta[1] 0 a[2] b[2] c[2] 0 ... 0 0 0 0 0 delta[2] 0 0 a[3] b[3] c[3] ... 0 0 0 0 0 delta[3] . . . . . ... . . . . . 0 0 0 0 0 ... a[n-4] b[n-4] c[n-4] 0 0 delta[n-4] 0 0 0 0 0 ... 0 a[n-3] b[n-3] c[n-3] 0 delta[n-3] 0 0 0 0 0 ... 0 0 a[n-2] b[n-2] c[n-2] delta[n-2] 0 0 0 0 0 ... 0 0 a[n-1] b[n-1] c[n-1] delta[n-1] p[0] p[1] p[2] p[3] p[4] ... p[n-5] p[n-4] p[n-3] p[n-2] p[n-1] fi dimensions: a[i], b[i], c[i] nphase x nphase delta[i] nphase x 1+nappend p[i] 1+nappend x nphase fi 1+nappend x 1+nappend */ typedef struct { Int2 n,m; /* dimensions */ Matrix R; /* from Decomp to Solve */ Matrix PNTR a; Matrix PNTR b; Matrix PNTR c; Matrix PNTR delta; Matrix PNTR p; Matrix PNTR fi; } rdMatrix, PNTR rdMatrixPtr; typedef rdMatrixPtr MatrPtr; #define MATRSIZE(n,m) (sizeof(rdMatrix)+ \ (5*nmesh+1)*sizeof(Matrix) \ ) Entry(void) rd_PrintMatrix(MatrPtr mp, CharPtr title, Int2 Level) { int i; Char buf[20]; if (mp==NULL) { #ifdef WIN_MSWIN DebOpen(); fprintf(deb,"\n%s=NULL\n",title); #else printf("\n%s=NULL\n",title); #endif return; } #ifdef WIN_MSWIN DebOpen(); fprintf(deb,"\n--------------------------------------\n%s\n",title); #else printf("\n--------------------------------------\n%s\n",title); #endif for (i=0; ifi[0][i][j])>s) {s=fabs(S->fi[0][i][j]); im=i; jm=j;} } if (s==0.0) return 6; /* Perestanovka stolbtsov */ if(jm != k && kfi[0][i][jm]; S->fi[0][i][jm]=S->fi[0][i][k]; S->fi[0][i][k]=w;} } /* Perestanovka strok */ if(im != k) { sign=-sign; for(j=k; jfi[0][im][j]; S->fi[0][im][j]=S->fi[0][k][j]; S->fi[0][k][j]=w;} } /* Otchistka stolbtsa "fi" */ for(i=k+1;ifi[0][i][k]/S->fi[0][k][k]; for(j=k;jfi[0][i][j]-=s*S->fi[0][k][j];} /* Determinant */ if (S->fi[0][k][k]<0) sign=-sign; *det+=log(fabs(S->fi[0][k][k])); } /* for(k=0;kfi[0][m-1][m-1]<0) sign=-sign; *det+=log(fabs(S->fi[0][m-1][m-1])); if (*det<=0) *det=sign*exp(*det); else *det=sign*(1+*det); #undef d return 0; } /* Returns det and cond numbers of a DECOMPOSED matrix */ Entry(Int2) rd_GetMatrixData(MatrPtr mp, FloatHiPtr deteq, FloatHiPtr det) { if (deteq && det) return Determinant(mp,deteq,det); return -1; } /* Transpose a matrix */ Entry(MatrPtr) rd_TransposeMatrix(MatrPtr from, MatrPtr to DEBPAR) { } /* Clears a Matrix */ Entry(void) rd_ClearMatrix(MatrPtr mp) { } /* Copy block */ Entry(void) rd_CopyMatrixBlock(MatrPtr from, Int2 frow, Int2 fcol, MatrPtr to, Int2 trow, Int2 tcol, Int2 nrow, Int2 ncol) { } #undef MATRSIZE /*****************************************************/ /* Numerical differentiation by finite differencies */ typedef EntryPtr(Int2,rdDiffFun,(Vector xx, Vector yy)); /* any differentiable function */ Entry(Int2) rd_der (rdDiffFun fun, int n, /* number of function components */ VectPtr x, Var d, MatrPtr A) { } /***********************************/ /* Standard solver and decomposer */ /*======================================*/ /* Decomposition for progonka procedure */ Entry(Int2) rd_Decomp(MatrPtr S DEBPAR) { Int2 np,nm,j,i,k; np=nphase; nm=nmesh; /* 1 */ stdalg->CopyMatrix(S->c[1],T); if (stdalg->Decomp(T)) return 1; stdalg->SolveMatrix(T,S->a[1],Z1,t); /* 2 */ stdalg->SolveMatrix(T,S->b[1],Z2,t); /* 3 */ stdalg->MultiplyMatrixMatrix(S->c[0],Z1,T); stdalg->AddScaledMatrix(S->a[0],T,-1.0,T); if (stdalg->Decomp(T)) return 3; stdalg->MultiplyMatrixMatrix(S->c[0],Z2,Z1); stdalg->AddScaledMatrix(Z1,S->b[0],-1.0,Z1); stdalg->SolveMatrix(T,Z1,A0,t); /* 4 */ stdalg->MultiplyMatrixMatrix(S->a[1],A0,T); stdalg->AddScaledMatrix(T,S->b[1],1.0,T); if (stdalg->Decomp(T)) return 4; stdalg->SolveMatrix(T,S->a[1],Z1,t); stdalg->CopyMatrix(T,S->c[0]); /* 5 - mimo */ /* 6 */ stdalg->MultiplyMatrixMatrix(S->a[0],A0,T); stdalg->AddScaledMatrix(T,S->b[0],1.0,S->R); stdalg->MultiplyMatrixMatrix(S->R,Z1,T); stdalg->AddScaledMatrix(S->a[0],T,-1.0,S->a[0]); if (stdalg->Decomp(S->a[0])) return 6; stdalg->CopyMatrix(A0,S->b[0]); /* 7 */ stdalg->SolveMatrix(S->c[0],S->delta[1],ZZ2,t); /* 8 */ stdalg->MultiplyMatrixMatrix(S->R,ZZ2,tt); stdalg->AddScaledMatrix(tt,S->delta[0],-1.0,ZZ2); stdalg->SolveMatrix(S->a[0],ZZ2,S->delta[0],t); /* 9,10,11 */ for(i=1; iMultiplyMatrixMatrix(S->a[i],S->b[i-1],T); stdalg->AddScaledMatrix(T,S->b[i],1.0,T); if(stdalg->Decomp(T)) return 9; for(j=0; jc[i][k][j]; stdalg->Solve(T,t); for(k=0; kb[i][k][j]=t[k]; } stdalg->CopyMatrix(T,S->c[i]); /* 10 */ stdalg->MultiplyMatrixMatrix(S->a[i],S->delta[i-1],tt); stdalg->AddScaledMatrix(tt,S->delta[i],1.0,tt); stdalg->AddScaledMatrix(NULL,tt,-1.0,ZZ2); stdalg->SolveMatrix(S->c[i],ZZ2,S->delta[i],t); /* 11 - mimo */ } /* 12 */ stdalg->MultiplyMatrixMatrix(S->a[nm-1],S->b[nm-3],T); stdalg->AddScaledMatrix(T,S->b[nm-1],1.0,S->b[nm-1]); stdalg->MultiplyMatrixMatrix(S->b[nm-1],S->delta[nm-2],tt); stdalg->AddScaledMatrix(tt,S->delta[nm-1],1.0,S->delta[nm-1]); stdalg->MultiplyMatrixMatrix(S->a[nm-1],S->delta[nm-3],tt); stdalg->AddScaledMatrix(tt,S->delta[nm-1],1.0,S->delta[nm-1]); stdalg->AddScaledMatrix(NULL,S->delta[nm-1],-1.0,S->delta[nm-1]); stdalg->MultiplyMatrixMatrix(S->b[nm-1],S->b[nm-2],T); stdalg->AddScaledMatrix(T,S->c[nm-1],1.0,S->c[nm-1]); if (stdalg->Decomp(S->c[nm-1])) return 12; stdalg->SolveMatrix(S->c[nm-1],S->delta[nm-1],tt,t); stdalg->CopyMatrix(tt,S->delta[nm-1]); /* 13 - mimo */ /* 14 - mimo */ /* 15 */ for(i=nm-2; i>-1; i--) {stdalg->MultiplyMatrixMatrix(S->b[i],S->delta[i+1],tt); stdalg->AddScaledMatrix(tt,S->delta[i],1.0,S->delta[i]); } /* 16 */ for(i=0; iMultiplyMatrixMatrix(S->p[i],S->delta[i],ttfi); stdalg->AddScaledMatrix(S->fi[0],ttfi,1.0,S->fi[0]); } if (stdalg->Decomp(S->fi[0])) return 16; /* 17 mimo */ return 0; } /*======================================*/ /* Solving for progonka procedure */ Entry(void) rd_Solve(MatrPtr S, VectPtr F) { Int2 i,np,nm; np=nphase; nm=nmesh; /* 1 - mimo */ /* 2 - mimo */ /* 3 - mimo */ /* 4 - mimo */ /* 5 */ stdalg->CopyVectorElements(F,1*np,ttt,0,np); stdalg->Solve(S->c[0],ttt); /* 6 */ stdalg->MultiplyMatrixVector(S->R,ttt,t); stdalg->CopyVectorElements(F,0*np,ttt,0,np); stdalg->AddScaledVector(ttt,t,-1.0,ttt); stdalg->Solve(S->a[0],ttt); stdalg->CopyVectorElements(ttt,0,F,0*np,np); /* 7 - mimo */ /* 8 - mimo */ /* 9 - mimo */ /* 10 - mimo */ /* 11 */ for(i=1; iMultiplyMatrixArray(S->a[i],F+(i-1)*np,t); stdalg->CopyVectorElements(F,i*np,ttt,0,np); stdalg->AddScaledVector(ttt,t,-1.0,ttt); stdalg->Solve(S->c[i],ttt); stdalg->CopyVectorElements(ttt,0,F,i*np,np); } /* 12 - mimo */ /* 13 */ stdalg->CopyVectorElements(F,(nm-2)*np,ttt,0,np); stdalg->MultiplyMatrixVector(S->b[nm-1],ttt,t); stdalg->CopyVectorElements(F,(nm-1)*np,ttt,0,np); stdalg->AddScaledVector(ttt,t,-1.0,t); stdalg->CopyVectorElements(F,(nm-3)*np,ttt,0,np); stdalg->MultiplyMatrixVector(S->a[nm-1],ttt,tttt); stdalg->AddScaledVector(t,tttt,-1.0,ttt); stdalg->Solve(S->c[nm-1],ttt); stdalg->CopyVectorElements(ttt,0,F,(nm-1)*np,np); /* 14 */ for(i=nm-2; i>-1; i--) { stdalg->MultiplyMatrixArray(S->b[i],F+(i+1)*np,t); stdalg->CopyVectorElements(F,i*np,ttt,0,np); stdalg->AddScaledVector(t,ttt,1.0,ttt); stdalg->CopyVectorElements(ttt,0,F,i*np,np); } /* 15 - mimo */ /* 16 */ MemMove(beta,F+nm*np,sizeof(VAR)*(nappend+1)); for(i=0; iMultiplyMatrixArray(S->p[i],F+i*np,beta1); stdalg->AddScaledVector(beta,beta1,-1.0,beta); } stdalg->Solve(S->fi[0],beta); stdalg->CopyVectorElements(beta,0,F,nm*np,nappend+1); /* 17 */ for(i=0; iMultiplyMatrixVector(S->delta[i],beta,t); stdalg->CopyVectorElements(F,i*np,ttt,0,np); stdalg->AddScaledVector(ttt,t,1.0,ttt); stdalg->CopyVectorElements(ttt,0,F,i*np,np); } } /*======================================*/ Entry(Int2) rd_SngSolve (MatrPtr AA, FloatHi EPS, VectPtr XX) { } Entry(Int2) rd_CharPolyCoeffs(MatrPtr AA, VectPtr PP) { } Entry(Int2) rd_dbalan(MatrPtr AA, Int2 *LOW, Int2 *IGH) { } Entry(Int2) rd_delmhe(MatrPtr AA, Int2 LOW, Int2 IGH) { } Entry(Int2) rd_dhqr(MatrPtr HH, Int2 LOW, Int2 IGH, VectPtr WWR, VectPtr WWI) { } Entry(Int2) rd_EigenValues(MatrPtr A, VectPtr Re, VectPtr Im) { } Entry(Var) rd_NormOfVector(VectPtr a) { return sqrt(stdalg->ScalProd(a,a)/nmesh); }