next up previous
Next: PME Veri Tipi ve Up: Örnek 3 Previous: Örnek 3: Derleme/Baglama Komutlari

Örnek 3: Program


#include <stddef.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
#include "libpme.h"
#include "petscsles.h"

/* fonksiyon prototipleri */
void   elem_tri(double  *x,double  *y,double *ek[3],double  ef[3]) ;
int    fem_poisson(pMesh mesh,int mypid) ;
double f(double x,double y) ;
double exact(double x,double y) ;
int    refine_uniform(pMesh) ;

main(
int   argc,
char *argv[])
{
   /* tanimlar */
   pMesh     mesh            ;
   char      filename[256]   ;
   int       rc,i            ;
   int       mypid, numprocs ;
   double    startwtime ; 
   double    endwtime ; 

   /* MPI ile PETSC'yi ilk kullanima hazirla */
   MPI_Init(&argc,&argv) ;
   MPI_Comm_rank(MPI_COMM_WORLD,&mypid) ;
   MPI_Comm_size(MPI_COMM_WORLD,&numprocs) ;
   PetscInitialize(&argc,&argv,(char *)0,0) ;

   /* 1.**** Grid'i oku *****************************************/
   sprintf(filename,"%s.%d.msh",argv[1],mypid) ;
   mesh  = pme_new_msh(MPI_COMM_WORLD,NULL) ;
   rc    = pme_read_msh(mesh,filename) ;

   /* Zamanlamayi baslat */ 
   MPI_Barrier(MPI_COMM_WORLD) ;
   startwtime = MPI_Wtime(); 

   /* 2.**** Grid'i parcala  ************************************/
   pme_part_inertia(mesh) ; 

   /* 3. *** Grid'e ince uyarlama yap ***************************/
   for(i=0 ; i < atoi(argv[2]) ; i++) refine_uniform(mesh) ;
   printf("%d\n",pme_num_entity(mesh,PME_FACE)) ;

   /* 4 ***  Sonlu Eleman yontemi ile Laplace denklemini coz ****/
   fem_poisson(mesh,mypid) ;

   /* Zamanlamayi bitir */ 
   endwtime = MPI_Wtime();
   printf("Zaman = %f\n",endwtime-startwtime) ;
   MPI_Finalize() ;
   exit(0) ;
}

int fem_poisson(
pMesh mesh,
int   mypid)
{

    void     *temp1   ;
    void     *temp2   ;
    pFace     f       ;
    pVertex   v       ;
    int       ids[3]  ;
    int       i,j     ;
    double    x[3]    ;
    double    y[3]    ;
    double    ef[3]   ; /* eleman    sag taraf                 */
    double    arry[9] ; /* eleman    matris                    */
    double   *ek[3]   ; /* eleman    matris 2d arry referansi  */
    pEnList   enlist  ;
    Vec       U, b, u ; /* hesaplanmis cozum, sag taraf, 
                           gercek cozum                         */
    Mat       A       ; /* dogrusal sistem matrisi              */
    SLES      sles    ; /* SLES ortami                          */
    int       ierr    ;
    int       n,N     ; /* sahip olunan yorel varlik sayisi 
                           global varlik sayisi */
    int       its     ; /* iterasyon sayisi */
    double    norm    ;
    Scalar    neg_one = -1.0, 
              zero=0.0, 
              one=1.0 ;
    IS        is      ;
    int      *rows    ;
    int       n_gb    ;
    double   *gb_f    ;
    Scalar   *solnu   ;
    Scalar   *solnU   ;
    double   *d       ;
    int       *indxs  ;
    pEntity    owner_entity ;
    int        owner_pid    ;
    pFace      face         ;
    pVertex    vertex       ;

    ek[0] = &(arry[0]) ; ek[1] = &(arry[3]) ; ek[2] = &(arry[6]) ; 
    /* 1 ** Vektorleri yarat ******************************/
    pme_glob_numbering(mesh,PME_VERTEX) ;
    pme_glob_num_entity(mesh,PME_VERTEX,&n,&N) ;
    MYMALLOC(indxs,int *,n*sizeof(int)) ;
    MYMALLOC(solnu,Scalar *,n*sizeof(Scalar)) ;
    ierr  = VecCreateMPI(MPI_COMM_WORLD,n,N,&U) ; 
    ierr  = VecDuplicate(U,&b)             ;     
    ierr  = VecDuplicate(U,&u)             ;     
    ierr  = VecSet(&zero,U)                ;     

    /* 2 *** Matrisi yarat, eleman hesaplari yap, 
         ve matris kurulumunu yap *******/

    ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,n,n,N,N,
                       0,PETSC_NULL,0,PETSC_NULL,&A);


    /* Elemen hesaplari */
    temp1 = NULL ;
    while(face = pme_next_entity(mesh,PME_FACE,&temp1)) {
       i = 2 ;
       temp2 = NULL ;
       pme_get_reln(mesh,face,PME_VERTEX,&enlist) ;
       while(vertex = pme_next_enlist(enlist,&temp2) ) {
         ids[i] = pme_glob_number(mesh,vertex) - 1 ;
         x[i]   = pme_get_vertex_xyz(vertex,0) ;
         y[i]   = pme_get_vertex_xyz(vertex,1) ;
         i-- ;
       }
       pme_free_enlist(enlist) ;
       elem_tri(x,y,ek,ef) ;
       ierr = MatSetValues(A,3,ids,3,ids,arry,ADD_VALUES);
       VecSetValues(b,3,ids,ef,ADD_VALUES);
    }

    /* matris kurulumu */
    ierr = VecAssemblyBegin(b)               ;             CHKERRQ(ierr);
    ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);         CHKERRQ(ierr);
    ierr = VecAssemblyEnd(b)                 ;             CHKERRQ(ierr);
    ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY)  ;         CHKERRQ(ierr);

    /** 3 * Dirichlet sinir kosullari     *********/
    n_gb = pme_num_gb_entity(mesh,PME_VERTEX) ;
    MYMALLOC(rows,int *,n_gb*sizeof(int)) ;
    MYMALLOC(gb_f,double *,n_gb*sizeof(double)) ;
    temp1 = NULL ;
    i = 0 ;
    while(v = pme_next_gb_entity(mesh,PME_VERTEX,&temp1) ) {
      pme_get_pb_owner(mesh,v,&owner_pid,&owner_entity) ;
      if (owner_pid == mypid) {
        rows[i] = pme_glob_number(mesh,v) - 1 ;
        gb_f[i] = exact(pme_get_vertex_xyz(v,0),
                        pme_get_vertex_xyz(v,1) ) ;
        i++ ;
      }
    }

    n_gb = i ;
    VecSetValues(b,n_gb,rows,gb_f,INSERT_VALUES);
    ierr = ISCreateGeneral(MPI_COMM_SELF,n_gb,rows,&is);   CHKERRQ(ierr);
    ierr = MatZeroRows(A,is,&one);                         CHKERRQ(ierr);
    ierr = ISDestroy(is);                                  CHKERRQ(ierr);

    /** 4 * Dogrusal denklemi coz   ************************/
    ierr = SLESCreate(MPI_COMM_WORLD,&sles) ;            CHKERRQ(ierr);
    ierr = SLESSetOperators(sles,A,A,
                            DIFFERENT_NONZERO_PATTERN);  CHKERRQ(ierr);
    ierr = SLESSetFromOptions(sles)       ;              CHKERRQ(ierr);
    ierr = SLESSolve(sles,b,U,&its)       ;              CHKERRQ(ierr);


    /** 5 * Hata'yi kontrol et ***********************/
    temp1 = NULL ;
    i = 0  ;
    while(v = pme_next_entity(mesh,PME_VERTEX,&temp1)) {
      pme_get_pb_owner(mesh,v,&owner_pid,&owner_entity);
      if(owner_pid == mypid) {
         solnu[i] = exact(pme_get_vertex_xyz(v,0),
                 pme_get_vertex_xyz(v,1) );
         indxs[i] = pme_glob_number(mesh,v) - 1;
         i++ ;
      }
    }
    n = i ;
    VecSetValues(u,n,indxs,solnu,INSERT_VALUES);
    ierr = VecAssemblyBegin(u);           CHKERRQ(ierr);
    ierr = VecAssemblyEnd(u)  ;           CHKERRQ(ierr);

    ierr = VecAXPY(&neg_one,u,U);         CHKERRQ(ierr);
    ierr = VecNorm(U,NORM_MAX,&norm);    
    printf("Norm= %lE Iter=%d\n",norm,its) ;

    ierr = VecDestroy(U);              
    ierr = VecDestroy(u);             
    ierr = VecDestroy(b);            
    ierr = MatDestroy(A);           
    ierr = SLESDestroy(sles);           
}


/*
 * Dogrusal sekil (shape) fonksiyonlari ile  ucgen uzerinde 
 * eleman hesaplarini yap
 */
void elem_tri(
double  *x,
double  *y,
double *ek[3],
double  ef[3])
{
    static  double psi[3]     = {0.33333333333,0.33333333333,0.33333333333} ;
    static  double weight = 0.5 ;
    double  x_l, y_l            ;
    double  detj, one_detj,fac  ;
    int     i,j,k               ;
    double  p1, p2 ;
    int     k1, k2 ;


    /* x,y */
    x_l = psi[0]*x[0] + psi[1]*x[1] + psi[2]*x[2] ;
    y_l = psi[0]*y[0] + psi[1]*y[1] + psi[2]*y[2] ;

    /* Jakobian */
    detj = (x[1]-x[0])*(y[2]-y[0]) - (x[2]-x[0])*(y[1]-y[0]) ;

    one_detj = 1.0/detj ;

    /* Integral hesaplamasi */
    for(i=0 ; i < 3 ; i++) {
       ef[i] = f(x_l,y_l)*psi[i]*detj*weight ;
       k1 = (i+1)%3 ; k2 = (i+2)%3 ;
       p1 = (y[k1]-y[k2]) ;
       p2 = (x[k1]-x[k2]) ;
       ek[i][i] = -weight*one_detj*( p1*p1 + p2*p2 ) ;
       for(j=i+1 ;  j < 3 ; j++) {
         k =  3 - i - j ;
         ek[j][i] =
         ek[i][j] =  -weight*one_detj*
                     ((y[j]-y[k])*(y[k]-y[i])+(x[k]-x[j])*(x[i]-x[k])) ;
       }
    }
}


double f(
double x,
double y)
{
 double t ;

 return(0.0) ;
}


double exact(
double x,
double y)
{
   return(x*y) ; 
}


/* Bu fonksiyon butun elemenlara ince uyarlama yapar */
refine_uniform(
pMesh mesh)
{
   AttchTag mark_tag ;
   pFace    face     ;
   void    *temp     ;

   pme_new_attch_tag(mesh,NULL,PME_ATTCH_NOT_FREE,&mark_tag) ;

   /* butun elemanlari ince uyarlama icin isaretle */
   temp = NULL ;
   while (face = pme_next_entity(mesh,PME_FACE,&temp) ) {
       pme_ins_data_attch(face,mark_tag,(void *)1) ;
   }

   /* Paralel Rivara ince uyarlama fonksiyonunu cagir */
   pme_ref_rivara(mesh,mark_tag) ;

   /* isaretleri sil */
   temp = NULL ;
   while( face = pme_next_entity(mesh,PME_FACE,&temp) ) {
       pme_del_data_attch(face,mark_tag) ;
   }

   pme_del_attch_tag(mesh,mark_tag) ;
}



Can Ozturan
2001-12-22