📄 geneigen.c
字号:
/***** program geneigen *****/
/* tridiagonalization and Wilkinson */
/* shift approach for symmetric matrices */
/* t.r.chandrupatla and a.d.belegundu */
/******************************************/
#include <stdio.h>
#include <math.h>
main()
{
FILE *fptr1, *fptr2;
double *s,*gm,*d,*b;
double omega,freq,c;
int *nord,nq,nbw,i,j,k,n,ii,jn,ifl,iter;
double pi = 3.14159;
char dummy[81], file1[81], file2[81];
printf("\n");
puts("Input file name < dr:fn.ext >: ");
gets(file1);
puts("Output file name < dr:fn.ext >: ");
gets(file2);
fptr1 = fopen(file1, "r");
fptr2 = fopen(file2, "w");
fgets(dummy,80,fptr1);
fgets(dummy,80,fptr1);
/* --- read in number of equations and bandwidth --- */
fscanf(fptr1,"%d %d\n", &nq, &nbw);
/* ----- memory allocation ----- */
s = (double *) calloc(nq*nq, sizeof(double));
gm = (double *) calloc(nq*nq, sizeof(double));
d = (double *) calloc(nq, sizeof(double));
b = (double *) calloc(nq*nq, sizeof(double));
nord = (int *) calloc(nq, sizeof(int));
/* --------------------------------------------- */
for (i = 0; i < nq; i++) {
nord[i] = i;
}
/* ----- banded stiffness matrix into s(nq,nq) ----- */
fgets(dummy,80,fptr1);
for (i = 1; i <= nq; i++) {
for (jn = 1; jn <= nbw; jn++) {
fscanf(fptr1, "%lg\n", &c);
j = i + jn - 1;
if (j <= nq) {
s[nq*(i-1)+j-1] = c;
s[nq*(j-1)+i-1] = c;
}
}
}
/* ----- banded mass matrix into gm(nq,nq) ----- */
fgets(dummy,80,fptr1);
for (i = 1; i <= nq; i++) {
for (jn = 1; jn <= nbw; jn++) {
fscanf(fptr1, "%lg\n", &c);
j = i + jn - 1;
if (j <= nq) {
gm[nq*(i-1)+j-1] = c;
gm[nq*(j-1)+i-1] = c;
}
}
}
fclose(fptr1);
/* ----- Cholesky Factorization of Mass Matrix */
cholesky(gm, nq);
/* ----- Update of Stiffness Matrix - Standard Form Ax=(lambda)x */
updatestiff(s, gm, nq);
/* ----- Tri-diagonalize D() Diagonal, B() Sub-diagonal */
/* ----- S() has the rotation matrix */
tridiag(s, d, b, nq);
/* ----- Find Eigenvalues and Eigenvectors */
eigentd(d, b, s, nq, iter);
/* ----- Determine Eigenvectors */
eigenvec(s, gm, nq);
/* ----- Ascending Order of Eigenvalues */
ascendeigen(d, nord, nq);
/* ----- results ----- */
printf("eigenvalues and eigenvectors for data in file %s\n)", file1);
fprintf(fptr2, "eigenvalues and eigenvectors for data in file %s\n", file1);
for (i = 0; i < nq; i++) {
ii = nord[i];
printf( "eigenvalue number %d\n ", i+1);
fprintf(fptr2, "eigenvalue number %d\n ", i+1);
c = d[ii];
omega = sqrt((float) c);
freq = .5 * omega / pi;
printf("eigenvalue = %11.4e", c);
fprintf(fptr2, "eigenvalue = %11.4e", c);
printf(" omega = %10.3e", omega);
fprintf(fptr2, " omega = %10.3e", omega);
printf(" freq = %10.3e hz\n", freq);
fprintf(fptr2, " freq = %10.3e hz\n", freq);
printf( "eigenvector \n");
fprintf(fptr2, "eigenvector \n");
ifl = 0;
for (j = 0; j < nq; j++) {
printf( "%10.3e ", s[nq*j+ii]);
fprintf(fptr2, "%10.3e ", s[nq*j+ii]);
ifl = ifl + 1;
if (ifl > 5)
ifl = 0;
if (ifl == 0) {
printf( "\n");
fprintf(fptr2, "\n");
}
}
printf("\n");
fprintf(fptr2, "\n");
}
fclose(fptr2);
return(0);
}
cholesky(a, n)
int n;
double *a;
{
int i, j, k;
/* ----- L into lower left triangle of a */
for ( k = 0; k < n; k++ ) {
a[k*n + k] = sqrt(a[k*n + k]);
for ( i = k + 1; i < n; i++) {
a[i*n + k] = a[i*n + k]/a[k*n + k];
}
for ( j = k + 1; j < n; j++ ) {
for ( i = j; i < n; i++) {
a[i*n + j] = a[i*n + j] - a[i*n + k] * a[j*n + k];
}
}
}
return(0);
}
updatestiff(a, b, n)
int n;
double *a, *b;
{
int i,j,k;
/* --- forward substitution i (invL)*a */
for ( j = 0; j < n; j++) {
a[j] = a[j] / b[0];
for ( i = 1; i < n; i++) {
for ( k = 0; k < i; k++) {
a[i*n + j] = a[i*n + j] - b[i*n + k] * a[k*n + j];
}
a[i*n + j] = a[i*n + j] / b[i*n + i];
}
}
/* --- forward substitution ii (invl)*a*(invl)' */
for ( j = 0; j < n; j++) {
a[j*n] = a[j*n] / b[0];
for ( i = 1; i < n; i++ ) {
for ( k = 0; k < i; k++ ) {
a[j*n + i] = a[j*n + i] - b[i*n + k] * a[j*n + k];
}
a[j*n + i] = a[j*n + i] / b[i*n + i];
}
}
return(0);
}
tridiag(a, d, b, n)
int n;
double *a, *d, *b;
{
int i,j,k,ia, ii, ij, ik;
double aa,ww,bet, c1;
for ( i = 0; i < n - 2; i++ ) {
aa = 0;
for ( j = i + 1; j < n; j++ ) {
aa = aa + a[j*n + i] * a[j*n + i];
}
aa = sqrt(aa);
ww = 2 * aa * (aa + fabs(a[(i + 1)*n + i]));
ww = sqrt(ww);
ia = 1;
if (a[(i + 1)*n + i] < 0)
ia = -1;
/* ----- diagonal and next to diagonal term */
d[i] = a[i*n + i];
b[i] = -ia * aa;
/* ----- unit vector w() in column i from row i+1 to n */
for ( j = i + 1; j < n; j++ ) {
a[j*n + i] = a[j*n + i] / ww;
}
a[(i + 1)*n + i] = a[(i + 1)*n + i] + ia * aa / ww;
/* ----- w'a in row i from col i+1 to n */
bet = 0;
for ( j = i + 1; j < n; j++ ) {
a[i*n + j] = 0;
for ( k = i + 1; k < n; k++ ) {
a[i*n + j] = a[i*n + j] + a[k*n + i] * a[k*n + j];
}
bet = bet + a[i*n + j] * a[j*n + i];
}
/* ----- modified a() */
for ( j = i + 1; j < n; j++ ) {
for ( k = i + 1; k < n; k++ ) {
c1 = - 2 * a[j*n + i] * a[i*n + k];
c1 = c1 - 2 * a[i*n + j] * a[k*n + i];
c1 = c1 + 4 * bet * a[k*n + i] * a[j*n + i];
a[j*n + k] = a[j*n + k] + c1;
}
}
}
d[n - 2] = a[(n - 2)*n + n - 2];
b[n - 2] = a[(n - 2)*n + n - 1];
d[n - 1] = a[(n - 1)*n +n - 1];
a[(n - 2)*n + n - 2] = 1;
a[(n - 1)*n +n - 1] = 1;
a[(n - 2)*n + n - 1] = 0;
a[(n - 1)*n +n - 2] = 0;
/* ----- now create the q matrix in a() */
for (i = 0; i < n - 2; i++) {
ii = n - i - 3;
a[ii*n + ii] = 1;
for (j = 1; j <= i + 2; j++) {
ij = ii + j;
c1 = 0;
for (k = 1; k <= i + 2; k++) {
ik = ii + k;
c1 = c1 + a[ik*n + ij] * a[ik*n + ii];
}
for (k = 1; k <= i + 2; k++) {
ik = ii + k;
a[ik*n + ij] = a[ik*n + ij] - 2 * c1 * a[ik*n + ii];
}
}
for (j = 1; j <= i + 2; j ++) {
ij = ii + j;
a[ii*n + ij] = 0;
a[ij*n + ii] = 0;
}
}
return(0);
}
eigentd(a, b, q, n, iter)
int n,iter;
double *a, *b, *q;
{
int m, i, k;
double dd,bb,p,pp,bot,x,a1,b1,a2,sn,cs;
iter = 0;
m = n;
do {
iter = iter + 1;
dd = 0.5 * (a[m - 2] - a[m - 1]);
bb = b[m - 2] * b[m - 2];
p = 1;
if ( dd < 1 )
p = -1;
bot = dd + p * sqrt(dd * dd + bb);
p = a[0] - a[m - 1] + bb / bot;
x = b[0];
for ( i = 0; i < m - 1; i++ ) {
pp = sqrt(p * p + x * x);
cs = -p / pp;
sn = x / pp;
if (i > 0)
b[i - 1] = cs * b[i - 1] - sn * x;
a1 = a[i];
a2 = a[i + 1];
b1 = b[i];
a[i] = a1 * cs * cs - 2 * b1 * cs * sn + a2 * sn * sn;
b[i] = (a1 - a2) * cs * sn + b1 * (cs * cs - sn * sn);
a[i + 1] = a1 * sn * sn + 2 * b1 * cs * sn + a2 * cs * cs;
/* ----- update q() */
for ( k = 0; k < n; k++) {
a1 = q[k*n + i];
a2 = q[k*n + i + 1];
q[k*n + i] = cs * a1 - sn * a2;
q[k*n + i + 1] = sn * a1 + cs * a2;
}
if (i == m - 2)
break;
x = -b[i + 1] * sn;
b[i + 1] = b[i + 1] * cs;
p = b[i];
}
while (m > 1 && fabs(b[m - 2]) < 0.000001) {
m = m - 1;
}
} while (m > 1);
m = m - 1;
return(0);
}
eigenvec(a, b, n)
int n;
double *a, *b;
{
int i,j,k;
/* --- backsubstitution --- */
for ( j = 0; j < n; j++ ) {
a[(n - 1)*n + j] = a[(n - 1)*n + j] / b[(n - 1)*n + n - 1];
for ( i = n - 2; i >= 0; i--) {
for ( k = n - 1; k >= i + 1; k-- ) {
a[i*n + j] = a[i*n + j] - b[k*n + i] * a[k*n + j];
}
a[i*n + j] = a[i*n + j] / b[i*n + i];
}
}
return(0);
}
ascendeigen(d, nord, n)
int *nord, n;
double *d;
{
int i, j, i1, j1, ii, ij;
double c1;
/* --- Initialization of nord[] --- */
for ( i = 0; i < n; i++ ) {
nord[i] = i;
}
/* ----- ascending order of eigenvalues */
for ( i = 0; i < n - 1; i++ ) {
ii = nord[i];
i1 = ii;
c1 = d[ii];
j1 = i;
for ( j = i + 1; j < n; j++) {
ij = nord[j];
if (c1 > d[ij]) {
c1 = d[ij];
i1 = ij;
j1 = j;
}
}
nord[i] = i1;
nord[j1] = ii;
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -