00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00043
00044
00045 #undef DAMP
00046
00047
00048
00049
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
00079
00080
00081
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
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
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
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
00125
00126
00127
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
00147
00148
00149
00150
00151
00152
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
00175
00176
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
00198 equil++;
00199 }
00200 else {
00201 ierr = TaoSetTerminationReason(tao,TAO_CONTINUE_ITERATING);CHKERRQ(ierr);
00202
00203 equil=0;
00204 }
00205
00206 #else
00207
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
00240
00241
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
00252 equil++;
00253 }
00254 }
00255 else {
00256 ierr = TaoSetTerminationReason(tao,TAO_CONTINUE_ITERATING);CHKERRQ(ierr);
00257
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
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
00315 if (ms==0.0) {
00316
00317
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
00342
00343
00344
00345
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
00369
00370
00371
00372
00373
00374
00375
00376 ierr = TaoSetOptions(taoapp,tao);CHKERRQ(ierr);
00377
00378
00379
00380
00381
00382
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
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
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
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
00455 ierr = DistortVec(rctx,gdata->M,magdist);CHKERRQ(ierr);
00456
00457
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
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
00497 Vec Vtmp;
00498 ierr = VecDuplicate(gdata->M,&Vtmp);CHKERRQ(ierr);
00499
00500 for (int i=0;i<NSMOOTHSTEPS;i++) {
00501
00502 ierr = FieldSmoothApply(gdata,gdata->M,Vtmp);
00503 ierr = FieldSmoothApply(gdata,Vtmp,gdata->M);
00504
00505
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
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
00536
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
00554 ierr = Htot(gdata);CHKERRQ(ierr);
00555 ierr = Htot_Energy(gdata);CHKERRQ(ierr);
00556
00557 MagparFunctionLogReturn(0);
00558 }
00559