distortmesh.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: distortmesh.c 2962 2010-02-04 19:50:44Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 #include "init.h"
00028 
00029 int DistortMesh(GridData *gdata)
00030 {
00031   PetscTruth   flg;
00032 
00033   MagparFunctionLogBegin;
00034 
00035   int rank,size;
00036   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00037   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00038 
00039   if (rank) {
00040     MagparFunctionLogReturn(0);
00041   }
00042 
00043   /* scale mesh */
00044 
00045   PetscReal mesh_scale[ND];
00046   int nmax;
00047 
00048   nmax=ND;
00049   ierr = PetscOptionsGetRealArray(PETSC_NULL,"-mesh_scale",mesh_scale,&nmax,&flg);CHKERRQ(ierr);
00050   if (flg!=PETSC_TRUE) {
00051     /* set default values if option is missing */
00052     mesh_scale[0]=mesh_scale[1]=mesh_scale[2]=1.0;
00053     PetscPrintf(PETSC_COMM_WORLD,"Option -mesh_scale not found or incorrect number of values given.\nUsing default value '%g,%g,%g'!\n",
00054       mesh_scale[0],mesh_scale[1],mesh_scale[2]
00055     );
00056   }
00057   else if (nmax!=ND) {
00058     /* set default values if option is missing */
00059     SETERRQ1(PETSC_ERR_ARG_CORRUPT,
00060       "Option -mesh_scale has incorrect number of values: %i!\n",
00061       nmax
00062     );
00063   }
00064   else {
00065     PetscPrintf(PETSC_COMM_WORLD,"Scaling mesh: '%g,%g,%g'!\n",
00066       mesh_scale[0],mesh_scale[1],mesh_scale[2]
00067     );
00068     for (int i=0; i<gdata->ln_vert; i++) {
00069       for (int j=0; j<ND; j++) {
00070         gdata->vertxyz[ND*i+j] *= mesh_scale[j];
00071       }
00072     }
00073   }
00074 
00075 
00076   /* shift mesh */
00077 
00078   PetscReal shift[ND];
00079   nmax=ND;
00080   ierr = PetscOptionsGetRealArray(PETSC_NULL,"-shift",shift,&nmax,&flg);CHKERRQ(ierr);
00081   if (flg!=PETSC_TRUE) {
00082     /* set default values if option is missing */
00083     shift[0]=shift[1]=shift[2]=0;
00084     PetscPrintf(PETSC_COMM_WORLD,"Option -shift not found, using default value '%g,%g,%g'!\n",
00085       shift[0],shift[1],shift[2]
00086     );
00087   }
00088   else if (nmax!=ND) {
00089     /* set default values if option is missing */
00090     SETERRQ1(PETSC_ERR_ARG_CORRUPT,
00091       "Option -shift has incorrect number of values: %i!\n",
00092       nmax
00093     );
00094   }
00095   else {
00096     PetscPrintf(PETSC_COMM_WORLD,"Shifting mesh: '%g,%g,%g'!\n",
00097       shift[0],shift[1],shift[2]
00098     );
00099     for (int i=0; i<gdata->ln_vert; i++) {
00100       for (int j=0; j<ND; j++) {
00101         gdata->vertxyz[ND*i+j] += shift[j];
00102       }
00103     }
00104   }
00105 
00106 
00107   /* distort the mesh */
00108 
00109   int meshdist;
00110   ierr = PetscOptionsGetInt(PETSC_NULL,"-meshdist",(PetscInt*)&meshdist,&flg);CHKERRQ(ierr);
00111   if (flg!=PETSC_TRUE) {
00112     /* set default values if option is missing */
00113     meshdist=0;
00114     PetscPrintf(PETSC_COMM_WORLD,
00115       "Option -meshdist not found, using default value %i!\n",
00116       meshdist
00117     );
00118   }
00119 
00120   PetscPrintf(PETSC_COMM_WORLD,"meshdist: %i\n",meshdist);
00121   if (meshdist==0) {
00122     PetscPrintf(PETSC_COMM_WORLD,"mesh undistorted\n");
00123     MagparFunctionLogReturn(0);
00124   }
00125 
00126   PetscReal distpar;
00127   ierr = PetscOptionsGetReal(PETSC_NULL,"-distpar",&distpar,&flg);CHKERRQ(ierr);
00128   if (flg!=PETSC_TRUE) {
00129     /* set default values if option is missing */
00130     distpar=0;
00131     PetscPrintf(PETSC_COMM_WORLD,
00132       "Option -distpar not found, using default value %g!\n",
00133       distpar
00134     );
00135   }
00136 
00137   /* elevertvol will check if the mesh is corrupted
00138      i.e. overlapping elements = negative volumes of tetrahedra
00139   */
00140 
00141   PetscReal elenmax,elenmin;
00142   elenmax=0.0;
00143   elenmin=1.0/D_EPS;
00144 
00145   for (int i=0; i<gdata->ln_ele; i++) {
00146     /* Get Vertex coordinates */
00147     int *t_v;
00148     t_v=gdata->elevert+i*NV;
00149 
00150     PetscReal *x1,*x2,*x3,*x4;
00151     x1=gdata->vertxyz+t_v[0]*ND;
00152     x2=gdata->vertxyz+t_v[1]*ND;
00153     x3=gdata->vertxyz+t_v[2]*ND;
00154     x4=gdata->vertxyz+t_v[3]*ND;
00155 
00156     /* Calculate edge lengths */
00157     PetscReal edge[ND];
00158     my_dcopy(ND,x1,1,edge,1);
00159     my_daxpy(ND,-1.0,x2,1,edge,1);
00160 
00161     PetscReal elen;
00162     elen=my_dnrm2(ND,edge,1);
00163     elenmax=PetscMax(elenmax,elen);
00164     elenmin=PetscMin(elenmin,elen);
00165 
00166     my_dcopy(ND,x1,1,edge,1);
00167     my_daxpy(ND,-1.0,x3,1,edge,1);
00168     elen=my_dnrm2(ND,edge,1);
00169     elenmax=PetscMax(elenmax,elen);
00170     elenmin=PetscMin(elenmin,elen);
00171 
00172     my_dcopy(ND,x1,1,edge,1);
00173     my_daxpy(ND,-1.0,x4,1,edge,1);
00174     elen=my_dnrm2(ND,edge,1);
00175     elenmax=PetscMax(elenmax,elen);
00176     elenmin=PetscMin(elenmin,elen);
00177 
00178     my_dcopy(ND,x2,1,edge,1);
00179     my_daxpy(ND,-1.0,x3,1,edge,1);
00180     elen=my_dnrm2(ND,edge,1);
00181     elenmax=PetscMax(elenmax,elen);
00182     elenmin=PetscMin(elenmin,elen);
00183 
00184     my_dcopy(ND,x2,1,edge,1);
00185     my_daxpy(ND,-1.0,x4,1,edge,1);
00186     elen=my_dnrm2(ND,edge,1);
00187     elenmax=PetscMax(elenmax,elen);
00188     elenmin=PetscMin(elenmin,elen);
00189 
00190     my_dcopy(ND,x3,1,edge,1);
00191     my_daxpy(ND,-1.0,x4,1,edge,1);
00192     elen=my_dnrm2(ND,edge,1);
00193     elenmax=PetscMax(elenmax,elen);
00194     elenmin=PetscMin(elenmin,elen);
00195   }
00196 
00197   PetscPrintf(PETSC_COMM_WORLD,"distorting mesh - meshdist: %i distpar: %g elenmin: %g\n",
00198     meshdist,distpar,elenmin
00199   );
00200 
00201   PetscRandom rctx;
00202   ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr);
00203   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
00204 
00205   for (int i=0; i<gdata->ln_vert; i++) {
00206     PetscReal randist[ND];
00207     PetscReal norm;
00208 
00209     /* calculate random vector for M, which lies within
00210        the |M|=1 sphere, to guarantee uniform distribution
00211        on the unit sphere
00212     */
00213     do {
00214       PetscRandomGetValue(rctx,&randist[0]); randist[0] = randist[0]*2.0-1.0;
00215       PetscRandomGetValue(rctx,&randist[1]); randist[1] = randist[1]*2.0-1.0;
00216       PetscRandomGetValue(rctx,&randist[2]); randist[2] = randist[2]*2.0-1.0;
00217     } while ((norm=my_dnrm2(ND,randist,1)) > 1.0);
00218 
00219     switch (meshdist) {
00220       case 1: /* distort only interior mesh */
00221         if (gdata->vertbndg2bnd[gdata->vertl2g[i]] == C_INT) {
00222           gdata->vertxyz[ND*i+0] += randist[0]/norm*distpar*elenmin;
00223           gdata->vertxyz[ND*i+1] += randist[1]/norm*distpar*elenmin;
00224           gdata->vertxyz[ND*i+2] += randist[2]/norm*distpar*elenmin;
00225         }
00226       break;
00227       case 2: /* distort only boundary mesh */
00228         if (gdata->vertbndg2bnd[gdata->vertl2g[i]] >= 0) {
00229           gdata->vertxyz[ND*i+0] += randist[0]/norm*distpar*elenmin;
00230           gdata->vertxyz[ND*i+1] += randist[1]/norm*distpar*elenmin;
00231           gdata->vertxyz[ND*i+2] += randist[2]/norm*distpar*elenmin;
00232         }
00233       break;
00234       case 3: /* distort whole mesh */
00235         gdata->vertxyz[ND*i+0] += randist[0]/norm*distpar*elenmin;
00236         gdata->vertxyz[ND*i+1] += randist[1]/norm*distpar*elenmin;
00237         gdata->vertxyz[ND*i+2] += randist[2]/norm*distpar*elenmin;
00238       break;
00239     }
00240   }
00241   ierr = PetscRandomDestroy(rctx);CHKERRQ(ierr);
00242 
00243   MagparFunctionLogReturn(0);
00244 }
00245 

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