eminisolve.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: eminisolve.c 2795 2009-10-19 18:54:30Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 #include "emini.h"
00028 #include "field/field.h"
00029 #include "util/util.h"
00030 #include "llg/llg.h"
00031 #include "io/magpario.h"
00032 
00033 #ifdef ADDONS
00034 #include "addons/addons.h"
00035 #endif
00036 
00037 #undef DEBUG
00038 #ifdef DEBUG
00039 static Vec dMdt=PETSC_NULL;
00040 #endif
00041 
00042 /* undef DAMP to use conventional gradient
00043    define DAMP to use damping term for gradient/line search
00044 */
00045 #undef DAMP
00046 
00047 /* TODO: problems with using Cartesian coordinates in micromagnetic model:
00048    |M|==1 is not preserved! M "runs away"! - need penalty term or such
00049    works great with nonlinear model
00050 */
00051 
00052 static TAO_SOLVER tao;
00053 static TAO_APPLICATION taoapp;
00054 static PetscRandom rctx=PETSC_NULL;
00055 static PetscReal magdist;
00056 static PetscReal tol;
00057 static int tao_max_its;
00058 
00059 static Vec Msphere;
00060 static Vec VHtotsphere;
00061 
00062 #undef TESTTORQ
00063 #ifdef TESTTORQ
00064 static Vec dMdt=PETSC_NULL;
00065 #endif
00066 
00067 #ifdef DAMP
00068 static Vec grad;
00069 #endif
00070 
00071 int TaoEvalEnergyGrad(TAO_APPLICATION taoapp,Vec X,double *f, Vec G,void *ptr)
00072 {
00073   GridData *gdata = (GridData*)ptr;
00074 
00075   MagparFunctionInfoBegin;
00076 
00077   if (gdata->mode==53) {
00078     /* FIXME: try to avoid copying vectors here
00079        can we do gdata->M=X instead?
00080        same for gdata->VHtot=G ?
00081        search for all VecCopy and try to do something smarter
00082     */
00083     ierr = VecCopy(X,gdata->M);CHKERRQ(ierr);
00084   }
00085   else {
00086     ierr = Sphere2Cart(X,gdata->M);CHKERRQ(ierr);
00087   }
00088 
00089   ierr = Htot_Gradient(gdata);CHKERRQ(ierr);
00090 
00091 #ifdef DAMP
00092   /* use damping term instead of field for gradient/line search */
00093 
00094   PetscReal *ta_M, *ta_Htot, *ta_grad;
00095   ierr = VecGetArray(gdata->M,&ta_M);CHKERRQ(ierr);
00096   ierr = VecGetArray(gdata->VHtot,&ta_Htot);CHKERRQ(ierr);
00097   ierr = VecGetArray(grad,&ta_grad);CHKERRQ(ierr);
00098 
00099   for (int i=0; i<gdata->ln_vert; i++) {
00100     PetscReal  *damp, mxh[ND];
00101     PetscReal  a1;
00102 
00103     /* skip non-magnetic vertices */
00104     if (gdata->propdat[NP*gdata->vertprop[i]+4]<=0.0) continue;
00105 
00106     damp=ta_grad+ND*i;
00107 
00108     douter(ND,ta_M+ND*i,ta_Htot+ND*i,mxh);
00109     douter(ND,ta_M+ND*i,mxh,damp);
00110 
00111     /* use small parameter to keep residual for TAO small */
00112     a1=0.001;
00113     my_dscal(ND,a1,damp,1);
00114   }
00115 
00116   ierr = VecRestoreArray(gdata->M,&ta_M);CHKERRQ(ierr);
00117   ierr = VecRestoreArray(gdata->VHtot,&ta_Htot);CHKERRQ(ierr);
00118   ierr = VecRestoreArray(grad,&ta_grad);CHKERRQ(ierr);
00119 #endif
00120 
00121   ierr = Htot_Energy(gdata);CHKERRQ(ierr);
00122   *f=gdata->Etot;
00123 
00124 /* Test gradient with these options:
00125   -tao_method tao_fd_test
00126   -tao_test_gradient
00127   -tao_test_display
00128 */
00129 
00130 #ifdef DAMP
00131   if (gdata->mode==53) {
00132     ierr = VecCopy(grad,G);CHKERRQ(ierr);
00133   }
00134   else {
00135     ierr = Cart2SphereDiff(grad,X,G);CHKERRQ(ierr);
00136   }
00137 #else
00138   if (gdata->mode==53) {
00139     ierr = VecCopy(gdata->VHtot,G);CHKERRQ(ierr);
00140   }
00141   else {
00142     ierr = Cart2SphereDiff(gdata->VHtot,X,G);CHKERRQ(ierr);
00143   }
00144 #endif
00145 
00146   /* DEBUG
00147   PetscPrintf(PETSC_COMM_WORLD,"deb01 X\n");
00148   VecView(X,PETSC_VIEWER_STDOUT_WORLD);
00149   PetscPrintf(PETSC_COMM_WORLD,"deb01 VHtot\n");
00150   VecView(gdata->VHtot,PETSC_VIEWER_STDOUT_WORLD);
00151   PetscPrintf(PETSC_COMM_WORLD,"deb01 G\n");
00152   VecView(G,PETSC_VIEWER_STDOUT_WORLD);
00153   */
00154 
00155   MagparFunctionProfReturn(0);
00156 }
00157 
00158 int ConvTest(TAO_SOLVER tao,void *cctx)
00159 {
00160   GridData *gdata = (GridData*)cctx;
00161 
00162   MagparFunctionInfoBegin;
00163 
00164   int iter;
00165   double ff,gnorm,cnorm,xdiff;
00166   TaoTerminateReason reason;
00167   ierr = TaoGetSolutionStatus(tao,&iter,&ff,&gnorm,&cnorm,&xdiff,&reason);CHKERRQ(ierr);
00168   if (iter>tao_max_its) {
00169     ierr = TaoSetTerminationReason(tao,TAO_DIVERGED_MAXITS);CHKERRQ(ierr);
00170     MagparFunctionProfReturn(0);
00171   }
00172 
00173 #ifdef TESTTORQ
00174   /* test based on torque dM/dt - does not work well
00175      torque>0 in energy minimum!?
00176      however torque->0 is not (strict) energy minimum
00177   */
00178   if (gdata->mode!=53) {
00179     Vec sol;
00180     ierr = TaoAppGetSolutionVec(taoapp,&sol);CHKERRQ(ierr);
00181     assert(sol==Msphere);
00182     ierr = Sphere2Cart(sol,gdata->M);CHKERRQ(ierr);
00183   }
00184 
00185   ierr = calc_dMdt(PETSC_NULL,0.0,gdata->M,dMdt,gdata);CHKERRQ(ierr);
00186   gdata->vequil=RenormVec(dMdt,0.0,PETSC_MAX,ND);
00187 
00188   ierr = TaoGetTerminationReason(tao,&reason);CHKERRQ(ierr);
00189 
00190   PetscPrintf(PETSC_COMM_WORLD,"torque = %g  Etot = %g %g  reason = %i\n",
00191     gdata->vequil,gdata->Etot,gdata->Etot*gdata->escale,reason
00192   );
00193 
00194   static int equil=0;
00195   if (gdata->vequil < tol) {
00196     ierr = TaoSetTerminationReason(tao,TAO_CONVERGED_USER);CHKERRQ(ierr);
00197     /* count how long we have been in equilibrium in succession */
00198     equil++;
00199   }
00200   else {
00201     ierr = TaoSetTerminationReason(tao,TAO_CONTINUE_ITERATING);CHKERRQ(ierr);
00202     /* reset counter if we are not in equilibrium */
00203     equil=0;
00204   }
00205 
00206 #else
00207   /* test based on change in energy */
00208   static PetscReal Etotold;
00209   static int equil;
00210 
00211   if (iter==0) {
00212     equil=0;
00213     Etotold=PETSC_MAX;
00214   }
00215 
00216   PetscLogDouble t_now;
00217   PetscGetTime(&t_now);
00218   static PetscLogDouble t_last=t_now;
00219 
00220   PetscPrintf(PETSC_COMM_WORLD,"%5i %4i %6.2f %22.16e %22.16e %22.16e %22.16e %22.16e",
00221     iter,
00222     equil,
00223     t_now-t_last,
00224     gdata->Etot,gdata->Etot*gdata->escale,
00225     Etotold,Etotold*gdata->escale,
00226     (Etotold-gdata->Etot)/PetscAbsReal(gdata->Etot)
00227   );
00228 #ifdef DEBUG
00229   ierr = calc_dMdt(PETSC_NULL,0.0,gdata->M,dMdt,gdata);CHKERRQ(ierr);
00230   gdata->vequil=RenormVec(dMdt,0.0,PETSC_MAX,ND);
00231 
00232   PetscPrintf(PETSC_COMM_WORLD,"%22.16e",
00233     gdata->vequil
00234   );
00235 #endif
00236   PetscPrintf(PETSC_COMM_WORLD,"\n");
00237   t_last=t_now;
00238 
00239   /* Etotold-gdata->Etot < 0 when energy increases
00240      This can happen around energy minimum, due to numerical errors.
00241      We allow it as long as |delta E|<tol.
00242   */
00243 #define NEQUIL 5
00244   if (PetscAbs(Etotold-gdata->Etot)/PetscAbsReal(gdata->Etot)<tol) {
00245     if (equil>=NEQUIL) {
00246       ierr = TaoSetTerminationReason(tao,TAO_CONVERGED_USER);CHKERRQ(ierr);
00247       equil=0;
00248     }
00249     else {
00250       ierr = TaoSetTerminationReason(tao,TAO_CONTINUE_ITERATING);CHKERRQ(ierr);
00251       /* count how long we have been in equilibrium in succession */
00252       equil++;
00253     }
00254   }
00255   else {
00256     ierr = TaoSetTerminationReason(tao,TAO_CONTINUE_ITERATING);CHKERRQ(ierr);
00257     /* reset counter if we are not in equilibrium */
00258     equil=0;
00259   }
00260   Etotold=gdata->Etot;
00261 #endif
00262 
00263 #ifdef DEBUG
00264   ierr = WriteLog(gdata);CHKERRQ(ierr);
00265   gdata->inp=PetscAbsInt(gdata->inp);
00266   ierr = WriteSet(gdata);CHKERRQ(ierr);
00267 #endif
00268 
00269   MagparFunctionProfReturn(0);
00270 }
00271 
00272 
00273 int myTSCreateEmini(GridData *gdata)
00274 {
00275   MagparFunctionLogBegin;
00276 
00277   gdata->time = 0.0;
00278 
00279 #ifdef DAMP
00280   PetscPrintf(PETSC_COMM_WORLD,"DAMP defined: Using damping term for gradient/line search\n");
00281   ierr = VecDuplicate(gdata->M,&grad);CHKERRQ(ierr);
00282 #else
00283   PetscPrintf(PETSC_COMM_WORLD,"DAMP undefined: Using field for gradient/line search\n");
00284 #endif
00285 
00286   /* set default for tao_lmm_vectors */
00287   PetscTruth flg;
00288   int tao_lmm_vectors;
00289   ierr = PetscOptionsGetInt(PETSC_NULL,"-tao_lmm_vectors",(PetscInt*)&tao_lmm_vectors,&flg);CHKERRQ(ierr);
00290   if (flg!=PETSC_TRUE) {
00291     ierr = PetscOptionsSetValue("-tao_lmm_vectors","100");CHKERRQ(ierr);
00292   }
00293 
00294   char str[256];
00295   PetscOptionsGetString(PETSC_NULL,"-tao_method",str,256,&flg);
00296   if (flg!=PETSC_TRUE) {
00297     ierr = PetscSNPrintf(str,255,"tao_lmvm");CHKERRQ(ierr);
00298     PetscPrintf(PETSC_COMM_WORLD,
00299       "Option -tao_method not found, using default value: %s\n",
00300       str
00301     );
00302   }
00303 
00304   ierr = TaoCreate(PETSC_COMM_WORLD,str,&tao);CHKERRQ(ierr);
00305   ierr = TaoApplicationCreate(PETSC_COMM_WORLD,&taoapp);CHKERRQ(ierr);
00306   if (gdata->mode==53) {
00307     PetscPrintf(PETSC_COMM_WORLD,"mode %i: Using 3D Cartesian coordinates\n",gdata->mode);
00308 
00309     PetscReal *ta_M;
00310     ierr = VecGetArray(gdata->M,&ta_M);CHKERRQ(ierr);
00311     for (int j=0;j<gdata->ln_vert;j++) {
00312       PetscReal ms;
00313       ms=gdata->propdat[NP*gdata->vertprop[j]+4];
00314       /* if the magnetic moment of the material is 0 */
00315       if (ms==0.0) {
00316         /* set magnetization to 0 */
00317         /* This is necessary, because we set Hnonlin=0 for Ms=0 or mu=1 / chi=0 in hnonlin.c */
00318         ta_M[ND*j+0] = 0.0;
00319         ta_M[ND*j+1] = 0.0;
00320         ta_M[ND*j+2] = 0.0;
00321       }
00322     }
00323     ierr = VecRestoreArray(gdata->M,&ta_M);CHKERRQ(ierr);
00324 
00325     ierr = TaoAppSetInitialSolutionVec(taoapp,gdata->M);CHKERRQ(ierr);
00326   }
00327   else {
00328     PetscPrintf(PETSC_COMM_WORLD,"Using spherical coordinates\n");
00329     ierr = VecCreate(PETSC_COMM_WORLD,&Msphere);CHKERRQ(ierr);
00330     ierr = VecSetSizes(Msphere,(ND-1)*gdata->ln_vert,(ND-1)*gdata->n_vert);CHKERRQ(ierr);
00331     ierr = VecSetFromOptions(Msphere);CHKERRQ(ierr);
00332 
00333     ierr = VecDuplicate(Msphere,&VHtotsphere);CHKERRQ(ierr);
00334 
00335     ierr = TaoAppSetInitialSolutionVec(taoapp,Msphere);CHKERRQ(ierr);
00336   }
00337   ierr = TaoAppSetObjectiveAndGradientRoutine(taoapp,TaoEvalEnergyGrad,(void *)gdata);CHKERRQ(ierr);
00338   ierr = TaoSetConvergenceTest(tao,ConvTest,(void *)gdata);CHKERRQ(ierr);
00339 
00340 /*
00341   PetscPrintf(PETSC_COMM_WORLD,"Activating TAO Monitor\n");
00342   ierr = PetscOptionsSetValue("-tao_monitor","");CHKERRQ(ierr);
00343 */
00344 
00345   /* set defaults for line search options */
00346   ierr = PetscOptionsHasName(PETSC_NULL,"-tao_ls_ftol",&flg);CHKERRQ(ierr);
00347   if (flg!=PETSC_TRUE) {
00348     ierr = PetscOptionsSetValue("-tao_ls_ftol","1e-20");CHKERRQ(ierr);
00349   }
00350   ierr = PetscOptionsHasName(PETSC_NULL,"-tao_ls_rtol",&flg);CHKERRQ(ierr);
00351   if (flg!=PETSC_TRUE) {
00352     ierr = PetscOptionsSetValue("-tao_ls_rtol","1e-1");CHKERRQ(ierr);
00353   }
00354   ierr = PetscOptionsHasName(PETSC_NULL,"-tao_ls_gtol",&flg);CHKERRQ(ierr);
00355   if (flg!=PETSC_TRUE) {
00356     ierr = PetscOptionsSetValue("-tao_ls_gtol","0.99");CHKERRQ(ierr);
00357   }
00358 
00359   ierr = PetscOptionsGetInt(PETSC_NULL,"-tao_max_its",(PetscInt*)&tao_max_its,&flg);CHKERRQ(ierr);
00360   if (flg!=PETSC_TRUE) {
00361     tao_max_its=500;
00362     PetscPrintf(PETSC_COMM_WORLD,
00363       "Option -tao_max_its not found, using default value: %i\n",
00364       tao_max_its
00365     );
00366   }
00367 
00368   /* Check for TAO command line options (listed here for consistency check with allopt.txt) */
00369   /* evaluates
00370       PetscOptions "-tao_fatol"
00371       PetscOptions "-tao_frtol"
00372   */
00373 /* defined in tao-1.9/src/petsctao/include/taopetsc.h - may not be supported in future releases
00374   ierr = TaoSetFromOptions(tao);CHKERRQ(ierr);
00375 */
00376   ierr = TaoSetOptions(taoapp,tao);CHKERRQ(ierr);
00377 
00378   /*
00379     disturb magnetization distribution with small random vector;
00380     larger distortions require many more interations in TaoSolve
00381     and do not help, because the solution is less accurate
00382     (relative tolerance!)
00383   */
00384   ierr = PetscOptionsGetReal(PETSC_NULL,"-magdist", &magdist,&flg);CHKERRQ(ierr);
00385   if (flg!=PETSC_TRUE) {
00386     magdist=0.0;
00387     PetscPrintf(PETSC_COMM_WORLD,
00388       "Option -magdist not found, using default value: %g\n",
00389       magdist
00390     );
00391   }
00392 
00393   if (magdist<0.0) {
00394     PetscPrintf(PETSC_COMM_WORLD,"magdist = %g < 0.0: Distorting M by tilting in direction MxMxH\n",magdist);
00395   }
00396   else if (magdist>0.0) {
00397     PetscPrintf(PETSC_COMM_WORLD,"magdist = %g > 0.0: Distorting M randomly\n",magdist);
00398   }
00399   else {
00400     PetscPrintf(PETSC_COMM_WORLD,"magdist==0.0: Not distorting M\n");
00401   }
00402 
00403   ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr);
00404   ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr);
00405 
00406   /* To View TAO solver information use */
00407   ierr = TaoView(tao);CHKERRQ(ierr);
00408 
00409   ierr = PetscOptionsGetReal(PETSC_NULL,"-tol",&tol,&flg);CHKERRQ(ierr);
00410   if (flg!=PETSC_TRUE) {
00411     tol=1e-7;
00412     PetscPrintf(PETSC_COMM_WORLD,
00413       "Option -tol not found, using default value: %g\n",
00414       tol
00415     );
00416   }
00417   PetscPrintf(PETSC_COMM_WORLD,"tol (equilibrium): %g\n",tol);
00418 
00419 #ifdef TESTTORQ
00420   ierr = VecDuplicate(gdata->M,&dMdt);
00421 #endif
00422 #ifdef DEBUG
00423   ierr = VecDuplicate(gdata->M,&dMdt);
00424 #endif
00425 
00426   MagparFunctionLogReturn(0);
00427 }
00428 
00429 
00430 int EminiSolve(GridData *gdata)
00431 {
00432   MagparFunctionInfoBegin;
00433 
00434   if (magdist<0.0) {
00435     /* distort by tilting magnetization in direction of MxMxH */
00436     PetscReal *ta_M, *ta_Htot;
00437     VecGetArray(gdata->M,&ta_M);
00438     VecGetArray(gdata->VHtot,&ta_Htot);
00439 
00440     for (int i=0; i<gdata->ln_vert; i++) {
00441       PetscReal  damp[ND], mxh[ND];
00442 
00443       douter(ND,ta_M+ND*i,ta_Htot+ND*i,mxh);
00444       douter(ND,ta_M+ND*i,mxh,damp);
00445 
00446       /* TODO: can lead to Inf/NaNs if "damping constant" is too large */
00447       my_daxpy(ND,magdist,damp,1,ta_M+ND*i,1);
00448     }
00449 
00450     VecRestoreArray(gdata->M,&ta_M);
00451     VecRestoreArray(gdata->VHtot,&ta_Htot);
00452   }
00453   else if (magdist>0.0) {
00454     /* randomly distort M */
00455     ierr = DistortVec(rctx,gdata->M,magdist);CHKERRQ(ierr);
00456 
00457     /* renormalize M */
00458     if (gdata->mode!=53) {
00459       PetscReal devNorm;
00460       devNorm=RenormVec(gdata->M,1.0,D_EPS,ND);
00461     }
00462   }
00463 
00464   PetscPrintf(MPI_COMM_WORLD,"Starting energy minimization with TAO...\n");
00465   PetscPrintf(PETSC_COMM_WORLD,"iter  equil  CPUtstep (s)   Etot (1)            (J/m^3)                Etotold  (1)             (J/m^3)               tol               torq\n");
00466   PetscPrintf(PETSC_COMM_WORLD,"--------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
00467 
00468   if (gdata->mode!=53) {
00469     ierr = Cart2Sphere(gdata->M,Msphere);CHKERRQ(ierr);
00470   }
00471 
00472   ierr = TaoSolveApplication(taoapp,tao);CHKERRQ(ierr);
00473 
00474 #ifdef ADDONS
00475 
00476 #ifdef DEBUG
00477   /* recalculate fields and energies */
00478   ierr = Htot(gdata);CHKERRQ(ierr);
00479   ierr = Htot_Energy(gdata);CHKERRQ(ierr);
00480 
00481   gdata->inp=PetscAbsInt(gdata->inp);
00482   ierr = WriteLog(gdata);CHKERRQ(ierr);
00483   ierr = WriteSet(gdata);CHKERRQ(ierr);
00484 #endif
00485 
00486   PetscTruth flg;
00487   int NSMOOTHSTEPS;
00488   ierr = PetscOptionsGetInt(PETSC_NULL,"-emini_mag_smooth_steps",(PetscInt*)&NSMOOTHSTEPS,&flg);CHKERRQ(ierr);
00489   if (flg!=PETSC_TRUE) {
00490     NSMOOTHSTEPS=1;
00491   }
00492 
00493   if (NSMOOTHSTEPS>0) {
00494     PetscPrintf(MPI_COMM_WORLD,"Smoothening magnetization distribution\n");
00495 
00496     /* smoothen magnetization distribution */
00497     Vec Vtmp;
00498     ierr = VecDuplicate(gdata->M,&Vtmp);CHKERRQ(ierr);
00499 
00500     for (int i=0;i<NSMOOTHSTEPS;i++) {
00501       /* perform smoothening (double) step */
00502       ierr = FieldSmoothApply(gdata,gdata->M,Vtmp);
00503       ierr = FieldSmoothApply(gdata,Vtmp,gdata->M);
00504 
00505       /* renormalize M (distorted due to smoothening) */
00506       PetscReal devNorm;
00507       devNorm=RenormVec(gdata->M,1.0,0.0,ND);
00508     }
00509 
00510     ierr = VecDestroy(Vtmp);CHKERRQ(ierr);
00511   }
00512 
00513   if (gdata->mode!=53) {
00514     ierr = Cart2Sphere(gdata->M,Msphere);CHKERRQ(ierr);
00515   }
00516 
00517   if (NSMOOTHSTEPS>0) {
00518     PetscPrintf(MPI_COMM_WORLD,"Restarting energy minimization with TAO after smoothening...\n");
00519     ierr = TaoSolveApplication(taoapp,tao);CHKERRQ(ierr);
00520   }
00521 #endif
00522 
00523   if (gdata->mode!=53) {
00524     Vec sol;
00525     ierr = TaoAppGetSolutionVec(taoapp,&sol);CHKERRQ(ierr);
00526     assert(sol==Msphere);
00527   }
00528   /* store this info in log file!? */
00529   int iter;
00530   double ff,gnorm,cnorm,xdiff;
00531   TaoTerminateReason reason;
00532   ierr = TaoGetSolutionStatus(tao,&iter,&ff,&gnorm,&cnorm,&xdiff,&reason);CHKERRQ(ierr);
00533   if (reason <= 0 ){
00534     PetscPrintf(MPI_COMM_WORLD,"TAO solver did NOT converge - ");
00535     /* continue even if TAO fails
00536        SETERRQ(PETSC_ERR_LIB,"TAO failed! Exiting!\n");
00537     */
00538     gdata->equil=0;
00539   }
00540   else {
00541     PetscPrintf(MPI_COMM_WORLD,"TAO solver converged - ");
00542     gdata->equil++;
00543   }
00544   PetscPrintf(MPI_COMM_WORLD,
00545     "TerminationReason: %i\n"
00546     "it: %i, f: %4.2e, res: %4.2e, cnorm: %4.2e, step %4.2e\n",
00547     reason,
00548     iter,ff,gnorm,cnorm,xdiff
00549   );
00550 
00551   ierr = TaoView(tao);CHKERRQ(ierr);
00552 
00553   /* otherwise Htot=0 */
00554   ierr = Htot(gdata);CHKERRQ(ierr);
00555   ierr = Htot_Energy(gdata);CHKERRQ(ierr);
00556 
00557   MagparFunctionLogReturn(0);
00558 }
00559 

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