def test_solve_proj_sadpnt_smw(self): """check the sadpnt as projection""" n = self.n # check whether it is a projection AuvInvZ = lau.solve_sadpnt_smw(amat=self.A, jmat=self.J, rhsv=self.Z, jmatT=self.Jt, umat=self.U, vmat=self.V) auvAUVinv = self.A * AuvInvZ[:n, :] - \ lau.comp_uvz_spdns(self.U, self.V, AuvInvZ[:n, :]) AuvInv2Z = lau.solve_sadpnt_smw(amat=self.A, jmat=self.J, rhsv=auvAUVinv, jmatT=self.Jt, umat=self.U, vmat=self.V) self.assertTrue(np.allclose(AuvInvZ[:n, :], AuvInv2Z[:n, :]), msg='likely to fail because of ill cond') prjz = lau.app_prj_via_sadpnt(amat=self.A, jmat=self.J, rhsv=self.Z, jmatT=self.Jt) prprjz = lau.app_prj_via_sadpnt(amat=self.A, jmat=self.J, rhsv=self.Z, jmatT=self.Jt) # check projector self.assertTrue(np.allclose(prprjz, prjz)) # onto kernel J self.assertTrue(np.linalg.norm(prjz) > 1e-8) self.assertTrue(np.linalg.norm(self.J*prjz)/np.linalg.norm(prjz) < 1e-6) # check transpose idmat = np.eye(n) prj = lau.app_prj_via_sadpnt(amat=self.A, jmat=self.J, rhsv=idmat, jmatT=self.Jt) prjT = lau.app_prj_via_sadpnt(amat=self.A, jmat=self.J, rhsv=idmat, jmatT=self.Jt, transposedprj=True) self.assertTrue(np.allclose(prj, prjT.T))
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 lqgbt(problemname='drivencavity', N=10, Re=1e2, plain_bt=False, use_ric_ini=None, t0=0.0, tE=1.0, Nts=11, NU=3, NY=3, bccontrol=True, palpha=1e-5, paraoutput=True, trunc_lqgbtcv=1e-6, nwtn_adi_dict=None, comp_freqresp=False, comp_stepresp='nonlinear', closed_loop=False, multiproc=False, perturbpara=1e-3): """Main routine for LQGBT Parameters ---------- problemname : string, optional what problem to be solved, 'cylinderwake' or 'drivencavity' N : int, optional parameter for the dimension of the space discretization Re : real, optional Reynolds number, defaults to `1e2` plain_bt : boolean, optional whether to try simple *balanced truncation*, defaults to False use_ric_ini : real, optional use the solution with this Re number as stabilizing initial guess, defaults to `None` t0, tE, Nts : real, real, int, optional starting and endpoint of the considered time interval, number of time instancses, default to `0.0, 1.0, 11` bccontrol : boolean, optional whether to apply boundary control via penalized robin conditions, defaults to `False` NU, NY : int, optional dimensions of components of in and output space (will double because there are two components), default to `3, 3` comp_freqresp : boolean, optional whether to compute and compare the frequency responses, defaults to `False` comp_stepresp : {'nonlinear', False, None} whether to compute and compare the step responses | if False -> no step response | if == 'nonlinear' -> compare linear reduced to nonlinear full model | else -> linear reduced versus linear full model defaults to `False` trunc_lqgbtcv : real, optional threshold at what the lqgbt characteristiv values are truncated, defaults to `1e-6` closed_loop : {'full_state_fb', 'red_output_fb', False, None} how to do the closed loop simulation: | if False -> no simulation | if == 'full_state_fb' -> full state feedback | if == 'red_output_fb' -> reduced output feedback | else -> no control is applied defaults to `False` """ typprb = 'BT' if plain_bt else 'LQG-BT' print '\n ### We solve the {0} problem for the {1} at Re={2} ###\n'.\ format(typprb, problemname, Re) if nwtn_adi_dict is not None: nap = nwtn_adi_dict else: nap = nwtn_adi_params()['nwtn_adi_dict'] # 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'], 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) femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \ = dnsps.get_sysmats(problem=problemname, N=N, Re=Re, bccontrol=bccontrol, scheme='TH') nu = femp['charlen']/Re # specify in what spatial direction Bu changes. The remaining is constant uspacedep = femp['uspacedep'] # casting some parameters invinds, NV = femp['invinds'], len(femp['invinds']) prbstr = '_bt' if plain_bt else '_lqgbt' # contsetupstr = 'NV{0}NU{1}NY{2}alphau{3}'.format(NV, NU, NY, alphau) if bccontrol: import scipy.sparse as sps contsetupstr = 'NV{0}_bcc_NY{1}'.format(NV, NY) stokesmatsc['A'] = stokesmatsc['A'] + 1./palpha*stokesmatsc['Arob'] b_mat = 1./palpha*stokesmatsc['Brob'] u_masmat = sps.eye(b_mat.shape[1], format='csr') else: contsetupstr = 'NV{0}NU{1}NY{2}'.format(NV, NU, NY) def get_fdstr(Re): return ddir + problemname + '_Re{0}_'.format(Re) + \ contsetupstr + prbstr fdstr = get_fdstr(Re) 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, data_prfx=fdstr) # # Prepare for control # # get the control and observation operators if not bccontrol: 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') b_mat = b_mat[invinds, :][:, :] # tb_mat = 1./np.sqrt(alphau) 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') c_mat = lau.apply_massinv(y_masmat, mc_mat, output='sparse') # restrict the operators to the inner nodes mc_mat = mc_mat[:, invinds][:, :] c_mat = c_mat[:, invinds][:, :] c_mat_reg = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'], jmat=stokesmatsc['J'], rhsv=c_mat.T, transposedprj=True).T # c_mat_reg = np.array(c_mat.todense()) # 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 # # # compute the uncontrolled steady state Stokes solution # v_ss_nse, list_norm_nwtnupd = snu.solve_steadystate_nse(**soldict) (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 mmat = stokesmatsc['M'] # ssv_rhs = rhsv_conbc + rhsv_conbc + rhsd_vfrc['fvc'] + rhsd_stbc['fv'] if plain_bt: get_gramians = pru.solve_proj_lyap_stein else: get_gramians = pru.proj_alg_ric_newtonadi truncstr = '__lqgbtcv{0}'.format(trunc_lqgbtcv) try: tl = dou.load_npa(fdstr + '__tl' + truncstr) tr = dou.load_npa(fdstr + '__tr' + truncstr) print 'loaded the left and right transformations: \n' + \ fdstr + '__tl/__tr' + truncstr except IOError: print 'computing the left and right transformations' + \ ' and saving to: \n' + fdstr + '__tl/__tr' + truncstr try: zwc = dou.load_npa(fdstr + '__zwc') zwo = dou.load_npa(fdstr + '__zwo') print 'loaded factor of the Gramians: \n\t' + \ fdstr + '__zwc/__zwo' except IOError: zinic, zinio = None, None if use_ric_ini is not None: fdstr = get_fdstr(use_ric_ini) try: zinic = dou.load_npa(fdstr + '__zwc') zinio = dou.load_npa(fdstr + '__zwo') print 'Initialize Newton ADI by zwc/zwo from ' + fdstr except IOError: raise UserWarning('No initial guess with Re={0}'. format(use_ric_ini)) fdstr = get_fdstr(Re) print 'computing factors of Gramians: \n\t' + \ fdstr + '__zwc/__zwo' def compobsg(): try: zwo = dou.load_npa(fdstr + '__zwo') print 'at least __zwo is there' except IOError: zwo = get_gramians(mmat=mmat.T, amat=f_mat.T, jmat=stokesmatsc['J'], bmat=c_mat_reg.T, wmat=b_mat, nwtn_adi_dict=nap, z0=zinio)['zfac'] dou.save_npa(zwo, fdstr + '__zwo') def compcong(): try: zwc = dou.load_npa(fdstr + '__zwc') print 'at least __zwc is there' except IOError: zwc = get_gramians(mmat=mmat, amat=f_mat, jmat=stokesmatsc['J'], bmat=b_mat, wmat=c_mat_reg.T, nwtn_adi_dict=nap, z0=zinic)['zfac'] dou.save_npa(zwc, fdstr + '__zwc') if multiproc: print '\n ### multithread start - ' +\ 'output might be intermangled' p1 = multiprocessing.Process(target=compobsg) p2 = multiprocessing.Process(target=compcong) p1.start() p2.start() p1.join() p2.join() print '### multithread end' else: compobsg() compcong() zwc = dou.load_npa(fdstr + '__zwc') zwo = dou.load_npa(fdstr + '__zwo') print 'computing the left and right transformations' + \ ' and saving to:\n' + fdstr + '__tr/__tl' + truncstr tl, tr = btu.\ compute_lrbt_transfos(zfc=zwc, zfo=zwo, mmat=stokesmatsc['M'], trunck={'threshh': trunc_lqgbtcv}) dou.save_npa(tl, fdstr + '__tl' + truncstr) dou.save_npa(tr, fdstr + '__tr' + truncstr) print 'NV = {0}, NP = {2}, k = {1}'.\ format(tl.shape[0], tl.shape[1], stokesmatsc['J'].shape[0]) if comp_freqresp: btu.compare_freqresp(mmat=stokesmatsc['M'], amat=f_mat, jmat=stokesmatsc['J'], bmat=b_mat, cmat=c_mat, tr=tr, tl=tl, plot=True, datastr=fdstr + '__tl' + truncstr) if comp_stepresp is not False: if comp_stepresp == 'nonlinear': stp_rsp_nwtn = 3 stp_rsp_dtpr = 'nonl_stepresp_' else: stp_rsp_nwtn = 1 stp_rsp_dtpr = 'stepresp_' def fullstepresp_lnse(bcol=None, trange=None, ini_vel=None, cmat=None, soldict=None): soldict.update(fv_stbc=rhsd_stbc['fv']+bcol, vel_nwtn_stps=stp_rsp_nwtn, trange=trange, iniv=ini_vel, lin_vel_point=ini_vel, clearprvdata=True, data_prfx=stp_rsp_dtpr, return_dictofvelstrs=True) dictofvelstrs = snu.solve_nse(**soldict) return cou.extract_output(strdict=dictofvelstrs, tmesh=trange, c_mat=cmat, load_data=dou.load_npa) # differences in the initial vector # print np.dot(c_mat_reg, v_ss_nse) # print np.dot(np.dot(c_mat_reg, tr), # np.dot(tl.T, stokesmatsc['M']*v_ss_nse)) jsonstr = fdstr + stp_rsp_dtpr + '_Nred{0}_t0tENts{1}{2}{3}.json'.\ format(tl.shape[1], t0, tE, Nts) btu.compare_stepresp(tmesh=np.linspace(t0, tE, Nts), a_mat=f_mat, c_mat=c_mat_reg, b_mat=b_mat, m_mat=stokesmatsc['M'], tr=tr, tl=tl, iniv=v_ss_nse, # ss_rhs=ssv_rhs, fullresp=fullstepresp_lnse, fsr_soldict=soldict, plot=True, jsonstr=jsonstr) # compute the regulated system trange = np.linspace(t0, tE, Nts) if closed_loop is False: return elif closed_loop == 'full_state_fb': zwc = dou.load_npa(fdstr + '__zwc') zwo = dou.load_npa(fdstr + '__zwo') mtxtb = pru.get_mTzzTtb(stokesmatsc['M'].T, zwc, b_mat) def fv_tmdp_fullstatefb(time=None, curvel=None, linv=None, tb_mat=None, tbxm_mat=None, **kw): """realizes a full state static feedback as a function that can be passed to a solution routine for the unsteady Navier-Stokes equations Parameters ---------- time : real current time curvel : (N,1) nparray current velocity linv : (N,1) nparray linearization point for the linear model tb_mat : (N,K) nparray input matrix containing the input weighting tbxm_mat : (N,K) nparray `tb_mat * gain * mass` Returns ------- actua : (N,1) nparray current contribution to the right-hand side , : dictionary dummy `{}` for consistency """ actua = -lau.comp_uvz_spdns(tb_mat, tbxm_mat, curvel-linv) # actua = 0*curvel print '\nnorm of deviation', np.linalg.norm(curvel-linv) # print 'norm of actuation {0}'.format(np.linalg.norm(actua)) return actua, {} tmdp_fsfb_dict = dict(linv=v_ss_nse, tb_mat=b_mat, tbxm_mat=mtxtb.T) fv_tmdp = fv_tmdp_fullstatefb fv_tmdp_params = tmdp_fsfb_dict fv_tmdp_memory = None elif closed_loop == 'red_output_fb': try: xok = dou.load_npa(fdstr+truncstr+'__xok') xck = dou.load_npa(fdstr+truncstr+'__xck') ak_mat = dou.load_npa(fdstr+truncstr+'__ak_mat') ck_mat = dou.load_npa(fdstr+truncstr+'__ck_mat') bk_mat = dou.load_npa(fdstr+truncstr+'__bk_mat') except IOError: print 'couldn"t load the red system - compute it' zwc = dou.load_npa(fdstr + '__zwc') zwo = dou.load_npa(fdstr + '__zwo') ak_mat = np.dot(tl.T, f_mat*tr) ck_mat = lau.mm_dnssps(c_mat_reg, tr) bk_mat = lau.mm_dnssps(tl.T, b_mat) tltm, trtm = tl.T*stokesmatsc['M'], tr.T*stokesmatsc['M'] xok = np.dot(np.dot(tltm, zwo), np.dot(zwo.T, tltm.T)) xck = np.dot(np.dot(trtm, zwc), np.dot(zwc.T, trtm.T)) dou.save_npa(xok, fdstr+truncstr+'__xok') dou.save_npa(xck, fdstr+truncstr+'__xck') dou.save_npa(ak_mat, fdstr+truncstr+'__ak_mat') dou.save_npa(ck_mat, fdstr+truncstr+'__ck_mat') dou.save_npa(bk_mat, fdstr+truncstr+'__bk_mat') obs_bk = np.dot(xok, ck_mat.T) DT = (tE - t0)/(Nts-1) sysmatk_inv = np.linalg.inv(np.eye(ak_mat.shape[1]) - DT*(ak_mat - np.dot(np.dot(xok, ck_mat.T), ck_mat) - np.dot(bk_mat, np.dot(bk_mat.T, xck)))) def fv_tmdp_redoutpfb(time=None, curvel=None, memory=None, linvel=None, ipsysk_mat_inv=None, obs_bk=None, cts=None, b_mat=None, c_mat=None, xck=None, bk_mat=None, **kw): """realizes a reduced static output feedback as a function that can be passed to a solution routine for the unsteady Navier-Stokes equations For convinience the Parameters ---------- time : real current time curvel : (N,1) nparray current velocity. For consistency, the full state is taken as input. However, internally, we only use the observation `y = c_mat*curvel` memory : dictionary contains values from previous call, in particular the previous state estimate linvel : (N,1) nparray linearization point for the linear model ipsysk_mat_inv : (K,K) nparray inverse of the system matrix that defines the update of the state estimate obs_bk : (K,NU) nparray input matrix in the observer cts : real time step length b_mat : (N,NU) sparse matrix input matrix of the full system c_mat=None, c_mat : (NY,N) sparse matrix output matrix of the full system xck : (K,K) nparray reduced solution of the CARE bk_mat : (K,NU) nparray reduced input matrix Returns ------- actua : (N,1) nparray the current actuation memory : dictionary to be passed back in the next timestep """ xk_old = memory['xk_old'] buk = cts*np.dot(obs_bk, lau.mm_dnssps(c_mat, (curvel-linvel))) xk_old = np.dot(ipsysk_mat_inv, xk_old + buk) # cts*np.dot(obs_bk, # lau.mm_dnssps(c_mat, (curvel-linvel)))) memory['xk_old'] = xk_old actua = -lau.mm_dnssps(b_mat, np.dot(bk_mat.T, np.dot(xck, xk_old))) print '\nnorm of deviation', np.linalg.norm(curvel-linvel) print 'norm of actuation {0}'.format(np.linalg.norm(actua)) return actua, memory fv_rofb_dict = dict(cts=DT, linvel=v_ss_nse, b_mat=b_mat, c_mat=c_mat_reg, obs_bk=obs_bk, bk_mat=bk_mat, ipsysk_mat_inv=sysmatk_inv, xck=xck) fv_tmdp = fv_tmdp_redoutpfb fv_tmdp_params = fv_rofb_dict fv_tmdp_memory = dict(xk_old=np.zeros((tl.shape[1], 1))) else: fv_tmdp = None fv_tmdp_params = {} fv_tmdp_memory = {} perturbini = perturbpara*np.ones((NV, 1)) reg_pertubini = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'], jmat=stokesmatsc['J'], rhsv=perturbini) soldict.update(fv_stbc=rhsd_stbc['fv'], trange=trange, iniv=v_ss_nse + reg_pertubini, lin_vel_point=None, clearprvdata=True, data_prfx=fdstr + truncstr, fv_tmdp=fv_tmdp, comp_nonl_semexp=True, fv_tmdp_params=fv_tmdp_params, fv_tmdp_memory=fv_tmdp_memory, return_dictofvelstrs=True) outstr = truncstr + '{0}'.format(closed_loop) \ + 't0{0}tE{1}Nts{2}N{3}Re{4}'.format(t0, tE, Nts, N, Re) if paraoutput: soldict.update(paraviewoutput=True, vfileprfx='results/vel_'+outstr, pfileprfx='results/p_'+outstr) dictofvelstrs = snu.solve_nse(**soldict) yscomplist = cou.extract_output(strdict=dictofvelstrs, tmesh=trange, c_mat=c_mat, load_data=dou.load_npa) dou.save_output_json(dict(tmesh=trange.tolist(), outsig=yscomplist), fstring=fdstr + truncstr + '{0}'.format(closed_loop) + 't0{0}tE{1}Nts{2}'.format(t0, tE, Nts) + 'inipert{0}'.format(perturbpara)) dou.plot_outp_sig(tmesh=trange, outsig=yscomplist)
def set_inival(whichinival='sstokes', soldict=None, perturbpara=None, v_ss_nse=None, trange=None, tpp=None, fdstr=None, retvssnse=False): ''' compute the wanted initial value and set it in the soldict ''' if (retvssnse or whichinival == 'sstate+d') and v_ss_nse is None: ret_v_ss_nse = snu.solve_steadystate_nse(**soldict) elif v_ss_nse is not None: ret_v_ss_nse = v_ss_nse else: ret_v_ss_nse is None if whichinival == 'sstokes': print('we start with Stokes -- `perturbpara` is not considered') soldict.update(dict(iniv=None, start_ssstokes=True)) shortinivstr = 'sks' return shortinivstr, ret_v_ss_nse if (whichinival == 'sstate+d' or whichinival == 'snse+d++' or whichinival == 'sstate+du'): perturbini = perturbpara*np.ones((soldict['M'].shape[0], 1)) reg_pertubini = lau.app_prj_via_sadpnt(amat=soldict['M'], jmat=soldict['J'], rhsv=perturbini) if whichinival == 'sstate+d': soldict.update(dict(iniv=ret_v_ss_nse + reg_pertubini)) shortinivstr = 'ssd{0}'.format(perturbpara) return shortinivstr, ret_v_ss_nse if whichinival == 'sstokes++' or whichinival == 'snse+d++': lctrng = (trange[trange < tpp]).tolist() lctrng.append(tpp) stksppdtstr = fdstr + 't0{0:.1f}tE{1:.4f}'.\ format(trange[0], tpp) + whichinival try: sstokspp = dou.load_npa(stksppdtstr) print('loaded ' + stksppdtstr + ' for inival') except IOError: inivsoldict = {} inivsoldict.update(soldict) # containing A, J, JT inivsoldict['fv_tmdp'] = None # don't want control here # import ipdb; ipdb.set_trace() inivsoldict.update(trange=np.array(lctrng), comp_nonl_semexp=True, return_dictofvelstrs=True) if whichinival == 'sstokes++': print('solving for `stokespp({0})` as inival'.format(tpp)) inivsoldict.update(iniv=None, start_ssstokes=True) else: inivsoldict.update(iniv=ret_v_ss_nse+reg_pertubini) print('solving for `nse+d+pp({0})` as inival'.format(tpp)) dcvlstrs = snu.solve_nse(**inivsoldict) sstokspp = dou.load_npa(dcvlstrs[tpp]) dou.save_npa(sstokspp, stksppdtstr) soldict.update(dict(iniv=sstokspp)) shortinivstr = 'sk{0}'.format(tpp) if whichinival == 'sstokes++' \ else 'nsk{0}'.format(tpp) return shortinivstr, ret_v_ss_nse
full_upd_norm_check=False, check_lyap_res=False) nwtn_pyadi_dict = dict(verbose=True, maxit=45, aditol=1e-8, nwtn_res2_tol=4e-8, linesearch=True) femp, stokesmatsc, rhsd_vfrc, rhsd_stbc \ = dnsps.get_sysmats(problem=problemname, N=N, Re=Re, bccontrol=bccontrol, scheme='TH') invinds, NV = femp['invinds'], len(femp['invinds']) stokesmatsc['A'] = stokesmatsc['A'] + 1./palpha*stokesmatsc['Arob'] b_mat = 1./palpha*stokesmatsc['Brob'] b_mat_reg = lau.app_prj_via_sadpnt(amat=stokesmatsc['M'], jmat=stokesmatsc['J'], rhsv=b_mat, transposedprj=True) contsetupstr = 'NV{0}_bcc_NY{1}_palpha{2}'.format(NV, NY, palpha) shortcontsetupstr = '{0}{1}{2}'.format(NV, NY, np.int(np.log2(palpha))) fdstr = ddir + problemname + '_Re{0}_gamma{1}_'.format(Re, gamma) + \ contsetupstr + prbstr try: mc_mat = dou.load_spa(ddir + contsetupstr + '__mc_mat') y_masmat = dou.load_spa(ddir + contsetupstr + '__y_masmat') print(('loaded `c_mat` from' + ddir + contsetupstr + '...')) except IOError: print('computing `c_mat`...') mc_mat, y_masmat = cou.get_mout_opa(odcoo=femp['odcoo'], V=femp['V'], NY=NY)
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 check_output_opa(NY, femp=None): if femp is None: # from dolfin_navier_scipy.problem_setups import cyl_fems # femp = cyl_fems(2) from dolfin_navier_scipy.problem_setups import drivcav_fems femp = drivcav_fems(20) V = femp['V'] Q = femp['Q'] odcoo = femp['odcoo'] testcase = 2 # 1,2 # testvelocities if testcase == 1: """case 1 -- not div free""" exv = dolfin.Expression(('x[1]', 'x[1]'), element=V.ufl_element()) if testcase == 2: """case 2 -- disc div free""" exv = dolfin.Expression(('1', '1'), element=V.ufl_element()) testv = dolfin.interpolate(exv, V) odcoo = femp['odcoo'] stokesmats = dts.get_stokessysmats(V, Q, nu=1) # remove the freedom in the pressure stokesmats['J'] = stokesmats['J'][:-1, :][:, :] stokesmats['JT'] = stokesmats['JT'][:, :-1][:, :] bc = dolfin.DirichletBC(V, exv, 'on_boundary') # reduce the matrices by resolving the BCs (stokesmatsc, rhsd_stbc, invinds, bcinds, bcvals) = dts.condense_sysmatsbybcs(stokesmats, [bc]) # check the C MyC, My = cou.get_mout_opa(odcoo=odcoo, V=V, NY=NY) # MyC = MyC[:, invinds][:, :] # signal space ymesh = dolfin.IntervalMesh(NY - 1, odcoo['ymin'], odcoo['ymax']) Y = dolfin.FunctionSpace(ymesh, 'CG', 1) y1 = dolfin.Function(Y) y2 = dolfin.Function(Y) # y3 = dolfin.Function(Y) # dolfin.plot(V.mesh()) ptmct = lau.app_prj_via_sadpnt(amat=stokesmats['M'], jmat=stokesmats['J'], rhsv=MyC.T, transposedprj=True) testvi = testv.vector().array() testvi0 = np.atleast_2d(testv.vector().array()).T testvi0 = lau.app_prj_via_sadpnt(amat=stokesmats['M'], jmat=stokesmats['J'], rhsv=testvi0) print "||J*v|| = {0}".format(np.linalg.norm(stokesmats['J'] * testvi)) print "||J* v_df|| = {0}".format(np.linalg.norm(stokesmats['J'] * testvi0)) # # testsignals from the test velocities testy = spsla.spsolve(My, MyC * testvi) testyv0 = spsla.spsolve(My, MyC * testvi0) # testyg = spsla.spsolve(My, MyC * (testvi.flatten() - testvi0)) testry = spsla.spsolve(My, np.dot(ptmct.T, testvi)) print "||C v_df - C_df v|| = {0}".format(np.linalg.norm(testyv0 - testry)) plt.figure(1) y1.vector().set_local(testy[:NY]) dolfin.plot(y1, title="x-comp of C*v") plt.figure(2) y2.vector().set_local(testy[NY:]) dolfin.plot(y2, title="y-comp of C*v") # y2.vector().set_local(testyv0[:NY]) # dolfin.plot(y2, title="x-comp of $C*(P_{df}v)$") # y3.vector().set_local(testyg[:NY]) # dolfin.plot(y3, title="x-comp of $C*(v - P_{df}v)$") plt.show(block=False)