regrefine.c

Go to the documentation of this file.
00001 /*
00002     This file is part of magpar.
00003 
00004     Copyright (C) 2002-2009 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: regrefine.c 2681 2009-07-31 04:30:53Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 #include "init.h"
00028 #include "util/util.h"
00029 
00030 int RegularRefinement(GridData *gdata)
00031 {
00032   const int midnod[4][4]=
00033             {
00034               {C_UNK,4,6,7},
00035               {C_UNK,C_UNK,5,8},
00036               {C_UNK,C_UNK,C_UNK,9},
00037               {C_UNK,C_UNK,C_UNK,C_UNK}
00038             };
00039   const int child[8][4]=
00040             {
00041               {0,4,6,7},
00042               {4,1,5,8},
00043               {6,5,2,9},
00044               {7,8,9,3},
00045               {4,6,7,8},
00046               {4,5,6,8},
00047               {6,8,5,9},
00048               {6,7,8,9}
00049             };
00050 
00051 
00052   MagparFunctionLogBegin;
00053 
00054   int rank,size;
00055   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00056   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00057 
00058   int refine;
00059   PetscTruth flg;
00060   ierr = PetscOptionsGetInt(PETSC_NULL,"-refine",(PetscInt*)&refine,&flg);CHKERRQ(ierr);
00061   if (flg!=PETSC_TRUE) {
00062     refine=0;
00063     PetscPrintf(PETSC_COMM_WORLD,
00064       "Option -refine not found, using default value: %i\n",
00065       refine
00066     );
00067   }
00068 
00069   PetscPrintf(PETSC_COMM_WORLD,
00070     "Requested number of refinement steps: %i\n",
00071     refine
00072   );
00073 
00074   if (rank) {
00075     for (int r=0;r<refine;r++) {
00076       Vec Mnew;
00077       ierr = VecCreate(PETSC_COMM_WORLD,&Mnew);CHKERRQ(ierr);
00078       ierr = VecSetSizes(Mnew,ND*gdata->ln_vert,PETSC_DECIDE);CHKERRQ(ierr);
00079       ierr = VecSetFromOptions(Mnew);CHKERRQ(ierr);
00080       ierr = VecSetBlockSize(Mnew,ND);CHKERRQ(ierr);
00081 
00082       ierr = VecDestroy(gdata->M);CHKERRQ(ierr);
00083       gdata->M=Mnew;
00084 
00085       PetscReal devNorm;
00086       devNorm=RenormVec(gdata->M,1.0,0.0,ND);
00087     }
00088     MagparFunctionLogReturn(0);
00089   }
00090 
00091   /* get connectivity matrix of nodes */
00092   /* recommended size (METIS manual):
00093      sizeof(ia): (n_vert+1)
00094      sizeof(ja): 15*n_vert
00095   */
00096 
00097   for (int r=0;r<refine;r++) {
00098     PetscPrintf(PETSC_COMM_WORLD,"Starting refinement step: %i\n",r+1);
00099 
00100     int *nxadj,*nadjncy;
00101     ierr = Mesh2Nodal(gdata->n_ele,gdata->n_vert,gdata->elevert,&nxadj,&nadjncy);CHKERRQ(ierr);
00102 
00103     /* the last entry in nxadj (nxadj[gdata->n_vert])
00104        gives us the total number of vertex neighbours,
00105        each pair of neighbours appears twice,
00106        thus we have nxadj[gdata->n_vert]/2 pairs of neighbours (=edges),
00107        thus the total number of edges is
00108        nxadj[gdata->n_vert]/2
00109     */
00110 
00111     int n_edge;
00112     n_edge=nxadj[gdata->n_vert]/2;
00113     PetscPrintf(PETSC_COMM_WORLD,
00114       "Number of edges: %i\n",
00115       n_edge
00116     );
00117 
00118     PetscPrintf(PETSC_COMM_WORLD,
00119       "Generating a FE mesh with %i nodes and %i elements.\n",
00120       gdata->n_vert+n_edge,
00121       8*gdata->n_ele
00122     );
00123 
00124 
00125     /* allocate memory for ids of new vertices */
00126     int *nvert;
00127     ierr = PetscMalloc(2*n_edge*sizeof(int),&nvert);CHKERRQ(ierr);
00128 
00129     for (int i=0;i<2*n_edge;i++) nvert[i]=C_UNK;
00130 
00131     /* reset counter for new vertices */
00132     int cnt;
00133     cnt=gdata->n_vert;
00134 
00135     /* allocate memory for cartesian coordinates of old and new vertices */
00136     PetscReal *nvertxyz;
00137     ierr = PetscMalloc(ND*(gdata->n_vert+n_edge)*sizeof(PetscReal),&nvertxyz);CHKERRQ(ierr);
00138 
00139     ierr = PetscMemcpy(nvertxyz,gdata->vertxyz,ND*gdata->n_vert*sizeof(PetscReal));CHKERRQ(ierr);
00140 
00141     /* allocate memory for new elements */
00142     int *nelevert;
00143     ierr = PetscMalloc(NV*8*gdata->n_ele*sizeof(int),&nelevert);CHKERRQ(ierr);
00144 
00145     /* regular refinement
00146        cf.
00147        J. Bey, Tetrahedral Grid Refinement. Computing 55 (1995) 355.
00148        http://www.igpm.rwth-aachen.de/bey/agm.html
00149        http://www.igpm.rwth-aachen.de/bey/ftp/agm.ps.Z
00150        p. 62
00151     */
00152     for (int i=0;i<gdata->n_ele;i++) {
00153       /* get vertex ids */
00154       int t_v[10];
00155       ierr = PetscMemcpy(t_v,gdata->elevert+i*NV,NV*sizeof(int));CHKERRQ(ierr);
00156 
00157       /* find new vertices */
00158       for (int m=0;m<NV-1;m++) {
00159         for (int n=m+1;n<NV;n++) {
00160           /* we take the minimum of the "parent node ids" since
00161              they are "equal partners" and have only one common child,
00162              and we want to have a unique address of the child's id in nvert
00163           */
00164           int lid,hid;
00165           lid=PetscMin(t_v[m],t_v[n]);
00166           hid=PetscMax(t_v[m],t_v[n]);
00167 
00168           int nnb;
00169           nnb=nxadj[lid+1]-nxadj[lid];
00170 
00171           /* search in list of newly created nodes first */
00172 
00173           /* go through the list of neigbours */
00174           int j;
00175           for (j=0;j<nnb;j++) {
00176             if (nadjncy[nxadj[lid]+j]==hid) {
00177               /* we found the neighbouring node */
00178 
00179               /* check if it the midnode has already been "created"
00180               */
00181               if (nvert[nxadj[lid]+j] == C_UNK) {
00182                 nvert[nxadj[lid]+j]=cnt;
00183                 /* set cartesian coordinates */
00184                 for (int k=0;k<ND;k++) {
00185                   nvertxyz[ND*cnt+k]=
00186                     0.5*(gdata->vertxyz[ND*lid+k]+gdata->vertxyz[ND*hid+k]);
00187                 }
00188                 /* increase vertex counter */
00189                 cnt++;
00190               }
00191               break;
00192             }
00193           }
00194           /* the neighbour must have been found
00195              (and the for loop terminated by the break command)
00196           */
00197           assert(j<nxadj[lid+1]-nxadj[lid]);
00198 
00199           t_v[midnod[m][n]]=nvert[nxadj[lid]+j];
00200         }
00201       }
00202       /* create new elements */
00203       for (int j=0;j<8;j++) {
00204         for (int k=0;k<NV;k++) {
00205           nelevert[NV*8*i+NV*j+k]=t_v[child[j][k]];
00206         }
00207       }
00208     }
00209 
00210     assert(cnt==gdata->n_vert+n_edge);
00211 
00212     ierr = PetscFree(gdata->vertxyz);CHKERRQ(ierr);
00213     gdata->vertxyz=nvertxyz;
00214 
00215     ierr = PetscFree(gdata->elevert);CHKERRQ(ierr);
00216     gdata->elevert=nelevert;
00217 
00218     /* interpolate magnetization on new vertices */
00219 
00220     Vec Mnew;
00221     ierr = VecCreate(PETSC_COMM_WORLD,&Mnew);CHKERRQ(ierr);
00222     ierr = VecSetSizes(Mnew,ND*(gdata->n_vert+n_edge),PETSC_DECIDE);CHKERRQ(ierr);
00223     ierr = VecSetFromOptions(Mnew);CHKERRQ(ierr);
00224     ierr = VecSetBlockSize(Mnew,ND);CHKERRQ(ierr);
00225 
00226     int cnt2;
00227     ierr = VecGetLocalSize(gdata->M,(PetscInt*)&cnt2);CHKERRQ(ierr);
00228     assert(cnt2==ND*gdata->n_vert);
00229     ierr = VecGetSize(gdata->M,(PetscInt*)&cnt2);CHKERRQ(ierr);
00230     assert(cnt2==ND*gdata->n_vert);
00231 
00232     ierr = VecGetLocalSize(Mnew,(PetscInt*)&cnt2);CHKERRQ(ierr);
00233     assert(cnt2==ND*(gdata->n_vert+n_edge));
00234 
00235     PetscReal *t_M, *t_Mnew;
00236     ierr = VecGetArray(gdata->M,&t_M);CHKERRQ(ierr);
00237     ierr = VecGetArray(Mnew,&t_Mnew);CHKERRQ(ierr);
00238 
00239     PetscPrintf(PETSC_COMM_WORLD,"Updating M\n");
00240 
00241     for (int i=0;i<gdata->n_vert;i++) {
00242       for (int k=0;k<ND;k++) {
00243         t_Mnew[ND*i+k]=t_M[ND*i+k];
00244       }
00245       for (int j=nxadj[i];j<nxadj[i+1];j++) {
00246         if (i<nadjncy[j]) {
00247           for (int k=0;k<ND;k++) {
00248             t_Mnew[ND*nvert[j]+k]=
00249               (t_M[ND*i+k]+t_M[ND*nadjncy[j]+k])/2.0;
00250           }
00251         }
00252       }
00253     }
00254 
00255     ierr = VecRestoreArray(gdata->M,&t_M);CHKERRQ(ierr);
00256     ierr = VecRestoreArray(Mnew,&t_Mnew);CHKERRQ(ierr);
00257     ierr = VecDestroy(gdata->M);CHKERRQ(ierr);
00258     gdata->M=Mnew;
00259 
00260     ierr = PetscFree(nvert);CHKERRQ(ierr);
00261 
00262     PetscReal devNorm;
00263     devNorm=RenormVec(gdata->M,1.0,0.0,ND);
00264 
00265 
00266     int *neleprop;
00267     ierr = PetscMalloc(8*gdata->n_ele*sizeof(int),&neleprop);CHKERRQ(ierr);
00268     for (int i=0;i<gdata->n_ele;i++) {
00269       for (int j=0;j<8;j++) {
00270         neleprop[8*i+j]=gdata->eleprop[i];
00271       }
00272     }
00273     ierr = PetscFree(gdata->eleprop);CHKERRQ(ierr);
00274     gdata->eleprop=neleprop;
00275 
00276     ierr = PetscFree(nxadj);CHKERRQ(ierr);
00277     ierr = PetscFree(nadjncy);CHKERRQ(ierr);
00278 
00279     /* update counters */
00280     gdata->n_vert  += n_edge;
00281     gdata->ln_vert = gdata->n_vert;
00282 
00283     gdata->n_ele   *= 8;
00284     gdata->ln_ele  = gdata->n_ele;
00285   }
00286 
00287 
00288   MagparFunctionLogReturn(0);
00289 }
00290 

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