⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lanczos.c

📁 cfd求解器使用与gmsh网格的求解
💻 C
📖 第 1 页 / 共 3 页
字号:
#define RCSID "$Id: Lanczos.c,v 1.34 2006/02/26 00:42:54 geuzaine Exp $"/* * Copyright (C) 1997-2006 P. Dular, C. Geuzaine * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * * Please report all bugs and problems to <getdp@geuz.org>. * * Contributor(s): *   Benoit Meys *   Andre Nicolet *   ohyeahq@yahoo.co.jp */#include "GetDP.h"#include "DofData.h"#include "CurrentData.h"#include "Numeric.h"#include "EigenPar.h"/* Version commentee par A. Nicolet de Lanczos.c le 2001/11/29 *//* Bibliographie   Numerical Linear Algebra, Trefethen & Bau, SIAM, Philadelphia,   1997.  Tres recent et tres clair, excellent ouvrage introductif sur   l'algebre lineaire numerique moderne!      Y. Saad, Numerical Methods for Large Eigenvalue Problems,   Manchester University Press Avantages: gratuit sur le Web   (http://www.users.cs.umn.edu/~saad/books.html et le bouquin sur la   resolution des systemes s'y trouve aussi maintenant!), assez recent   (1992), tres cible sur le probleme comme son titre l'indique, tres   clair avec peu de prerequis (le premier chapitre vous rememore tout   ce que vous devez savoir sur les matrices pour commencer), bon   niveau theorique sans abstraction stratospherique et decrit   precisement les ALGORITHMES (dont par exemple la methode   d'Arnoldi-Tchebychev conu par Saad lui-meme).      Golub & Van Loan, Matrix Computations, Johns Hopkins University   Press, 3rd ed, 1996.  La troisieme edition de la bible du calcul   matriciel applique!   Valeurs propres des matrices, Franoise Chatelin, Masson, Paris,   1988.  Bien cible et assez theorique, plutot court, un bon texte   complementaire pour se faire un synthese.   Analyse Numerique, sous la direction de Jacques Baranger, Hermann,   Paris, 1991, Chapitre 7 par Franoise Chatelin. Bon chapitre   synthetique par l'auteur de l'ouvrage precedent.   M. Geradin, D. Rixen, Theorie des Vibrations, Masson, Paris, 2eme   ed, 1996.  La reference utilisee par Benoit Meys. Introduction   de la methode de Lanczos comme outil pour l'ingenieur donc approche   tres pragmatique et tres instructive pour le passage aux   applications.   Isaacson & Keller, Analysis of Numerical Methods, Dover (edition   originale 1966).  L'ouvrage general de reference en calcul   numerique dans les annees 60.   J. Stoer, R. Bulirsh, introduction to Numerical Analysis, Springer   Verlag, 1979.  Un des meilleurs ouvrages generaux de reference en   calcul numerique dans les annees 80. Entre Isaacson & Keller et   Stoer & Bulirsh, il y a le Dahlquist et Bjork des annees 70 mais   c'est un ouvrage beaucoup plus introductif.   W.H. Press & al., Numerical Recipes, Cambridge University Press,   ... Le best seller du calcul numerique des annees 90. Generation   fast food oblige, c'est le fast programming. Indispensable en fait   comme trousse de secours: un petit rappel theorique rapide ou une   petite routine toute faite peuvent etre des gestes qui   sauvent...   Et enfin, les Wilkinson: J. H. Wilkinson, Rounding Errors in   Algebraic Processes, Dover Petit ouvrage sur l'analyse d'erreur   comme son nom l'indique.   J. H. Wilkinson, C. Reinsch, Linear Algebra, Springer Verlag, 1971.   Un pre-Numerical Recipes plus pousse sur l'algebre lineaire et avec   tous les algorithmes en Algol (Je vous parle d'un temps que les   moins de vingt ans ne peuvent pas connaitre...).   J. H. Wilkinson, Algebraic eigenvalue problem, Clarendon Press,   1965.  Le livre sacre du calcul des valeurs propres... que je n'ai   jamais eu en main. Il va falloir que je mette la main dessus...*//* Quelques modifications envisagees dans le futur (par ordre   approximatif de difficulte et probablement par ordre chronologique   de realisation future...) :   1) Normer les vecteurs propres (valeur absolue max d'un element =   1) -> OK mais ne resout pas entierement le probleme de l'affichage   dans le post.   2) Examiner de plus pres et eventuellement valider ou ameliorer   quelques details comme par exemple je verrais bien le test if   (fabs(shift) > 1.e-10) en relatif plutot qu'en absolu. De toute   facon, si on essaye d'imposer un shift si petit, il vaudrait mieux   afficher un message d'avertissement!  CHANGER LES NOMS DE CERTAINES   VARIABLES   3) Faire fonctionner LinAlg correctement pour les complexes (au   moins le produit scalaire!!). En gros le codage des matrices et des   vecteurs complexes du systeme est   | Re Im |   et  | Re |   |-Im Re |       | Im |   Les matrices rectangulaires orthogonales sont stockees dans une   liste de vecteurs Lan (Changer le nom en Q ou V ?).  Ce qui doit   tre fait est le passage a une matrice de Hessenberg complexe Hes ->   HesR,HesI ... mais on ne peut pas utiliser le codage ci-dessus car   on perdrait la structure de Hessenberg.   4) Calculer le RESIDU associe a un couple : la theorie permet de   calculer facilement ce resultat, voir plus loin -> OK utilise pour   selectionner les valeurs propres qui ont converge.   5) Ameliorer les valeurs propres et les vecteurs propres a   posteriori (il y a une methode simple expliquee dans Numerical   Recipes, je crois...) et eventuellemnt introduire un critere   d'arret.   6) Amelioration de l'algorithme: Preconditionner (il y a des trucs   la dessus dans Saad, je crois).  Reorthogonaliser les colonnes de   Qn -> OK mais n'apporte pas grand chose !  Faire des redemarrages   ... a essayer, ce n'est pas un gros travail, par exemple prendre   comme point de depart une combinaison lineaire (somme !)  des   vecteurs (normes !) qui ont deja plus ou moins converges ! Hn   incomplet etc. (cf. Golub & Van Loan, Chatelin) L'algorithme de   Saad 'Arnoldi-Tchebyshev' semble un bon candidat !   7) 'Fixer omega et chercher gamma' conduit a un probleme aux VP   generalise du type: lambda^2 M1 v + lambda M2 v + M3 v = 0 On peut   mettre ce probleme sous la forme d'un probleme generalise de taille   'double' du type   | M1 M2 | |v1| lambda +  | 0  M3 | |v1| = 0   | 0  I  | |v2|           |-I  0  | |v2|   Comme d'habitude, on n'a besoin que du produit Matrice Vecteur ce   qui revient a travailler avec les 'demi-vecteurs' v1, v2 de v et   les sous-matrices M1, M2, M3: on doit calculer le vecteur 'double':   | -M1 v2 + M2 M3^-1 v1 |    | M3^-1 v1             |    Il sera surtout necessaire d'avoir acces aux sous-matrices M1, M2,   M3.  On peut egalement envisager le probleme des courbes de   dispersion: Trouver des paires de nombres (omega,gamma) telles   qu'il existe un vecteur v verifiant: gamma^2 M1 v + gamma M2 v +   omega^2 M3 v + M4 v = 0 Le jeu consiste a faire varier (pas trop   vite) omega et calculer les nouveaux gammas en utilisant si   possible l'information fournie par les resolutions precedentes ...      8) Autres methodes(puissance inverse?)      Question: et si on utilisait une librairie comme ARPACK et son   interface objet en C++ ARPACK++?   http://www.caam.rice.edu/software/ARPACK/*/#if !defined(HAVE_GSL)#include "nrutil.h"#else#include <gsl/gsl_rng.h>/* base-1 index: numerical recipes convention */#define dvector(dummy, A) (double *)Malloc(sizeof(double) * ((A) + 1))#define dmatrix(dummy, A, dummy2, B) newmatrix((A) + 1, (B) + 1)#define free_dvector(A, dummy, dummy2) Free(A)#define free_dmatrix(M, dummy, A, dummy2, dummy3) freematrix((M), (A))double **newmatrix(int nrow, int ncol){ /* accessible as a[i][j] */  int i;  double **a;   a = (double **)Malloc(sizeof(double *) * nrow);  for (i = 0; i < nrow; i++)    a[i] = (double *)Malloc(sizeof(double) * ncol);  return a;}void freematrix(double **a, int nrow){  int i;  double **b;    b = a;  for (i = 0; i < nrow; i++) Free(*b++);  Free(a);}double gsl_random(){ /* uniform random numbers in range [0.0, 1.0) */  double u;  static const gsl_rng_type *T = NULL;  static gsl_rng *r;    if (T == NULL) { /* initialize */    gsl_rng_env_setup();    T = gsl_rng_default;    r = gsl_rng_alloc(T);  }  /* we never free this: gsl_rng_free(r); */  u = gsl_rng_uniform(r);  return u;}/* calc complex eigenvalues of Hessenberg form of real non-symmetrical   matrix: GSL doesn't have it, so we use LAPACK's DHSEQR routine */#if !defined(HAVE_BLAS_LAPACK)void hqr(double **hin, int nhess, double *wrout, double *wiout){  Msg(GERROR, "Lanczos algorithm not available without BLAS and LAPACK");}#else#include "Compat.h"#if defined(HAVE_UNDERSCORE)#define dhseqr_ dhseqr#endifEXTERN_C_BEGINvoid dhseqr_(char *JOB, char *COMPZ, int *N, int *ILO, int *IHI, double *H, 	     int *LDH, double *WR, double *WI, double **Z, int *LDZ,	     double *WORK, int *LWORK, int *IRET);EXTERN_C_ENDvoid hqr(double **hin, int nhess, double *wrout, double *wiout){  int n, ilo, ihi, ldh, ldz, lwork, info, i, j, k;  double *h, *wr, *wi, *work, **dummy;  char job[] = "E", compz[] = "N";    n = nhess;  ilo = 1;  ihi = n;  ldh = n;  ldz = n;  lwork = n;    wr = (double *)Malloc(sizeof(double) * n);  wi = (double *)Malloc(sizeof(double) * n);  work = (double *)Malloc(sizeof(double) * n);    h = (double *)Malloc(sizeof(double) * (n * n));    /* C to F77 interface: Fortran uses "column-major ordering" in     arrays, so transpose matrix and pack into h[] (or h[][]).  This     may or may not work with other systems.  "cfortran.h" would be a     better way */  k = 0;  for (i = 0; i < n; i++) {    for (j = 0; j < n; j++) {      h[k++] = hin[j + 1][i + 1]; /* hin: base-1 index */    }  }    dhseqr_(job, compz, &n, &ilo, &ihi, h, &ldh, wr, wi, dummy, &ldz, work, 	  &lwork, &info);  if (info != 0)    Msg(GERROR, "Lanczos/lapack dhseqr error = %d", info);    for (i = 0; i < n; i++) {    wrout[i + 1] = wr[i]; /* base-1 */    wiout[i + 1] = wi[i];  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -