htot.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: htot.c 2966 2010-02-08 23:31:15Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 #include "field.h"
00028 
00029 #ifdef ADDONS
00030 #include "addons/addons.h"
00031 #endif
00032 
00033 #ifdef SPINTORQ
00034 #include "spintorq/spintorq.h"
00035 #endif
00036 
00037 static int doinit=1;
00038 static Vec VHtotsum=PETSC_NULL;
00039 static Vec VMom; 
00041 int Htot_Init(GridData *gdata)
00042 {
00043   MagparFunctionLogBegin;
00044 
00045   PetscPrintf(PETSC_COMM_WORLD,"Htot on\n");
00046 
00047   ierr = VecDuplicate(gdata->M,&gdata->VHtot);CHKERRQ(ierr);
00048   ierr = VecDuplicate(gdata->M,&VMom);CHKERRQ(ierr);
00049   ierr = VecDuplicate(gdata->M,&VHtotsum);CHKERRQ(ierr);
00050 
00051   MagparFunctionLogReturn(0);
00052 }
00053 
00054 
00055 int Htot(GridData *gdata)
00056 {
00057   MagparFunctionInfoBegin;
00058 
00059   /* initialize if necessary */
00060   if (doinit) {
00061     ierr = Htot_Init(gdata);CHKERRQ(ierr);
00062     doinit=0;
00063   }
00064 
00065   ierr = VecZeroEntries(VHtotsum);CHKERRQ(ierr);
00066 
00067   ierr = Hcubic(gdata,VHtotsum);CHKERRQ(ierr);
00068   ierr = Hdemag(gdata,VHtotsum);CHKERRQ(ierr);
00069   ierr = Helastic(gdata,VHtotsum);CHKERRQ(ierr);
00070   ierr = Hexchani(gdata,VHtotsum);CHKERRQ(ierr);
00071   ierr = Hexternal(gdata,VHtotsum);CHKERRQ(ierr);
00072 #ifdef ADDONS
00073   ierr = HIlayerExch(gdata,VHtotsum);CHKERRQ(ierr);
00074   ierr = Hnonlin(gdata,VHtotsum);CHKERRQ(ierr);
00075   ierr = Hcancel(gdata,VHtotsum);CHKERRQ(ierr);
00076 #endif
00077 #ifdef SPINTORQ
00078   /* initialize vectors to NULL */
00079   gdata->VHspintorque=PETSC_NULL;
00080   gdata->VHspinforce=PETSC_NULL;
00081 
00082   ierr = Hspintorq(gdata);CHKERRQ(ierr);
00083   ierr = Hspinforce(gdata);CHKERRQ(ierr);
00084 
00085   if (gdata->VHspintorque!=PETSC_NULL && gdata->VHspinforce!=PETSC_NULL) {
00086     SETERRQ(PETSC_ERR_ARG_INCOMP,"Spin torque and spin force are switched on at the same time!\n");
00087   }
00088 #endif
00089 
00090   ierr = VecCopy(VHtotsum,gdata->VHtot);CHKERRQ(ierr);
00091 
00092   MagparFunctionProfReturn(0);
00093 }
00094 
00095 
00096 int Htot_Gradient(GridData *gdata)
00097 {
00098   Vec VHtemp;
00099 
00100   MagparFunctionInfoBegin;
00101 
00102   /* abusing VMom */
00103   VHtemp=VMom;
00104 
00105   /* initialize if necessary */
00106   if (doinit) {
00107     ierr = Htot_Init(gdata);CHKERRQ(ierr);
00108     doinit=0;
00109   }
00110 
00111 #if 1
00112   /* gives correct result for Etot in example mumag3: 1.240375e+05 ; LLG: 1.240388e+05 */
00113   /* appears to converge faster for example fept, headfield_nonlin w/o demag (but higher Etot) ! */
00114   /*
00115   m=M*Ms*V
00116   grad(E)=dE/dm=dE/d(M*Ms*V)
00117   H=-dE/dm
00118   grad(E)=-H
00119 
00120   However, Ms and V are fixed and only M varies in our formulation:
00121   grad(E)=dE/dM=Ms*V*dE/d(M*Ms*V)=Ms*V*dE/dm=Ms*V*(-H)
00122   */
00123 
00124   ierr = Htot(gdata);CHKERRQ(ierr);
00125 
00126   /* This scaling with gdata->VMs3 is necessary for big writer models to converge properly.
00127      Causes wiggles in M in headfield_nonlin while iterating, but converges fine.
00128   */
00129   ierr = VecPointwiseMult(gdata->VHtot,gdata->VHtot,gdata->VMs3);CHKERRQ(ierr);
00130 #else
00131   /* for comparison between hand-coded and TAO's finite difference gradient: magpar_examples5/cube_test_grad */
00132   /* gives incorrect result for Etot in example mumag3: 1.256195e+05 (too high) */
00133 
00134   ierr = VecZeroEntries(VHtotsum);CHKERRQ(ierr);
00135 
00136   /* calculate field/gradient contributions and apply fudge (?) factor */
00137   VecZeroEntries(VHtemp);Hcubic(gdata,VHtemp);     VecAXPY(VHtotsum,1.0,VHtemp); /* ok */
00138   VecZeroEntries(VHtemp);Hdemag(gdata,VHtemp);     VecAXPY(VHtotsum,0.5,VHtemp); /* ok */
00139   VecZeroEntries(VHtemp);Helastic(gdata,VHtemp);   VecAXPY(VHtotsum,2.0,VHtemp); /* ok */
00140   VecZeroEntries(VHtemp);Hexchani(gdata,VHtemp);   VecAXPY(VHtotsum,1.0,VHtemp); /* ok */
00141   VecZeroEntries(VHtemp);Hexternal(gdata,VHtemp);  VecAXPY(VHtotsum,1.0,VHtemp); /* ok */
00142 
00143 #ifdef ADDONS
00144   VecZeroEntries(VHtemp);HIlayerExch(gdata,VHtemp);VecAXPY(VHtotsum,1.0,VHtemp); /* ok */
00145   VecZeroEntries(VHtemp);Hnonlin(gdata,VHtemp);    VecAXPY(VHtotsum,1.0,VHtemp); /* ok */
00146   VecZeroEntries(VHtemp);Hcancel(gdata,VHtemp);    VecAXPY(VHtotsum,1.0,VHtemp); /* TODO */
00147 #endif
00148 
00149   ierr = VecCopy(VHtotsum,gdata->VHtot);CHKERRQ(ierr);
00150   ierr = VecPointwiseMult(gdata->VHtot,gdata->VHtot,gdata->VMs3);CHKERRQ(ierr);
00151 #endif
00152 
00153   ierr = VecScale(gdata->VHtot,-1.0);CHKERRQ(ierr);
00154 
00155   PetscReal *ta_Htot;
00156   VecGetArray(gdata->VHtot,&ta_Htot);
00157 
00158   /* TODO: set up Vec and do VecPointwiseMult instead of the loop */
00159   for (int i=0;i<gdata->ln_vert;i++) {
00160     /* skip non-magnetic vertices and vertices with alpha >= RIGID_M_ALPHA */
00161     if (gdata->propdat[NP*gdata->vertprop[i]+4]<=0.0 ||
00162         gdata->propdat[NP*gdata->vertprop[i]+9]>=RIGID_M_ALPHA) {
00163       ta_Htot[ND*i+0]=0.0;
00164       ta_Htot[ND*i+1]=0.0;
00165       ta_Htot[ND*i+2]=0.0;
00166       continue;
00167     }
00168   }
00169 
00170   VecRestoreArray(gdata->VHtot,&ta_Htot);
00171 
00172   MagparFunctionProfReturn(0);
00173 }
00174 
00175 
00176 int CalcEnergy(Vec M,GridData *gdata)
00177 {
00178   MagparFunctionInfoBegin;
00179 
00180   /* calculate "magnetic moments" VMom on vertices */
00181   ierr = VecPointwiseMult(VMom,gdata->VMs3,gdata->M);CHKERRQ(ierr);
00182 
00183   PetscReal e,etot;
00184   etot=0;
00185 
00186   ierr = Hcubic_Energy(gdata,M,&e);     CHKERRQ(ierr);etot += e;gdata->Eexchani  = e/gdata->totvol; /* part of anisotropy energy */
00187   ierr = Hdemag_Energy(gdata,M,&e);     CHKERRQ(ierr);etot += e;gdata->Edem      = e/gdata->totvol;
00188   ierr = Helastic_Energy(gdata,M,&e);   CHKERRQ(ierr);etot += e;
00189   ierr = Hexchani_Energy(gdata,M,&e);   CHKERRQ(ierr);etot += e;gdata->Eexchani += e/gdata->totvol; /* add to anisotropy+exchange energy */
00190 #ifdef EXCH
00191   ierr = Hexchonly_Energy(gdata,M,&e);  CHKERRQ(ierr);          gdata->Eexchonly = e/gdata->totvol; /* don't add to etot!!! */
00192 #endif
00193   ierr = Hexternal_Energy(gdata,M,&e);  CHKERRQ(ierr);etot += e;gdata->Eext      = e/gdata->totvol;
00194 #ifdef ADDONS
00195   ierr = Hcancel_Energy(gdata,M,&e);    CHKERRQ(ierr);etot += e;gdata->Eext     += e/gdata->totvol;
00196   ierr = HIlayerExch_Energy(gdata,M,&e);CHKERRQ(ierr);etot += e;gdata->Eexchani += e/gdata->totvol; /* add to anisotropy+exchange energy */
00197   ierr = Hnonlin_Energy(gdata,M,&e);    CHKERRQ(ierr);etot += e;gdata->Eexchani += e/gdata->totvol; /* add to anisotropy+exchange energy */
00198 #ifdef EXCH
00199                                                                 gdata->Eexchonly+= e/gdata->totvol; /* add to exchange only energy */
00200 #endif
00201 #endif
00202 #ifdef SPINTORQ
00203 /* TODO: implement
00204   ierr = Hspintorq_Energy(gdata,M,&e);  CHKERRQ(ierr);etot += e;
00205   ierr = Hspinforce_Energy(gdata,M,&e); CHKERRQ(ierr);etot += e;
00206 */
00207 #endif
00208 
00209   gdata->Etot=etot/gdata->totvol;
00210 
00211   MagparFunctionProfReturn(0);
00212 }
00213 
00214 
00215 int Htot_Energy(GridData *gdata)
00216 {
00217   MagparFunctionInfoBegin;
00218 
00219   /* calculate "magnetic moments" VMom on vertices */
00220   ierr = VecPointwiseMult(VMom,gdata->VMs3,gdata->M);CHKERRQ(ierr);
00221 
00222   ierr = CalcEnergy(VMom,gdata);CHKERRQ(ierr);
00223 
00224   MagparFunctionProfReturn(0);
00225 }
00226 
00227 
00228 int Htot_EminiEnergy(GridData *gdata, PetscReal *f)
00229 {
00230   MagparFunctionInfoBegin;
00231 
00232 #ifdef NO_VMS3
00233   /* calculate "pseudo" energy for energy minmizer */
00234   ierr = CalcEnergy(gdata->M,gdata);CHKERRQ(ierr);
00235   *f = gdata->Etot*gdata->totvol;
00236 #endif
00237 
00238   /* calculate real energy with "magnetic moments" VMom on vertices */
00239   ierr = VecPointwiseMult(VMom,gdata->VMs3,gdata->M);CHKERRQ(ierr);
00240   ierr = CalcEnergy(VMom,gdata);CHKERRQ(ierr);
00241 
00242 #ifndef NO_VMS3
00243 #endif
00244   if (gdata->mode==53) {
00245     *f = gdata->Etot*gdata->totvol;
00246   }
00247 
00248   PetscPrintf(PETSC_COMM_WORLD,"debug Etot=%g\n",*f);
00249 /*
00250   gdata->inp=PetscAbs(gdata->inp);
00251   ierr = WriteLog(gdata);CHKERRQ(ierr);
00252   ierr = WriteSet(gdata);CHKERRQ(ierr);
00253 */
00254 
00255   MagparFunctionProfReturn(0);
00256 }
00257 

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