def get_conv_curfv_rearr(v, PrP, tcur, B2BoolInv): ConV = dts.get_convvec(u0_dolfun=v, V=PrP.V) ConV = ConV[PrP.invinds, ] ConV = np.vstack([ConV[~B2BoolInv], ConV[B2BoolInv]]) CurFv = dts.get_curfv(PrP.V, PrP.fv, PrP.invinds, tcur) if len(CurFv) != len(PrP.invinds): raise Warning('Need fv at innernodes here') CurFv = np.vstack([CurFv[~B2BoolInv], CurFv[B2BoolInv]]) return ConV, CurFv
def roth_upd_ind2(vvec=None, cts=None, nu=None, Vc=None, diribcsc=None, nmd=dict(V=None, Q=None, M=None, A=None, J=None, fv=None, fp=None, invinds=None, diribcs=None, coefalu=None), returnalu=False, **kwargs): """ advancing `v, p` for one time using Rothe's method Parameters --- nmd : dict containing the data (mesh, matrices, rhs) from the next time step vvec : (n,1)-array current solution Vc : dolfin.mesh current mesh Notes ----- Time dependent Dirichlet conditions are not supported by now """ logger.debug("length of vvec={0}".format(vvec.size)) if not nmd['V'] == Vc: vvec = _vctovn(vvec=vvec, Vc=Vc, Vn=nmd['V']) logger.debug('len(vvec)={0}, dim(Vn)={1}, dim(Vc)={2}'. format(vvec.size, nmd['V'].dim(), Vc.dim())) mvvec = nmd['M']*vvec[nmd['invinds'], :] convvec = dts.get_convvec(u0_vec=vvec, V=nmd['V'], diribcs=nmd['diribcs'], invinds=nmd['invinds']) if nmd['coefalu'] is None: mta = nmd['M'] + cts*nmd['A'] mtJT = -cts*nmd['J'].T else: mta = None mtJT = None rhsv = mvvec + cts*(nmd['fv'] - convvec) lsdpdict = dict(amat=mta, jmat=nmd['J'], jmatT=mtJT, rhsv=rhsv, rhsp=nmd['fp'], sadlu=nmd['coefalu'], return_alu=returnalu) if returnalu: vp_new, coefalu = lau.solve_sadpnt_smw(**lsdpdict) return vp_new, coefalu else: vp_new = lau.solve_sadpnt_smw(**lsdpdict) return vp_new
def test_linearized_mat_NSE_form(self): """check the conversion: dolfin form <-> numpy arrays and the linearizations""" import dolfin_navier_scipy.dolfin_to_sparrays as dts u = self.fenics_sol_u u.t = 1.0 ufun = dolfin.project(u, self.V) uvec = ufun.vector().get_local().reshape(len(ufun.vector()), 1) N1, N2, fv = dts.get_convmats(u0_dolfun=ufun, V=self.V) conv = dts.get_convvec(u0_dolfun=ufun, V=self.V) self.assertTrue(np.allclose(conv, N1 * uvec)) self.assertTrue(np.allclose(conv, N2 * uvec))
def test_linearized_mat_NSE_form(self): """check the conversion: dolfin form <-> numpy arrays and the linearizations""" import dolfin_navier_scipy.dolfin_to_sparrays as dts u = self.fenics_sol_u u.t = 1.0 ufun = dolfin.project(u, self.V) uvec = ufun.vector().get_local().reshape(len(ufun.vector()), 1) N1, N2, fv = dts.get_convmats(u0_dolfun=ufun, V=self.V) conv = dts.get_convvec(u0_dolfun=ufun, V=self.V) self.assertTrue(np.allclose(conv, N1 * uvec)) self.assertTrue(np.allclose(conv, N2 * uvec))
def getconvvec(vvec): return dts.get_convvec(u0_vec=vvec, V=V, diribcs=diribcs, invinds=invinds)
def test_residuals(self): femp, stokesmatsc, rhsd = \ dnsps.get_sysmats(problem=self.problem, nu=self.nu, bccontrol=False, charvel=self.charvel, scheme=self.scheme, mergerhs=True, meshparams=self.meshparams) # setting some parameters t0 = 0.0 tE = .1 Nts = 2 tips = dict(t0=t0, tE=tE, Nts=Nts) soldict = stokesmatsc # containing A, J, JT soldict.update(femp) # adding V, Q, invinds, diribcs soldict.update(tips) # adding time integration params soldict.update(fv=rhsd['fv'], fp=rhsd['fp'], treat_nonl_explct=True, return_vp_dict=True, no_data_caching=True, start_ssstokes=True) vpdct = snu.solve_nse(**soldict) M, A, JT = stokesmatsc['M'], stokesmatsc['A'], stokesmatsc['JT'] fv = rhsd['fv'] V, invinds = femp['V'], femp['invinds'] dt = (tE - t0) / Nts tm = (tE - t0) / 2 reschkdict = dict(V=V, nu=self.nu, gradvsymmtrc=True, outflowds=femp['outflowds']) euleres = get_imex_res(explscheme='eule', **reschkdict) heunres = get_imex_res(explscheme='heun', **reschkdict) crnires = get_imex_res(explscheme='abtw', **reschkdict) # the initial value inivwbcs = vpdct[t0]['v'] iniv = inivwbcs[invinds] iniconvvec = dts.get_convvec(V=V, u0_vec=inivwbcs, invinds=invinds) inivelfun = dts.expand_vp_dolfunc(vc=inivwbcs, **femp)[0] # the Heun prediction step cneevwbcs = vpdct[(tm, 'heunpred')]['v'] cneev = cneevwbcs[invinds] cneep = vpdct[(tm, 'heunpred')]['p'] # the Heun step cnhevwbcs = vpdct[tm]['v'] cnhev = cnhevwbcs[invinds] cnhep = vpdct[tm]['p'] hpconvvec = dts.get_convvec(V=V, u0_vec=cneevwbcs, invinds=invinds) hpvelfun = dts.expand_vp_dolfunc(vc=cneevwbcs, **femp)[0] # the AB2 step cnabvwbcs = vpdct[tE]['v'] cnabv = cnabvwbcs[invinds] cnabp = vpdct[tE]['p'] hcconvvec = dts.get_convvec(V=V, u0_vec=cnhevwbcs, invinds=invinds) hcvelfun = dts.expand_vp_dolfunc(vc=cnhevwbcs, **femp)[0] print('Heun-Prediction: one step of Euler') resvec = (1. / dt * M * (cneev - iniv) + .5 * A * (iniv + cneev) + iniconvvec - JT * cneep - fv) hpscres = np.linalg.norm(resvec) print('Scipy residual: ', hpscres) curv, curp = dts.expand_vp_dolfunc(vc=cneevwbcs, pc=cneep, **femp) res = euleres(curv, curp, dt, lastvel=inivelfun) hpfnres = np.linalg.norm(res.get_local()[invinds]) print('dolfin residua: ', hpfnres) self.assertTrue(np.allclose(hpfnres, 0.)) self.assertTrue(np.allclose(hpscres, 0.)) print('\nHeun-Step:') heunrhs = M * iniv - .5 * dt * \ (A * iniv + iniconvvec + hpconvvec) + dt * fv matvp = M * cnhev + .5 * dt * A * cnhev - dt * JT * cnhep hcscres = np.linalg.norm(matvp - heunrhs) print('Scipy residual: ', hcscres) # import ipdb; ipdb.set_trace() curv, curp = dts.expand_vp_dolfunc(vc=cnhevwbcs, pc=cnhep, **femp) heunres = heunres(curv, curp, dt, lastvel=inivelfun, othervel=hpvelfun) hcfnres = np.linalg.norm(heunres.get_local()[invinds]) print('dolfin residua: ', hcfnres) self.assertTrue(np.allclose(hcfnres, 0.)) self.assertTrue(np.allclose(hcscres, 0.)) print('\nAB2-Step:') abtrhs = M * cnhev - .5 * dt * \ (A * cnhev + -iniconvvec + 3. * hcconvvec) + dt * fv matvp = M * cnabv + .5 * dt * A * cnabv - dt * JT * cnabp abscres = np.linalg.norm(matvp - abtrhs) print('Scipy residual: ', abscres) # import ipdb; ipdb.set_trace() curv, curp = dts.expand_vp_dolfunc(vc=cnabvwbcs, pc=cnabp, **femp) crnires = crnires(curv, curp, dt, lastvel=hcvelfun, othervel=inivelfun) abfnres = np.linalg.norm(crnires.get_local()[invinds]) print('dolfin residua: ', abfnres) self.assertTrue(np.allclose(abfnres, 0.)) self.assertTrue(np.allclose(abscres, 0.))
def roth_upd_smmx(vvec=None, cts=None, nu=None, Vc=None, diribcsc=None, nmd=dict(V=None, Q=None, M=None, invinds=None, npc=None, MSme=None, ASme=None, JSme=None, fvSme=None, fp=None, diribcs=None, coefalu=None, smmxqq2vel=None, vel2smmxqq=None), returnalu=False, **kwargs): """ advancing `v, p` for one time using Rothe's method Parameters --- vvec : (n, 1) array the current velocity solution vector incl. bcs in the actual coors nmd : dict containing the data (mesh, matrices, rhs) from the next time step, with the `*Sme` matrices resorted according to the minimal extension vvec : (n,1)-array current solution Vc : dolfin.mesh current mesh Notes ----- Time dependent Dirichlet conditions are not supported by now """ Npc = nmd['npc'] # split the coeffs J1Sme = nmd['JSme'][:, :-Npc] J2Sme = nmd['JSme'][:, -Npc:] M1Sme = nmd['MSme'][:, :-Npc] M2Sme = nmd['MSme'][:, -Npc:] A1Sme = nmd['ASme'][:, :-Npc] A2Sme = nmd['ASme'][:, -Npc:] if not nmd['V'] == Vc: vvec = _vctovn(vvec=vvec, Vc=Vc, Vn=nmd['V']) logger.debug('interpolate v: len(vvec)={0}, dim(Vn)={1}, dim(Vc)={2}'. format(vvec.size, nmd['V'].dim(), Vc.dim())) q1c, q2c = nmd['vel2smmxqq'](vvec[nmd['invinds']]) convvec = dts.get_convvec(u0_vec=vvec, V=nmd['V'], diribcs=nmd['diribcs'], invinds=nmd['invinds']) logger.debug('in `roth_upd_smmx`: |[q1,q2]|={0}'. format(npla.norm(np.vstack([q1c, q2c])))) logger.debug('in `roth_upd_smmx`: cts={0}'.format(cts)) logger.debug('in `roth_upd_smmx`: |vvec|={0}'. format(npla.norm(vvec[nmd['invinds']]))) coefmatmom = sps.hstack([1/cts*M1Sme+A1Sme, M2Sme, -nmd['JSme'].T, A2Sme]) coefmdivdrv = sps.hstack([1/cts*J1Sme, J2Sme, sps.csr_matrix((Npc, 2*Npc))]) coefmdiv = sps.hstack([J1Sme, sps.csr_matrix((Npc, 2*Npc)), J2Sme]) coefmat = sps.vstack([coefmatmom, coefmdivdrv, coefmdiv]) rhsmom = 1/cts*M1Sme*q1c - nmd['vel2smmxqq'](convvec, getitstacked=True) +\ nmd['fvSme'] rhsdivdrv = 1/cts*J1Sme*q1c rhsdiv = nmd['fp'] rhs = np.vstack([rhsmom, rhsdivdrv, rhsdiv]) logger.debug('in `roth_upd_smmx`: |rhs|={0}'.format(npla.norm(rhs))) qqpqnext = spsla.spsolve(coefmat, rhs) Nvc = A1Sme.shape[0] q1, q2 = qqpqnext[:Nvc-Npc], qqpqnext[Nvc+Npc:Nvc+2*Npc] p_new = qqpqnext[Nvc:Nvc+Npc] v_new = nmd['smmxqq2vel'](q1=q1, q2=q2) vp_new = np.vstack([v_new, p_new.reshape((p_new.size, 1))]) logger.debug('in `roth_upd_smmx`: |vpnew|={0}'.format(npla.norm(vp_new))) if returnalu: return vp_new, None else: return vp_new
def get_v_conv_conts(prev_v=None, V=None, invinds=None, diribcs=None, dbcvals=None, dbcinds=None, semi_explicit=False, Picard=False, retparts=False, zerodiribcs=False): """ get and condense the linearized convection to be used in a Newton scheme .. math:: (u \\cdot \\nabla) u \\to (u_0 \\cdot \\nabla) u + \ (u \\cdot \\nabla) u_0 - (u_0 \\cdot \\nabla) u_0 or in a Picard scheme .. math:: (u \\cdot \\nabla) u \\to (u_0 \\cdot \\nabla) u Parameters ---------- prev_v : (N,1) ndarray convection velocity V : dolfin.VectorFunctionSpace FEM space of the velocity invinds : (N,) ndarray or list indices of the inner nodes diribcs : list of dolfin Dirichlet boundary conditons Picard : Boolean whether Picard linearization is applied, defaults to `False` semi_explicit: Boolean, optional whether to return minus the convection vector, and zero convmats as needed for semi-explicit integration, defaults to `False` retparts : Boolean, optional whether to return both components of the matrices and contributions to the rhs through the boundary conditions, defaults to `False` Returns ------- convc_mat : (N,N) sparse matrix representing the linearized convection at the inner nodes rhs_con : (N,1) array representing :math:`(u_0 \\cdot \\nabla )u_0` at the inner nodes rhsv_conbc : (N,1) ndarray representing the boundary conditions """ if semi_explicit: rhs_con = dts.get_convvec(V=V, u0_vec=prev_v, diribcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals, invinds=invinds) return 0., -rhs_con, 0. N1, N2, rhs_con = dts.get_convmats(u0_vec=prev_v, V=V, invinds=invinds, dbcinds=dbcinds, dbcvals=dbcvals, diribcs=diribcs) if zerodiribcs: def _cndnsmts(mat, diribcs, **kw): return mat[invinds, :][:, invinds], np.zeros((invinds.size, 1)) else: _cndnsmts = dts.condense_velmatsbybcs if Picard: convc_mat, rhsv_conbc = _cndnsmts(N1, velbcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals) # return convc_mat, rhs_con[invinds, ], rhsv_conbc return convc_mat, None, rhsv_conbc elif retparts: picrd_convc_mat, picrd_rhsv_conbc = _cndnsmts(N1, velbcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals) anti_picrd_convc_mat, anti_picrd_rhsv_conbc = \ _cndnsmts(N2, velbcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals) return ((picrd_convc_mat, anti_picrd_convc_mat), rhs_con[invinds, ], (picrd_rhsv_conbc, anti_picrd_rhsv_conbc)) else: convc_mat, rhsv_conbc = _cndnsmts(N1+N2, velbcs=diribcs, dbcinds=dbcinds, dbcvals=dbcvals) return convc_mat, rhs_con[invinds, ], rhsv_conbc
def halfexp_euler_nseind2(Mc, MP, Ac, BTc, Bc, fvbc, fpbc, PrP, TsP, vp_init=None): """halfexplicit euler for the NSE in index 2 formulation """ # # # Basic Eqn: # # 1/dt*M -B.T q+ 1/dt*M*qc - K(qc) + fc # B * pc = g # # Nts, t0, tE, dt, Nv = init_time_stepping(PrP, TsP) tcur = t0 MFac = dt CFac = 1 # /dt # PFac = -1 # -1 for symmetry (if CFac==1) PFacI = -1./dt dtstrdct = dict(prefix=TsP.svdatapath, method=2, N=PrP.N, tolcor=TsP.TolCorB, nu=PrP.nu, Nts=TsP.Nts, tol=TsP.linatol, te=TsP.tE) cdatstr = get_dtstr(t=t0, **dtstrdct) try: np.load(cdatstr + '.npy') print 'loaded data from ', cdatstr, ' ...' except IOError: np.save(cdatstr, vp_init) print 'saving to ', cdatstr, ' ...' v, p = expand_vp_dolfunc(PrP, vp=vp_init, vc=None, pc=None) TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur Bcc, BTcc, MPc, fpbcc, vp_init, Npc = pinthep(Bc, BTc, MP, fpbc, vp_init, PrP.Pdof) IterAv = MFac*sps.hstack([1.0/dt*Mc + Ac, PFacI*(-1)*BTcc]) IterAp = CFac*sps.hstack([Bcc, sps.csr_matrix((Npc, Npc))]) IterA = sps.vstack([IterAv, IterAp]) if TsP.linatol == 0: IterAfac = spsla.factorized(IterA) vp_old = vp_init vp_old = np.vstack([vp_init[:Nv], 1./PFacI*vp_init[Nv:]]) vp_oldold = vp_old ContiRes, VelEr, PEr, TolCorL = [], [], [], [] # Mvp = sps.csr_matrix(sps.block_diag((Mc, MPc))) # Mvp = sps.eye(Mc.shape[0] + MPc.shape[0]) # Mvp = None # M matrix for the minres routine # M accounts for the FEM discretization Mcfac = spsla.splu(Mc) MPcfac = spsla.splu(MPc) def _MInv(vp): # v, p = vp[:Nv, ], vp[Nv:, ] # lsv = krypy.linsys.LinearSystem(Mc, v, self_adjoint=True) # lsp = krypy.linsys.LinearSystem(MPc, p, self_adjoint=True) # Mv = (krypy.linsys.Cg(lsv, tol=1e-14)).xk # Mp = (krypy.linsys.Cg(lsp, tol=1e-14)).xk v, p = vp[:Nv, ], vp[Nv:, ] Mv = np.atleast_2d(Mcfac.solve(v.flatten())).T Mp = np.atleast_2d(MPcfac.solve(p.flatten())).T return np.vstack([Mv, Mp]) MInv = spsla.LinearOperator( (Nv + Npc, Nv + Npc), matvec=_MInv, dtype=np.float32) def ind2_ip(vp1, vp2): """ for applying the fem inner product """ v1, v2 = vp1[:Nv, ], vp2[:Nv, ] p1, p2 = vp1[Nv:, ], vp2[Nv:, ] return mass_fem_ip(v1, v2, Mcfac) + mass_fem_ip(p1, p2, MPcfac) inikryupd = TsP.inikryupd iniiterfac = TsP.iniiterfac # the first krylov step needs more maxiter for etap in range(1, TsP.NOutPutPts + 1): for i in range(Nts / TsP.NOutPutPts): cdatstr = get_dtstr(t=tcur+dt, **dtstrdct) try: vp_next = np.load(cdatstr + '.npy') print 'loaded data from ', cdatstr, ' ...' vp_next = np.vstack([vp_next[:Nv], 1./PFacI*vp_next[Nv:]]) vp_oldold = vp_old vp_old = vp_next if tcur == dt+dt: iniiterfac = 1 # fac only in the first Krylov Call except IOError: print 'computing data for ', cdatstr, ' ...' ConV = dts.get_convvec(u0_dolfun=v, V=PrP.V) CurFv = dts.get_curfv(PrP.V, PrP.fv, PrP.invinds, tcur) Iterrhs = np.vstack([MFac*1.0/dt*Mc*vp_old[:Nv, ], np.zeros((Npc, 1))]) +\ np.vstack([MFac*(fvbc + CurFv - ConV[PrP.invinds, ]), CFac*fpbcc]) if TsP.linatol == 0: # ,vp_old,tol=TsP.linatol) vp_new = IterAfac(Iterrhs.flatten()) # vp_new = spsla.spsolve(IterA, Iterrhs) vp_old = np.atleast_2d(vp_new).T TolCor = 0 else: if inikryupd and tcur == t0: print '\n1st step direct solve to initialize krylov\n' vp_new = spsla.spsolve(IterA, Iterrhs) vp_old = np.atleast_2d(vp_new).T TolCor = 0 inikryupd = False # only once !! else: if TsP.TolCorB: NormRhsInd2 = \ np.sqrt(ind2_ip(Iterrhs, Iterrhs))[0][0] TolCor = 1.0 / np.max([NormRhsInd2, 1]) else: TolCor = 1.0 curls = krypy.linsys.LinearSystem(IterA, Iterrhs, M=MInv) tstart = time.time() # extrapolating the initial value upv = (vp_old - vp_oldold) ret = krypy.linsys.\ RestartedGmres(curls, x0=vp_old + upv, tol=TolCor*TsP.linatol, maxiter=iniiterfac*TsP.MaxIter, max_restarts=100) # ret = krypy.linsys.\ # Minres(curls, maxiter=20*TsP.MaxIter, # x0=vp_old + upv, tol=TolCor*TsP.linatol) tend = time.time() vp_oldold = vp_old vp_old = ret.xk print ('Needed {0} of max {4}*{1} iterations: ' + 'final relres = {2}\n TolCor was {3}').\ format(len(ret.resnorms), TsP.MaxIter, ret.resnorms[-1], TolCor, iniiterfac) print 'Elapsed time {0}'.format(tend - tstart) iniiterfac = 1 # fac only in the first Krylov Call np.save(cdatstr, np.vstack([vp_old[:Nv], PFacI*vp_old[Nv:]])) vc = vp_old[:Nv, ] print 'Norm of current v: ', np.linalg.norm(vc) pc = PFacI*vp_old[Nv:, ] v, p = expand_vp_dolfunc(PrP, vp=None, vc=vc, pc=pc) tcur += dt # the errors vCur, pCur = PrP.v, PrP.p try: vCur.t = tcur pCur.t = tcur - dt ContiRes.append(comp_cont_error(v, fpbc, PrP.Q)) VelEr.append(errornorm(vCur, v)) PEr.append(errornorm(pCur, p)) TolCorL.append(TolCor) except AttributeError: ContiRes.append(0) VelEr.append(0) PEr.append(0) TolCorL.append(0) print '%d of %d time steps completed ' % (etap*Nts/TsP.NOutPutPts, Nts) if TsP.ParaviewOutput: TsP.UpFiles.u_file << v, tcur TsP.UpFiles.p_file << p, tcur TsP.Residuals.ContiRes.append(ContiRes) TsP.Residuals.VelEr.append(VelEr) TsP.Residuals.PEr.append(PEr) TsP.TolCor.append(TolCorL) return