area.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 static char const Id[] = "$Id: area.c 2992 2010-03-10 21:57:41Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 #include "util.h"
00028 
00029 int AreaCal(Mat AIpol, PetscReal *p_area)
00030 {
00031   PetscReal area;
00032 
00033   int ngrows,ngcols;
00034   int nlrows,nlcols;
00035 
00036   Vec       test1,test2;
00037   PetscReal vmin,vmax;
00038   int       imin,imax;
00039 
00040   MagparFunctionLogBegin;
00041 
00042   ierr = MatGetSize(AIpol,&ngrows,&ngcols);CHKERRQ(ierr);
00043   ierr = MatGetLocalSize(AIpol,&nlrows,&nlcols);CHKERRQ(ierr);
00044 
00045   ierr = VecCreate(PETSC_COMM_WORLD,&test1);CHKERRQ(ierr);
00046   ierr = VecCreate(PETSC_COMM_WORLD,&test2);CHKERRQ(ierr);
00047   ierr = VecSetSizes(test1,nlcols,ngcols);CHKERRQ(ierr);
00048   ierr = VecSetSizes(test2,nlrows,ngrows);CHKERRQ(ierr);
00049   ierr = VecSetFromOptions(test1);CHKERRQ(ierr);
00050   ierr = VecSetFromOptions(test2);CHKERRQ(ierr);
00051 
00052   ierr = VecSet(test1,1.0);CHKERRQ(ierr);
00053 
00054   ierr = MatMult(AIpol,test1,test2);CHKERRQ(ierr);
00055 
00056   /* check result of interpolation */
00057   ierr = VecMin(test2,&imin,&vmin);CHKERRQ(ierr);
00058   ierr = VecMax(test2,&imax,&vmax);CHKERRQ(ierr);
00059 
00060   if (vmin<0.0 || vmax>1.0+D_EPS) {
00061     PetscPrintf(PETSC_COMM_WORLD,
00062       "need to rescale matrix: %i: %e  %i: %e\n",
00063       imin,vmin,imax,vmax
00064     );
00065 
00066     /* TODO: rescale AIpol (not sure why this is necessary)
00067        seems like some pixels belong to two elements (just on interface!?)
00068     */
00069     PetscReal *atest2;
00070     ierr = VecGetArray(test2,&atest2);CHKERRQ(ierr);
00071     for (int i=0;i<nlrows;i++) {
00072       if (atest2[i]>1.0) atest2[i]=1.0/atest2[i];
00073     }
00074     ierr = VecRestoreArray(test2,&atest2);CHKERRQ(ierr);
00075 
00076     ierr = MatDiagonalScale(AIpol,test2,PETSC_NULL);CHKERRQ(ierr);
00077 
00078     ierr = MatMult(AIpol,test1,test2);CHKERRQ(ierr);
00079   }
00080 
00081   /* double check result of interpolation */
00082   ierr = VecMin(test2,&imin,&vmin);CHKERRQ(ierr);
00083   ierr = VecMax(test2,&imax,&vmax);CHKERRQ(ierr);
00084 
00085   PetscPrintf(PETSC_COMM_WORLD,
00086     "min/max: %i: %e  %i: %e\n",
00087     imin,vmin,imax,vmax
00088   );
00089 
00090   assert(vmin>=0.0);
00091   assert(vmax<=1.0+D_EPS);
00092 
00093   /* area calculation */
00094   ierr = VecSum(test2,&area);CHKERRQ(ierr);
00095   PetscPrintf(PETSC_COMM_WORLD,"area = %g/%i=%g%%\n",area,ngrows,area/ngrows*100);
00096 
00097   *p_area=area;
00098 
00099   ierr = VecDestroy(test1);
00100   ierr = VecDestroy(test2);
00101 
00102   MagparFunctionLogReturn(0);
00103 }
00104 
00105 
00106 /* FIXME
00107  * save elevertall in griddata.h during initialization
00108  * save/use connectivity matrices:
00109  *   elements sharing faces
00110  *   elements sharing nodes
00111  *   nodes connected by edges
00112  */
00113 
00114 int PidSharedArea(GridData *gdata,int pid1,int pid2,PetscReal *sharedarea_area,PetscReal *sharedarea_point,PetscReal *sharedarea_norm)
00115 {
00116   MagparFunctionLogBegin;
00117 
00118   int rank,size;
00119   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00120   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00121 
00122   if (pid1==pid2)
00123     SETERRQ2(PETSC_ERR_ARG_INCOMP,"Pids have to be different to calculate shared area (%i==%i)!\n",pid1+1,pid2+1);
00124 
00125   if (pid1>=gdata->n_prop)
00126     SETERRQ2(PETSC_ERR_ARG_INCOMP,"pid1 too large (%i>%i)!\n",pid1+1,gdata->n_prop);
00127   if (pid2>=gdata->n_prop)
00128     SETERRQ2(PETSC_ERR_ARG_INCOMP,"pid2 too large (%i>%i)!\n",pid1+1,gdata->n_prop);
00129   if (pid1<=-1 && pid2<=-1)
00130     SETERRQ2(PETSC_ERR_ARG_INCOMP,"pids too small (%i,%i)<1!\n",pid1+1,pid2+1);
00131 
00132   PetscPrintf(PETSC_COMM_WORLD,"Search shared area for pids %i, %i\n",pid1+1,pid2+1);
00133 
00134   /* get ownership range */
00135   int low,high;
00136   ierr = VecGetOwnershipRange(gdata->elevol,&low,&high);CHKERRQ(ierr);
00137 
00138   int *elevertall;
00139 
00140 #ifdef HAVE_ELEVERTALL
00141   elevertall=gdata->elevertall;
00142 #else
00143   if (size>1) {
00144     ierr = PetscMalloc(NV*gdata->n_ele*sizeof(int),&elevertall);CHKERRQ(ierr);
00145     ierr = PetscMemcpy(elevertall+NV*low,gdata->elevert,NV*gdata->ln_ele*sizeof(int));CHKERRQ(ierr);
00146 
00147     int *p;
00148     p=elevertall;
00149 
00150     int recvcount[size];
00151     recvcount[rank]=NV*gdata->ln_ele;
00152     for (int i=0;i<size;i++) {
00153       ierr = MPI_Bcast(recvcount+i,1,MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00154       /* we could also use MPI_Send/Recv to get everything just to the first processor */
00155       ierr = MPI_Bcast(p,recvcount[i],MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00156       p+=recvcount[i];
00157     }
00158     assert(p==elevertall+NV*gdata->n_ele);
00159   }
00160   else {
00161     elevertall=gdata->elevert;
00162   }
00163 #endif
00164 
00165   int *elepropall;
00166   if (size>1) {
00167     ierr = PetscMalloc(gdata->n_ele*sizeof(int),&elepropall);CHKERRQ(ierr);
00168     ierr = PetscMemcpy(elepropall+low,gdata->eleprop,gdata->ln_ele*sizeof(int));CHKERRQ(ierr);
00169 
00170     int *p;
00171     p=elepropall;
00172 
00173     int recvcount[size];
00174     recvcount[rank]=gdata->ln_ele;
00175     for (int i=0;i<size;i++) {
00176       ierr = MPI_Bcast(recvcount+i,1,MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00177 
00178       ierr = MPI_Bcast(p,recvcount[i],MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00179       p+=recvcount[i];
00180     }
00181     assert(p==elepropall+gdata->n_ele);
00182   }
00183   else {
00184     elepropall=gdata->eleprop;
00185   }
00186 
00187   int *elevertcoupled;
00188   ierr = PetscMalloc(NV*gdata->n_ele*sizeof(int),&elevertcoupled);CHKERRQ(ierr);
00189   ierr = PetscMemcpy(elevertcoupled,elevertall,NV*gdata->n_ele*sizeof(int));CHKERRQ(ierr);
00190 
00191 #ifndef HAVE_ELEVERTALL
00192   if (size>1) {
00193     ierr = PetscFree(elevertall);CHKERRQ(ierr);
00194   }
00195 #endif
00196 
00197   PetscReal sarea_area;
00198   sarea_area=0;
00199 
00200   PetscReal sarea_point[ND];
00201   PetscReal sarea_norm[ND];
00202   for (int i=0;i<ND;i++) {
00203     sarea_point[i]=sarea_norm[i]=0.0;
00204   }
00205 
00206   /* only first processor does everything */
00207   if (!rank) {
00208 
00209 #ifdef ADDONS
00210     /* map all coupled vertices to common vertex (lowest id) */
00211     if (gdata->vertcoupl!=PETSC_NULL) {
00212       for (int i=0;i<NV*gdata->n_ele;i++) {
00213         if (gdata->vertcoupl[elevertcoupled[i]]>=0 &&
00214             gdata->vertcoupl[elevertcoupled[i]]<elevertcoupled[i]) {
00215           elevertcoupled[i]=gdata->vertcoupl[elevertcoupled[i]];
00216         }
00217       }
00218     }
00219 #endif
00220 
00221     PetscPrintf(PETSC_COMM_WORLD,"Calculating mesh connectivity\n");
00222 
00223     int *ia,*ja;
00224     ierr = Mesh2Dual(gdata->n_ele,gdata->n_vert,elevertcoupled,&ia,&ja);CHKERRQ(ierr);
00225 
00226     for (int i=1;i<gdata->n_ele+1;i++) {
00227       if (ia[i]-ia[i-1]>NF) {
00228         SETERRQ2(PETSC_ERR_MEMC,"Found element with %i neighbors (>NF)!\n",ia[i]-ia[i-1],NF);
00229       }
00230     }
00231 
00232     /* check for array overrun */
00233     assert(ia[gdata->n_ele]<NF*gdata->n_ele);
00234 
00235     PetscPrintf(PETSC_COMM_WORLD,"Searching shared faces\n");
00236     for (int i=0; i<gdata->n_ele; i++) {
00237       if (elepropall[i]!=pid1) continue;
00238 
00239       if (pid2>=0) {
00240         for (int j2=ia[i];j2<ia[i+1];j2++) {
00241           int j;
00242           j=ja[j2];
00243 
00244           if (elepropall[j]!=pid2) continue;
00245 
00246           int s[NV-1];
00247           int k;
00248           k=TetSharedVertices(elevertcoupled+NV*i,elevertcoupled+NV*j,s);
00249           assert(k==NV-1);
00250 
00251           PetscReal a;
00252           PetscReal n[ND];
00253           a=triarea(
00254             gdata->vertxyz+ND*s[0],
00255             gdata->vertxyz+ND*s[1],
00256             gdata->vertxyz+ND*s[2],
00257             n
00258           );
00259 
00260           sarea_area+=a;
00261 
00262           for (int p=0;p<ND;p++) {
00263             if (n[2]>=0.0) {
00264               sarea_norm[p]+=n[p]*a;
00265             }
00266             else {
00267               sarea_norm[p]-=n[p]*a;
00268             }
00269             for (int q=0;q<NV-1;q++) {
00270               sarea_point[p]+=gdata->vertxyz[ND*s[q]+p]*a/(NV-1.0);
00271             }
00272           }
00273         }
00274       }
00275       else if (pid2==-1) {
00276         /* total surface of vol with pid1: complicated to implement (see facnb.c) */
00277         SETERRQ1(PETSC_ERR_ARG_INCOMP,"Program branch for pid2==%i not implemented!\n",pid2);
00278       }
00279       else if (pid2==-2) {
00280         /* free surface of vol with pid1: complicated to implement (see facnb.c) */
00281         SETERRQ1(PETSC_ERR_ARG_INCOMP,"Program branch for pid2==%i not implemented!\n",pid2);
00282       }
00283     }
00284 
00285     ierr = PetscFree(ia);CHKERRQ(ierr);
00286     ierr = PetscFree(ja);CHKERRQ(ierr);
00287 
00288   }
00289 
00290   ierr = MPI_Bcast(&sarea_area,1,MPIU_SCALAR,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
00291   ierr = MPI_Bcast(sarea_point,ND,MPIU_SCALAR,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
00292   ierr = MPI_Bcast(sarea_norm,ND,MPIU_SCALAR,0,PETSC_COMM_WORLD);CHKERRQ(ierr);
00293 
00294   if (size>1) {
00295     ierr = PetscFree(elepropall);CHKERRQ(ierr);
00296   }
00297 
00298   *sharedarea_area=sarea_area;
00299 
00300   if (sharedarea_point!=PETSC_NULL) {
00301     my_dscal(ND,1.0/sarea_area,sarea_point,1);
00302     my_dcopy(ND,sarea_point,1,sharedarea_point,1);
00303   }
00304 
00305   if (sharedarea_norm!=PETSC_NULL) {
00306     my_dscal(ND,1.0/sarea_area,sarea_norm,1);
00307     my_dcopy(ND,sarea_norm,1,sharedarea_norm,1);
00308   }
00309 
00310   MagparFunctionLogReturn(0);
00311 }
00312 

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