bmatrix.c

Go to the documentation of this file.
00001 /*
00002     This file is part of magpar.
00003 
00004     Copyright (C) 2002-2010 Werner Scholz
00005 
00006     www:   http://www.magpar.net/
00007     email: magpar(at)magpar.net
00008 
00009     magpar is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     magpar is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with magpar; if not, write to the Free Software
00021     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "field/field.h"
00025 #include "init/init.h"
00026 #include "util/util.h"
00027 
00028 int VertBSA(GridData *gdata,Vec vertbsa)
00029 {
00030   MagparFunctionLogBegin;
00031 
00032   /* Calculate solid angles of boundary vertices */
00033 
00034   /* loop over all local elements */
00035   for (int i=0; i<gdata->ln_ele; i++) {
00036     /* loop over all vertices */
00037     for (int j=0; j<NV; j++) {
00038       PetscReal  t_omega;
00039       ierr = SolidAngle(
00040         gdata->vertxyz+gdata->elevert[NV*i+j]*ND,
00041         gdata->vertxyz+gdata->elevert[NV*i+(j+1+NV)%NV]*ND,
00042         gdata->vertxyz+gdata->elevert[NV*i+(j+2+NV)%NV]*ND,
00043         gdata->vertxyz+gdata->elevert[NV*i+(j+3+NV)%NV]*ND,
00044         &t_omega
00045       );CHKERRQ(ierr);
00046 
00047       int v;
00048       v=gdata->elevert[NV*i+j];
00049       ierr = VecSetValue(
00050         vertbsa,
00051         v,
00052         t_omega,
00053       ADD_VALUES);CHKERRQ(ierr);
00054     }
00055   }
00056 
00057   ierr = VecAssemblyBegin(vertbsa);CHKERRQ(ierr);
00058   ierr = VecAssemblyEnd(vertbsa);CHKERRQ(ierr);
00059 
00060   MagparFunctionLogReturn(0);
00061 }
00062 
00063 
00064 int BMatrix(GridData *gdata,Mat *Bmat)
00065 {
00066   MagparFunctionLogBegin;
00067 
00068   int rank,size;
00069   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00070   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00071 
00072   PetscPrintf(PETSC_COMM_WORLD,"Using dense boundary matrix\n");
00073 
00074   PetscPrintf(PETSC_COMM_WORLD,
00075     "Size of dense B matrix: %i x %i = %g matrix elements = %g MB.\n",
00076     gdata->n_vert_bnd,
00077     gdata->n_vert_bnd,
00078     1.0*gdata->n_vert_bnd*gdata->n_vert_bnd,
00079     (gdata->n_vert_bnd/1024.0*gdata->n_vert_bnd/1024.0*sizeof(PetscReal))
00080   );
00081 
00082   /* create boundary matrix (boundary nodes only) */
00083 
00084   int ln_bmatrixrows,rowstart,rowend;
00085   ln_bmatrixrows=gdata->n_vert_bnd/size;
00086   rowstart=rank*(gdata->n_vert_bnd/size);
00087   rowend=rowstart+gdata->n_vert_bnd/size-1;
00088   if ((gdata->n_vert_bnd%size)/(rank+1)>=1) {
00089     ln_bmatrixrows++;
00090     rowstart+=rank;
00091     rowend+=rank+1;
00092   }
00093   else {
00094     rowstart+=gdata->n_vert_bnd%size;
00095     rowend+=gdata->n_vert_bnd%size;
00096   }
00097   PetscSynchronizedPrintf(PETSC_COMM_WORLD,
00098     "<%i>local rows of boundary matrix: %i (from %i to %i)\n",
00099     rank,ln_bmatrixrows,
00100     rowstart,rowend
00101   );
00102   PetscSynchronizedFlush(PETSC_COMM_WORLD);
00103   assert(ln_bmatrixrows==rowend-rowstart+1);
00104 
00105   Mat B;
00106 
00107   PetscPrintf(PETSC_COMM_WORLD,
00108     "Allocating %i MB of memory for boundary matrix on each processor (total %i MB)\n",
00109     (gdata->n_vert_bnd/1024*gdata->n_vert_bnd/1024*sizeof(PetscReal)+1)/size+1,
00110     (gdata->n_vert_bnd/1024*gdata->n_vert_bnd/1024*sizeof(PetscReal)+2)
00111   );
00112 
00113   ierr = MatCreateMPIDense(PETSC_COMM_WORLD,
00114     ln_bmatrixrows,ln_bmatrixrows,
00115     gdata->n_vert_bnd,gdata->n_vert_bnd,
00116     PETSC_NULL,
00117     &B);CHKERRQ(ierr);
00118   ierr = MatSetFromOptions(B);CHKERRQ(ierr);
00119 
00120   PetscPrintf(PETSC_COMM_WORLD,"Calculating boundary matrix...\n");
00121 
00122   int zeroes=0;
00123 
00124   /*
00125   hybrid FEM/BEM method from:
00126   T. R. Koehler, D. R. Fredkin,
00127   "Finite Element Methods for Micromagnetics"
00128   IEEE Trans. Magn. 28 (1992) 1239-1244
00129 
00130   matrix elements calculated according to:
00131   D. A. Lindholm,
00132   "Three-Dimensional Magnetostatic Fields from
00133   Point-Matched Integral Equations with Linearly Varying Scalar Sources",
00134   IEEE Trans. Magn. MAG-20 (1984) 2025-2032.
00135   */
00136 
00137   /* loop over all (!) vertices (R) */
00138   int i;
00139   for (i=0; i<gdata->n_vert; i++) {
00140     ierr = ProgressBar(i,gdata->n_vert,10);
00141     /* skip if R is not a boundary node */
00142     if (gdata->vertbndg2bnd[i]==C_INT) continue;
00143 
00144     /* loop over local surface triangles */
00145 
00146     for (int j=0; j<gdata->ln_bnd_fac; j++) {
00147       /* skip if R is a node of j */
00148       if (gdata->bndfacvert[j*NN+0]==i ||
00149           gdata->bndfacvert[j*NN+1]==i ||
00150           gdata->bndfacvert[j*NN+2]==i
00151       ) continue;
00152 
00153       PetscReal matele[ND];
00154       ierr = Bele(
00155                   gdata->vertxyz+ND*i,
00156                   gdata->vertxyz+ND*gdata->bndfacvert[j*NN+0],
00157                   gdata->vertxyz+ND*gdata->bndfacvert[j*NN+1],
00158                   gdata->vertxyz+ND*gdata->bndfacvert[j*NN+2],
00159                   matele
00160       );CHKERRQ(ierr);
00161 
00162       if (PetscAbsReal(matele[0])+PetscAbsReal(matele[1])+PetscAbsReal(matele[2])<D_EPS)
00163         continue;
00164 
00165       for (int k=0;k<NN;k++) {
00166         /* set (dense) full boundary matrix */
00167         ierr = MatSetValue(B,
00168           gdata->vertbndg2bnd[i],
00169           gdata->vertbndg2bnd[gdata->bndfacvert[j*NN+k]],
00170           matele[k],
00171         ADD_VALUES);CHKERRQ(ierr);
00172       }
00173     }
00174 
00175     /* flush caches to save memory (and avoid swapping) */
00176     if (i % 100 == 99) {
00177       ierr = MatAssemblyBegin(B,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00178       ierr = MatAssemblyEnd(B,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00179     }
00180 
00181   }
00182   ierr = ProgressBar(1,1,10);
00183 
00184   if (size>1) {
00185     ierr = PetscGetTime(&t_t2);CHKERRQ(ierr);
00186     PetscPrintf(PETSC_COMM_WORLD,"<%i> took %g s\n",rank,t_t2-t_t1);
00187     PetscPrintf(PETSC_COMM_WORLD,"waiting for other processors to complete...");
00188   }
00189 
00190   /* continue assembling to stay in sync with other processors */
00191   for (;i<gdata->n_vert;i++) {
00192     if (i % 100 == 99) {
00193       ierr = MatAssemblyBegin(B,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00194       ierr = MatAssemblyEnd(B,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00195     }
00196   }
00197 
00198   /* TODO not quite accurate */
00199   int tzeroes=0;
00200   ierr=MPI_Allreduce((int*)&zeroes,(int*)&tzeroes,1,MPI_INT,MPI_SUM,PETSC_COMM_WORLD);CHKERRQ(ierr);
00201   PetscInfo3(0,
00202     "total zero entries: %i (%i) of %i\n",
00203     (tzeroes+gdata->n_vert_bnd)/3,
00204     tzeroes,
00205     gdata->n_vert_bnd*gdata->n_vert_bnd
00206   );
00207 
00208   ierr = PetscGetTime(&t_t2);CHKERRQ(ierr);
00209   PetscPrintf(PETSC_COMM_WORLD,
00210     "boundary matrix calculation took %g s = %g min\n",
00211     t_t2-t_t1,
00212     (t_t2-t_t1)/60.0
00213   );
00214 
00215   /* set diagonal matrix elements */
00216 
00217   Vec vertbsa; /* boundary solid angle (4*pi for interior vertices) */
00218   ierr = VecCreate(PETSC_COMM_WORLD,&vertbsa);CHKERRQ(ierr);
00219   ierr = VecSetSizes(vertbsa,gdata->ln_vert,gdata->n_vert);CHKERRQ(ierr);
00220   ierr = VecSetFromOptions(vertbsa);CHKERRQ(ierr);
00221 
00222   ierr = VertBSA(gdata,vertbsa);CHKERRQ(ierr);
00223 
00224   PetscReal *t_array;
00225   ierr = VecGetArray(vertbsa,&t_array);CHKERRQ(ierr);
00226 
00227   for (i=0; i<gdata->ln_vert; i++) {
00228 
00229     /* skip if R is not a boundary node */
00230     if (gdata->vertbndg2bnd[gdata->vertl2g[i]]==C_INT) continue;
00231 
00232     PetscReal matele;
00233     matele=t_array[i]/(4.0*PETSC_PI)-1.0;
00234     ierr = MatSetValue(B,
00235       gdata->vertbndg2bnd[gdata->vertl2g[i]],
00236       gdata->vertbndg2bnd[gdata->vertl2g[i]],
00237       matele,
00238     ADD_VALUES);CHKERRQ(ierr);
00239   }
00240 
00241   ierr = VecRestoreArray(vertbsa,&t_array);CHKERRQ(ierr);
00242   ierr = VecDestroy(vertbsa);CHKERRQ(ierr);
00243 
00244   PetscPrintf(PETSC_COMM_WORLD,"B matrix assembly complete\n");
00245   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00246   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00247   ierr = PrintMatInfoAll(B);CHKERRQ(ierr);
00248 
00249   /* scale B*=-1 since Au2*=-1 and ABu2*=1 is not */
00250   ierr = MatScale(B,-1.0);CHKERRQ(ierr);
00251 
00252   *Bmat=B;
00253 
00254 /* DEBUG
00255   PetscPrintf(PETSC_COMM_WORLD,"B matrix::\n");
00256   ierr = MatView(B,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00257 */
00258 
00259 /* DEBUG
00260   ierr = PetscViewerSetFormat(PETSC_VIEWER_DRAW_WORLD,PETSC_VIEWER_ASCII_DENSE);CHKERRQ(ierr);
00261   ierr = MatView(B,PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr);
00262 
00263   char fmesh[256];
00264   PetscViewer viewer;
00265 
00266   ierr = PetscSNPrintf(fmesh,255,"%s%s",gdata->simname,".ba");CHKERRQ(ierr);
00267   ierr = PetscViewerASCIIOpen(PETSC_COMM_WORLD,fmesh,&viewer);CHKERRQ(ierr);
00268   ierr = PetscViewerSetFormat(viewer,PETSC_VIEWER_ASCII_DENSE);CHKERRQ(ierr);
00269   ierr = MatView(B,viewer);CHKERRQ(ierr);
00270   ierr = PetscViewerDestroy(viewer);CHKERRQ(ierr);
00271 */
00272 
00273   ierr = PetscGetTime(&t_t2);CHKERRQ(ierr);
00274 
00275   MagparFunctionLogReturn(0);
00276 }
00277 

magpar - Parallel Finite Element Micromagnetics Package
Copyright (C) 2002-2010 Werner Scholz