Previous Up Next

Chapter 5  Manuale utente

In questo capitolo si illustreranno le modalità di utilizzo dei sorgenti allegati; verranno descritte le routine principali in Fortran e C, e verranno mostrati alcuni esempi di compilazione dei programmi.

5.1  Nomenclatura

Nella scelta dei nomi da dare alle routine sviluppate, si è scelto di seguire lo schema già usato da Fortran e LAPACK:

Si può quindi generalizzare lo schema dei nomi in questo modo:

{s|d|c|z}wa[pvt]sv1

5.2  Funzioni per la generazione degli elementi di A

Come accennato in precedenza, il metodo di Wassing non richiede la memorizzazione esplicita della matrice. Risulta dunque necessario stabilire un formato standard per le funzioni che restituiscono gli elementi della matrice dei coefficienti del sistema lineare in esame.

Si tenga presente che la matrice è intesa essere AT. Le funzioni, perciò, dovranno essere tali che f(i,j)aji, cioè richiedendo l’elemento (i,j) all’interno delle librerie per il metodo di Wassing, questo deve essere l’elemento (j,i) della matrice dei coefficienti del sistema lineare Ax=b. In seguito, si farà sempre riferimento ad AT: l’elemento aij è l’elemento (i,j) di AT, e dunque l’elemento (j,i) di A.

Il formato che deve essere rispettato da queste funzioni, è il seguente:

<tipo> <nome>(int i, int j, int n)

dove

<tipo>è il tipo di dato opportuno
<nome>è il nome scelto per la funzione
iè la riga dell’elemento
jè la colonna dell’elemento
nè la dimensione della matrice


Le routine di risoluzione dispongono di un parametro, attraverso il quale viene indicato il <nome> della funzione da utilizzare per ottenere gli elementi della matrice dei coefficienti: in questo modo le routine sono più flessibili in quanto consentono di utilizzare un nome arbitrario per queste funzioni.

5.3  Routine di risoluzione in Fortran

Le routine Fortran restituiscono, in un parametro, il risultato dell’applicazione del metodo, come avviene nelle routine LAPACK; poi, a seconda che si utilizzi la versione con pivoting o meno, il numero ed il tipo dei parametri da passare cambia, come descritto di seguito:

{s|d|c|z}wasv(n, b, nb, z, nz, c, getk, valid)

calcola la soluzione di un sistema lineare A X = B, dove A è una matrice n × n, e X e B sono matrici n × nb, tramite il metodo di Wassing

@percentf_wasv_tab.tex

{s|d|c|z}wapvtsv(n, b, nb, z, nz, c, zt, ip, ipk, getk)

calcola la soluzione di un sistema lineare A X = B, dove A è una matrice n × n, e X e B sono matrici n × nb, tramite il metodo di Wassing con l’utilizzo del pivoting parziale

@percentf_wapvtsv_tab.tex

5.4  Routine di risoluzione in C

Nell’implementazione in C, le routine sono delle funzioni, il cui valore di ritorno indica se la risoluzione ha avuto successo o meno, in maniera simile a valid o ip(n+1) visto in precedenza per le routine Fortran.

int {s|d|c|z}wasv(int n, <tipo> b[], int nb, (* getk))

calcola la soluzione di un sistema lineare A X = B, dove A è una matrice n × n, e X e B sono matrici n × nb, tramite il metodo di Wassing

@percentc_wasv_tab.tex

int {s|d|c|z}wapvtsv(int n, <tipo> b[], int nb, (* getk))

calcola la soluzione di un sistema lineare A X = B, dove A è una matrice n × n, e X e B sono matrici n × nb, tramite il metodo di Wassing con l’utilizzo del pivoting parziale

@percentc_wapvtsv_tab.tex

5.5  Compilazione ed utilizzo

Di seguito, verrà mostrato come utilizzare i codici implementati, facendo uso di semplici esempi di compilazione.

5.5.1  Compilazione del codice Fortran

Per poter compilare il sorgente Fortran è necessario dichiarare, all’interno del programma principale, tutti i vettori di cui farà uso la routine di risoluzione. Definite, dunque, le strutture dati opportune, si devono anche dichiarare le funzioni per gli elementi della matrice dei coefficienti A e della matrice dei termini noti B; dopo aver costruito il vettore b, è infine possibile richiamare la routine di risoluzione.

Si consideri un codice di esempio:

      Program sxolve

      Implicit None

      Integer n, nz, nb, i, j, k, valid
 
      Parameter (n=10)
      Parameter (nz=(n*n)/4)
      Parameter (nb=1)

      Real z(nz), c(n), b(n*nb)

      Real sgetb, sgetk
      External sgetb, sgetk

      do i=1,n
         k=nb*(i-1)
         do j=1,nb
            b(k+j)=-sgetb(i,n)
         enddo
      enddo

      call swasv(n,b,nb,z,nz,c,sgetk,valid)

      if (valid.ne.0) then
         print *, 'Minore principale di ordine ',valid,' nullo'
      endif

      end

Se il programma precedente viene chiamato sxolve.f, allora per compilarlo si utilizza la seguente linea di comando:

g77 -O3 -o <output> sxolve.f swasv.f sgetk.f sgetb.f

dove con <output> si è indicato il nome del file eseguibile risultato della compilazione. Sono state attivate anche le opzioni di ottimizzazione -O3 che, come detto, consentono di ottenere eseguibili più performanti.

Nel caso il programma principale e le altre routine non si trovino tutti nella stessa directory, si dovrà precisare, oltre al nome del file, anche il percorso per raggiungerlo.

5.5.2  Compilazione del codice C

Per la compilazione del codice C le cose sono leggermente differenti da quanto visto in precedenza: per poter chiamare una funzione, è necessario dichiararne l’intestazione, che è composta dal tipo di ritorno, dal nome della funzione e dalla lista dei parametri con il rispettivo tipo. Per facilitare la fase di dichiarazione delle funzioni, è stato utilizzato il file wassing.h che contiene tutte le intestazioni delle funzioni utilizzate: esso deve essere incluso tramite la direttiva del preprocessore #include wassing.h all’interno del proprio codice sorgente. Dopo aver costruito il vettore dei termini noti b, è possibile richiamare la routine di risoluzione.

Si consideri il file sorgente che segue:

#include <stdio.h>
#include <stdlib.h>
#include "wassing.h"

#define dim 10
#define nbb 1

int main()
{
  float *b;
  int res, i, j;

  b=(float *) calloc(dim*nbb, sizeof(float));
  if (b==NULL) {
    fprintf(stderr, "%s: Impossibile allocare
                         la memoria necessaria\n", __FILE__);
    exit(1);
  }

  for (i=0; i<dim; i++)
  {
    for(j=0; j<nbb; j++)
      { b[nbb*i+j]=-sgetb(i+1,dim); }
  }

  res=swasv(dim, b, nbb, sgetk);

  if(res!=0)
  { printf("Minore principale di ordine %d nullo\n", res); }

  free(b);

  return 0;
}

che si suppone chiamato sxolve.c. Per compilarlo, si deve eseguire questa riga di compilazione:

gcc -O3 -o <output> sxolve.c swasv.c sgetk.c sgetb.c -lm

Come detto, il C non dispone dell’aritmetica dei numeri complessi: a questo proposito sono state definite delle macro del preprocessore, riunite nel file ccomplex.h, che deve essere incluso in maniera simile a wassing.h all’interno del codice che fa uso delle routine per i numeri complessi. Inoltre, deve anche essere indicato, sulla riga di compilazione, il file ccomplex.c: dunque, la riga di compilazione da eseguire sarà simile alla seguente (i nomi dei file iniziano con c, ad indicare l’utilizzo di numeri complessi in singola precisione, ed il programma principale è chiamato cxolve.c):

gcc -O3 -o <output> cxolve.c cwasv.c cgetk.c cgetb.c ccomplex.c -lm

È inoltre presente un file di intestazioni per le routine LAPACK, chiamato lapack.h, da usare come descritto in precedenza.

È necessario anche utilizzare il parametro di linking -lm, che include nel programma le funzioni matematiche della libreria C math.h, in quanto sia wassing.h che ccomplex.h le richiedono.

Anche in questo caso, è consigliabile attivare le ottimizzazioni.


1
Con la notazione {a1|...|an} si intende che uno degli elementi ai deve essere indicato, mentre con [x] si indica la presenza opzionale di x; questa notazione viene utilizzata anche nel seguito del capitolo.

Previous Up Next