hdemag.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: hdemag.c 2897 2009-12-04 03:56:51Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ "  " __DATE__ "  "  __TIME__  " $\n\n";
00026 
00027 /*
00028      Calculate magnetostatic field using a hybrid FE/BE method:
00029 
00030      D. R. Fredkin, T. R. Koehler,
00031      "Hybrid Method for Computing Demagnetizing Fields"
00032      IEEE Trans. Magn. 26 (1990) 415-417
00033 */
00034 
00035 #include "field/field.h"
00036 #include "init/init.h"
00037 #include "util/util.h"
00038 
00039 static int doinit=1;
00040 static int fieldon=0;
00041 
00042 static Mat Bmat;     
00043 static Mat AdivM;    
00044 static Mat Agradu;   
00045 static Mat ABu1;     
00046 static Mat ABu2;     
00047 static Vec u2bnd;    
00048 static Vec u1;       
00049 static Vec u1bnd;    
00050 static Vec u2;       
00051 static Vec bu1;      
00052 static Vec bu2;      
00053 static Vec utot;     
00055 KSP ksp_Au1;
00056 KSP ksp_Au2;
00057 
00058 #ifdef HDEMAGUEPOL
00059 static Vec u1bak; 
00060 static Vec u2bak; 
00061 static Vec du1dt; 
00062 static Vec du2dt; 
00063 #endif
00064 
00065 #include "bmatrix.c"
00066 
00067 int Hdemag_Init(GridData *gdata)
00068 {
00069   MagparFunctionLogBegin;
00070 
00071   int rank,size;
00072   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00073   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00074 
00075   gdata->VHdem=PETSC_NULL;
00076 
00077   PetscTruth flg;
00078   ierr = PetscOptionsGetInt(PETSC_NULL,"-demag",(PetscInt*)&fieldon,&flg);CHKERRQ(ierr);
00079   if (flg!=PETSC_TRUE) {
00080     fieldon=1;
00081     PetscPrintf(PETSC_COMM_WORLD,
00082       "Option -demag not found, using default value: %i\n",
00083       fieldon
00084     );
00085   }
00086 
00087   if (!fieldon) {
00088     PetscPrintf(PETSC_COMM_WORLD,"Hdemag off\n");
00089     MagparFunctionLogReturn(0);
00090   }
00091   PetscPrintf(PETSC_COMM_WORLD,"Hdemag on\n");
00092 
00093 /* activate this define to enforce Dirichlet boundary condition
00094    on one node (id given by U1DIRICHLET) for u1
00095 */
00096 #if 0
00097 #define U1DIRICHLET 0
00098   PetscPrintf(PETSC_COMM_WORLD,"Using 1 Dirichlet BC for u1 on node %i\n",U1DIRICHLET);
00099 #else
00100   PetscPrintf(PETSC_COMM_WORLD,"No Dirichlet BC for u1 (floating)\n");
00101 #endif
00102 
00103   /* Create stiffness matrix */
00104 
00105   /* Creates a sparse parallel matrix in AIJ format - speedup: 50 !!! */
00106   /* sensible values for preallocated memory !? */
00107 
00108   int ln_bmatrixrows;
00109   ln_bmatrixrows=gdata->n_vert_bnd/size;
00110   if ((gdata->n_vert_bnd%size)/(rank+1)>=1) ln_bmatrixrows++;
00111 
00112   int ln_vert;
00113   ln_vert=gdata->ln_vert;
00114   int n_vert;
00115   n_vert=gdata->n_vert;
00116 
00117   PetscPrintf(PETSC_COMM_WORLD,"Calculating sparsity pattern for matrix preallocation\n");
00118 
00119   /* get ownership range */
00120   int low,high;
00121   ierr = VecGetOwnershipRange(gdata->elevol,&low,&high);CHKERRQ(ierr);
00122 
00123   PetscSynchronizedPrintf(PETSC_COMM_WORLD,
00124     "<%i>element ownership: %i - %i\n",
00125     rank,low,high-1
00126   );
00127   PetscSynchronizedFlush(PETSC_COMM_WORLD);
00128 
00129   int *elevertall;
00130 
00131 #ifdef HAVE_ELEVERTALL
00132   elevertall=gdata->elevertall;
00133 #else
00134   if (size>1) {
00135     ierr = PetscMalloc(NV*gdata->n_ele*sizeof(int),&elevertall);CHKERRQ(ierr);
00136     ierr = PetscMemcpy(elevertall+NV*low,gdata->elevert,NV*gdata->ln_ele*sizeof(int));CHKERRQ(ierr);
00137 
00138     int *p;
00139     p=elevertall;
00140 
00141     int recvcount[size];
00142     recvcount[rank]=NV*gdata->ln_ele;
00143     for (int i=0;i<size;i++) {
00144       ierr = MPI_Bcast(recvcount+i,1,MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00145       /* we could also use MPI_Send/Recv to get everything just to the first processor */
00146       ierr = MPI_Bcast(p,recvcount[i],MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00147       p+=recvcount[i];
00148     }
00149     assert(p==elevertall+NV*gdata->n_ele);
00150   }
00151   else {
00152     elevertall=gdata->elevert;
00153   }
00154 #endif
00155 
00156   int *ia,*ja;
00157 #ifdef HAVE_M2IJ
00158   ia=gdata->mesh2nodal_ia;
00159   ja=gdata->mesh2nodal_ja;
00160 #else
00161   ierr = Mesh2Nodal(gdata->n_ele,gdata->n_vert,elevertall,&ia,&ja);CHKERRQ(ierr);
00162 #endif
00163 
00164   /* get ownership range */
00165   ierr = VecGetOwnershipRange(gdata->M,&low,&high);CHKERRQ(ierr);
00166   low/=ND;
00167   high/=ND;
00168 
00169   /* create utot here, so we can use VecGetOwnershipRange below */
00170   ierr = VecCreate(PETSC_COMM_WORLD,&utot);CHKERRQ(ierr);
00171   ierr = VecSetSizes(utot,ln_vert,n_vert);CHKERRQ(ierr);
00172   ierr = VecSetFromOptions(utot);CHKERRQ(ierr);
00173 
00174 #define XND 1
00175   int *d_nnz;
00176   int *o_nnz;
00177   ierr = PetscMalloc(ND*gdata->n_vert*sizeof(int),&d_nnz);CHKERRQ(ierr);
00178   ierr = PetscMalloc(ND*gdata->n_vert*sizeof(int),&o_nnz);CHKERRQ(ierr);
00179   /* calculate number of nonzeroes for each line */
00180   for (int i=0;i<gdata->n_vert;i++) {
00181     for (int j=0;j<XND;j++) {
00182       d_nnz[XND*i+j]=XND;
00183       o_nnz[XND*i+j]=0;
00184       for (int l=ia[i];l<ia[i+1];l++) {
00185         if (ja[l]>=low && ja[l]<high) {
00186           d_nnz[XND*i+j]+=1;
00187         }
00188         else {
00189           o_nnz[XND*i+j]+=1;
00190         }
00191       }
00192     }
00193   }
00194 
00195   int *d_nnzm;
00196   int *o_nnzm;
00197   ierr = PetscMalloc(ND*n_vert*sizeof(int),&d_nnzm);CHKERRQ(ierr);
00198   ierr = PetscMalloc(ND*n_vert*sizeof(int),&o_nnzm);CHKERRQ(ierr);
00199 
00200   /* connectivity matrix for merged mesh */
00201   int lowm,highm;
00202 
00203     lowm=low;
00204     highm=high;
00205 
00206     ierr = PetscMemcpy(d_nnzm,d_nnz,ND*n_vert*sizeof(int));CHKERRQ(ierr);
00207     ierr = PetscMemcpy(o_nnzm,o_nnz,ND*n_vert*sizeof(int));CHKERRQ(ierr);
00208 
00209   /* conventional MPIAIJ matrix */
00210   Mat Au1;
00211   ierr = MatCreateMPIAIJ(
00212     PETSC_COMM_WORLD,
00213     ln_vert,ln_vert,
00214     n_vert,n_vert,
00215     0,d_nnzm+lowm,0,o_nnzm+lowm,
00216     &Au1
00217   );CHKERRQ(ierr);
00218   ierr = MatSetFromOptions(Au1);CHKERRQ(ierr);
00219 
00220   ierr = MatCreateMPIAIJ(
00221     PETSC_COMM_WORLD,
00222     ln_bmatrixrows,ln_vert,
00223     gdata->n_vert_bnd,n_vert,
00224     1,PETSC_NULL,1,PETSC_NULL,
00225     &ABu1
00226   );CHKERRQ(ierr);
00227   ierr = MatSetFromOptions(ABu1);CHKERRQ(ierr);
00228 
00229   Mat Au2;
00230   ierr = MatCreateMPIAIJ(
00231     PETSC_COMM_WORLD,
00232     ln_vert,ln_vert,
00233     n_vert,n_vert,
00234     0,d_nnzm+lowm,0,o_nnzm+lowm,
00235     &Au2
00236   );CHKERRQ(ierr);
00237   ierr = MatSetFromOptions(Au2);CHKERRQ(ierr);
00238 
00239   /* preallocate with d_nnz for diag. and off-diag. because of boundary vertex columns */
00240 
00241   for (int i=lowm; i<highm; i++) {
00242     d_nnzm[i] = PetscMin(d_nnzm[i],ln_bmatrixrows);
00243     o_nnzm[i] = PetscMin(d_nnzm[i],gdata->n_vert_bnd-ln_bmatrixrows);
00244     assert(d_nnzm[i]>=0);
00245     assert(o_nnzm[i]>=0);
00246   }
00247 
00248   ierr = MatCreateMPIAIJ(
00249     PETSC_COMM_WORLD,
00250     ln_vert,ln_bmatrixrows,
00251     n_vert,gdata->n_vert_bnd,
00252     0,d_nnzm+lowm,0,o_nnzm+lowm,
00253     &ABu2
00254   );CHKERRQ(ierr);
00255   ierr = MatSetFromOptions(ABu2);CHKERRQ(ierr);
00256 
00257 
00258   for (int i=0; i<n_vert; i++) {
00259     d_nnzm[i] = 0;
00260     o_nnzm[i] = 0;
00261   }
00262   for (int i=0; i<gdata->n_vert; i++) {
00263     int i2;
00264     i2=i;
00265       if (i<lowm || i>=highm) continue;
00266     assert(d_nnz[i]>=0);
00267     assert(o_nnz[i]>=0);
00268     d_nnzm[i2] += ND*d_nnz[i]+ND*o_nnz[i];
00269     o_nnzm[i2] += ND*d_nnz[i]+ND*o_nnz[i];
00270     assert(i2<n_vert);
00271     assert(d_nnzm[i2]>=0);
00272     assert(o_nnzm[i2]>=0);
00273   }
00274 
00275   /* create matrix to calculate div M */
00276   ierr = MatCreateMPIAIJ(
00277     PETSC_COMM_WORLD,
00278     ln_vert,ND*gdata->ln_vert,
00279     n_vert,ND*gdata->n_vert,
00280     0,d_nnzm+lowm,0,o_nnzm+lowm,
00281     &AdivM
00282   );CHKERRQ(ierr);
00283   ierr = MatSetFromOptions(AdivM);CHKERRQ(ierr);
00284 
00285   for (int i=ND*gdata->n_vert-1; i>=0; i--) {
00286     d_nnz[i] = d_nnz[i/ND]+o_nnz[i/ND];
00287     o_nnz[i] = d_nnz[i/ND]+o_nnz[i/ND];
00288     assert(d_nnz[i]>=0);
00289     assert(o_nnz[i]>=0);
00290   }
00291 
00292   /* create matrix to calculate Hdem = -grad u */
00293   ierr = MatCreateMPIAIJ(
00294     PETSC_COMM_WORLD,
00295     ND*gdata->ln_vert,ln_vert,
00296     ND*gdata->n_vert,n_vert,
00297     0,d_nnz+ND*low,0,o_nnz+ND*low,
00298     &Agradu
00299   );CHKERRQ(ierr);
00300   ierr = MatSetFromOptions(Agradu);CHKERRQ(ierr);
00301 
00302 #ifndef HAVE_M2IJ
00303   ierr = PetscFree(ia);CHKERRQ(ierr);
00304   ierr = PetscFree(ja);CHKERRQ(ierr);
00305 #endif
00306   ierr = PetscFree(d_nnz);CHKERRQ(ierr);
00307   ierr = PetscFree(o_nnz);CHKERRQ(ierr);
00308 #ifndef HAVE_ELEVERTALL
00309   if (size>1) {
00310     ierr = PetscFree(elevertall);CHKERRQ(ierr);
00311   }
00312 #endif
00313   ierr = PetscFree(d_nnzm);CHKERRQ(ierr);
00314   ierr = PetscFree(o_nnzm);CHKERRQ(ierr);
00315 
00316   PetscReal *ta_elevol;
00317   ierr = VecGetArray(gdata->elevol,&ta_elevol);CHKERRQ(ierr);
00318 
00319   PetscPrintf(PETSC_COMM_WORLD,"Calculating stiffness matrices...\n");
00320   for (int i=0; i<gdata->ln_ele; i++) {
00321     ierr = ProgressBar(i,gdata->ln_ele,10);
00322 
00323     /* get vertex ids */
00324     int t_v[NV];
00325     int t_w[NV];
00326 
00327     for (int j=0; j<NV; j++) {
00328       t_v[j]=gdata->elevert[i*NV+j];
00329       t_w[j]=t_v[j];
00330     }
00331 
00332     /* calculate gradients */
00333     PetscReal D_etaj[NV][ND];
00334     tetgrad(
00335       gdata->vertxyz+t_v[0]*ND,
00336       gdata->vertxyz+t_v[1]*ND,
00337       gdata->vertxyz+t_v[2]*ND,
00338       gdata->vertxyz+t_v[3]*ND,
00339       D_etaj
00340     );
00341 
00342     /* set matrix elements */
00343 
00344     for (int l=0;l<NV;l++) {
00345       for (int j=0;j<NV;j++) {
00346         /* calculate stiffness matrix element */
00347         PetscReal matele;
00348         matele=-ta_elevol[i]*my_ddot(ND,D_etaj[j],1,D_etaj[l],1);
00349 
00350         /* inserted many of these if clauses to avoid zero entries
00351            and save memory
00352         */
00353         if (PetscAbsReal(matele)>D_EPS) {
00354 #ifdef U1DIRICHLET
00355           /* skip first row and first column, where we impose the
00356              Dirichlet BC: u1=0
00357           */
00358           if (t_w[j] != U1DIRICHLET &&
00359               t_w[l] != U1DIRICHLET) {
00360 #endif
00361             ierr = MatSetValue(
00362               Au1,
00363               t_w[j],
00364               t_w[l],
00365               matele,
00366               ADD_VALUES
00367             );CHKERRQ(ierr);
00368 
00369             assert(t_w[j]<n_vert);
00370             assert(t_w[l]<n_vert);
00371 #ifdef U1DIRICHLET
00372           }
00373 #endif
00374 
00375           int tvj,tvl;
00376           tvj=t_v[j];
00377           tvl=t_v[l];
00378           if (gdata->vertbndg2bnd[tvj]==C_INT) {
00379             /* set non-Dirichlet rows (i.e. for interior nodes) only */
00380             if (gdata->vertbndg2bnd[tvl]==C_INT) {
00381               /* set non-Dirichlet columns only to keep Au2 symmetric
00382                * columns eliminated and worked into rhs through ABu2 (see below)
00383                */
00384               ierr = MatSetValue(
00385                 Au2,
00386                 t_w[j],
00387                 t_w[l],
00388                 matele,
00389                 ADD_VALUES
00390               );CHKERRQ(ierr);
00391               assert(t_w[j]>=0);
00392               assert(t_w[l]>=0);
00393               assert(t_w[j]<n_vert);
00394               assert(t_w[l]<n_vert);
00395             }
00396             else {
00397               /* Dirichlet columns eliminated from Au2 and merged into RHS through ABu2 */
00398               ierr = MatSetValue(
00399                 ABu2,
00400                 t_w[j],
00401                 gdata->vertbndg2bnd[tvl],
00402                 -matele,
00403                 ADD_VALUES
00404               );CHKERRQ(ierr);
00405               assert(t_w[j]<n_vert);
00406               assert(gdata->vertbndg2bnd[tvl]<gdata->n_vert_bnd);
00407             }
00408           }
00409         }
00410       } /* end for j loop */
00411     } /* end for l loop */
00412 
00413     for (int l=0;l<NV;l++) {
00414       for (int k=0;k<ND;k++) {
00415         PetscReal matele;
00416         matele=ta_elevol[i]/NV*D_etaj[l][k];
00417         if (PetscAbsReal(matele)>D_EPS) {
00418           for (int j=0;j<NV;j++) {
00419             ierr = MatSetValue(
00420               Agradu,
00421               ND*t_v[j]+k,
00422               t_w[l],
00423               matele,
00424               ADD_VALUES
00425             );CHKERRQ(ierr);
00426             assert(t_v[j]<gdata->n_vert);
00427             assert(t_w[l]<n_vert);
00428 
00429 #ifdef U1DIRICHLET
00430             /* skip nodes with Dirichlet BC */
00431             if (t_w[l] != U1DIRICHLET) {
00432 #endif
00433             /* skip non-magnetic elements */
00434             if (gdata->propdat[NP*gdata->eleprop[i]+4]>0.0) {
00435               ierr = MatSetValue(
00436                 AdivM,
00437                 t_w[l],
00438                 ND*t_v[j]+k,
00439                 matele*gdata->propdat[NP*gdata->eleprop[i]+4],
00440                 ADD_VALUES
00441               );CHKERRQ(ierr);
00442               assert(t_w[l]<n_vert);
00443               assert(t_v[j]<gdata->n_vert);
00444             }
00445 #ifdef U1DIRICHLET
00446             }
00447 #endif
00448           }
00449         }
00450       }
00451     }
00452   }
00453   ierr = ProgressBar(1,1,10);
00454 
00455 #undef MATFLUSH
00456 #ifdef MATFLUSH
00457   ierr = MatAssemblyBegin(Au1,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00458   ierr = MatAssemblyEnd(Au1,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00459   ierr = MatAssemblyBegin(Au2,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00460   ierr = MatAssemblyEnd(Au2,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00461   ierr = MatAssemblyBegin(ABu2,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00462   ierr = MatAssemblyEnd(ABu2,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00463   ierr = MatAssemblyBegin(Agradu,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00464   ierr = MatAssemblyEnd(Agradu,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00465   ierr = MatAssemblyBegin(AdivM,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00466   ierr = MatAssemblyEnd(AdivM,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
00467 #endif
00468 
00469   ierr = PetscGetTime(&t_t2);CHKERRQ(ierr);
00470   PetscPrintf(PETSC_COMM_WORLD,
00471     "stiffness matrix calculation took %g s = %g min\n",
00472     t_t2-t_t1,
00473     (t_t2-t_t1)/60.0
00474   );
00475 
00476   ierr = VecRestoreArray(gdata->elevol,&ta_elevol);CHKERRQ(ierr);
00477 
00478     /* set diagonal matrix element for nodes with Dirichlet BC */
00479     if (!rank) {
00480 #ifdef U1DIRICHLET
00481       ierr = MatSetValue(Au1,U1DIRICHLET,U1DIRICHLET,-1.0,ADD_VALUES);CHKERRQ(ierr);
00482 #endif
00483 
00484       for (int i=0; i<gdata->n_vert; i++) {
00485         int j,k;
00486         j=i;
00487         k=j;
00488         if (gdata->vertbndg2bnd[j] >= 0) {
00489           assert(gdata->vertbndg2bnd[j]<gdata->n_vert_bnd);
00490 
00491           ierr = MatSetValue(Au2,k,k,-1.0,ADD_VALUES);CHKERRQ(ierr);
00492           ierr = MatSetValue(ABu2,k,gdata->vertbndg2bnd[j],-1.0,ADD_VALUES);CHKERRQ(ierr);
00493           ierr = MatSetValue(ABu1,gdata->vertbndg2bnd[j],k,1.0,INSERT_VALUES);CHKERRQ(ierr);
00494         }
00495       }
00496     }
00497 
00498 #undef DOMATCOMPRESS
00499     PetscPrintf(PETSC_COMM_WORLD,"Au1 matrix assembly complete\n");
00500     ierr = MatAssemblyBegin(Au1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00501     ierr = MatAssemblyEnd(Au1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00502     /* TODO: MatCompress does not do anything */
00503 #ifdef DOMATCOMPRESS
00504     ierr = MatCompress(Au1);CHKERRQ(ierr);
00505 #endif
00506     ierr = PrintMatInfoAll(Au1);CHKERRQ(ierr);
00507 
00508     PetscPrintf(PETSC_COMM_WORLD,"Au2 matrix assembly complete\n");
00509     ierr = MatAssemblyBegin(Au2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00510     ierr = MatAssemblyEnd(Au2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00511 #ifdef DOMATCOMPRESS
00512     ierr = MatCompress(Au2);CHKERRQ(ierr);
00513 #endif
00514     ierr = PrintMatInfoAll(Au2);CHKERRQ(ierr);
00515 
00516     PetscPrintf(PETSC_COMM_WORLD,"AdivM matrix assembly complete\n");
00517     ierr = MatAssemblyBegin(AdivM,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00518     ierr = MatAssemblyEnd(AdivM,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00519 #ifdef DOMATCOMPRESS
00520     ierr = MatCompress(AdivM);CHKERRQ(ierr);
00521 #endif
00522     ierr = PrintMatInfoAll(AdivM);CHKERRQ(ierr);
00523 
00524     PetscPrintf(PETSC_COMM_WORLD,"Agradu matrix assembly complete\n");
00525     ierr = MatAssemblyBegin(Agradu,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00526     ierr = MatAssemblyEnd(Agradu,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00527 #ifdef DOMATCOMPRESS
00528     ierr = MatCompress(Agradu);CHKERRQ(ierr);
00529 #endif
00530     ierr = PrintMatInfoAll(Agradu);CHKERRQ(ierr);
00531 
00532     PetscPrintf(PETSC_COMM_WORLD,"ABu1 matrix assembly complete\n");
00533     ierr = MatAssemblyBegin(ABu1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00534     ierr = MatAssemblyEnd(ABu1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00535 #ifdef DOMATCOMPRESS
00536     ierr = MatCompress(ABu1);CHKERRQ(ierr);
00537 #endif
00538     ierr = PrintMatInfoAll(ABu1);CHKERRQ(ierr);
00539 
00540     PetscPrintf(PETSC_COMM_WORLD,"ABu2 matrix assembly complete\n");
00541     ierr = MatAssemblyBegin(ABu2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00542     ierr = MatAssemblyEnd(ABu2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
00543 #ifdef DOMATCOMPRESS
00544     ierr = MatCompress(ABu2);CHKERRQ(ierr);
00545 #endif
00546     ierr = PrintMatInfoAll(ABu2);CHKERRQ(ierr);
00547 
00548   Vec vertvolrec3;
00549   ierr = VecDuplicate(gdata->M,&vertvolrec3);CHKERRQ(ierr);
00550   for (int i=0;i<ND;i++) {
00551     ierr = VecStrideScatter(gdata->vertvol,i,vertvolrec3,INSERT_VALUES);CHKERRQ(ierr);
00552   }
00553   ierr = VecReciprocal(vertvolrec3);CHKERRQ(ierr);
00554   ierr = MatDiagonalScale(Agradu,vertvolrec3,PETSC_NULL);CHKERRQ(ierr);
00555 
00556   ierr = VecDestroy(vertvolrec3);CHKERRQ(ierr);
00557 
00558   ierr = MatScale(Au1,-1.0);CHKERRQ(ierr);
00559   ierr = MatScale(AdivM,-1.0);CHKERRQ(ierr);
00560   /* scale B*=-1 since Au2*=-1 and ABu2*=1 is not */
00561   ierr = MatScale(Au2,-1.0);CHKERRQ(ierr);
00562 
00563 /* DEBUG
00564   PetscPrintf(PETSC_COMM_WORLD,"deb01: AdivM\n");
00565   ierr = MatView(AdivM,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00566   PetscPrintf(PETSC_COMM_WORLD,"deb01: Au1\n");
00567   ierr = MatView(Au1,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00568   PetscPrintf(PETSC_COMM_WORLD,"deb01: ABu1\n");
00569   ierr = MatView(ABu1,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00570   PetscPrintf(PETSC_COMM_WORLD,"deb01: ABu2\n");
00571   ierr = MatView(ABu2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00572   PetscPrintf(PETSC_COMM_WORLD,"deb01: Au2\n");
00573   ierr = MatView(Au2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00574   PetscPrintf(PETSC_COMM_WORLD,"deb01: Agradu\n");
00575   ierr = MatView(Agradu,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00576 */
00577 
00578     /* convert the stiffness matrix (if requested) */
00579 #ifdef SUPERLU
00580     Mat Au1tmp;
00581     ierr = MatConvert(Au1,MATSUPERLU_DIST,MAT_INITIAL_MATRIX,&Au1tmp);CHKERRQ(ierr);
00582     ierr = MatDestroy(Au1);CHKERRQ(ierr);
00583     Au1=Au1tmp;
00584 #elif defined(BLOCKSOLVE)
00585     Mat Au1tmp;
00586     ierr = MatConvert(Au1,MATMPIROWBS,MAT_INITIAL_MATRIX,&Au1tmp);CHKERRQ(ierr);
00587     ierr = MatDestroy(Au1);CHKERRQ(ierr);
00588     Au1=Au1tmp;
00589 #endif
00590 
00591 #ifdef SUPERLU
00592     Mat Au2tmp;
00593     ierr = MatConvert(Au2,MATSUPERLU_DIST,MAT_INITIAL_MATRIX,&Au2tmp);CHKERRQ(ierr);
00594     ierr = MatDestroy(Au2);CHKERRQ(ierr);
00595     Au2=Au2tmp;
00596 #elif defined(BLOCKSOLVE)
00597     Mat Au2tmp;
00598     ierr = MatConvert(Au2,MATMPIROWBS,MAT_INITIAL_MATRIX,&Au2tmp);CHKERRQ(ierr);
00599     ierr = MatDestroy(Au2);CHKERRQ(ierr);
00600     Au2=Au2tmp;
00601 #endif
00602 
00603 
00604 #if PETSC_VERSION >= 300
00605     ierr = MatSetOption(Au1,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
00606     ierr = MatSetOption(Au2,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
00607     ierr = MatSetOption(Au1,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);CHKERRQ(ierr);
00608     ierr = MatSetOption(Au2,MAT_SYMMETRY_ETERNAL,PETSC_TRUE);CHKERRQ(ierr);
00609 #else
00610     ierr = MatSetOption(Au1,MAT_SYMMETRIC);CHKERRQ(ierr);
00611     ierr = MatSetOption(Au2,MAT_SYMMETRIC);CHKERRQ(ierr);
00612     ierr = MatSetOption(Au1,MAT_SYMMETRY_ETERNAL);CHKERRQ(ierr);
00613     ierr = MatSetOption(Au2,MAT_SYMMETRY_ETERNAL);CHKERRQ(ierr);
00614 #endif
00615 
00616     ierr = VecDuplicate(utot,&u1);CHKERRQ(ierr);
00617     ierr = VecDuplicate(utot,&u2);CHKERRQ(ierr);
00618 
00619     ierr = VecDuplicate(utot,&bu1);CHKERRQ(ierr);
00620     ierr = VecDuplicate(utot,&bu2);CHKERRQ(ierr);
00621 
00622     ierr = VecCreate(PETSC_COMM_WORLD,&u1bnd);CHKERRQ(ierr);
00623     ierr = VecSetSizes(u1bnd,ln_bmatrixrows,gdata->n_vert_bnd);CHKERRQ(ierr);
00624     ierr = VecSetFromOptions(u1bnd);CHKERRQ(ierr);
00625 
00626     ierr = VecDuplicate(u1bnd,&u2bnd);CHKERRQ(ierr);
00627 
00628 
00629     /* set up VecScatter from u1 to u1bnd and u2bnd to u2 */
00630 
00631     ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_Au1);CHKERRQ(ierr);
00632     ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_Au2);CHKERRQ(ierr);
00633     ierr = KSPSetOperators(ksp_Au1,Au1,Au1,SAME_PRECONDITIONER);CHKERRQ(ierr);
00634     ierr = KSPSetOperators(ksp_Au2,Au2,Au2,SAME_PRECONDITIONER);CHKERRQ(ierr);
00635 
00636     /* check if options are set old style
00637        FIXME: just for backward compatibility, remove in next release
00638     */
00639     ierr = PetscOptionsHasName(PETSC_NULL,"-ksp_type",&flg);CHKERRQ(ierr);
00640     if (flg==PETSC_TRUE) {
00641       PetscPrintf(PETSC_COMM_WORLD,"Warning: Options '-ksp_*' are deprecated! Please use -hdemag_u{1,2}_ksp_* instead!\n");
00642       ierr = KSPSetFromOptions(ksp_Au1);CHKERRQ(ierr);
00643       ierr = KSPSetFromOptions(ksp_Au2);CHKERRQ(ierr);
00644     }
00645     else { /* new style */
00646 
00647     /* evaluates
00648         PetscOptions "-hdemag_u1_ksp_type"
00649         PetscOptions "-hdemag_u1_ksp_atol"
00650         PetscOptions "-hdemag_u1_ksp_rtol"
00651         PetscOptions "-hdemag_u2_ksp_type"
00652         PetscOptions "-hdemag_u2_ksp_atol"
00653         PetscOptions "-hdemag_u2_ksp_rtol"
00654     */
00655 
00656     for (int i=1;i<=2;i++) {
00657       char str[256],ostr[256];
00658 
00659       /* by default use conjugate gradient solver */
00660       sprintf(ostr,"-hdemag_u%i_ksp_type",i);
00661       ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00662       if (flg!=PETSC_TRUE) {
00663         sprintf(str,"cg");
00664         PetscOptionsSetValue(ostr,str);
00665         PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00666       }
00667 
00668       if (size>1) {
00669         /* by default use BlockJacobi preconditioner */
00670         sprintf(ostr,"-hdemag_u%i_pc_type",i);
00671         ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00672         if (flg!=PETSC_TRUE) {
00673           sprintf(str,"bjacobi");
00674           PetscOptionsSetValue(ostr,str);
00675           PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00676         }
00677 
00678         /* by default use ICC preconditioner on subblocks */
00679         sprintf(ostr,"-hdemag_u%i_sub_pc_type",i);
00680         ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00681         if (flg!=PETSC_TRUE) {
00682           sprintf(str,"icc");
00683           PetscOptionsSetValue(ostr,str);
00684           PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00685         }
00686 
00687         /* by default use Manteuffel shift */
00688         sprintf(ostr,"-hdemag_u%i_sub_pc_factor_shift_positive_definite",i);
00689         ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00690         if (flg!=PETSC_TRUE) {
00691           sprintf(str,"1");
00692           PetscOptionsSetValue(ostr,str);
00693           PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00694         }
00695       }
00696       else {
00697         /* by default use ICC preconditioner */
00698         sprintf(ostr,"-hdemag_u%i_pc_type",i);
00699         ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00700         if (flg!=PETSC_TRUE) {
00701           sprintf(str,"icc");
00702           PetscOptionsSetValue(ostr,str);
00703           PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00704         }
00705 
00706         /* by default use Manteuffel shift */
00707         sprintf(ostr,"-hdemag_u%i_pc_factor_shift_positive_definite",i);
00708         ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00709         if (flg!=PETSC_TRUE) {
00710           sprintf(str,"1");
00711           PetscOptionsSetValue(ostr,str);
00712           PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00713         }
00714       }
00715     }
00716     } /* new style */
00717 
00718     /* use prefix for options */
00719     ierr = KSPSetOptionsPrefix(ksp_Au1,"hdemag_u1_");CHKERRQ(ierr);
00720     /* possibly override defaults with settings from user defined options */
00721     ierr = KSPSetFromOptions(ksp_Au1);CHKERRQ(ierr);
00722 
00723     /* use prefix for options */
00724     ierr = KSPSetOptionsPrefix(ksp_Au2,"hdemag_u2_");CHKERRQ(ierr);
00725     /* possibly override defaults with settings from user defined options */
00726     ierr = KSPSetFromOptions(ksp_Au2);CHKERRQ(ierr);
00727 
00728     /* allow user to override tolerances of ksp_Au2 */
00729     ierr = PetscOptionsHasName(PETSC_NULL,"-hdemag_u2_ksp_rtol",&flg);CHKERRQ(ierr);
00730     /* set default values if undefined */
00731     if (flg!=PETSC_TRUE) {
00732       PetscReal rtol,atol,dtol;
00733       int maxits;
00734       ierr = KSPGetTolerances(ksp_Au1,&rtol,&atol,&dtol,&maxits);CHKERRQ(ierr);
00735       /* set stricter rtol for u2 */
00736       PetscPrintf(PETSC_COMM_WORLD,"Adjusting tolerances for ksp_Au2\n");
00737       ierr = KSPSetTolerances(ksp_Au2,rtol*1e-3,atol,dtol,maxits);CHKERRQ(ierr);
00738     }
00739 
00740     /* just to get correct info from KSPView below */
00741     ierr = KSPSetInitialGuessNonzero(ksp_Au1,PETSC_TRUE);CHKERRQ(ierr);
00742     ierr = KSPSetInitialGuessNonzero(ksp_Au2,PETSC_TRUE);CHKERRQ(ierr);
00743 
00744     /* KSPSetUp only necessary to get more useful output from KSPView */
00745     ierr = KSPSetUp(ksp_Au1);CHKERRQ(ierr);
00746     ierr = KSPSetUp(ksp_Au2);CHKERRQ(ierr);
00747 
00748 #if defined(SUPERLU) || defined(BLOCKSOLVE)
00749     ierr = KSPGetTolerances(ksp_Au1,&rtol,&atol,&dtol,&maxits);CHKERRQ(ierr);
00750     PetscPrintf(PETSC_COMM_WORLD,"KSP for A*u1=divM:\n");
00751     PetscPrintf(PETSC_COMM_WORLD,"rtol: %g atol: %g dtol: %g maxits: %i\n",
00752       rtol,atol,dtol,maxits
00753     );
00754     ierr = KSPGetTolerances(ksp_Au2,&rtol,&atol,&dtol,&maxits);CHKERRQ(ierr);
00755     PetscPrintf(PETSC_COMM_WORLD,"KSP for Au2*u2=u2bnd:\n");
00756     PetscPrintf(PETSC_COMM_WORLD,"rtol: %g atol: %g dtol: %g maxits: %i\n",
00757       rtol,atol,dtol,maxits
00758     );
00759 #else
00760     PetscPrintf(PETSC_COMM_WORLD,"KSP for A*u1=divM:\n");
00761     ierr = KSPView(ksp_Au1,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00762     PetscPrintf(PETSC_COMM_WORLD,"KSP for Au2*u2=u2bnd:\n");
00763     ierr = KSPView(ksp_Au2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00764 #endif
00765 
00766     ierr = VecDuplicate(gdata->M,&gdata->VHdem);CHKERRQ(ierr);
00767 
00768 #ifdef HDEMAGUEPOL
00769   ierr = VecDuplicate(utot,&u1bak);CHKERRQ(ierr);
00770   ierr = VecDuplicate(utot,&u2bak);CHKERRQ(ierr);
00771   ierr = VecDuplicate(utot,&du1dt);CHKERRQ(ierr);
00772   ierr = VecDuplicate(utot,&du2dt);CHKERRQ(ierr);
00773   ierr = VecZeroEntries(du1dt);CHKERRQ(ierr);
00774   ierr = VecZeroEntries(du2dt);CHKERRQ(ierr);
00775 #endif
00776 
00777   ierr = BMatrix(gdata,&Bmat);CHKERRQ(ierr);
00778 
00779   MagparFunctionLogReturn(0);
00780 }
00781 
00782 
00783 int Hdemag(GridData *gdata,Vec VHtotsum)
00784 {
00785 #ifdef HDEMAGUEPOL
00786   static PetscReal tubak=0.0;
00787   PetscReal dt;
00788 #endif
00789 
00790   int its1,its2;
00791 
00792   MagparFunctionInfoBegin;
00793 
00794   int rank,size;
00795   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00796   ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00797 
00798   if (doinit) {
00799     ierr = Hdemag_Init(gdata);CHKERRQ(ierr);
00800     doinit=0;
00801     /* reset timer to exclude initialization  */
00802     ierr = PetscGetTime(&t_t1);CHKERRQ(ierr);
00803   }
00804   if (!fieldon) {
00805     MagparFunctionInfoReturn(0);
00806   }
00807 
00808   PetscLogDouble t_t3;
00809   t_t3=t_t1;
00810 
00811   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00812          Compute the matrix and right-hand-side vector that define
00813          the linear system, Au = b.
00814      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00815 
00816   /* set bu1 = div(M) */
00817   ierr = MatMult(AdivM,gdata->M,bu1);CHKERRQ(ierr);
00818 
00819 #ifdef HDEMAGUEPOL
00820   dt=gdata->time-tubak;
00821   if (gdata->mode==0 && PetscAbsReal(dt) > 1e-8){
00822     /* extrapolate u1 (weakened) */
00823     PetscReal dt2;
00824     dt2=dt*0.5; /* TODO: good factor? */
00825     ierr = VecWAXPY(u1,dt2,du1dt,u1bak);CHKERRQ(ierr);
00826   }
00827   else {
00828     dt=0.0;
00829   }
00830 #endif
00831 
00832   t_t2=t_t3;
00833   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
00834 
00835   PetscTruth oprofile;
00836   PetscOptionsHasName(PETSC_NULL,"-profile",&oprofile);
00837   if (oprofile) {
00838     PetscPrintf(PETSC_COMM_WORLD," timing: %s - div(M) - took %g s\n",__FUNCT__,t_t3-t_t2);
00839   } else {
00840     PetscInfo2(0," timing: %s - div(M) - took %g s\n",__FUNCT__,t_t3-t_t2);
00841   }
00842 
00843   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00844                       Solve the linear system
00845      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00846 
00847 #ifndef U1DIRICHLET
00848   /* shift potential u1 to set value on first node to zero
00849      this fixes problem with u1 "running away"
00850      TODO: better use ||u1||/n_vert ???
00851   */
00852   PetscReal u1a,*ta_u1;
00853   ierr = VecGetArray(u1,&ta_u1);CHKERRQ(ierr);
00854   u1a = -ta_u1[0];
00855   ierr = VecRestoreArray(u1,&ta_u1);CHKERRQ(ierr);
00856   if (fabs(u1a)>1e6) {
00857     ierr = VecShift(u1,u1a);CHKERRQ(ierr);
00858     PetscPrintf(PETSC_COMM_WORLD,"u1 shifted by %g\n",u1a);
00859   }
00860 #endif
00861 
00862   /* do we need to call KSPSetInitialGuess* before every KSPSolve?
00863      KSP tutorial ex 9 indicates that
00864   */
00865   ierr = KSPSetInitialGuessNonzero(ksp_Au1,PETSC_TRUE);CHKERRQ(ierr);
00866 
00867 /* TODO: better performance with this!?
00868   ierr = KSPSetInitialGuessKnoll(ksp_Au1,PETSC_TRUE);CHKERRQ(ierr);
00869 */
00870 
00871   ierr = KSPSolve(ksp_Au1,bu1,u1);CHKERRQ(ierr);
00872   ierr = KSPGetIterationNumber(ksp_Au1,(PetscInt*)&its1);CHKERRQ(ierr);
00873 
00874   KSPConvergedReason reason;
00875   ierr = KSPGetConvergedReason(ksp_Au1,&reason);CHKERRQ(ierr);
00876 
00877   PetscInfo2(0,"Au1*u1=divM: %i its, reason: %i\n",its1, reason);
00878   if (reason<0) {
00879     PetscReal rnorm;
00880 
00881 /*  does not work:
00882 
00883     PCGetFactoredMatrix
00884     Gets the factored matrix from the preconditioner context.
00885     This routine is valid only for the LU, incomplete LU, Cholesky, and incomplete Cholesky methods.
00886 
00887     PC pc;
00888     Mat M;
00889     Vec D;
00890     ierr = KSPGetPC(ksp_Au1,&pc);CHKERRQ(ierr);
00891     ierr = PCGetFactoredMatrix(pc,&M);CHKERRQ(ierr);
00892     ierr = VecDuplicate(bu1,&D);CHKERRQ(ierr);
00893     ierr = MatGetDiagonal(M,D);CHKERRQ(ierr);
00894     PetscPrintf(PETSC_COMM_WORLD,"Pivots:\n");
00895     ierr = VecView(D,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00896 */
00897 
00898     ierr = KSPGetResidualNorm(ksp_Au1,&rnorm);CHKERRQ(ierr);
00899     SETERRQ3(PETSC_ERR_CONV_FAILED,
00900       "Warning: Au1*u1=divM: KSP did not converge at t=%g ns - reason: %i, rnorm: %g\n",
00901       gdata->time*gdata->tscale*1e9,reason,rnorm
00902     );
00903   }
00904 
00905   t_t2=t_t3;
00906   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
00907 
00908   if (oprofile) {
00909     PetscPrintf(PETSC_COMM_WORLD," timing: %s - u1 - took %g s\n",__FUNCT__,t_t3-t_t2);
00910   } else {
00911     PetscInfo2(0," timing: %s - u1 - took %g s\n",__FUNCT__,t_t3-t_t2);
00912   }
00913 
00914 /* skip the calculation of u2 and the rest, if u1 has not changed!
00915    with CG and ICC its1 is always >=1
00916    but LU solver checks residual first and may give its==0
00917 
00918    PETSc 2.3.0:
00919    great speed up for cg-icc
00920    does not work with lu
00921 */
00922 if (its1>0) {
00923   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00924                           calculate u2=B*u1
00925      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00926 
00927   /* copy boundary values of u1 into u1bnd */
00928   ierr = MatMult(ABu1,u1,u1bnd);CHKERRQ(ierr);
00929 
00930   t_t2=t_t3;
00931   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
00932 
00933   if (oprofile) {
00934     PetscPrintf(PETSC_COMM_WORLD," timing: %s - u1 scatter - took %g s\n",__FUNCT__,t_t3-t_t2);
00935   } else {
00936     PetscInfo2(0," timing: %s - u1 scatter - took %g s\n",__FUNCT__,t_t3-t_t2);
00937   }
00938 
00939   /* calculate u2=B*u1 (boundary vertices) */
00940   ierr = MatMult(Bmat,u1bnd,u2bnd);CHKERRQ(ierr);
00941 
00942   t_t2=t_t3;
00943   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
00944 
00945   if (oprofile) {
00946     PetscPrintf(PETSC_COMM_WORLD," timing: %s - u2=B*u1 - took %g s\n",__FUNCT__,t_t3-t_t2);
00947   } else {
00948     PetscInfo2(0," timing: %s - u2=B*u1 - took %g s\n",__FUNCT__,t_t3-t_t2);
00949   }
00950 
00951   /* copy boundary values of u2 (in u2bnd) into global load vector bu2 */
00952   ierr = MatMult(ABu2,u2bnd,bu2);CHKERRQ(ierr);
00953 
00954   t_t2=t_t3;
00955   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
00956 
00957   if (oprofile) {
00958     PetscPrintf(PETSC_COMM_WORLD," timing: %s - u2 scatter - took %g s\n",__FUNCT__,t_t3-t_t2);
00959   } else {
00960     PetscInfo2(0," timing: %s - u2 scatter - took %g s\n",__FUNCT__,t_t3-t_t2);
00961   }
00962 
00963 #ifdef HDEMAGUEPOL
00964     /* extrapolate u2 (weakened) */
00965 /*
00966   if (gdata->mode==0 && PetscAbsReal(dt) > 1e-8){
00967     PetscReal dt2;
00968     dt2=dt*0.5;
00969     ierr = VecWAXPY(u2,dt2,du2dt,u2bak);CHKERRQ(ierr);
00970   }
00971 */
00972 #endif
00973 
00974   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
00975                       Solve the linear system
00976      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
00977 
00978   ierr = KSPSetInitialGuessNonzero(ksp_Au2,PETSC_TRUE);CHKERRQ(ierr);
00979 
00980 /* TODO: better performance with this!?
00981   ierr = KSPSetInitialGuessKnoll(ksp_Au2,PETSC_TRUE);CHKERRQ(ierr);
00982 */
00983 
00984   ierr = KSPSolve(ksp_Au2,bu2,u2);CHKERRQ(ierr);
00985   ierr = KSPGetIterationNumber(ksp_Au2,(PetscInt*)&its2);CHKERRQ(ierr);
00986   ierr = KSPGetConvergedReason(ksp_Au2,&reason);CHKERRQ(ierr);
00987 
00988   PetscInfo2(0,"Au2*u2=bu2: %i its, reason: %i\n",its2, reason);
00989   if (reason<0) {
00990     PetscReal rnorm;
00991 
00992     ierr = KSPGetResidualNorm(ksp_Au2,&rnorm);CHKERRQ(ierr);
00993     PetscPrintf(PETSC_COMM_WORLD,
00994       "Warning: Au2*u2=bu2: KSP did not converge at t=%g ns - reason: %i, rnorm: %g\n",
00995       gdata->time*gdata->tscale*1e9,reason,rnorm
00996     );
00997   }
00998 
00999   t_t2=t_t3;
01000   ierr = PetscGetTime(&t_t3);CHKERRQ(ierr);
01001 
01002   if (oprofile) {
01003     PetscPrintf(PETSC_COMM_WORLD," timing: %s - u2 - took %g s\n",__FUNCT__,t_t3-t_t2);
01004   } else {
01005     PetscInfo2(0," timing: %s - u2 - took %g s\n",__FUNCT__,t_t3-t_t2);
01006   }
01007 
01008   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
01009                       calculate H = -grad u
01010      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
01011 
01012   ierr = VecWAXPY(utot,1.0,u1,u2);CHKERRQ(ierr);
01013   ierr = MatMult(Agradu,utot,gdata->VHdem);CHKERRQ(ierr);
01014 
01015 #ifdef HDEMAGUEPOL
01016   if (gdata->mode==0 && PetscAbsReal(dt) > 1e-8){
01017     dt=1.0/dt;
01018 
01019     /* calculate rate of change of u1 */
01020     ierr = VecCopy(u1,du1dt);CHKERRQ(ierr);
01021     ierr = VecAXPY(du1dt,c_mone,u1bak);CHKERRQ(ierr);
01022     ierr = VecScale(du1dt,dt);CHKERRQ(ierr);
01023     ierr = VecCopy(u1,u1bak);CHKERRQ(ierr);
01024 
01025     /* calculate rate of change of u2 */
01026 /*
01027     ierr = VecCopy(u2,du2dt);CHKERRQ(ierr);
01028     ierr = VecAXPY(du2dt,c_mone,u2bak);CHKERRQ(ierr);
01029     ierr = VecScale(du2dt,dt);CHKERRQ(ierr);
01030     ierr = VecCopy(u2,u2bak);CHKERRQ(ierr);
01031 */
01032 
01033     tubak=gdata->time;
01034   }
01035 #endif
01036 
01037 /* endif (its1>0) */
01038 }
01039 else {
01040   PetscInfo2(0,
01041     "Info (t=%g ns): Skipped calculation of u2: %i\n",
01042     gdata->time*gdata->tscale*1e9,
01043     its1
01044   );
01045 }
01046 
01047   ierr = VecAXPY(VHtotsum,1.0,gdata->VHdem);CHKERRQ(ierr);
01048 
01049 /* DEBUG
01050   PetscPrintf(PETSC_COMM_WORLD,"deb02: bu1\n");
01051   ierr = VecView(bu1,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01052   PetscPrintf(PETSC_COMM_WORLD,"deb02: u1\n");
01053   ierr = VecView(u1,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01054   PetscPrintf(PETSC_COMM_WORLD,"deb02: u1bnd\n");
01055   ierr = VecView(u1bnd,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01056   PetscPrintf(PETSC_COMM_WORLD,"deb02: u2bnd\n");
01057   ierr = VecView(u2bnd,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01058   PetscPrintf(PETSC_COMM_WORLD,"deb02: bu2\n");
01059   ierr = VecView(bu2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01060   PetscPrintf(PETSC_COMM_WORLD,"deb02: u2\n");
01061   ierr = VecView(u2,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01062   PetscPrintf(PETSC_COMM_WORLD,"deb02: utot\n");
01063   ierr = VecView(utot,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01064   PetscPrintf(PETSC_COMM_WORLD,"deb02: VHdem\n");
01065   ierr = VecView(gdata->VHdem,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
01066 */
01067 
01068   MagparFunctionProfReturn(0);
01069 }
01070 
01071 
01072 int Hdemag_Energy(GridData *gdata,Vec VMom,PetscReal *energy)
01073 {
01074   PetscReal e;
01075 
01076   MagparFunctionInfoBegin;
01077 
01078   if (!fieldon) {
01079     *energy=0.0;
01080     MagparFunctionInfoReturn(0);
01081   }
01082 
01083   ierr = VecDot(VMom,gdata->VHdem,&e);CHKERRQ(ierr);
01084   e /= -2.0;
01085 
01086   *energy=e;
01087 
01088   MagparFunctionProfReturn(0);
01089 }
01090 

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