bele.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 #include "field.h"
00025 #include "util/util.h"
00026 
00027 /*
00028   hybrid FEM/BEM method from:
00029   T. R. Koehler, D. R. Fredkin, "Finite Element Methods for
00030   Micromagnetics", IEEE Trans. Magn. 28 (1992) 1239-1244
00031 
00032   matrix elements calculated according to:
00033   D. A. Lindholm, "Three-Dimensional Magnetostatic Fields from
00034   Point-Matched Integral Equations with Linearly Varying Scalar
00035   Sources", IEEE Trans. Magn. MAG-20 (1984) 2025-2032.
00036 */
00037 
00038 int Bele(PetscReal* bvert,PetscReal* facv1,PetscReal* facv2,PetscReal* facv3,PetscReal* matele)
00039 {
00040   PetscReal   *rr,zeta[ND],zetal;
00041   PetscReal   rho1[ND],rho2[ND],rho3[ND];
00042   PetscReal   rho1l,rho2l,rho3l;
00043   PetscReal   s1,s2,s3;
00044   PetscReal   eta1[ND],eta2[ND],eta3[ND];
00045   PetscReal   eta1l,eta2l,eta3l;
00046   PetscReal   xi1[ND],xi2[ND],xi3[ND];
00047   PetscReal   gamma1[ND],gamma2[ND],gamma3[ND];
00048   PetscReal   p[ND],a,omega;
00049 
00050   matele[0]=matele[1]=matele[2]=0.0;
00051 
00052   /* get coordinates of face's vertices */
00053   my_dcopy(ND,facv1,1,rho1,1);
00054   my_dcopy(ND,facv2,1,rho2,1);
00055   my_dcopy(ND,facv3,1,rho3,1);
00056 
00057   /* calculate edge vectors and store them in xi_j */
00058   my_dcopy(ND,rho2,1,xi1,1);
00059   my_daxpy(ND,-1.0,rho1,1,xi1,1);
00060   my_dcopy(ND,rho3,1,xi2,1);
00061   my_daxpy(ND,-1.0,rho2,1,xi2,1);
00062   my_dcopy(ND,rho1,1,xi3,1);
00063   my_daxpy(ND,-1.0,rho3,1,xi3,1);
00064 
00065   /* calculate zeta direction */
00066   douter(ND,xi1,xi2,zeta);
00067 
00068   /* calculate area of the triangle */
00069   zetal=my_dnrm2(ND,zeta,1);
00070   a=0.5*zetal;
00071 
00072   /* renorm zeta */
00073   my_dscal(ND,1.0/zetal,zeta,1);
00074 
00075   /* calculate s_j and normalize xi_j */
00076   s1=my_dnrm2(ND,xi1,1);
00077   my_dscal(ND,1.0/s1,xi1,1);
00078   s2=my_dnrm2(ND,xi2,1);
00079   my_dscal(ND,1.0/s2,xi2,1);
00080   s3=my_dnrm2(ND,xi3,1);
00081   my_dscal(ND,1.0/s3,xi3,1);
00082 
00083   douter(ND,zeta,xi1,eta1);
00084   douter(ND,zeta,xi2,eta2);
00085   douter(ND,zeta,xi3,eta3);
00086 
00087   gamma1[0]=gamma3[1]=my_ddot(ND,xi2,1,xi1,1);
00088   gamma1[1]=my_ddot(ND,xi2,1,xi2,1);
00089   gamma1[2]=gamma2[1]=my_ddot(ND,xi2,1,xi3,1);
00090 
00091   gamma2[0]=gamma3[2]=my_ddot(ND,xi3,1,xi1,1);
00092   gamma2[2]=my_ddot(ND,xi3,1,xi3,1);
00093 
00094   gamma3[0]=my_ddot(ND,xi1,1,xi1,1);
00095 
00096   /* get R=rr */
00097   rr=bvert;
00098 
00099   PetscReal d;
00100   PointFromPlane(rr,rho1,rho2,rho3,&d);
00101   if (PetscAbsReal(d)<D_EPS) return(0);
00102 
00103   /* calculate rho_j */
00104   my_daxpy(ND,-1.0,rr,1,rho1,1);
00105   my_daxpy(ND,-1.0,rr,1,rho2,1);
00106   my_daxpy(ND,-1.0,rr,1,rho3,1);
00107 
00108   /* zetal gives ("normal") distance of R from the plane of the triangle */
00109   zetal=my_ddot(ND,zeta,1,rho1,1);
00110 
00111   /* skip the rest if zetal==0 (R in plane of the triangle)
00112      -> omega==0 and zetal==0 -> matrix entry=0
00113   */
00114   if (PetscAbsReal(zetal)<=D_EPS) {
00115     return(0);
00116   }
00117 
00118   rho1l=my_dnrm2(ND,rho1,1);
00119   rho2l=my_dnrm2(ND,rho2,1);
00120   rho3l=my_dnrm2(ND,rho3,1);
00121 
00122   PetscReal t_nom,t_denom;
00123   t_nom=
00124     rho1l*rho2l*rho3l+
00125     rho1l*my_ddot(ND,rho2,1,rho3,1)+
00126     rho2l*my_ddot(ND,rho3,1,rho1,1)+
00127     rho3l*my_ddot(ND,rho1,1,rho2,1);
00128   t_denom=
00129     sqrt(2.0*
00130       (rho2l*rho3l+my_ddot(ND,rho2,1,rho3,1))*
00131       (rho3l*rho1l+my_ddot(ND,rho3,1,rho1,1))*
00132       (rho1l*rho2l+my_ddot(ND,rho1,1,rho2,1))
00133     );
00134 
00135   /* catch special cases where the argument of acos
00136      is close to -1.0 or 1.0 or even outside this interval
00137 
00138      use 0.0 instead of D_EPS?
00139      fixes problems with demag field calculation
00140      suggested by Hiroki Kobayashi, Fujitsu
00141   */
00142   if (t_nom/t_denom<-1.0) {
00143     omega=(zetal >= 0.0 ? 1.0 : -1.0)*2.0*M_PI;
00144   }
00145   /* this case should not occur, but does - e.g. examples1/headfield */
00146   else if (t_nom/t_denom>1.0) {
00147     return(0);
00148   }
00149   else {
00150     omega=(zetal >= 0.0 ? 1.0 : -1.0)*2.0*acos(t_nom/t_denom);
00151   }
00152 
00153   eta1l=my_ddot(ND,eta1,1,rho1,1);
00154   eta2l=my_ddot(ND,eta2,1,rho2,1);
00155   eta3l=my_ddot(ND,eta3,1,rho3,1);
00156 
00157   p[0]=log((rho1l+rho2l+s1)/(rho1l+rho2l-s1));
00158   p[1]=log((rho2l+rho3l+s2)/(rho2l+rho3l-s2));
00159   p[2]=log((rho3l+rho1l+s3)/(rho3l+rho1l-s3));
00160 
00161   matele[0]=(eta2l*omega-zetal*my_ddot(ND,gamma1,1,p,1))*s2/(8.0*PETSC_PI*a);
00162   matele[1]=(eta3l*omega-zetal*my_ddot(ND,gamma2,1,p,1))*s3/(8.0*PETSC_PI*a);
00163   matele[2]=(eta1l*omega-zetal*my_ddot(ND,gamma3,1,p,1))*s1/(8.0*PETSC_PI*a);
00164 
00165   return(0);
00166 }

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