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: precond.c 2699 2009-08-07 18:16:34Z scholz $\n\n";
00025 static char const Td[] = "$Today: " __FILE__ " " __DATE__ " " __TIME__ " $\n\n";
00026
00027 #include "llg.h"
00028 #include "field/field.h"
00029 #include "util/util.h"
00030
00031 static KSP ksp_Jac;
00032 static Mat vode_Jac;
00033 static Vec vode_w1,vode_w2;
00034 static Mat vode_pmat;
00036 int Precond_Init(GridData *gdata)
00037 {
00038 MagparFunctionLogBegin;
00039
00040 int rank,size;
00041 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr);
00042 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
00043
00044 PetscPrintf(PETSC_COMM_WORLD,"Calculating sparsity pattern for matrix preallocation\n");
00045
00046
00047 int low,high;
00048 ierr = VecGetOwnershipRange(gdata->elevol,&low,&high);CHKERRQ(ierr);
00049
00050 int *elevertall;
00051
00052 #ifdef HAVE_ELEVERTALL
00053 elevertall=gdata->elevertall;
00054 #else
00055 if (size>1) {
00056 ierr = PetscMalloc(NV*gdata->n_ele*sizeof(int),&elevertall);CHKERRQ(ierr);
00057 ierr = PetscMemcpy(elevertall+NV*low,gdata->elevert,NV*gdata->ln_ele*sizeof(int));CHKERRQ(ierr);
00058
00059 int *p;
00060 p=elevertall;
00061
00062 int recvcount[size];
00063 recvcount[rank]=NV*gdata->ln_ele;
00064 for (int i=0;i<size;i++) {
00065 ierr = MPI_Bcast(recvcount+i,1,MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00066
00067 ierr = MPI_Bcast(p,recvcount[i],MPI_INT,i,PETSC_COMM_WORLD);CHKERRQ(ierr);
00068 p+=recvcount[i];
00069 }
00070 assert(p==elevertall+NV*gdata->n_ele);
00071 }
00072 else {
00073 elevertall=gdata->elevert;
00074 }
00075 #endif
00076
00077 int *ia,*ja;
00078 #ifdef HAVE_M2IJ
00079 ia=gdata->mesh2nodal_ia;
00080 ja=gdata->mesh2nodal_ja;
00081 #else
00082 ierr = Mesh2Nodal(gdata->n_ele,gdata->n_vert,elevertall,&ia,&ja);CHKERRQ(ierr);
00083 #endif
00084
00085 #ifndef HAVE_ELEVERTALL
00086 if (size>1) {
00087 ierr = PetscFree(elevertall);CHKERRQ(ierr);
00088 }
00089 #endif
00090
00091
00092 ierr = VecGetOwnershipRange(gdata->M,&low,&high);CHKERRQ(ierr);
00093 low/=ND;
00094 high/=ND;
00095
00096 int *d_nnz;
00097 int *o_nnz;
00098 ierr = PetscMalloc(ND*(high-low)*sizeof(int),&d_nnz);CHKERRQ(ierr);
00099 ierr = PetscMalloc(ND*(high-low)*sizeof(int),&o_nnz);CHKERRQ(ierr);
00100
00101 for (int i=low;i<high;i++) {
00102 for (int j=0;j<ND;j++) {
00103 d_nnz[ND*(i-low)+j]=ND;
00104 o_nnz[ND*(i-low)+j]=0;
00105 for (int l=ia[i];l<ia[i+1];l++) {
00106 if (ja[l]>=low && ja[l]<high) {
00107 d_nnz[ND*(i-low)+j]+=ND;
00108 }
00109 else {
00110 o_nnz[ND*(i-low)+j]+=ND;
00111 }
00112 }
00113 }
00114 }
00115
00116 #if 0
00117 #define PREALLOC_DG 25
00118 #define PREALLOC_OD 15
00119 PetscPrintf(PETSC_COMM_WORLD,"Creating matrix with fixed preallocation\n");
00120
00121 ierr = MatCreateMPIAIJ(
00122 PETSC_COMM_WORLD,
00123 ND*gdata->ln_vert,ND*gdata->ln_vert,
00124 ND*gdata->n_vert,ND*gdata->n_vert,
00125 PREALLOC_DG,0,PREALLOC_OD,0,
00126 &vode_Jac
00127 );CHKERRQ(ierr);
00128 #else
00129 PetscPrintf(PETSC_COMM_WORLD,"Creating matrix with calculated preallocation\n");
00130 ierr = MatCreateMPIAIJ(
00131 PETSC_COMM_WORLD,
00132 ND*gdata->ln_vert,ND*gdata->ln_vert,
00133 ND*gdata->n_vert,ND*gdata->n_vert,
00134 0,d_nnz,0,o_nnz,
00135 &vode_Jac
00136 );CHKERRQ(ierr);
00137 #endif
00138 ierr = MatSetFromOptions(vode_Jac);CHKERRQ(ierr);
00139
00140 #ifndef HAVE_M2IJ
00141 ierr = PetscFree(ia);CHKERRQ(ierr);
00142 ierr = PetscFree(ja);CHKERRQ(ierr);
00143 #endif
00144 ierr = PetscFree(d_nnz);CHKERRQ(ierr);
00145 ierr = PetscFree(o_nnz);CHKERRQ(ierr);
00146
00147 ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,ND*gdata->ln_vert,ND*gdata->n_vert,PETSC_NULL,&vode_w1);CHKERRQ(ierr);
00148 ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,ND*gdata->ln_vert,ND*gdata->n_vert,PETSC_NULL,&vode_w2);CHKERRQ(ierr);
00149
00150 PetscPrintf(PETSC_COMM_WORLD,"Calculating matrix elements...\n");
00151
00152 for (int i=0;i<gdata->ln_vert;i++) {
00153
00154
00155
00156
00157
00158 int rows[ND];
00159 rows[0]=gdata->vertl2g[i]*ND;
00160 rows[1]=rows[0]+1;
00161 rows[2]=rows[0]+2;
00162
00163 ierr = MatSetValue(vode_Jac,rows[0],rows[0],0.0,ADD_VALUES);CHKERRQ(ierr);
00164 ierr = MatSetValue(vode_Jac,rows[1],rows[1],0.0,ADD_VALUES);CHKERRQ(ierr);
00165 ierr = MatSetValue(vode_Jac,rows[2],rows[2],0.0,ADD_VALUES);CHKERRQ(ierr);
00166 }
00167
00168
00169 MatStructure str2 = DIFFERENT_NONZERO_PATTERN;
00170 ierr = myLLGJacobian(PETSC_NULL,gdata->time,gdata->M,&vode_Jac,&vode_Jac,&str2,gdata);CHKERRQ(ierr);
00171
00172 ierr = MatDuplicate(vode_Jac,MAT_DO_NOT_COPY_VALUES,&vode_pmat);CHKERRQ(ierr);
00173 #ifdef SUPERLUX
00174 ierr = MatConvert(vode_Jac,MATSUPERLU_DIST,&vode_Jac);CHKERRQ(ierr);
00175 ierr = MatConvert(vode_pmat,MATSUPERLU_DIST,&vode_pmat);CHKERRQ(ierr);
00176 ierr = MatDestroy(vode_Jac);CHKERRQ(ierr);
00177 #elif defined(BLOCKSOLVEX)
00178 ierr = MatConvert(vode_Jac,MATMPIROWBS,&vode_Jac);CHKERRQ(ierr);
00179 ierr = MatConvert(vode_pmat,MATMPIROWBS,&vode_pmat);CHKERRQ(ierr);
00180 ierr = MatDestroy(vode_Jac);CHKERRQ(ierr);
00181 #endif
00182
00183 PetscPrintf(PETSC_COMM_WORLD,"Initializing linear solver...\n");
00184
00185 ierr = KSPCreate(PETSC_COMM_WORLD,&ksp_Jac);CHKERRQ(ierr);
00186 ierr = KSPSetOperators(ksp_Jac,vode_Jac,vode_Jac,SAME_PRECONDITIONER);CHKERRQ(ierr);
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 PetscTruth flg;
00203 char str[256];
00204
00205 #undef ostr
00206 #define ostr "-psolve_ksp_type"
00207 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00208 if (flg!=PETSC_TRUE) {
00209 sprintf(str,"gmres");
00210 PetscOptionsSetValue(ostr,str);
00211 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00212 }
00213
00214 #undef ostr
00215 #define ostr "-psolve_ksp_atol"
00216 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00217 if (flg!=PETSC_TRUE) {
00218 sprintf(str,"1e-7");
00219 PetscOptionsSetValue(ostr,str);
00220 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00221 }
00222
00223 #undef ostr
00224 #define ostr "-psolve_ksp_rtol"
00225 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00226 if (flg!=PETSC_TRUE) {
00227 sprintf(str,"0.01");
00228 PetscOptionsSetValue(ostr,str);
00229 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00230 }
00231
00232 #undef ostr
00233 #define ostr "-psolve_ksp_divtol"
00234 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00235 if (flg!=PETSC_TRUE) {
00236 sprintf(str,"100");
00237 PetscOptionsSetValue(ostr,str);
00238 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00239 }
00240
00241 if (size>1) {
00242
00243 #undef ostr
00244 #define ostr "-psolve_pc_type"
00245 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00246 if (flg!=PETSC_TRUE) {
00247 sprintf(str,"bjacobi");
00248 PetscOptionsSetValue(ostr,str);
00249 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00250 }
00251
00252
00253 #undef ostr
00254 #define ostr "-psolve_sub_pc_type"
00255 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00256 if (flg!=PETSC_TRUE) {
00257 sprintf(str,"ilu");
00258 PetscOptionsSetValue(ostr,str);
00259 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 }
00274 else {
00275
00276 #undef ostr
00277 #define ostr "-psolve_pc_type"
00278 ierr = PetscOptionsGetString(PETSC_NULL,ostr,str,256,&flg);CHKERRQ(ierr);
00279 if (flg!=PETSC_TRUE) {
00280 sprintf(str,"ilu");
00281 PetscOptionsSetValue(ostr,str);
00282 PetscPrintf(PETSC_COMM_WORLD,"Option %s not found, using default value %s!\n",ostr,str);
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 }
00297
00298
00299 ierr = KSPSetOptionsPrefix(ksp_Jac,"psolve_");CHKERRQ(ierr);
00300
00301
00302 ierr = KSPSetFromOptions(ksp_Jac);CHKERRQ(ierr);
00303
00304
00305
00306
00307
00308
00309
00310
00311 if (size>1) {
00312 ierr = KSPSetUp(ksp_Jac);CHKERRQ(ierr);
00313 }
00314
00315 PetscPrintf(PETSC_COMM_WORLD,"KSP for preconditioning: P*z=r:\n");
00316 #if defined(SUPERLU) || defined(BLOCKSOLVE)
00317 PetscReal rtol,atol,divtol;
00318 int maxits;
00319 ierr = KSPGetTolerances(ksp_Jac,&rtol,&atol,&divtol,&maxits);CHKERRQ(ierr);
00320 PetscPrintf(PETSC_COMM_WORLD,"rtol: %g atol: %g divtol: %g maxits: %i\n",
00321 rtol,atol,divtol,maxits
00322 );
00323 #else
00324 ierr = KSPView(ksp_Jac,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
00325 #endif
00326
00327 MagparFunctionLogReturn(0);
00328 }
00329
00330
00331 int Precond(realtype t,N_Vector y,N_Vector fy,booleantype jok,booleantype *jcurPtr,realtype gamma,void *P_data,N_Vector vtemp1,N_Vector vtemp2,N_Vector vtemp3)
00332 {
00333 GridData *gdata = (GridData*)P_data;
00334 MatStructure str = DIFFERENT_NONZERO_PATTERN;
00335
00336 MagparFunctionInfoBegin;
00337
00338
00339 if (jok) {
00340 ierr = MatCopy(vode_pmat,vode_Jac,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
00341 str = SAME_NONZERO_PATTERN;
00342 *jcurPtr = FALSE;
00343 } else {
00344
00345 #ifdef UNIPROC
00346 ierr = VecPlaceArray(gdata->M,NV_DATA_S(y));CHKERRQ(ierr);
00347 #else
00348 ierr = VecPlaceArray(gdata->M,NV_DATA_P(y));CHKERRQ(ierr);
00349 #endif
00350
00351
00352 ierr = Htot(gdata);CHKERRQ(ierr);
00353
00354
00355 ierr = myLLGJacobian(PETSC_NULL,gdata->time,gdata->M,&vode_Jac,&vode_Jac,&str,gdata);CHKERRQ(ierr);
00356
00357 ierr = VecResetArray(gdata->M);CHKERRQ(ierr);
00358
00359
00360 ierr = MatCopy(vode_Jac,vode_pmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
00361
00362 *jcurPtr = TRUE;
00363 }
00364
00365
00366
00367 ierr = MatScale(vode_Jac,-gamma);CHKERRQ(ierr);
00368 ierr = MatShift(vode_Jac,1.0);CHKERRQ(ierr);
00369
00370 ierr = KSPSetOperators(ksp_Jac,vode_Jac,vode_Jac,str);CHKERRQ(ierr);
00371
00372 MagparFunctionProfReturn(0);
00373 }
00374
00375
00376
00377
00378 int PSolve(realtype t,N_Vector y,N_Vector fy,N_Vector r,N_Vector z,realtype gamma,realtype delta,int lr,void *P_data,N_Vector vtemp)
00379 {
00380 MagparFunctionInfoBegin;
00381
00382
00383 assert(lr==1);
00384
00385 #ifdef UNIPROC
00386 ierr = VecPlaceArray(vode_w1,NV_DATA_S(r));CHKERRQ(ierr);
00387 ierr = VecPlaceArray(vode_w2,NV_DATA_S(z));CHKERRQ(ierr);
00388 #else
00389 ierr = VecPlaceArray(vode_w1,NV_DATA_P(r));CHKERRQ(ierr);
00390 ierr = VecPlaceArray(vode_w2,NV_DATA_P(z));CHKERRQ(ierr);
00391 #endif
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 int its1;
00414 ierr = KSPSolve(ksp_Jac,vode_w1,vode_w2);CHKERRQ(ierr);
00415
00416 ierr = VecResetArray(vode_w1);CHKERRQ(ierr);
00417 ierr = VecResetArray(vode_w2);CHKERRQ(ierr);
00418
00419 ierr = KSPGetIterationNumber(ksp_Jac,(PetscInt*)&its1);CHKERRQ(ierr);
00420 KSPConvergedReason reason;
00421 ierr = KSPGetConvergedReason(ksp_Jac,&reason);CHKERRQ(ierr);
00422
00423 ierr = PetscGetTime(&t_t2);CHKERRQ(ierr);
00424 PetscInfo2(0,"timing: %s took %g s\n",__FUNCT__,t_t2-t_t1);
00425 PetscInfo2(0,"psolve: %i its, reason: %i\n",its1,reason);
00426 if (reason<0) {
00427 PetscReal rnorm;
00428
00429 ierr = KSPGetResidualNorm(ksp_Jac,&rnorm);CHKERRQ(ierr);
00430 PetscPrintf(PETSC_COMM_WORLD,
00431 "Warning: psolve: KSP did not converge - reason: %i, rnorm: %g, its: %i\n",
00432 reason,rnorm,its1
00433 );
00434 }
00435
00436 MagparFunctionProfReturn(0);
00437 }
00438
00439
00440 int Jtimes(N_Vector v,N_Vector Jv,realtype t,N_Vector y,N_Vector fy,void *jac_data,N_Vector tmp)
00441 {
00442 MagparFunctionInfoBegin;
00443
00444 #ifdef UNIPROC
00445 ierr = VecPlaceArray(vode_w1,NV_DATA_S(v));CHKERRQ(ierr);
00446 ierr = VecPlaceArray(vode_w2,NV_DATA_S(Jv));CHKERRQ(ierr);
00447 #else
00448 ierr = VecPlaceArray(vode_w1,NV_DATA_P(v));CHKERRQ(ierr);
00449 ierr = VecPlaceArray(vode_w2,NV_DATA_P(Jv));CHKERRQ(ierr);
00450 #endif
00451
00452 ierr = MatMult(vode_pmat,vode_w1,vode_w2);CHKERRQ(ierr);
00453
00454 ierr = VecResetArray(vode_w1);CHKERRQ(ierr);
00455 ierr = VecResetArray(vode_w2);CHKERRQ(ierr);
00456
00457 MagparFunctionProfReturn(0);
00458 }