def optcon_nse(problemname='drivencavity', N=10, Nts=10, nu=1e-2, clearprvveldata=False, ini_vel_stokes=False, stst_control=False, closed_loop=True, outernwtnstps=1, t0=None, tE=None, use_ric_ini_nu=None, alphau=1e-9, gamma=1e-3, spec_tip_dict=None, nwtn_adi_dict=None, linearized_nse=False, stokes_flow=False, ystar=None): tip = time_int_params(Nts, t0=t0, tE=tE) if spec_tip_dict is not None: tip.update(spec_tip_dict) if nwtn_adi_dict is not None: tip['nwtn_adi_dict'] = nwtn_adi_dict problemdict = dict(drivencavity=dnsps.drivcav_fems, cylinderwake=dnsps.cyl_fems) problemfem = problemdict[problemname] femp = problemfem(N) # output ddir = 'data/' try: os.chdir(ddir) except OSError: raise Warning('need "' + ddir + '" subdir for storing the data') os.chdir('..') if linearized_nse and not outernwtnstps == 1: raise Warning('Linearized problem can have only one Newton step') if closed_loop: if stst_control: data_prfx = ddir + 'stst_' + problemname + '__' else: data_prfx = ddir + 'tdst_' + problemname + '__' else: data_prfx = ddir + problemname + '__' if stokes_flow: data_prfx = data_prfx + 'stokes__' # specify in what spatial direction Bu changes. The remaining is constant if problemname == 'drivencavity': uspacedep = 0 elif problemname == 'cylinderwake': uspacedep = 1 stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu) rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'], femp['fv'], femp['fp'], t=0) # remove the freedom in the pressure stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :] # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, femp['diribcs']) print 'Dimension of the div matrix: ', stokesmatsc['J'].shape # pressure freedom and dirichlet reduced rhs rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ]) # add the info on boundary and inner nodes bcdata = {'bcinds': bcinds, 'bcvals': bcvals, 'invinds': invinds} femp.update(bcdata) # casting some parameters NV = len(femp['invinds']) soldict = stokesmatsc # containing A, J, JT soldict.update(femp) # adding V, Q, invinds, diribcs # soldict.update(rhsd_vfrc) # adding fvc, fpr soldict.update(fv=rhsd_stbc['fv'] + rhsd_vfrc['fvc'], fp=rhsd_stbc['fp'] + rhsd_vfrc['fpr'], N=N, nu=nu, trange=tip['tmesh'], get_datastring=get_datastr, data_prfx=data_prfx, clearprvdata=clearprvveldata, paraviewoutput=tip['ParaviewOutput'], vfileprfx=tip['proutdir'] + 'vel_', pfileprfx=tip['proutdir'] + 'p_') # # Prepare for control # contp = ContParams(femp['odcoo'], ystar=ystar, alphau=alphau, gamma=gamma) # casting some parameters NY, NU = contp.NY, contp.NU contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY) # get the control and observation operators try: b_mat = dou.load_spa(ddir + contsetupstr + '__b_mat') u_masmat = dou.load_spa(ddir + contsetupstr + '__u_masmat') print 'loaded `b_mat`' except IOError: print 'computing `b_mat`...' b_mat, u_masmat = cou.get_inp_opa(cdcoo=femp['cdcoo'], V=femp['V'], NU=NU, xcomp=uspacedep) dou.save_spa(b_mat, ddir + contsetupstr + '__b_mat') dou.save_spa(u_masmat, ddir + contsetupstr + '__u_masmat') try: mc_mat = dou.load_spa(ddir + contsetupstr + '__mc_mat') y_masmat = dou.load_spa(ddir + contsetupstr + '__y_masmat') print 'loaded `c_mat`' except IOError: print 'computing `c_mat`...' mc_mat, y_masmat = cou.get_mout_opa(odcoo=femp['odcoo'], V=femp['V'], NY=NY) dou.save_spa(mc_mat, ddir + contsetupstr + '__mc_mat') dou.save_spa(y_masmat, ddir + contsetupstr + '__y_masmat') # restrict the operators to the inner nodes mc_mat = mc_mat[:, invinds][:, :] b_mat = b_mat[invinds, :][:, :] # for further use: c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse') if contp.ystarx is None: c_mat = c_mat[NY:, :][:, :] # TODO: Do this right mc_mat = mc_mat[NY:, :][:, :] # TODO: Do this right y_masmat = y_masmat[:NY, :][:, :NY] # TODO: Do this right mct_mat_reg = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'], jmat=stokesmatsc['J'], rhsv=mc_mat.T, transposedprj=True) # set the weighing matrices contp.R = contp.alphau * u_masmat # # solve the differential-alg. Riccati eqn for the feedback gain X # via computing factors Z, such that X = -Z*Z.T # # at the same time we solve for the affine-linear correction w # # tilde B = BR^{-1/2} tb_mat = lau.apply_invsqrt_fromright(contp.R, b_mat, output='sparse') # tb_dense = np.array(tb_mat.todense()) trct_mat = lau.apply_invsqrt_fromright(y_masmat, mct_mat_reg, output='dense') if closed_loop: cntpstr = 'NV{3}NY{0}NU{1}alphau{2}gamma{4}'.\ format(contp.NU, contp.NY, contp.alphau, NV, contp.gamma) else: cntpstr = '' # we gonna use this quite often M, A = stokesmatsc['M'], stokesmatsc['A'] datastrdict = dict(time=None, meshp=N, nu=nu, Nts=Nts, data_prfx=data_prfx) # compute the uncontrolled steady state (Navier-)Stokes solution # as initial value if ini_vel_stokes: # compute the uncontrolled steady state Stokes solution ini_vel, newtonnorms = snu.solve_steadystate_nse(vel_nwtn_stps=0, vel_pcrd_stps=0, **soldict) soldict.update(dict(iniv=ini_vel)) else: ini_vel, newtonnorms = snu.solve_steadystate_nse(**soldict) soldict.update(dict(iniv=ini_vel)) if closed_loop: if stst_control: if stokes_flow: convc_mat = sps.csr_matrix((NV, NV)) rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1)) lin_point = None else: lin_point, newtonnorms = snu.solve_steadystate_nse(**soldict) (convc_mat, rhs_con, rhsv_conbc) = snu.get_v_conv_conts(prev_v=lin_point, invinds=invinds, V=femp['V'], diribcs=femp['diribcs']) # infinite control horizon, steady target state cdatstr = get_datastr(time=None, meshp=N, nu=nu, Nts=None, data_prfx=data_prfx) try: Z = dou.load_npa(cdatstr + cntpstr + '__Z') print 'loaded ' + cdatstr + cntpstr + '__Z' except IOError: if use_ric_ini_nu is not None: cdatstr = get_datastr(nwtn=None, time=None, meshp=N, nu=use_ric_ini_nu, Nts=None, data_prfx=data_prfx) try: zini = dou.load_npa(ddir + cdatstr + cntpstr + '__Z') print 'Initialize Newton ADI by Z from ' + cdatstr except IOError: raise Warning('No data for initialization of ' ' Newton ADI -- need ' + cdatstr + '__Z') cdatstr = get_datastr(meshp=N, nu=nu, data_prfx=data_prfx) else: zini = None parnadi = pru.proj_alg_ric_newtonadi Z = parnadi(mmat=M, amat=-A - convc_mat, jmat=stokesmatsc['J'], bmat=tb_mat, wmat=trct_mat, z0=zini, nwtn_adi_dict=tip['nwtn_adi_dict'])['zfac'] dou.save_npa(Z, fstring=cdatstr + cntpstr + '__Z') print 'saved ' + cdatstr + cntpstr + '__Z' if tip['compress_z']: Zc = pru.compress_Zsvd(Z, thresh=tip['comprz_thresh'], k=tip['comprz_maxc']) Z = Zc fvnstst = rhs_con + rhsv_conbc + rhsd_stbc['fv'] + rhsd_vfrc['fvc'] # X = -ZZ.T mtxtb_stst = -pru.get_mTzzTtb(M.T, Z, tb_mat) mtxfv_stst = -pru.get_mTzzTtb(M.T, Z, fvnstst) fl = mc_mat.T * contp.ystarvec(0) wft = lau.solve_sadpnt_smw(amat=A.T + convc_mat.T, jmat=stokesmatsc['J'], rhsv=fl + mtxfv_stst, umat=mtxtb_stst, vmat=tb_mat.T)[:NV] auxstrg = cdatstr + cntpstr dou.save_npa(wft, fstring=cdatstr + cntpstr + '__w') dou.save_npa(mtxtb_stst, fstring=cdatstr + cntpstr + '__mtxtb') feedbackthroughdict = { None: dict(w=auxstrg + '__w', mtxtb=auxstrg + '__mtxtb') } cns = 0 soldict.update(data_prfx=data_prfx + '_cns{0}'.format(cns)) if linearized_nse: soldict.update(vel_pcrd_stps=0, vel_nwtn_stps=1, lin_vel_point={None: lin_point}) dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, static_feedback=True, tb_mat=tb_mat, stokes_flow=stokes_flow, clearprvveldata=True, feedbackthroughdict=feedbackthroughdict, **soldict) else: # time dep closed loop cns_data_prfx = 'data/cnsvars' invd = init_nwtnstps_value_dict curnwtnsdict = invd(tmesh=tip['tmesh'], data_prfx=cns_data_prfx) # initialization: compute the forward solution if stokes_flow: dictofvels = None else: dictofvels = snu.solve_nse(return_dictofvelstrs=True, stokes_flow=stokes_flow, **soldict) # dbs.plot_vel_norms(tip['tmesh'], dictofvels) # function for the time depending parts # -- to be passed to the solver def get_tdpart(time=None, dictofvalues=None, feedback=False, V=None, invinds=None, diribcs=None, **kw): if stokes_flow: convc_mat = sps.csr_matrix((NV, NV)) rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1)) else: curvel = dou.load_npa(dictofvalues[time]) convc_mat, rhs_con, rhsv_conbc = \ snu.get_v_conv_conts(prev_v=curvel, invinds=invinds, V=V, diribcs=diribcs) return convc_mat, rhsv_conbc + rhs_con gttdprtargs = dict(dictofvalues=dictofvels, V=femp['V'], diribcs=femp['diribcs'], invinds=invinds) # old version rhs # ftilde = rhs_con + rhsv_conbc + rhsd_stbc['fv'] for cns in range(outernwtnstps): datastrdict.update(data_prfx=data_prfx + cntpstr + '_cns{0}'.format(cns)) soldict.update(data_prfx=data_prfx + cntpstr + '_cns{0}'.format(cns)) sfd = sdr.solve_flow_daeric feedbackthroughdict = \ sfd(mmat=M, amat=A, jmat=stokesmatsc['J'], bmat=b_mat, # cmat=ct_mat_reg.T, mcmat=mct_mat_reg.T, v_is_my=True, rmat=contp.alphau*u_masmat, vmat=y_masmat, rhsv=rhsd_stbc['fv'], gamma=contp.gamma, rhsp=None, tmesh=tip['tmesh'], ystarvec=contp.ystarvec, nwtn_adi_dict=tip['nwtn_adi_dict'], comprz_thresh=tip['comprz_thresh'], comprz_maxc=tip['comprz_maxc'], save_full_z=False, get_tdpart=get_tdpart, gttdprtargs=gttdprtargs, curnwtnsdict=curnwtnsdict, get_datastr=get_datastr, gtdtstrargs=datastrdict) # for t in tip['tmesh']: # feedbackthroughdict.keys(): # curw = dou.load_npa(feedbackthroughdict[t]['mtxtb']) # print cns, t, np.linalg.norm(curw) cdatstr = get_datastr(time='all', meshp=N, nu=nu, Nts=None, data_prfx=data_prfx) if linearized_nse: dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, tb_mat=tb_mat, lin_vel_point=dictofvels, feedbackthroughdict=feedbackthroughdict, vel_nwtn_stps=1, vel_pcrd_stps=0, **soldict) else: dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, tb_mat=tb_mat, stokes_flow=stokes_flow, feedbackthroughdict=feedbackthroughdict, vel_pcrd_stps=1, vel_nwtn_stps=2, **soldict) # for t in dictofvels.keys(): # curw = dou.load_npa(dictofvels[t]) # print cns, t, np.linalg.norm(curw) gttdprtargs.update(dictofvalues=dictofvels) else: # no control feedbackthroughdict = None tb_mat = None cdatstr = get_datastr(meshp=N, nu=nu, time='all', Nts=Nts, data_prfx=data_prfx) soldict.update(clearprvdata=True) dictofvels = snu.solve_nse(feedbackthroughdict=feedbackthroughdict, tb_mat=tb_mat, closed_loop=closed_loop, stokes_flow=stokes_flow, return_dictofvelstrs=True, static_feedback=stst_control, **soldict) (yscomplist, ystarlist) = dou.extract_output(dictofpaths=dictofvels, tmesh=tip['tmesh'], c_mat=c_mat, ystarvec=contp.ystarvec) save_output_json(yscomplist, tip['tmesh'].tolist(), ystar=ystarlist, fstring=cdatstr + cntpstr + '__sigout') costfunval = eval_costfunc(W=y_masmat, V=contp.gamma * y_masmat, R=None, tbmat=tb_mat, cmat=c_mat, ystar=contp.ystarvec, tmesh=tip['tmesh'], veldict=dictofvels, fbftdict=feedbackthroughdict) print 'Value of cost functional: ', costfunval costfunval = eval_costfunc(W=y_masmat, V=contp.gamma * y_masmat, R=None, tbmat=tb_mat, cmat=c_mat, ystar=contp.ystarvec, penau=False, tmesh=tip['tmesh'], veldict=dictofvels, fbftdict=feedbackthroughdict) print 'Value of cost functional not considering `u`: ', costfunval print 'dim of v :', femp['V'].dim() charlene = .15 if problemname == 'cylinderwake' else 1.0 print 'Re = charL / nu = {0}'.format(charlene / nu)
def get_sysmats(problem='drivencavity', N=10, scheme=None, ppin=None, Re=None, nu=None, bccontrol=False, mergerhs=False, onlymesh=False): """ retrieve the system matrices for stokes flow Parameters ---------- problem : {'drivencavity', 'cylinderwake'} problem class N : int mesh parameter nu : real, optional kinematic viscosity, is set to `L/Re` if `Re` is provided Re : real, optional Reynoldsnumber, is set to `L/nu` if `nu` is provided bccontrol : boolean, optional whether to consider boundary control via penalized Robin \ defaults to `False` mergerhs : boolean, optional whether to merge the actual rhs and the contribution from the \ boundary conditions into one rhs, defaults to `False` onlymesh : boolean, optional whether to only return `femp`, containing the mesh and FEM spaces, \ defaults to `False` Returns ------- femp : dict with the keys: * `V`: FEM space of the velocity * `Q`: FEM space of the pressure * `diribcs`: list of the (Dirichlet) boundary conditions * `bcinds`: indices of the boundary nodes * `bcvals`: values of the boundary nodes * `invinds`: indices of the inner nodes * `fv`: right hand side of the momentum equation * `fp`: right hand side of the continuity equation * `charlen`: characteristic length of the setup * `nu`: the kinematic viscosity * `Re`: the Reynolds number * `odcoo`: dictionary with the coordinates of the domain of \ observation * `cdcoo`: dictionary with the coordinates of the domain of \ * `ppin` : {int, None} which dof of `p` is used to pin the pressure, typically \ `-1` for internal flows, and `None` for flows with outflow control stokesmatsc : dict a dictionary of the condensed matrices: * `M`: the mass matrix of the velocity space, * `MP`: the mass matrix of the pressure space, * `A`: the stiffness matrix, * `JT`: the gradient matrix, and * `J`: the divergence matrix * `Jfull`: the uncondensed divergence matrix and, if `bccontrol=True`, the boundary control matrices that weakly \ impose `Arob*v = Brob*u`, where * `Arob`: contribution to `A` * `Brob`: input operator `if mergerhs` rhsd : dict `rhsd_vfrc` and `rhsd_stbc` merged `else` rhsd_vfrc : dict of the dirichlet and pressure fix reduced right hand sides rhsd_stbc : dict of the contributions of the boundary data to the rhs: * `fv`: contribution to momentum equation, * `fp`: contribution to continuity equation Examples -------- femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \ = get_sysmats(problem='drivencavity', N=10, nu=1e-2) """ problemdict = dict(drivencavity=drivcav_fems, cylinderwake=cyl_fems) problemfem = problemdict[problem] femp = problemfem(N, scheme=scheme, bccontrol=bccontrol) if onlymesh: return femp # setting some parameters if Re is not None: nu = femp['charlen']/Re else: Re = femp['charlen']/nu if bccontrol: cbclist = femp['contrbcssubdomains'] cbshapefuns = femp['contrbcsshapefuns'] else: cbclist, cbshapefuns = None, None stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu, cbclist=cbclist, cbshapefuns=cbshapefuns, bccontrol=bccontrol) rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'], femp['fv'], femp['fp'], t=0) # remove the freedom in the pressure if required if problem == 'cylinderwake': print('cylinderwake: pressure need not be pinned') if ppin is not None: raise UserWarning('pinning the p will give wrong results') elif ppin is None: print('pressure is not pinned - `J` may be singular for internal flow') elif ppin == -1: stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :] print('pressure pinned at last dof `-1`') else: raise NotImplementedError('Cannot pin `p` other than at `-1`') # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, femp['diribcs']) stokesmatsc.update({'Jfull': stokesmats['J']}) # pressure freedom and dirichlet reduced rhs rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ]) if bccontrol: Arob, fvrob = dts.condense_velmatsbybcs(stokesmats['amatrob'], femp['diribcs']) if np.linalg.norm(fvrob) > 1e-15: raise UserWarning('diri and control bc must not intersect') Brob = stokesmats['bmatrob'][invinds, :] stokesmatsc.update({'Brob': Brob, 'Arob': Arob}) # add the info on boundary and inner nodes bcdata = {'bcinds': bcinds, 'bcvals': bcvals, 'invinds': invinds, 'ppin': ppin} femp.update(bcdata) femp.update({'nu': nu}) femp.update({'Re': Re}) if mergerhs: rhsd = dict(fv=rhsd_vfrc['fvc']+rhsd_stbc['fv'], fp=rhsd_vfrc['fpr']+rhsd_stbc['fp']) return femp, stokesmatsc, rhsd else: return femp, stokesmatsc, rhsd_vfrc, rhsd_stbc
def get_sysmats(problem='drivencavity', N=10, scheme=None, ppin=None, Re=None, nu=None, bccontrol=False, mergerhs=False, onlymesh=False): """ retrieve the system matrices for stokes flow Parameters ---------- problem : {'drivencavity', 'cylinderwake'} problem class N : int mesh parameter nu : real, optional kinematic viscosity, is set to `L/Re` if `Re` is provided Re : real, optional Reynoldsnumber, is set to `L/nu` if `nu` is provided bccontrol : boolean, optional whether to consider boundary control via penalized Robin \ defaults to `False` mergerhs : boolean, optional whether to merge the actual rhs and the contribution from the \ boundary conditions into one rhs onlymesh : boolean, optional whether to only return `femp`, containing the mesh and FEM spaces, \ defaults to `False` Returns ------- femp : dict with the keys: * `V`: FEM space of the velocity * `Q`: FEM space of the pressure * `diribcs`: list of the (Dirichlet) boundary conditions * `bcinds`: indices of the boundary nodes * `bcvals`: values of the boundary nodes * `invinds`: indices of the inner nodes * `fv`: right hand side of the momentum equation * `fp`: right hand side of the continuity equation * `charlen`: characteristic length of the setup * `nu`: the kinematic viscosity * `Re`: the Reynolds number * `odcoo`: dictionary with the coordinates of the domain of \ observation * `cdcoo`: dictionary with the coordinates of the domain of \ * `ppin` : {int, None} which dof of `p` is used to pin the pressure, typically \ `-1` for internal flows, and `None` for flows with outflow control stokesmatsc : dict a dictionary of the condensed matrices: * `M`: the mass matrix of the velocity space, * `A`: the stiffness matrix, * `JT`: the gradient matrix, and * `J`: the divergence matrix * `Jfull`: the uncondensed divergence matrix and, if `bccontrol=True`, the boundary control matrices that weakly \ impose `Arob*v = Brob*u`, where * `Arob`: contribution to `A` * `Brob`: input operator `if mergerhs` rhsd : dict `rhsd_vfrc` and `rhsd_stbc` merged `else` rhsd_vfrc : dict of the dirichlet and pressure fix reduced right hand sides rhsd_stbc : dict of the contributions of the boundary data to the rhs: * `fv`: contribution to momentum equation, * `fp`: contribution to continuity equation Examples -------- femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \ = get_sysmats(problem='drivencavity', N=10, nu=1e-2) """ problemdict = dict(drivencavity=drivcav_fems, cylinderwake=cyl_fems) problemfem = problemdict[problem] femp = problemfem(N, scheme=scheme, bccontrol=bccontrol) if onlymesh: return femp # setting some parameters if Re is not None: nu = femp['charlen']/Re else: Re = femp['charlen']/nu if bccontrol: cbclist = femp['contrbcssubdomains'] cbshapefuns = femp['contrbcsshapefuns'] else: cbclist, cbshapefuns = None, None stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu, cbclist=cbclist, cbshapefuns=cbshapefuns, bccontrol=bccontrol) rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'], femp['fv'], femp['fp'], t=0) # remove the freedom in the pressure if required if problem == 'cylinderwake': print 'cylinderwake: pressure need not be pinned' if ppin is not None: raise UserWarning('pinning the p will give wrong results') elif ppin is None: print 'pressure is not pinned - `J` may be singular for internal flow' elif ppin == -1: stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :] print 'pressure pinned at last dof `-1`' else: raise NotImplementedError('Cannot pin `p` other than at `-1`') # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, femp['diribcs']) stokesmatsc.update({'Jfull': stokesmats['J']}) # pressure freedom and dirichlet reduced rhs rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ]) if bccontrol: Arob, fvrob = dts.condense_velmatsbybcs(stokesmats['amatrob'], femp['diribcs']) if np.linalg.norm(fvrob) > 1e-15: raise UserWarning('diri and control bc must not intersect') Brob = stokesmats['bmatrob'][invinds, :] stokesmatsc.update({'Brob': Brob, 'Arob': Arob}) # add the info on boundary and inner nodes bcdata = {'bcinds': bcinds, 'bcvals': bcvals, 'invinds': invinds, 'ppin': ppin} femp.update(bcdata) femp.update({'nu': nu}) femp.update({'Re': Re}) if mergerhs: rhsd = dict(fv=rhsd_vfrc['fvc']+rhsd_stbc['fv'], fp=rhsd_vfrc['fpr']+rhsd_stbc['fp']) return femp, stokesmatsc, rhsd else: return femp, stokesmatsc, rhsd_vfrc, rhsd_stbc
def lqgbt(problemname='drivencavity', N=10, Nts=10, nu=1e-2, plain_bt=True, savetomatfiles=False): tip = time_int_params(Nts, nu) problemdict = dict(drivencavity=dnsps.drivcav_fems, cylinderwake=dnsps.cyl_fems) problemfem = problemdict[problemname] femp = problemfem(N) data_prfx = problemname + '__' NU, NY = 3, 4 # specify in what spatial direction Bu changes. The remaining is constant if problemname == 'drivencavity': uspacedep = 0 elif problemname == 'cylinderwake': uspacedep = 1 # output ddir = 'data/' try: os.chdir(ddir) except OSError: raise Warning('need "' + ddir + '" subdir for storing the data') os.chdir('..') stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], tip['nu']) rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'], femp['fv'], femp['fp'], t=0) # remove the freedom in the pressure stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :] # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, femp['diribcs']) # pressure freedom and dirichlet reduced rhs rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ]) # add the info on boundary and inner nodes bcdata = {'bcinds': bcinds, 'bcvals': bcvals, 'invinds': invinds} femp.update(bcdata) # casting some parameters NV, DT, INVINDS = len(femp['invinds']), tip['dt'], femp['invinds'] soldict = stokesmatsc # containing A, J, JT soldict.update(femp) # adding V, Q, invinds, diribcs soldict.update(rhsd_vfrc) # adding fvc, fpr soldict.update(fv_stbc=rhsd_stbc['fv'], fp_stbc=rhsd_stbc['fp'], N=N, nu=tip['nu'], nnewtsteps=tip['nnewtsteps'], vel_nwtn_tol=tip['vel_nwtn_tol'], ddir=ddir, get_datastring=None, data_prfx=data_prfx, paraviewoutput=tip['ParaviewOutput'], vfileprfx=tip['proutdir']+'vel_', pfileprfx=tip['proutdir']+'p_') # # compute the uncontrolled steady state Stokes solution # v_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(**soldict) # # Prepare for control # contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY) # get the control and observation operators try: b_mat = dou.load_spa(ddir + contsetupstr + '__b_mat') u_masmat = dou.load_spa(ddir + contsetupstr + '__u_masmat') print 'loaded `b_mat`' except IOError: print 'computing `b_mat`...' b_mat, u_masmat = cou.get_inp_opa(cdcoo=femp['cdcoo'], V=femp['V'], NU=NU, xcomp=uspacedep) dou.save_spa(b_mat, ddir + contsetupstr + '__b_mat') dou.save_spa(u_masmat, ddir + contsetupstr + '__u_masmat') try: mc_mat = dou.load_spa(ddir + contsetupstr + '__mc_mat') y_masmat = dou.load_spa(ddir + contsetupstr + '__y_masmat') print 'loaded `c_mat`' except IOError: print 'computing `c_mat`...' mc_mat, y_masmat = cou.get_mout_opa(odcoo=femp['odcoo'], V=femp['V'], NY=NY) dou.save_spa(mc_mat, ddir + contsetupstr + '__mc_mat') dou.save_spa(y_masmat, ddir + contsetupstr + '__y_masmat') # restrict the operators to the inner nodes mc_mat = mc_mat[:, invinds][:, :] b_mat = b_mat[invinds, :][:, :] c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse') # TODO: right choice of norms for y # and necessity of regularization here # by now, we go on number save # # setup the system for the correction # (convc_mat, rhs_con, rhsv_conbc) = snu.get_v_conv_conts(prev_v=v_ss_nse, invinds=invinds, V=femp['V'], diribcs=femp['diribcs']) f_mat = - stokesmatsc['A'] - convc_mat cdatstr = snu.get_datastr_snu(time=None, meshp=N, nu=tip['nu'], Nts=None, dt=None) if savetomatfiles: import datetime import scipy.io (coors, xinds, yinds, corfunvec) = dts.get_dof_coors(femp['V'], invinds=invinds) infostr = 'These are the coefficient matrices of the linearized ' +\ 'Navier-Stokes Equations \n for the ' +\ problemname + ' to be used as \n\n' +\ ' $M \\dot v = Av + J^Tp + Bu$ and $Jv = 0$ \n\n' +\ ' the Reynoldsnumber is computed as L/nu \n' +\ ' Note that this is the reduced system for the velocity update\n' +\ ' caused by the control, i.e., no boundary conditions\n' +\ ' or inhomogeneities here. To get the actual flow, superpose \n' +\ ' the steadystate velocity solution `v_ss_nse` \n\n' +\ ' the control setup is as follows \n' +\ ' B maps into the domain of control - the first half of the colums' +\ 'actuate in x-direction, the second in y direction \n' +\ ' C measures averaged velocities in the domain of observation' +\ ' the first components are in x, the last in y-direction \n\n' +\ ' Visualization: \n\n' +\ ' `coors` -- array of (x,y) coordinates in ' +\ ' the same order as v[xinds] or v[yinds] \n' +\ ' `xinds`, `yinds` -- indices of x and y components' +\ ' of v = [vx, vy] -- note that indexing starts with 0\n' +\ ' for testing use corfunvec wich is the interpolant of\n' +\ ' f(x,y) = [x, y] on the grid \n\n' +\ 'Created in `exp_cylinder_mats.py` ' +\ '(see https://github.com/highlando/lqgbt-oseen) at\n' +\ datetime.datetime.now().strftime("%I:%M%p on %B %d, %Y") mddir = '/afs/mpi-magdeburg.mpg.de/data/csc/projects/qbdae-nse/data/' if problemname == 'cylinderwake': charlen = 0.15 # diameter of the cylinder Re = charlen/nu elif problemname == 'drivencavity': Re = nu else: Re = nu scipy.io.savemat(mddir + problemname + '__mats_N{0}_Re{1}'.format(NV, Re), dict(A=f_mat, M=stokesmatsc['M'], nu=nu, Re=Re, J=stokesmatsc['J'], B=b_mat, C=c_mat, v_ss_nse=v_ss_nse, info=infostr, contsetupstr=contsetupstr, datastr=cdatstr, coors=coors, xinds=xinds, yinds=yinds, corfunvec=corfunvec)) return
def optcon_nse(problemname='drivencavity', N=10, Nts=10, nu=1e-2, clearprvveldata=False, ini_vel_stokes=False, stst_control=False, closed_loop=True, outernwtnstps=1, t0=None, tE=None, use_ric_ini_nu=None, alphau=1e-9, gamma=1e-3, spec_tip_dict=None, nwtn_adi_dict=None, linearized_nse=False, stokes_flow=False, ystar=None): tip = time_int_params(Nts, t0=t0, tE=tE) if spec_tip_dict is not None: tip.update(spec_tip_dict) if nwtn_adi_dict is not None: tip['nwtn_adi_dict'] = nwtn_adi_dict problemdict = dict(drivencavity=dnsps.drivcav_fems, cylinderwake=dnsps.cyl_fems) problemfem = problemdict[problemname] femp = problemfem(N) # output ddir = 'data/' try: os.chdir(ddir) except OSError: raise Warning('need "' + ddir + '" subdir for storing the data') os.chdir('..') if linearized_nse and not outernwtnstps == 1: raise Warning('Linearized problem can have only one Newton step') if closed_loop: if stst_control: data_prfx = ddir + 'stst_' + problemname + '__' else: data_prfx = ddir + 'tdst_' + problemname + '__' else: data_prfx = ddir + problemname + '__' if stokes_flow: data_prfx = data_prfx + 'stokes__' # specify in what spatial direction Bu changes. The remaining is constant if problemname == 'drivencavity': uspacedep = 0 elif problemname == 'cylinderwake': uspacedep = 1 stokesmats = dts.get_stokessysmats(femp['V'], femp['Q'], nu) rhsd_vf = dts.setget_rhs(femp['V'], femp['Q'], femp['fv'], femp['fp'], t=0) # remove the freedom in the pressure stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] rhsd_vf['fp'] = rhsd_vf['fp'][:-1, :] # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, femp['diribcs']) print 'Dimension of the div matrix: ', stokesmatsc['J'].shape # pressure freedom and dirichlet reduced rhs rhsd_vfrc = dict(fpr=rhsd_vf['fp'], fvc=rhsd_vf['fv'][invinds, ]) # add the info on boundary and inner nodes bcdata = {'bcinds': bcinds, 'bcvals': bcvals, 'invinds': invinds} femp.update(bcdata) # casting some parameters NV = len(femp['invinds']) soldict = stokesmatsc # containing A, J, JT soldict.update(femp) # adding V, Q, invinds, diribcs # soldict.update(rhsd_vfrc) # adding fvc, fpr soldict.update(fv=rhsd_stbc['fv']+rhsd_vfrc['fvc'], fp=rhsd_stbc['fp']+rhsd_vfrc['fpr'], N=N, nu=nu, trange=tip['tmesh'], get_datastring=get_datastr, data_prfx=data_prfx, clearprvdata=clearprvveldata, paraviewoutput=tip['ParaviewOutput'], vfileprfx=tip['proutdir']+'vel_', pfileprfx=tip['proutdir']+'p_') # # Prepare for control # contp = ContParams(femp['odcoo'], ystar=ystar, alphau=alphau, gamma=gamma) # casting some parameters NY, NU = contp.NY, contp.NU contsetupstr = problemname + '__NV{0}NU{1}NY{2}'.format(NV, NU, NY) # get the control and observation operators try: b_mat = dou.load_spa(ddir + contsetupstr + '__b_mat') u_masmat = dou.load_spa(ddir + contsetupstr + '__u_masmat') print 'loaded `b_mat`' except IOError: print 'computing `b_mat`...' b_mat, u_masmat = cou.get_inp_opa(cdcoo=femp['cdcoo'], V=femp['V'], NU=NU, xcomp=uspacedep) dou.save_spa(b_mat, ddir + contsetupstr + '__b_mat') dou.save_spa(u_masmat, ddir + contsetupstr + '__u_masmat') try: mc_mat = dou.load_spa(ddir + contsetupstr + '__mc_mat') y_masmat = dou.load_spa(ddir + contsetupstr + '__y_masmat') print 'loaded `c_mat`' except IOError: print 'computing `c_mat`...' mc_mat, y_masmat = cou.get_mout_opa(odcoo=femp['odcoo'], V=femp['V'], NY=NY) dou.save_spa(mc_mat, ddir + contsetupstr + '__mc_mat') dou.save_spa(y_masmat, ddir + contsetupstr + '__y_masmat') # restrict the operators to the inner nodes mc_mat = mc_mat[:, invinds][:, :] b_mat = b_mat[invinds, :][:, :] # for further use: c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse') if contp.ystarx is None: c_mat = c_mat[NY:, :][:, :] # TODO: Do this right mc_mat = mc_mat[NY:, :][:, :] # TODO: Do this right y_masmat = y_masmat[:NY, :][:, :NY] # TODO: Do this right mct_mat_reg = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'], jmat=stokesmatsc['J'], rhsv=mc_mat.T, transposedprj=True) # set the weighing matrices contp.R = contp.alphau * u_masmat # # solve the differential-alg. Riccati eqn for the feedback gain X # via computing factors Z, such that X = -Z*Z.T # # at the same time we solve for the affine-linear correction w # # tilde B = BR^{-1/2} tb_mat = lau.apply_invsqrt_fromright(contp.R, b_mat, output='sparse') # tb_dense = np.array(tb_mat.todense()) trct_mat = lau.apply_invsqrt_fromright(y_masmat, mct_mat_reg, output='dense') if closed_loop: cntpstr = 'NV{3}NY{0}NU{1}alphau{2}gamma{4}'.\ format(contp.NU, contp.NY, contp.alphau, NV, contp.gamma) else: cntpstr = '' # we gonna use this quite often M, A = stokesmatsc['M'], stokesmatsc['A'] datastrdict = dict(time=None, meshp=N, nu=nu, Nts=Nts, data_prfx=data_prfx) # compute the uncontrolled steady state (Navier-)Stokes solution # as initial value if ini_vel_stokes: # compute the uncontrolled steady state Stokes solution ini_vel, newtonnorms = snu.solve_steadystate_nse(vel_nwtn_stps=0, vel_pcrd_stps=0, **soldict) soldict.update(dict(iniv=ini_vel)) else: ini_vel, newtonnorms = snu.solve_steadystate_nse(**soldict) soldict.update(dict(iniv=ini_vel)) if closed_loop: if stst_control: if stokes_flow: convc_mat = sps.csr_matrix((NV, NV)) rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1)) lin_point = None else: lin_point, newtonnorms = snu.solve_steadystate_nse(**soldict) (convc_mat, rhs_con, rhsv_conbc) = snu.get_v_conv_conts(prev_v=lin_point, invinds=invinds, V=femp['V'], diribcs=femp['diribcs']) # infinite control horizon, steady target state cdatstr = get_datastr(time=None, meshp=N, nu=nu, Nts=None, data_prfx=data_prfx) try: Z = dou.load_npa(cdatstr + cntpstr + '__Z') print 'loaded ' + cdatstr + cntpstr + '__Z' except IOError: if use_ric_ini_nu is not None: cdatstr = get_datastr(nwtn=None, time=None, meshp=N, nu=use_ric_ini_nu, Nts=None, data_prfx=data_prfx) try: zini = dou.load_npa(ddir + cdatstr + cntpstr + '__Z') print 'Initialize Newton ADI by Z from ' + cdatstr except IOError: raise Warning('No data for initialization of ' ' Newton ADI -- need ' + cdatstr + '__Z') cdatstr = get_datastr(meshp=N, nu=nu, data_prfx=data_prfx) else: zini = None parnadi = pru.proj_alg_ric_newtonadi Z = parnadi(mmat=M, amat=-A-convc_mat, jmat=stokesmatsc['J'], bmat=tb_mat, wmat=trct_mat, z0=zini, nwtn_adi_dict=tip['nwtn_adi_dict'])['zfac'] dou.save_npa(Z, fstring=cdatstr + cntpstr + '__Z') print 'saved ' + cdatstr + cntpstr + '__Z' if tip['compress_z']: Zc = pru.compress_Zsvd(Z, thresh=tip['comprz_thresh'], k=tip['comprz_maxc']) Z = Zc fvnstst = rhs_con + rhsv_conbc + rhsd_stbc['fv'] + rhsd_vfrc['fvc'] # X = -ZZ.T mtxtb_stst = -pru.get_mTzzTtb(M.T, Z, tb_mat) mtxfv_stst = -pru.get_mTzzTtb(M.T, Z, fvnstst) fl = mc_mat.T * contp.ystarvec(0) wft = lau.solve_sadpnt_smw(amat=A.T+convc_mat.T, jmat=stokesmatsc['J'], rhsv=fl+mtxfv_stst, umat=mtxtb_stst, vmat=tb_mat.T)[:NV] auxstrg = cdatstr + cntpstr dou.save_npa(wft, fstring=cdatstr + cntpstr + '__w') dou.save_npa(mtxtb_stst, fstring=cdatstr + cntpstr + '__mtxtb') feedbackthroughdict = {None: dict(w=auxstrg + '__w', mtxtb=auxstrg + '__mtxtb')} cns = 0 soldict.update(data_prfx=data_prfx+'_cns{0}'.format(cns)) if linearized_nse: soldict.update(vel_pcrd_stps=0, vel_nwtn_stps=1, lin_vel_point={None: lin_point}) dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, static_feedback=True, tb_mat=tb_mat, stokes_flow=stokes_flow, clearprvveldata=True, feedbackthroughdict=feedbackthroughdict, **soldict) else: # time dep closed loop cns_data_prfx = 'data/cnsvars' invd = init_nwtnstps_value_dict curnwtnsdict = invd(tmesh=tip['tmesh'], data_prfx=cns_data_prfx) # initialization: compute the forward solution if stokes_flow: dictofvels = None else: dictofvels = snu.solve_nse(return_dictofvelstrs=True, stokes_flow=stokes_flow, **soldict) # dbs.plot_vel_norms(tip['tmesh'], dictofvels) # function for the time depending parts # -- to be passed to the solver def get_tdpart(time=None, dictofvalues=None, feedback=False, V=None, invinds=None, diribcs=None, **kw): if stokes_flow: convc_mat = sps.csr_matrix((NV, NV)) rhs_con, rhsv_conbc = np.zeros((NV, 1)), np.zeros((NV, 1)) else: curvel = dou.load_npa(dictofvalues[time]) convc_mat, rhs_con, rhsv_conbc = \ snu.get_v_conv_conts(prev_v=curvel, invinds=invinds, V=V, diribcs=diribcs) return convc_mat, rhsv_conbc+rhs_con gttdprtargs = dict(dictofvalues=dictofvels, V=femp['V'], diribcs=femp['diribcs'], invinds=invinds) # old version rhs # ftilde = rhs_con + rhsv_conbc + rhsd_stbc['fv'] for cns in range(outernwtnstps): datastrdict.update(data_prfx=data_prfx+cntpstr+'_cns{0}'. format(cns)) soldict.update(data_prfx=data_prfx+cntpstr+'_cns{0}'. format(cns)) sfd = sdr.solve_flow_daeric feedbackthroughdict = \ sfd(mmat=M, amat=A, jmat=stokesmatsc['J'], bmat=b_mat, # cmat=ct_mat_reg.T, mcmat=mct_mat_reg.T, v_is_my=True, rmat=contp.alphau*u_masmat, vmat=y_masmat, rhsv=rhsd_stbc['fv'], gamma=contp.gamma, rhsp=None, tmesh=tip['tmesh'], ystarvec=contp.ystarvec, nwtn_adi_dict=tip['nwtn_adi_dict'], comprz_thresh=tip['comprz_thresh'], comprz_maxc=tip['comprz_maxc'], save_full_z=False, get_tdpart=get_tdpart, gttdprtargs=gttdprtargs, curnwtnsdict=curnwtnsdict, get_datastr=get_datastr, gtdtstrargs=datastrdict) # for t in tip['tmesh']: # feedbackthroughdict.keys(): # curw = dou.load_npa(feedbackthroughdict[t]['mtxtb']) # print cns, t, np.linalg.norm(curw) cdatstr = get_datastr(time='all', meshp=N, nu=nu, Nts=None, data_prfx=data_prfx) if linearized_nse: dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, tb_mat=tb_mat, lin_vel_point=dictofvels, feedbackthroughdict=feedbackthroughdict, vel_nwtn_stps=1, vel_pcrd_stps=0, **soldict) else: dictofvels = snu.\ solve_nse(return_dictofvelstrs=True, closed_loop=True, tb_mat=tb_mat, stokes_flow=stokes_flow, feedbackthroughdict=feedbackthroughdict, vel_pcrd_stps=1, vel_nwtn_stps=2, **soldict) # for t in dictofvels.keys(): # curw = dou.load_npa(dictofvels[t]) # print cns, t, np.linalg.norm(curw) gttdprtargs.update(dictofvalues=dictofvels) else: # no control feedbackthroughdict = None tb_mat = None cdatstr = get_datastr(meshp=N, nu=nu, time='all', Nts=Nts, data_prfx=data_prfx) soldict.update(clearprvdata=True) dictofvels = snu.solve_nse(feedbackthroughdict=feedbackthroughdict, tb_mat=tb_mat, closed_loop=closed_loop, stokes_flow=stokes_flow, return_dictofvelstrs=True, static_feedback=stst_control, **soldict) (yscomplist, ystarlist) = dou.extract_output(dictofpaths=dictofvels, tmesh=tip['tmesh'], c_mat=c_mat, ystarvec=contp.ystarvec) save_output_json(yscomplist, tip['tmesh'].tolist(), ystar=ystarlist, fstring=cdatstr + cntpstr + '__sigout') costfunval = eval_costfunc(W=y_masmat, V=contp.gamma*y_masmat, R=None, tbmat=tb_mat, cmat=c_mat, ystar=contp.ystarvec, tmesh=tip['tmesh'], veldict=dictofvels, fbftdict=feedbackthroughdict) print 'Value of cost functional: ', costfunval costfunval = eval_costfunc(W=y_masmat, V=contp.gamma*y_masmat, R=None, tbmat=tb_mat, cmat=c_mat, ystar=contp.ystarvec, penau=False, tmesh=tip['tmesh'], veldict=dictofvels, fbftdict=feedbackthroughdict) print 'Value of cost functional not considering `u`: ', costfunval print 'dim of v :', femp['V'].dim() charlene = .15 if problemname == 'cylinderwake' else 1.0 print 'Re = charL / nu = {0}'.format(charlene/nu)
def solve_euler_timedep(method=1, Omega=8, tE=None, Prec=None, N=40, NtsList=None, LinaTol=None, MaxIter=None, UsePreTStps=None, SaveTStps=None, SaveIniVal=None, scheme='TH', nu=0, Re=None, inikryupd=None, tolcor=False, prob=None): """system to solve du\dt + (u*D)u + grad p = fv div u = fp """ methdict = { 1: 'HalfExpEulSmaMin', 2: 'HalfExpEulInd2'} # instantiate object containing mesh, V, Q, rhs, velbcs, invinds # set nu=0 for Euler flow if prob == 'cyl': femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \ = dnsps.get_sysmats(problem='cylinderwake', N=N, Re=Re, scheme=scheme) Mc, Ac = stokesmatsc['M'], stokesmatsc['A'] MPa = stokesmatsc['MP'] BTc, Bc = stokesmatsc['JT'], stokesmatsc['J'] Ba = stokesmatsc['Jfull'] # bcinds, bcvals = femp['bcinds'], femp['bcvals'] fvbc, fpbc = rhsd_stbc['fv'], rhsd_stbc['fp'] inivdict = dict(A=Ac, J=Bc, JT=BTc, M=Mc, ppin=None, V=femp['V'], Q=femp['Q'], fv=fvbc, fp=fpbc, vel_pcrd_stps=0, vel_nwtn_stps=0, return_vp=True, diribcs=femp['diribcs'], invinds=femp['invinds']) dimredsys = Bc.shape[1] + Bc.shape[0] vp_init = snu.solve_steadystate_nse(**inivdict)[0] PrP = FempToProbParams(N, omega=Omega, femp=femp, pdof=None) PrP.Pdof = None # No p pinning for outflow flow print 'Nv, Np -- w/o boundary nodes', BTc.shape else: if Re is not None: nu = 1./Re PrP = ProbParams(N, omega=Omega, nu=nu, scheme=scheme) # get system matrices as np.arrays smts = dts.get_stokessysmats(PrP.V, PrP.Q, nu=nu) rhsvecs = dts.setget_rhs(PrP.V, PrP.Q, PrP.fv, PrP.fp) # Ma, Aa, BTa, Ba = smts['A'], smts['JT'], smts['J'] # MPa = smts['MP'] # Ma, Aa, BTa, Ba, MPa = dtn.get_sysNSmats(PrP.V, PrP.Q, nu=nu) # fv, fp = rhsvecs['fv'], rhsvecs['fp'] # fv, fp = dtn.setget_rhs(PrP.V, PrP.Q, PrP.fv, PrP.fp) print 'Nv, Np -- w/ boundary nodes', smts['BTa'].shape # condense the system by resolving the boundary values # (Mc, Ac, BTc, Bc, fvbc, fpbc, bcinds, bcvals, # invinds) = dtn.condense_sysmatsbybcs(Ma, Aa, BTa, Ba, smts.update(rhsvecs) smtsc = dts.condense_sysmatsbybcs(smts, PrP.velbcs) Mc, Ac, BTc, Bc = smtsc['Mc'], smtsc['Ac'], smtsc['BTc'], smtsc['Bc'] fvbc, fpbc = smtsc['fvbc'], smtsc['fpbc'] # invinds print 'Nv, Np -- w/o boundary nodes', BTc.shape PrP.Pdof = 0 # Thats how the smamin is constructed dimredsys = Bc.shape[0] + Bc.shape[1] # TODO: this should sol(0) vp_init = np.zeros((dimredsys, 1)) # instantiate the Time Int Parameters TsP = TimestepParams(methdict[method], N, scheme=scheme) if NtsList is not None: TsP.Ntslist = NtsList if LinaTol is not None: TsP.linatol = LinaTol if MaxIter is not None: TsP.MaxIter = MaxIter if tE is not None: TsP.tE = tE if Omega is not None: TsP.Omega = Omega if SaveTStps is not None: TsP.SaveTStps = SaveTStps if UsePreTStps is not None: TsP.UsePreTStps = UsePreTStps if SaveIniVal is not None: TsP.SaveIniVal = SaveIniVal if inikryupd is not None: TsP.inikryupd = inikryupd TsP.TolCorB = tolcor print 'Mesh parameter N = %d' % N print 'Time interval [%d,%1.2f]' % (TsP.t0, TsP.tE) print 'Omega = %d' % TsP.Omega print 'You have chosen %s for time integration' % methdict[method] print 'The tolerance for the linear solver is %e' % TsP.linatol print 'tolcor -- controlling the abs residuals -- is ', tolcor if method == 1: # Rearrange the matrices and rhs # from smamin_utils import col_columns_atend from scipy.io import loadmat if prob == 'cyl' and scheme == 'CR': if N == 0: cricell = 758 elif N == 1: cricell = 1498 elif N == 2: cricell = 2386 elif N == 3: cricell = 4843 else: raise NotImplementedError() # TODO: this is hard coded... # dptatnb = dolfin.Point(2.2, 0.2) # cricell = smt.get_cellid_nexttopoint(PrP.mesh, dptatnb) elif prob == 'cyl': raise NotImplementedError() else: cricell = None MSmeCL, ASmeCL, BSme, B2Inds, B2BoolInv, B2BI = smt.\ get_smamin_rearrangement(N, PrP, M=Mc, A=Ac, B=Bc, crinicell=cricell, addnedgeat=cricell, scheme=scheme, fullB=Ba) FvbcSme = np.vstack([fvbc[~B2BoolInv, ], fvbc[B2BoolInv, ]]) FpbcSme = fpbc # inivalue dname = 'IniValSmaMinN%s' % N try: IniV = loadmat(dname) qqpq_init = IniV['qqpq_old'] vp_init = None except IOError: qqpq_init = None # Output try: os.chdir('json') except OSError: raise Warning('need "json" subdirectory for storing the data') os.chdir('..') if TsP.ParaviewOutput: os.chdir('results/') for fname in glob.glob(TsP.method + scheme + '*'): os.remove(fname) os.chdir('..') # ## Time stepping ## # for i, CurNTs in enumerate(TsP.Ntslist): TsP.Nts = CurNTs if method == 2: tis.halfexp_euler_nseind2(Mc, MPa, Ac, BTc, Bc, fvbc, fpbc, PrP, TsP, vp_init=vp_init) elif method == 1: tis.halfexp_euler_smarminex(MSmeCL, ASmeCL, BSme, MPa, FvbcSme, FpbcSme, B2BoolInv, PrP, TsP, qqpq_init=qqpq_init, vp_init=vp_init) # Output only in first iteration! TsP.ParaviewOutput = False save_simu(TsP, PrP) return