/* Fortran interface to C routine ARKodeGetErrWeights; see farkode.h for further details */ void FARK_GETERRWEIGHTS(realtype *eweight, int *ier) { /* store pointer existing F2C_ARKODE_vec data array */ realtype *f2c_data = N_VGetArrayPointer(F2C_ARKODE_vec); /* attach output data array to F2C_ARKODE_vec */ N_VSetArrayPointer(eweight, F2C_ARKODE_vec); /* call ARKodeGetErrWeights */ *ier = 0; *ier = ARKodeGetErrWeights(ARK_arkodemem, F2C_ARKODE_vec); /* reattach F2C_ARKODE_vec to previous data array */ N_VSetArrayPointer(f2c_data, F2C_ARKODE_vec); return; }
/* This routine generates the block-diagonal part of the Jacobian corresponding to the interaction rates, multiplies by -gamma, adds the identity matrix, and calls denseGETRF to do the LU decomposition of each diagonal block. The computation of the diagonal blocks uses the preset block and grouping information. One block per group is computed. The Jacobian elements are generated by difference quotients using calls to the routine fblock. This routine can be regarded as a prototype for the general case of a block-diagonal preconditioner. The blocks are of size mp, and there are ngrp=ngx*ngy blocks computed in the block-grouping scheme. */ static int Precond(realtype t, N_Vector c, N_Vector fc, booleantype jok, booleantype *jcurPtr, realtype gamma, void *user_data, N_Vector vtemp1, N_Vector vtemp2, N_Vector vtemp3) { realtype ***P; int ier; long int **pivot; int i, if0, if00, ig, igx, igy, j, jj, jx, jy; int *jxr, *jyr, ngrp, ngx, ngy, mxmp, flag; long int mp; realtype uround, fac, r, r0, save, srur; realtype *f1, *fsave, *cdata, *rewtdata; WebData wdata; void *arkode_mem; N_Vector rewt; wdata = (WebData) user_data; arkode_mem = wdata->arkode_mem; cdata = NV_DATA_S(c); rewt = wdata->rewt; flag = ARKodeGetErrWeights(arkode_mem, rewt); if(check_flag(&flag, "ARKodeGetErrWeights", 1)) return(1); rewtdata = NV_DATA_S(rewt); uround = UNIT_ROUNDOFF; P = wdata->P; pivot = wdata->pivot; jxr = wdata->jxr; jyr = wdata->jyr; mp = wdata->mp; srur = wdata->srur; ngrp = wdata->ngrp; ngx = wdata->ngx; ngy = wdata->ngy; mxmp = wdata->mxmp; fsave = wdata->fsave; /* Make mp calls to fblock to approximate each diagonal block of Jacobian. Here, fsave contains the base value of the rate vector and r0 is a minimum increment factor for the difference quotient. */ f1 = NV_DATA_S(vtemp1); fac = N_VWrmsNorm (fc, rewt); r0 = RCONST(1000.0)*SUNRabs(gamma)*uround*NEQ*fac; if (r0 == ZERO) r0 = ONE; for (igy = 0; igy < ngy; igy++) { jy = jyr[igy]; if00 = jy*mxmp; for (igx = 0; igx < ngx; igx++) { jx = jxr[igx]; if0 = if00 + jx*mp; ig = igx + igy*ngx; /* Generate ig-th diagonal block */ for (j = 0; j < mp; j++) { /* Generate the jth column as a difference quotient */ jj = if0 + j; save = cdata[jj]; r = SUNMAX(srur*SUNRabs(save),r0/rewtdata[jj]); cdata[jj] += r; fac = -gamma/r; fblock (t, cdata, jx, jy, f1, wdata); for (i = 0; i < mp; i++) { P[ig][j][i] = (f1[i] - fsave[if0+i])*fac; } cdata[jj] = save; } } } /* Add identity matrix and do LU decompositions on blocks. */ for (ig = 0; ig < ngrp; ig++) { denseAddIdentity(P[ig], mp); ier = denseGETRF(P[ig], mp, mp, pivot[ig]); if (ier != 0) return(1); } *jcurPtr = TRUE; return(0); }