def create_pcd_problem(F, bcs, J, J_pc, w, nu, boundary_markers, pcd_variant): W = w.function_space() # Artificial BC for PCD preconditioner if pcd_variant == "BRM1": bc_pcd = DirichletBC(W.sub(1), 0.0, boundary_markers, 1) elif pcd_variant == "BRM2": bc_pcd = DirichletBC(W.sub(1), 0.0, boundary_markers, 2) # Arguments and coefficients of the form u, p = TrialFunctions(W) v, q = TestFunctions(W) # FIXME: Which split is correct? Both work but one might use # restrict_as_ufc_function u_, p_ = split(w) #u_, p_ = w.split() # PCD operators mp = Constant(1.0/nu)*p*q*dx kp = Constant(1.0/nu)*dot(grad(p), u_)*q*dx ap = inner(grad(p), grad(q))*dx if pcd_variant == "BRM2": n = FacetNormal(W.mesh()) ds = Measure("ds", subdomain_data=boundary_markers) kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(1) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? # Collect forms in PCD assembler pcd_assembler = PCDAssembler(J, F, bcs, J_pc, ap=ap, kp=kp, mp=mp, bcs_pcd=bc_pcd) # Create nonlinear problem problem = PCDNonlinearProblem(pcd_assembler) return problem
def setup(self): # Set up nonlinear CH solver based on provided linear solver factory = PETScFactory.instance() solver_ch = NewtonSolver(self.comm(), self.data["solver"]["CH"]["lin"], factory) solver_ch.parameters['absolute_tolerance'] = 1E-8 solver_ch.parameters['relative_tolerance'] = 1E-16 solver_ch.parameters['maximum_iterations'] = 25 #solver_ch.parameters['relaxation_parameter'] = 1.0 #solver_ch.parameters['error_on_nonconvergence'] = False #solver_ch.parameters['convergence_criterion'] = 'incremental' assert solver_ch.parameters["linear_solver"] == "user_defined" assert solver_ch.parameters["preconditioner"] == "user_defined" assert "nln" not in self.data["solver"]["CH"] self.data["solver"]["CH"]["nln"] = solver_ch # Set up NS solver if hasattr(self.data["solver"]["NS"], "ksp"): ksp = getattr(self.data["solver"]["NS"], "ksp")() if isinstance(ksp, PCDKSP): forms = self.data["forms"] bcs_ns = self.data["bcs_ns"] bc_pcd = self.data["model"].bcs()["pcd"] self.data["pcd_assembler"] = PCDAssembler( forms["lin"]["lhs"], # A forms["lin"]["rhs"], # b bcs_ns, # bcs forms["pcd"]["a_pc"], # P gp=forms["pcd"]["gp"], # B^T ap=forms["pcd"]["ap"], kp=forms["pcd"]["kp"], mp=forms["pcd"]["mp"], mu=forms["pcd"]["mu"], bcs_pcd=bc_pcd) self.data["pcd_assembler"].get_pcd_form("mp").constant = False self.data["pcd_assembler"].get_pcd_form("mu").constant = False #self.data["pcd_assembler"].get_pcd_form("gp").phantom = False self._flags["init_pcd_called"] = False else: info("") info("'LUSolver' will be applied to the Navier-Stokes subproblem.") info("")
#a, L = lhs(F), rhs(F) f = Constant((0.0,0.0,0.0)) L = inner(f,v)*dx # PCD operators mp = Constant(1.0/nu)*p*q*dx kp = Constant(1.0/nu)*dot(grad(p), u_)*q*dx ap = inner(grad(p), grad(q))*dx if args.pcd_variant == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=boundary_markers) kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(1) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? #SystemAssembler(F, L, [bc0, bc1]) # Collect forms to define nonlinear problem pcd_assembler = PCDAssembler(F, L, [bc0, bc1], ap=ap, kp=kp, mp=mp, bcs_pcd=bc_pcd) problem = PCDNonlinearProblem(pcd_assembler) #problem = PCDLinearProblem(pcd_assembler) # Set up linear solver (GMRES with right preconditioning using Schur fact) linear_solver = PCDKrylovSolver(comm=mesh.mpi_comm()) linear_solver.parameters["relative_tolerance"] = 1e-10 PETScOptions.set("ksp_monitor") PETScOptions.set("ksp_gmres_restart", 150) # Set up subsolvers PETScOptions.set("fieldsplit_p_pc_python_type", "fenapack.PCDPC_" + args.pcd_variant) PETScOptions.set("fieldsplit_u_ksp_type", "richardson") PETScOptions.set("fieldsplit_u_ksp_max_it", 1) PETScOptions.set("fieldsplit_u_pc_type", "hypre")
J_pc = J + delta*inner(dot(grad(u), u_), dot(grad(v), u_))*dx elif args.ls == "direct": J_pc = None # PCD operators mp = Constant(1.0/nu)*p*q*dx kp = Constant(1.0/nu)*dot(grad(p), u_)*q*dx ap = inner(grad(p), grad(q))*dx if args.pcd_variant == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=boundary_markers) kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(1) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? # Collect forms to define nonlinear problem pcd_assembler = PCDAssembler(J, F, [bc0, bc1], J_pc, ap=ap, kp=kp, mp=mp, bcs_pcd=bc_pcd) problem = PCDNonlinearProblem(pcd_assembler) # Set up linear solver (GMRES with right preconditioning using Schur fact) linear_solver = PCDKrylovSolver(comm=mesh.mpi_comm()) linear_solver.parameters["relative_tolerance"] = 1e-6 PETScOptions.set("ksp_monitor") PETScOptions.set("ksp_gmres_restart", 150) # Set up subsolvers PETScOptions.set("fieldsplit_p_pc_python_type", "fenapack.PCDPC_" + args.pcd_variant) if args.ls == "iterative": PETScOptions.set("fieldsplit_u_ksp_type", "richardson") PETScOptions.set("fieldsplit_u_ksp_max_it", 1) PETScOptions.set("fieldsplit_u_pc_type", "hypre") PETScOptions.set("fieldsplit_u_pc_hypre_type", "boomeramg")
def residual(self, z, params, w): (u, p) = split(z) (v, q) = split(w) Re = params[0] mesh = z.function_space().mesh() # Variational form F = (1.0 / Re * inner(grad(u), grad(v)) * dx + inner(grad(u) * u, v) * dx - p * div(v) * dx - q * div(u) * dx) # Trial functions u_, p_ = TrialFunctions(z.function_space()) # Jacobian if self.args.nls == "picard": J = (1.0 / Re * inner(grad(u_), grad(v)) * dx + inner(grad(u_) * u, v) * dx - p_ * div(v) * dx - q * div(u_) * dx) elif self.args.nls == "newton": J = derivative(F, z) # Store for later use self._J = J # If not using PCD we are done if self.args.pcd == "none": return F if self.args.pcdls == "iterative": # Add stabilization for AMG 00-block iRe = Expression("1./Re", Re=Re, degree=0, mpi_comm=mesh.mpi_comm()) delta = StabilizationParameterSD(z.sub(0), iRe) J_pc = J + delta * inner(grad(u_) * u, grad(v) * u) * dx J_pc = None else: J_pc = None # Fetch problem BCs and facet markers bcs = self.boundary_conditions(z.function_space(), self.parameters()) colours = self._colours # PCD operators mp = Re * p_ * q * dx kp = Re * dot(grad(p_), u) * q * dx ap = inner(grad(p_), grad(q)) * dx if self.args.pcd == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=colours) kp -= Re * dot(u, n) * p_ * q * ds(1) #kp -= Re*dot(u, n)*p_*q*ds(0) # TODO: Is this beneficial? # Artificial BC for PCD preconditioner if self.args.pcd == "BRM1": bc_pcd = DirichletBC(z.function_space().sub(1), 0.0, colours, 1) elif self.args.pcd == "BRM2": bc_pcd = DirichletBC(z.function_space().sub(1), 0.0, colours, 2) # Store what needed for later self._pcd_assembler = PCDAssembler(J, F, bcs, J_pc, ap=ap, kp=kp, mp=mp, bcs_pcd=bc_pcd) return F
def NS_leray_localSensitivity(comm, meshPath, boundaryMeshPath,dt, NT, rho, vis, indicatorOption, deconOrder, filterOn, sensitivityOn, chi): file_handler_press = XDMFFile(comm,'output/press_NS_BDF2_pcd.xdmf') file_handler_vel = XDMFFile(comm,'output/vel_NS_BDF2_pcd.xdmf') csvDir = "csv/NS_BDF2_PCD/" liftFile =csvDir + "lift_simu_semiImplicitBDF2_pcd.csv" dragFile =csvDir + "drag_simu_semiImplicitBDF2_pcd.csv" pressDiffFile =csvDir + "pressDiff_simu_semiImplicitBDF2_pcd.csv" file_handler_indicator = XDMFFile(comm,'output/indicator_'+indicatorOption+'_N'+str(deconOrder)+'.xdmf') if filterOn: file_handler_vel_leray = XDMFFile(comm,'output/vel_leray_BDF2_pcd.xdmf') file_handler_press_leray = XDMFFile(comm,'output/press_leray_BDF2_pcd.xdmf') file_handler_vel_relax = XDMFFile(comm,'output/vel_relax_BDF2_pcd.xdmf') file_handler_press_relax = XDMFFile(comm,'output/press_relax_BDF2_pcd.xdmf') if sensitivityOn: file_handler_vel_delta = XDMFFile(comm,'output/vel_delta_BDF2_pcd.xdmf') file_handler_press_delta = XDMFFile(comm,'output/press_delta_BDF2_pcd.xdmf') file_handler_vel_leray_delta = XDMFFile(comm,'output/vel_leray_delta_BDF2_pcd.xdmf') file_handler_press_leray_delta = XDMFFile(comm,'output/press_leray_delta_BDF2_pcd.xdmf') file_indicator_delta = XDMFFile(MPI.comm_world,'output/Indicator_delta.xdmf') ## Mesh=============================================================== ## read mesh file----------------------------------------------------- mesh = Mesh(comm) with XDMFFile(comm, meshPath) as xdmf: xdmf.read(mesh) boundaries = MeshFunction('size_t', mesh, mesh.topology().dim()-1) with XDMFFile(comm, boundaryMeshPath) as xdmf: xdmf.read(boundaries) ## create toy mesh inside for debugging purpose------------------------- # nx=100 # ny=50 # mesh = RectangleMesh(Point(0.0, 0.0), Point(10., 1.0), nx, ny,"right") # boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1) # boundaries.set_all(0) # Top = CompiledSubDomain("x[1]==side && on_boundary",side=1.) # Top.mark(boundaries,1) # Bottom = CompiledSubDomain("x[1]==side && on_boundary",side=0.) # Bottom.mark(boundaries,2) # Left = CompiledSubDomain("x[0]==side && on_boundary",side=0.) # Left.mark(boundaries,3) # Right = CompiledSubDomain("x[0]==side && on_boundary",side=10.) # Right.mark(boundaries,4) ## define measure based on mesh--------------------------------------- info("hmin= %e, hmax = %e" % (mesh.hmin() , mesh.hmax())) dx = Measure('dx',domain=mesh) ds = Measure('ds',domain=mesh, subdomain_data=boundaries) ## Basis and function space============================================ Dim = mesh.topology().dim() Vel = VectorElement("Lagrange", mesh.ufl_cell(), 2) #P2 P = FiniteElement("Lagrange", mesh.ufl_cell(), 1) #P1 element = MixedElement([Vel, P]) M_ns = FunctionSpace(mesh, element) dm_ns = TrialFunction(M_ns) ddm_ns= TestFunction(M_ns) # tuple Trial Function of velocity and pressure = split(m) (du,dp) = split(dm_ns) # tuple Test Function of velocity and pressure = split(dm) (ddv,ddp) = split(ddm_ns) m_ns = Function(M_ns) # Define the Zero initial condition m0_ns = Function(M_ns) # for second order time discretization m00_ns =Function (M_ns) m_relax = Function(M_ns) ##end of step velocities m0_relax = Function(M_ns) m00_relax = Function(M_ns) ## Define Leray Problem now for filtering =============================== # pdb.set_trace() # delta = 0.1 delta = mesh.hmin() ## filter radius # if filterOn: M_leray = FunctionSpace(mesh,element) # Trial and test function for leray dm_leray = TrialFunction(M_leray) ddm_leray = TestFunction(M_leray) # tuple Trial Function of velocity and pressure = split(m) (dv_leray,dp_leray) = split(dm_leray) # tuple Test Function of velocity and pressure =split(dm) (ddv_leray,ddp_leray) = split(ddm_leray) m_l = Function(M_leray) m0_l = Function(M_leray) # if sensitivityOn: m_ns_delta = Function(M_ns) m0_ns_delta = Function(M_ns) m00_ns_delta = Function(M_ns) m_leray_delta = Function(M_leray) m0_leray_delta = Function(M_leray) m00_leray_delta = Function(M_leray) # initizalize numpy array for lift and drag lift_array = np.empty((0,2),float) drag_array = np.empty((0,2),float) pDiff_array = np.empty((0,2),float) # Strain Rate D = lambda v : (grad(v).T + grad(v)) / 2 # Spin tensor Spin = lambda v: (grad(v) - grad(v).T)/2 ## Boundary conditions=============================================== t = 0.0 inflow_profile = Expression(('4*Um*(x[1]*(ymax-x[1]))*sin(pi*t/8.0)/(ymax*ymax)', '0'), ymax=0.41,Um = 1.5, t = t, degree=2) bcs = [DirichletBC(M_ns.sub(0), inflow_profile , boundaries, 5 )] bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 2 )) bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 4 )) bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 6 )) bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 7 )) bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 8 )) bcs.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 9 )) # if filterOn: bcs_l = [DirichletBC(M_leray.sub(0), inflow_profile , boundaries, 5 )] bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 2 )) bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 4 )) bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 6 )) bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 7 )) bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 8 )) bcs_l.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 9 )) # if sensitivityOn: bcs_delta = [DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 5 )] bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 2 )) bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 4 )) bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 6 )) bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 7 )) bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 8 )) bcs_delta.append(DirichletBC(M_ns.sub(0),Constant(tuple([0.] * Dim)),boundaries, 9 )) bcs_l_delta = [DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 5 )] bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 2 )) bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 4 )) bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 6 )) bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 7 )) bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 8 )) bcs_l_delta.append(DirichletBC(M_leray.sub(0),Constant(tuple([0.] * Dim)),boundaries, 9 )) ## Weak forms===================================================================================== def NSsemiImplicit_BDF2(m0_ns,m00_ns,m0_relax,m00_relax,dt): v0, _ = split(m0_ns) v00,_ = split(m00_ns) ## time discretization is computed from previous NS velocities vEnd0,_ = split(m0_relax) vEnd00,_= split(m00_relax) v_star= 2*vEnd0 - vEnd00 ##convection filed is computed from previous end-of-step velocities # Residual form a_00 = + 1.5/dt * inner( ddv, rho * du ) * dx \ + inner( ddv , rho * grad(du) * v_star) * dx \ + inner( D(ddv) , vis * 2*D(du) ) * dx a_01 = - inner( div(ddv) , dp ) * dx a_10 = + inner( ddp , div(du) ) * dx L = + 2. /dt * inner( ddv, rho * v0 ) * dx \ - 0.5/dt * inner( ddv, rho * v00) * dx f = a_00 + a_01 + a_10 - L # PCD forms - need elaboration! mu = 1.5/dt * inner( ddv, rho * du ) * dx ap = inner(grad(ddp), grad(dp)) * dx mp = 1./vis * ddp * dp * dx kp = rho/vis * ddp * dot(grad(dp), v_star) * dx gp = a_01 return f, mu, ap, mp, kp, gp def lerayFilter(m_ns, indicator): u_ns, _ = split(m_ns) leray_00 = + inner(D(ddv_leray) , (delta**2)*indicator*2*D(dv_leray))*dx \ + inner(ddv_leray , dv_leray )*dx leray_01 = - inner(div(ddv_leray), dp_leray )*dx leray_10 = + inner(ddp_leray , div(dv_leray) )*dx leray_rhs = + inner(ddv_leray ,u_ns)*dx f_leray = leray_00 + leray_01 + leray_10 - leray_rhs mu_leray = inner(ddv_leray, dv_leray)*dx ap_leray = inner(grad(ddp_leray), grad(dp_leray)) * dx mp_leray = 1./((delta**2)*indicator) * ddp * dp * dx kp_leray = rho/((delta**2)*indicator)* ddp * dot(grad(dp), u_ns) * dx gp_leray = leray_01 return f_leray, mu_leray, ap_leray, mp_leray, kp_leray, gp_leray def localSensitivityDelta_NS(m_ns, m0_relax, m00_relax, m0_ns_delta, m00_ns_delta, m0_leray_delta, m00_leray_delta, dt): ## same functionSpace used for sensitivity as forward NS ## TODO: reuse the matrix from NS, only change assemble the L(rhs) v_ns,_ = split(m_ns) v0, _ = split(m0_relax) ## end-of-step velocity v00, _ = split(m00_relax) v_star = 2 * v0 - v00 # pdb.set_trace() v0_delta, _ = split(m0_ns_delta) # deepcopy. v00_delta, _ = split(m00_ns_delta) # vf_star = 2 * v0_delta - v00_delta vf0_delta, _ = split(m0_leray_delta) # deepcopy. vf00_delta, _ = split(m00_leray_delta) vf_delta_star = 2 * vf0_delta - vf00_delta # Residual form ## need to double check the convection term a_00 = + 1.5/dt * inner( ddv, rho * du ) * dx \ + inner( ddv , rho * grad(du) * v_star ) * dx \ + inner( D(ddv) , vis * 2*D(du) ) * dx a_01 = - inner( div(ddv) , dp ) * dx a_10 = + inner( ddp , div(du) ) * dx rhs_delta = + 2./dt * inner( ddv, rho * v0_delta ) * dx \ - 0.5/dt * inner( ddv, rho * v00_delta ) * dx \ - inner( ddv , rho * grad(v_ns) * vf_delta_star) * dx ## double check f_delta = a_00 + a_01 + a_10 - rhs_delta # PCD forms - need elaboration! # mu = 1.5/dt * inner( ddv, rho * du ) * dx # ap = inner(grad(ddp), grad(dp)) * dx # mp = 1./nu * ddp * dp * dx # kp = rho/nu * ddp * dot(grad(dp), v_star) * dx # gp = a_01 return f_delta # return f_delta, mu, ap, mp, kp, gp # return rhs_delta def localSensitivityDelta_leray(m_ns, m_ns_delta, indicator, indicator_delta, m_l): ## same functionSpace used for sensitivity as forward NS u, _ = split(m_ns) u_delta, _ = split(m_ns_delta) uf, _ = split(m_l) leray_00 = + inner(D(ddv_leray), (delta**2) * indicator* 2*D(dv_leray)) * dx \ + inner(ddv_leray,dv_leray)*dx leray_01 = - inner(div(ddv_leray),dp_leray)*dx leray_10 = + inner(ddp_leray, div(dv_leray))*dx rhs_leray_delta = + inner(ddv_leray,u_delta) * dx\ - inner(D(ddv_leray), 2* delta * indicator * 2*D(uf)) * dx\ - inner(D(ddv_leray), delta**2 * indicator_delta * 2*D(uf)) * dx\ - inner(D(ddv_leray), delta*2 * indicator * 2*D(uf)) * ds(3) \ - inner(D(ddv_leray), delta**2 * indicator_delta * 2*D(uf)) * ds(3) ## neumann bc (assume the NS has zero-stress on the outlet) f_leray_delta = leray_00 + leray_01 + leray_10 - rhs_leray_delta mu_leray = inner(ddv_leray,dv_leray)*dx # ap_leray = inner(grad(ddp_leray), grad(dp_leray)) * dx # mp_leray = 1./nu * ddp * dp * dx # kp_leray = rho/nu * ddp * dot(grad(dp), v_star) * dx # gp_leray = leray_01 # return rhs_leray_delta return f_leray_delta ## forms ==================================================================================== F, mu, ap, mp, kp, gp = NSsemiImplicit_BDF2(m0_ns,m00_ns,m0_relax,m00_relax,dt) a, R = lhs(F), rhs(F) v, _ = m_ns.split(True) deconvolution = deconvolution_EFR(N=deconOrder, delta=delta, velocity=v, boundaryMesh = boundaries) indicator = deconvolution.computeIndicator(option=indicatorOption) # F_leray = lerayFilter(m_ns, indicator) F_leray, mu_leray, ap_leray, mp_leray, kp_leray, gp_leray = lerayFilter(m_ns, indicator) a_leray, R_leray = lhs(F_leray), rhs(F_leray) # # if sensitivityOn: F_delta = localSensitivityDelta_NS(m_ns, m0_relax, m00_relax, m0_ns_delta, m00_ns_delta, m0_leray_delta, m00_leray_delta, dt) a_delta, R_delta = lhs(F_delta), rhs(F_delta) # v_delta,_ = m_ns_delta.split(True) # indicator_delta = deconvolution.computeIndicatorlocalSensitivity(v_delta) # F_leray_delta = localSensitivityDelta_leray(m_ns, m_ns_delta, indicator, indicator_delta, m_l) ## setup linear solver==================================================================== null_space = build_nullspace(M_ns) solver = create_pcd_solver(mesh.mpi_comm(), "BRM1", "direct") # Add another options for pcd solver if you wish prefix = solver.get_options_prefix() PETScOptions.set(prefix+"ksp_monitor") solver.set_from_options() # bc for pcd?????? bcs_pcd_ns = DirichletBC(M_ns.sub(1), 0.0, boundaries, 5) bcs_pcd_leray = DirichletBC(M_ns.sub(1), 0.0, boundaries, 5) bcs_pcd_delta = DirichletBC(M_ns.sub(1), 0.0, boundaries, 5) pcd_assembler_NS = PCDAssembler( a, R, bcs, gp=gp, ap=ap, kp=kp, mp=mp, mu=mu, bcs_pcd=bcs_pcd_ns) pcd_assembler_leray = PCDAssembler( a_leray, R_leray, bcs_l, gp=gp_leray, ap=ap_leray, kp=kp_leray, mp=mp_leray, mu=mu_leray, bcs_pcd=bcs_pcd_leray) # if sensitivityOn: pcd_assembler_NS_delta = PCDAssembler( a_delta, R_delta, bcs_delta, gp=gp, ap=ap, kp=kp, mp=mp, mu=mu, bcs_pcd=bcs_pcd_delta) ## time interation==================================================== _init_pcd_flag = False for i in range(NT): t = i*dt if MPI.rank(comm) == 0: print("time =", t,"======================================================") inflow_profile.t = t A, b = PETScMatrix(mesh.mpi_comm()), PETScVector(mesh.mpi_comm()) pcd_assembler_NS.system_matrix(A) pcd_assembler_NS.rhs_vector(b) #solve(A,m_ns.vector(),b) P = A # you have the possibility to use P != A solver.set_operators(A, P) if not _init_pcd_flag: solver.init_pcd(pcd_assembler_NS) _init_pcd_flag = True solver.solve(m_ns.vector(), b) # extract solution of NS v, p = m_ns.split(True) # deepcopy. # TODO: put parameter for do not save mesh at each time step. # write output====================================================== v.rename('vel', 'vel') p.rename('press', 'press') # TODO: put parameter for do not save mesh at each time step. file_handler_press.write(p, float(t)) file_handler_vel.write( v, float(t)) ## compute indicator function deconvolution.vel = v indicator = deconvolution.computeIndicator(option=indicatorOption) ## memory leak? file_handler_indicator.write(indicator, float(t)) if filterOn: # F_leray = lerayFilter(m_ns, indicator) A_leray, b_leray = PETScMatrix(mesh.mpi_comm()), PETScVector(mesh.mpi_comm()) pcd_assembler_leray.system_matrix(A_leray) pcd_assembler_leray.rhs_vector(b_leray) #solve(A,m_ns.vector(),b) P_leray = A_leray # you have the possibility to use P != A solver.set_operators(A_leray, P_leray) if not _init_pcd_flag: solver.init_pcd(pcd_assembler_leray) _init_pcd_flag = True solver.solve(m_l.vector(), b_leray) # solve(lhs(F_leray) == rhs(F_leray), m_l, bcs_l ) v_leray, p_leray = m_l.split(True) # deepcopy. v_leray.rename('vel_leray' , 'vel_leray') p_leray.rename('press_leray', 'press_leray') # TODO: put parameter for do not save mesh at each time step. file_handler_press_leray.write(p_leray,float(t)) file_handler_vel_leray.write(v_leray, float(t)) assignerVel = FunctionAssigner(v.function_space(), v_leray.function_space()) ## memory leak? assignerPress = FunctionAssigner(p.function_space(), p_leray.function_space()) v_tmp = Function(v.function_space()) p_tmp = Function(p.function_space()) assignerVel.assign(v_tmp, v_leray) assignerPress.assign(p_tmp, p_leray) v_relax = Function(m_relax.sub(0).function_space().collapse()) p_relax = Function(m_relax.sub(1).function_space().collapse()) v_relax.assign((1 - chi) * v + chi * v_tmp) p_relax.assign(p + 1.5 * chi * p_tmp) assign(m_relax,[v_relax, p_relax]) # assign(m_relax,[v, p]) v_relax.rename('vel_relax', 'vel_relax') p_relax.rename('press_relax', 'press_relax') file_handler_press_relax.write(p_relax,float(t)) file_handler_vel_relax.write(v_relax, float(t)) if sensitivityOn: if MPI.rank(comm) == 0: print("time =", t, " computing sensitivity======================================================") # F_delta = localSensitivityDelta_NS(m_ns, m0_relax, m00_relax, m0_ns_delta, m00_ns_delta, m0_leray_delta, m00_leray_delta, dt) # a_delta, R_delta = lhs(F_delta), rhs(F_delta) # solve(lhs(F_delta) == rhs(F_delta), m_ns_delta, bcs_delta ) A_delta, b_delta = PETScMatrix(mesh.mpi_comm()), PETScVector(mesh.mpi_comm()) pcd_assembler_NS_delta.system_matrix(A_delta) pcd_assembler_NS_delta.rhs_vector(b_delta) P_delta = A_delta # you have the possibility to use P != A solver.set_operators(A_delta, P_delta) if not _init_pcd_flag: solver.init_pcd(pcd_assembler_NS_delta) _init_pcd_flag = True solver.solve(m_ns_delta.vector(), b_delta) v_delta, p_delta = m_ns_delta.split(True) v_delta.rename('vel_delta','vel_delta') p_delta.rename('pressure_delta','pressure_delta') file_handler_press_delta.write(p_delta,float(t)) file_handler_vel_delta.write(v_delta, float(t)) if MPI.rank(comm) == 0: print("norm of v_delta =",norm(v_delta)) ##checking if the sensitivity is zero indicator_delta = deconvolution.computeIndicatorlocalSensitivity(v_delta) indicator_delta.rename('indicator_delta','indicator_delta') file_indicator_delta.write(indicator_delta,float(t)) F_leray_delta = localSensitivityDelta_leray(m_ns, m_ns_delta, indicator, indicator_delta, m_l) solve(lhs(F_leray_delta) == rhs(F_leray_delta), m_leray_delta, bcs_l_delta) vf_delta, pf_delta = m_leray_delta.split(True) vf_delta.rename('vel_leray_delta','vel_leray_delta') pf_delta.rename('pressure_leray_delta','pressure_leray_delta') file_handler_press_leray_delta.write(pf_delta,float(t)) file_handler_vel_leray_delta.write(vf_delta, float(t)) ## finalize the timestep if filterOn: m00_ns.assign(m0_ns) m0_ns.assign(m_ns) m00_relax.assign(m0_relax) m0_relax.assign(m_relax) if sensitivityOn: m00_ns_delta.assign(m0_ns_delta) m0_ns_delta.assign(m_ns_delta) m00_leray_delta.assign(m0_leray_delta) m0_leray_delta.assign(m_leray_delta) # lift, drag, p_diff = computeDragLift( mesh, ds, v, p, vis) else: m00_ns.assign(m0_ns) m0_ns.assign(m_ns) m00_relax.assign(m0_ns) m0_relax.assign(m_ns) # lift, drag, p_diff = computeDragLift( mesh, ds, v, p, vis) del assignerVel, assignerPress
J_pc = None # PCD operators mu = idt*inner(u, v)*dx mp = Constant(1.0/nu)*p*q*dx kp = Constant(1.0/nu)*dot(grad(p), u_)*q*dx ap = inner(grad(p), grad(q))*dx if args.pcd_variant == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=boundary_markers) # TODO: What about the reaction term? Does it appear here? kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(1) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? # Collect forms to define nonlinear problem pcd_assembler = PCDAssembler(J, F, [bc0, bc1], J_pc, ap=ap, kp=kp, mp=mp, mu=mu, bcs_pcd=bc_pcd) assert pcd_assembler.get_pcd_form("gp").phantom # pressure grad obtained from J problem = PCDNonlinearProblem(pcd_assembler) # Set up linear solver (GMRES with right preconditioning using Schur fact) linear_solver = PCDKrylovSolver(comm=mesh.mpi_comm()) linear_solver.parameters["relative_tolerance"] = 1e-6 #PETScOptions.set("ksp_monitor") PETScOptions.set("ksp_gmres_restart", 150) # Set up subsolvers PETScOptions.set("fieldsplit_p_pc_python_type", "fenapack.PCDRPC_" + args.pcd_variant) if args.ls == "iterative": PETScOptions.set("fieldsplit_u_ksp_type", "richardson") PETScOptions.set("fieldsplit_u_ksp_max_it", 1) PETScOptions.set("fieldsplit_u_pc_type", "hypre")
mu = idt * inner(u, v) * dx mp = Constant(1.0 / nu) * p * q * dx kp = Constant(1.0 / nu) * dot(grad(p), u_) * q * dx ap = inner(grad(p), grad(q)) * dx if args.pcd_variant == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=boundary_markers) # TODO: What about the reaction term? Does it appear here? kp -= Constant(1.0 / nu) * dot(u_, n) * p * q * ds(1) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? # Collect forms to define nonlinear problem pcd_assembler = PCDAssembler(J, F, [bc0, bc1], J_pc, ap=ap, kp=kp, mp=mp, mu=mu, bcs_pcd=bc_pcd) assert pcd_assembler.get_pcd_form( "gp").phantom # pressure grad obtained from J problem = PCDNonlinearProblem(pcd_assembler) # Set up linear solver (GMRES with right preconditioning using Schur fact) linear_solver = PCDKrylovSolver(comm=mesh.mpi_comm()) linear_solver.parameters["relative_tolerance"] = 1e-6 #PETScOptions.set("ksp_monitor") PETScOptions.set("ksp_gmres_restart", 150) # Set up subsolvers PETScOptions.set("fieldsplit_p_pc_python_type",
## setup linear solver============================================= null_space = build_nullspace(M_ns) solver = create_pcd_solver(mesh.mpi_comm(), "BRM1", "direct") # Add another options for pcd solver if you wish prefix = solver.get_options_prefix() PETScOptions.set(prefix + "ksp_monitor") solver.set_from_options() # bc for pcd?????? bcs_pcd = DirichletBC(M_ns.sub(1), 0.0, boundaries, 5) bcs_pcd_delta = DirichletBC(M_ns.sub(1), 0.0, boundaries, 5) pcd_assembler_NS = PCDAssembler(a, R, bcs, gp=gp, ap=ap, kp=kp, mp=mp, mu=mu, bcs_pcd=bcs_pcd) # if sensitivityOn: # pcd_assembler_NS_delta = PCDAssembler( # a, # R_delta, # bcs_delta, # gp=gp, # ap=ap, # kp=kp, # mp=mp, # mu=mu,
#mu = alpha(gamma)*inner(u, v)*dx mp = Constant(1.0 / nu) * p * q * dx kp = Constant(1.0 / nu) * (dot(grad(p), u_)) * q * dx ap = inner(grad(p), grad(q)) * dx if args.pcd_variant == "BRM2": n = FacetNormal(mesh) ds = Measure("ds", subdomain_data=boundary_markers) # TODO: What about the reaction term? Does it appear here? kp -= Constant(1.0 / nu) * dot(u_, n) * p * q * ds(1) + Constant( 1.0 / nu) * dot(u_, n) * p * q * ds(2) #kp -= Constant(1.0/nu)*dot(u_, n)*p*q*ds(0) # TODO: Is this beneficial? pcd_assembler = PCDAssembler(J_pc, F, [bc0, bc1, bc2, bc3, bc4], ap=ap, kp=kp, mp=mp, bcs_pcd=[bc_pcd1, bc_pcd2]) problem = PCDNonlinearProblem(pcd_assembler) linear_solver = PCDKrylovSolver(comm=mesh.mpi_comm()) linear_solver.parameters["relative_tolerance"] = 1e-6 PETScOptions.set("ksp_monitor") PETScOptions.set("ksp_gmres_restart", 150) # Set up subsolvers PETScOptions.set("fieldsplit_p_pc_python_type", "fenapack.PCDPC_" + args.pcd_variant) """ PETScOptions.set("fieldsplit_u_ksp_type", "richardson") PETScOptions.set("fieldsplit_u_ksp_max_it", 1)