def testDenseGET(): """ Simple test of denseGETRF and denseGETRS to solve a linear system """ N = 2 A = np.array([[4.0, 6.0], [3.0, 3.0]], dtype=np.float64, order='F') A_sp = np.ascontiguousarray(A) P = np.arange(N, dtype=np.int32) b = np.ones(N, dtype=np.float64) b_sp = linalg.lu_solve(linalg.lu_factor(A_sp), b) ret = denseGETRF(A, P) assert ret == 0 denseGETRS(A, P, b) assert_allclose(b, b_sp) assert ret == 0
def testDenseGET(): """ Simple test of denseGETRF and denseGETRS to solve a linear system """ N = 2 A = np.array( [[4.0,6.0],[3.0,3.0]], dtype=np.float64, order='F') A_sp = np.ascontiguousarray(A) P = np.arange( N, dtype=np.int32 ) b = np.ones( N, dtype=np.float64 ) b_sp = linalg.lu_solve(linalg.lu_factor(A_sp), b) ret = denseGETRF(A, P) assert ret == 0 denseGETRS(A, P, b) assert_allclose(b, b_sp) assert ret == 0
def SpilsPrecSetup(self, t, c, fc, jok, jcurPtr, gamma, vtemp1, vtemp2, vtemp3): """ 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. """ cdata = c.data rewt = self.rewt self.errWeights(rewt) rewtdata = rewt.data uround = UNIT_ROUNDOFF P = self.P pivot = self.pivot jxr = self.jxr jyr = self.jyr mp = self.mp srur = self.srur #ngrp = self.ngrp ngx = self.ngx ngy = self.ngy #mxmp = self.mxmp fsave = self.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 = vtemp1.data fac = fc.WrmsNorm(rewt) r0 = 1000.0 * np.abs(gamma) * uround * NEQ * fac if (r0 == ZERO): r0 = ONE for igy in range(ngy): jy = jyr[igy] #if00 = jy*mxmp for igx in range(ngx): jx = jxr[igx] #if0 = if00 + jx*mp #ig = igx + igy*ngx # Generate ig-th diagonal block for j in range(mp): # Generate the jth column as a difference quotient #jj = if0 + j save = cdata[:, igx, igy] r = np.max(srur * np.abs(save), r0 / rewtdata[:, igx, igy]) cdata[:, igx, igy] += r fac = -gamma / r self.fblock(t, cdata, jx, jy, f1) for i in range(mp): P[igx, igy, j, i] = (f1[i] - fsave[i, jx, jy]) * fac cdata[j, jx, jy] = save # Add identity matrix and do LU decompositions on blocks. for igy in range(ngy): for igx in range(ngx): denseAddIdentity(P[igx, igy, ...]) ier = denseGETRF(P[igx, igy, ...], pivot[igx, igy, ...]) if (ier != 0): return 1 jcurPtr = True return 0
def SpilsPrecSetup(self, tn, u, fu, jok, gamma, vtemp1, vtemp2, vtemp3): """ Preconditioner setup routine. Generate and preprocess P. """ # Make local copies of pointers in user_data, and of pointer to u's data P = self.P Jbd = self.Jbd pivot = self.pivot udata = u.data if jok: # jok = TRUE: Copy Jbd to P for jy in range(MY): for jx in range(MX): P[jx, jy, ...] = Jbd[jx, jy, ...] jcurPtr = False else: # jok = FALSE: Generate Jbd from scratch and copy to P # Make local copies of problem variables, for efficiency. q4coef = self.q4 dely = self.dy verdco = self.vdco hordco = self.hdco # Compute 2x2 diagonal Jacobian blocks (using q4 values # computed on the last f call). Load into P. for jy in range(MY): ydn = YMIN + (jy - 0.5) * dely yup = ydn + dely cydn = verdco * np.exp(0.2 * ydn) cyup = verdco * np.exp(0.2 * yup) diag = -(cydn + cyup + TWO * hordco) for jx in range(MX): c1 = udata[jx, jy, 0] c2 = udata[jx, jy, 1] Jbd[jx, jy, 0, 0] = (-Q1 * C3 - Q2 * c2) + diag # Transposed in Python Jbd[jx, jy, 1, 0] = -Q2 * c1 + q4coef Jbd[jx, jy, 0, 1] = Q1 * C3 - Q2 * c2 Jbd[jx, jy, 1, 1] = (-Q2 * c1 - q4coef) + diag P[jx, jy, ...] = Jbd[jx, jy, ...] jcurPtr = True # Scale by -gamma for jy in range(MY): for jx in range(MX): P[jx, jy, ...] *= -gamma # Add identity matrix and do LU decompositions on blocks in place. for jy in range(MY): for jx in range(MX): P[jx, jy, ...] += np.eye(NUM_SPECIES) ier = denseGETRF(P[jx, jy, ...], pivot[jx, jy, ...]) # print ier, P[jx,jy,...] if ier != 0: return 1, jcurPtr return 0, jcurPtr
def SpilsPrecSetup(self, tn, u, fu, jok, gamma, vtemp1, vtemp2, vtemp3): """ Preconditioner setup routine. Generate and preprocess P. """ # Make local copies of pointers in user_data, and of pointer to u's data P = self.P Jbd = self.Jbd pivot = self.pivot udata = u.data if jok: # jok = TRUE: Copy Jbd to P for jy in range(MY): for jx in range(MX): P[jx,jy,...] = Jbd[jx,jy,...] jcurPtr = False else: # jok = FALSE: Generate Jbd from scratch and copy to P # Make local copies of problem variables, for efficiency. q4coef = self.q4; dely = self.dy; verdco = self.vdco; hordco = self.hdco; # Compute 2x2 diagonal Jacobian blocks (using q4 values # computed on the last f call). Load into P. for jy in range(MY): ydn = YMIN + (jy - 0.5)*dely; yup = ydn + dely; cydn = verdco*np.exp(0.2*ydn); cyup = verdco*np.exp(0.2*yup); diag = -(cydn + cyup + TWO*hordco); for jx in range(MX): c1 = udata[jx,jy,0] c2 = udata[jx,jy,1] Jbd[jx,jy,0,0] = (-Q1*C3 - Q2*c2) + diag # Transposed in Python Jbd[jx,jy,1,0] = -Q2*c1 + q4coef Jbd[jx,jy,0,1] = Q1*C3 - Q2*c2 Jbd[jx,jy,1,1] = (-Q2*c1 - q4coef) + diag P[jx,jy,...] = Jbd[jx,jy,...] jcurPtr = True # Scale by -gamma for jy in range(MY): for jx in range(MX): P[jx,jy,...] *= -gamma # Add identity matrix and do LU decompositions on blocks in place. for jy in range(MY): for jx in range(MX): P[jx,jy,...] += np.eye(NUM_SPECIES) ier = denseGETRF(P[jx,jy,...], pivot[jx,jy,...] ) # print ier, P[jx,jy,...] if ier != 0: return 1, jcurPtr return 0, jcurPtr