def __init__(self, coarse_mesh, nref, p_coarse, p_fine): super(LaplaceEigenvalueProblem, self).__init__(coarse_mesh, nref, p_coarse, p_fine) print0("Assembling fine-mesh problem") self.dirichlet_bdry = lambda x,on_boundary: on_boundary bc = DirichletBC(self.V_fine, 0.0, self.dirichlet_bdry) u = TrialFunction(self.V_fine) v = TestFunction(self.V_fine) a = inner(grad(u), grad(v))*dx m = u*v*dx # Assemble the stiffness matrix and the mass matrix. b = v*dx # just need this to feed an argument to assemble_system assemble_system(a, b, bc, A_tensor=self.A_fine) assemble_system(m, b, bc, A_tensor=self.B_fine) # set the diagonal elements of M corresponding to boundary nodes to zero to # remove spurious eigenvalues. bc.zero(self.B_fine) print0("Assembling coarse-mesh problem") self.bc_coarse = DirichletBC(self.V_coarse, 0.0, self.dirichlet_bdry) u = TrialFunction(self.V_coarse) v = TestFunction(self.V_coarse) a = inner(grad(u), grad(v))*dx m = u*v*dx # Assemble the stiffness matrix and the mass matrix, without Dirichlet BCs. Dirichlet DOFs will be removed later. assemble(a, tensor=self.A_coarse) assemble(m, tensor=self.B_coarse)
def solveFwd(self, state, x, tol): """ Solve the possibly nonlinear forward problem: Given :math:`m`, find :math:`u` such that .. math:: \\delta_p F(u, m, p;\\hat{p}) = 0,\\quad \\forall \\hat{p}.""" if self.solver is None: self.solver = self._createLUSolver() if self.is_fwd_linear: u = dl.TrialFunction(self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, m, p) A_form = dl.lhs(res_form) b_form = dl.rhs(res_form) A, b = dl.assemble_system(A_form, b_form, bcs=self.bc) self.solver.set_operator(A) self.solver.solve(state, b) else: u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, m, p) dl.solve(res_form == 0, u, self.bc) state.zero() state.axpy(1., u.vector())
def __init__(self, a, L, u, bcs): ''' Solve a problem of this form: a u = L ''' if bcs is None: bcs = () elif not isinstance(bcs, (list, tuple)): bcs = (bcs, ) if not all(isinstance(bc, DirichletBC) for bc in bcs): raise TypeError('Parameter `bcs` must contain ' 'homogenized `DirichletBC`(\'s)') V = u.function_space() v0 = dolfin.TestFunction(V) L_dummy = dot(v0, Constant((0.0, ) * len(u))) * dx K, self._rhs_bcs = assemble_system(a, L_dummy, bcs) self._solver = dolfin.LUSolver(K, "mumps") dof_bcs = [] for bc in bcs: dof_bcs.extend(bc.get_boundary_values().keys()) self._dof_bcs = tuple(sorted(dof_bcs)) self._x = u.vector() self._L = L
def __init__(self, adjoint_a, L, z, bcs): ''' Solve a problem of this form: adjoint_a z = L Note, "adjoint" means that the Dirichlet boundary conditions are zero. ''' if bcs is None: bcs = () elif not isinstance(bcs, (list, tuple)): bcs = (bcs, ) if not all(isinstance(bc, DirichletBC) for bc in bcs): raise TypeError('Parameter `bcs` must contain ' 'homogenized `DirichletBC`(\'s)') if any(any(bc.get_boundary_values().values()) for bc in bcs): raise ValueError('Parameter `bcs` must contain ' 'homogenized `DirichletBC`(\'s)') V = z.function_space() v0 = dolfin.TestFunction(V) if adjoint_a is not None: L_dummy = dot(v0, Constant((0.0, ) * len(z))) * dx K, _ = assemble_system(adjoint_a, L_dummy, bcs) self._solver = dolfin.LUSolver(K, "mumps") dof_bcs = [] for bc in bcs: dof_bcs.extend(bc.get_boundary_values().keys()) self._dof_bcs = tuple(sorted(dof_bcs)) self._x = z.vector() self._L = L
def assemble_rhs(self, basis, coeff=None, withDirichletBC=True, withNeumannBC=True, f=None): """Assemble the discrete right-hand side.""" coeff = get_default(coeff, self.coeff) f = get_default(f, self.f) Dirichlet_boundary = self.dirichlet_boundary uD = self.uD # get FEniCS function space V = basis._fefs a = self.weak_form.bilinear_form(V, coeff) L = self.weak_form.loading_linear_form(V, f) # treat Neumann boundary if withNeumannBC and self.neumann_boundary: L += self.weak_form.neumann_linear_form(V, self.neumann_boundary, self.g) # treat Dirichlet boundary bcs = [] if withDirichletBC: bcs = self.create_dirichlet_bcs(V, self.uD, self.dirichlet_boundary) # assemble linear form if True: # activate quick hack for system assembler facet_function = self.weak_form.neumann_facet_function(self.neumann_boundary, self.g, V.mesh()) _, F = _assemble_system(a, L, bcs, facet_function) else: _, F = assemble_system(a, L, bcs) return F
def system0(n): import dolfin as df mesh = df.UnitIntervalMesh(n) V = df.FunctionSpace(mesh, 'CG', 1) u = df.TrialFunction(V) v = df.TestFunction(V) bc = df.DirichletBC(V, df.Constant(0), 'on_boundary') a = df.inner(df.grad(u), df.grad(v))*df.dx m = df.inner(u, v)*df.dx L = df.inner(df.Constant(0), v)*df.dx A, _ = df.assemble_system(a, L, bc) M, _ = df.assemble_system(m, L, bc) return A, M
def assign_initial_conditions(self, function): function_space = function.function_space() markers = self.markers() u = TrialFunction(function_space) v = TestFunction(function_space) dy = Measure("dx", domain=self.mesh(), subdomain_data=markers) # Define projection into multiverse a = inner(u, v) * dy() Ls = list() for k, model in enumerate(self.models()): ic = model.initial_conditions() # Extract initial conditions n_k = model.num_states() # Extract number of local states i_k = self.keys()[k] # Extract domain index of cell model k L_k = sum(ic[j] * v[j] * dy(i_k) for j in range(n_k + 1)) # include v and s Ls.append(L_k) L = sum(Ls) # solve(a == L, function) # really inaccurate params = df.KrylovSolver.default_parameters() params["absolute_tolerance"] = 1e-14 params["relative_tolerance"] = 1e-14 params["nonzero_initial_guess"] = True solver = df.KrylovSolver() solver.update_parameters(params) A, b = df.assemble_system(a, L) solver.set_operator(A) solver.solve(function.vector(), b)
def setLinearizationPoint(self, x, gauss_newton_approx): """ Set the values of the state and parameter for the incremental forward and adjoint solvers. """ x_fun = [vector2Function(x[i], self.Vh[i]) for i in range(3)] f_form = self.varf_handler(*x_fun) g_form = [None, None, None] for i in range(3): g_form[i] = dl.derivative(f_form, x_fun[i]) self.A, dummy = dl.assemble_system( dl.derivative(g_form[ADJOINT], x_fun[STATE]), g_form[ADJOINT], self.bc0) self.At, dummy = dl.assemble_system( dl.derivative(g_form[STATE], x_fun[ADJOINT]), g_form[STATE], self.bc0) self.C = dl.assemble(dl.derivative(g_form[ADJOINT], x_fun[PARAMETER])) [bc.zero(self.C) for bc in self.bc0] if self.solver_fwd_inc is None: self.solver_fwd_inc = self._createLUSolver() self.solver_adj_inc = self._createLUSolver() self.solver_fwd_inc.set_operator(self.A) self.solver_adj_inc.set_operator(self.At) if gauss_newton_approx: self.Wuu = None self.Wmu = None self.Wmm = None else: self.Wuu = dl.assemble(dl.derivative(g_form[STATE], x_fun[STATE])) [bc.zero(self.Wuu) for bc in self.bc0] Wuu_t = Transpose(self.Wuu) [bc.zero(Wuu_t) for bc in self.bc0] self.Wuu = Transpose(Wuu_t) self.Wmu = dl.assemble( dl.derivative(g_form[PARAMETER], x_fun[STATE])) Wmu_t = Transpose(self.Wmu) [bc.zero(Wmu_t) for bc in self.bc0] self.Wmu = Transpose(Wmu_t) self.Wmm = dl.assemble( dl.derivative(g_form[PARAMETER], x_fun[PARAMETER]))
def run_steady_state_model(function_space, kappa, forcing, boundary_conditions=None, velocity=None): """ Solve steady-state diffusion equation -grad (k* grad u) = f """ mesh = function_space.mesh() if boundary_conditions == None: bndry_obj = dl.CompiledSubDomain("on_boundary") boundary_conditions = [['dirichlet', bndry_obj, dl.Constant(0)]] num_bndrys = len(boundary_conditions) boundaries = mark_boundaries(mesh, boundary_conditions) dirichlet_bcs = collect_dirichlet_boundaries(function_space, boundary_conditions, boundaries) # To express integrals over the boundary parts using ds(i), we must first # redefine the measure ds in terms of our boundary markers: ds = dl.Measure('ds', domain=mesh, subdomain_data=boundaries) dx = dl.Measure('dx', domain=mesh) # Variational problem at each time u = dl.TrialFunction(function_space) v = dl.TestFunction(function_space) a = kappa * dl.inner(dl.grad(u), dl.grad(v)) * dx L = forcing * v * dx if velocity is not None: a += v * dl.dot(velocity, dl.grad(u)) * dx beta_1_list = [] alpha_1_list = [] for ii in range(num_bndrys): if (boundary_conditions[ii][0] == 'robin'): alpha = boundary_conditions[ii][3] a += alpha * u * v * ds(ii) if ((boundary_conditions[ii][0] == 'robin') or (boundary_conditions[ii][0] == 'neumann')): beta = boundary_conditions[ii][2] L -= beta * v * ds(ii) u = dl.Function(function_space) A, b = dl.assemble_system(a, L, dirichlet_bcs) # apply boundary conditions for bc in dirichlet_bcs: bc.apply(A, b) dl.solve(A, u.vector(), b) return u
def _get_constant_pressure(self, W): w = TrialFunction(W) w_ = TestFunction(W) p_ = self.test_functions()["p"] A, b = assemble_system(inner(w, w_) * dx, p_ * dx) null_fcn = Function(W) solver = LUSolver("mumps") solver.solve(A, null_fcn.vector(), b) return null_fcn
def setLinearizationPoint(self,x): return assert False assert self.extra_args[-1] == True """ Set the values of the state and parameter for the incremental Fwd and Adj solvers """ state_fun = vector2Function(x[STATE], self.Vh[STATE]) param_fun = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) adjoint_fun = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) x_fun = [state_fun,param_fun, adjoint_fun] x_test = [dl.TestFunction(self.Vh[STATE]), dl.TestFunction(self.Vh[PARAMETER]), dl.TestFunction(self.Vh[ADJOINT])] x_trial = [dl.TrialFunction(self.Vh[STATE]), dl.TrialFunction(self.Vh[PARAMETER]), dl.TrialFunction(self.Vh[ADJOINT])] self.extra_args[self.parameter_location] = param_fun f_form = self.model.residual(state_fun, adjoint_fun, *self.extra_args ) g_form = [None,None,None] g_form[STATE] = dl.derivative(f_form, x_fun[STATE], x_test[STATE]) g_form[PARAMETER] = dl.derivative(f_form, x_fun[PARAMETER], x_test[PARAMETER]) g_form[ADJOINT] = dl.derivative(f_form, x_fun[ADJOINT], x_test[ADJOINT]) Aform = dl.derivative(g_form[ADJOINT],state_fun, x_trial[STATE]) self.A, dummy = dl.assemble_system(Aform, g_form[ADJOINT], self.bcs0, form_compiler_parameters = self.fcp) self.C = dl.assemble(dl.derivative(g_form[ADJOINT],param_fun, x_trial[PARAMETER]),form_compiler_parameters = self.fcp ) [bc.zero(self.C) for bc in self.bcs0] self.Wum = dl.assemble(dl.derivative(g_form[STATE],param_fun, x_trial[PARAMETER]), form_compiler_parameters = self.fcp) [bc.zero(self.Wum) for bc in self.bcs0] Wuuform = dl.derivative(g_form[STATE],state_fun, x_trial[STATE]) self.Wuu, dummy = dl.assemble_system(Wuuform, g_form[STATE], self.bcs0, form_compiler_parameters = self.fcp) [bc.zero(self.Wuu) for bc in self.bcs0] self.Wmm = dl.assemble(dl.derivative(g_form[PARAMETER],param_fun, x_trial[PARAMETER]), form_compiler_parameters = self.fcp) self.Asolver.set_operator(self.A) self.extra_args[self.parameter_location] = None
def setLinearizationPoint(self,x, gauss_newton_approx): """ Set the values of the state and parameter for the incremental Fwd and Adj solvers """ u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = vector2Function(x[ADJOINT], self.Vh[ADJOINT]) x_fun = [u,a,p] f_form = self.varf_handler(u,a,p) g_form = [None,None,None] for i in range(3): g_form[i] = dl.derivative(f_form, x_fun[i]) self.A, dummy = dl.assemble_system(dl.derivative(g_form[ADJOINT],u), g_form[ADJOINT], self.bc0) self.At, dummy = dl.assemble_system(dl.derivative(g_form[STATE],p), g_form[STATE], self.bc0) self.C = dl.assemble(dl.derivative(g_form[ADJOINT],a)) [bc.zero(self.C) for bc in self.bc0] if self.solver_fwd_inc is None: self.solver_fwd_inc = self._createLUSolver() self.solver_adj_inc = self._createLUSolver() self.solver_fwd_inc.set_operator(self.A) self.solver_adj_inc.set_operator(self.At) if gauss_newton_approx: self.Wuu = None self.Wau = None self.Waa = None else: self.Wuu = dl.assemble(dl.derivative(g_form[STATE],u)) [bc.zero(self.Wuu) for bc in self.bc0] Wuu_t = Transpose(self.Wuu) [bc.zero(Wuu_t) for bc in self.bc0] self.Wuu = Transpose(Wuu_t) self.Wau = dl.assemble(dl.derivative(g_form[PARAMETER],u)) Wau_t = Transpose(self.Wau) [bc.zero(Wau_t) for bc in self.bc0] self.Wau = Transpose(Wau_t) self.Waa = dl.assemble(dl.derivative(g_form[PARAMETER],a))
def Jacobian(self, x, extra_args=()): """ Assemble the Jacobian operator at point x. extra_args is a tuple of additional arguments necessary to assemble the Jacobian """ xfun = vector2Function(x, self.Vh) Jform = self.model.Jacobian(xfun, self.x_test, self.x_trial, *extra_args) J, dummy = dl.assemble_system(Jform, self.dummyform, self.bcs0, form_compiler_parameters=self.fcp) return J
def assembleA(self,x, assemble_adjoint = False, assemble_rhs = False): """ Assemble the matrices and rhs for the forward/adjoint problems """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) Avarf = ufl.inner(ufl.exp(m)*sigma(trial), strain(test))*ufl.dx if not assemble_adjoint: bform = ufl.inner(self.f, test)*ufl.dx Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc) else: # Assemble the adjoint of A (i.e. the transpose of A) u = vector2Function(x[STATE], self.Vh[STATE]) obs = vector2Function(self.u_o, self.Vh[STATE]) bform = ufl.inner(obs - u, test)*ufl.dx Matrix, rhs = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0) if assemble_rhs: return Matrix, rhs else: return Matrix
def assemble_lhs(self, basis, coeff=None, withDirichletBC=True): """Assemble the discrete problem (i.e. the stiffness matrix).""" # get FEniCS function space V = basis._fefs coeff = get_default(coeff, self.coeff) a = self.weak_form.bilinear_form(V, coeff) L = self.weak_form.loading_linear_form(V, self.f) bcs = [] if withDirichletBC: bcs = self.create_dirichlet_bcs(V, self.uD, self.dirichlet_boundary) A, _ = assemble_system(a, L, bcs) return A
def assembleA(self,x, assemble_adjoint = False, assemble_rhs = False): """ Assemble the matrices and rhs for the forward/adjoint problems """ trial = dl.TrialFunction(self.Vh[STATE]) test = dl.TestFunction(self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) Avarf = dl.inner(dl.exp(m)*dl.grad(trial), dl.grad(test))*dl.dx if not assemble_adjoint: bform = dl.inner(self.f, test)*dl.dx Matrix, rhs = dl.assemble_system(Avarf, bform, self.bc) else: # Assemble the adjoint of A (i.e. the transpose of A) u = vector2Function(x[STATE], self.Vh[STATE]) obs = vector2Function(self.u_o, self.Vh[STATE]) bform = dl.inner(obs - u, test)*dl.dx Matrix, rhs = dl.assemble_system(dl.adjoint(Avarf), bform, self.bc0) if assemble_rhs: return Matrix, rhs else: return Matrix
def assemble(self): ## Time function execution ## timer = df.Timer("pFibs: Assemble") timer.start() if self.log_level >= 1: ## Time system assembly ## timer1 = df.Timer("pFibs: Assemble - System") ## Assembly system of equations ## df.assemble_system(self.a, self.L, self.bcs, A_tensor=self.A, b_tensor=self.b) if self.log_level >= 1: timer1.stop() if self.log_level >= 1: ## Time preconditioner assembly ## timer2 = df.Timer("pFibs: Assemble - Preconditioner") ## Assemble preconditioner if provided ## if self.aP is not None: df.assemble(self.aP, tensor=self.P) if isinstance(self.bcs, list): for bc in self.bcs: bc.apply(self.P) else: self.bcs.apply(self.P) if self.log_level >= 1: timer2.stop() # self.A.mat().zeroEntries() # self.A.mat().shift(1.0) timer.stop()
def assemble_system_fenics(self, x, bc, *, only_free_dofs=True): self.set_x(x) L = bc.neumann_boundary_condition.compile_form() K, f = df.assemble_system(self.a, L, bcs=bc.dirichlet_boundary_condition.transfer( self.V)) if not only_free_dofs: return ConvertFenicsBackendToScipyCSRSparse(K), f else: raise NotImplementedError
def harmonic_interpolation(setup, points=(), values=(), subdomains=dict(), boundaries=None): if isinstance(setup, Geometry): geo = setup phys = Physics(geo=geo) phys.update(cyl=phys.dim == 2) else: geo = setup.geo phys = setup.phys mesh = geo.mesh # Laplace equation V = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) a = dolfin.inner(dolfin.grad(u), dolfin.grad(v)) * phys.r2pi * geo.dx() L = dolfin.Constant(0.) * v * phys.r2pi * geo.dx() # Point-wise boundary condition bc = PointBC(V, points, values) bcs = [bc] # Volume boundary conditions for sub, f in subdomains.items(): bc = geo.VolumeBC(V, sub, f) bcs.append(bc) # Normal boundary conditions if boundaries is not None: bc = geo.pwBC(V, "", value=boundaries) bcs.extend(bc) # Assemble, apply bc and solve A, b = dolfin.assemble_system(a, L) for bc in bcs: bc.apply(A) bc.apply(b) u = dolfin.Function(V) dolfin.solve(A, u.vector(), b, "bicgstab", "hypre_euclid") # if phys.cyl: # dolfin.solve(A, u.vector(), b, "bicgstab", "hypre_euclid") # else: # dolfin.solve(A, u.vector(), b, "cg", "hypre_amg") return u
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear Adj Problem: Given a, u; find p such that \delta_u F(u,a,p;\hat_u) = 0 \for all \hat_u """ u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.Function(self.Vh[ADJOINT]) du = dl.TestFunction(self.Vh[STATE]) dp = dl.TrialFunction(self.Vh[ADJOINT]) varf = self.varf_handler(u,a,p) adj_form = dl.derivative( dl.derivative(varf, u, du), p, dp ) Aadj, dummy = dl.assemble_system(adj_form, dl.Constant(0.)*dl.inner(u,du)*dl.dx, self.bc0) solver = dl.PETScLUSolver() solver.set_operator(Aadj) solver.solve(adj, adj_rhs)
def Norm(self, coeffsL2=None, coeffsH1=None, apply_bc=False): """ Returns a finite element matrix for a (weighted) H^1 norm. INPUTS: - coeffsL2: weights for the L2 norm (DEFAULT: 1) - coeffsH1: weights for the H1 norm (DEFAULT: 1) - apply_bc: if True apply essential b.c. (DEFAULT: False) """ Wform = self.model.mass(self.x_trial, self.x_test, coeffsL2) \ +self.model.stiffness(self.x_trial, self.x_test, coeffsH1) if apply_bc: W, dummy = dl.assemble_system(Wform, self.dummyform, self.bcs0, form_compiler_parameters=self.fcp) else: W = dl.assemble(Wform, form_compiler_parameters=self.fcp) return W
def forward_sensitivities(self, sm, dm): assert self.extra_args[self.parameter_location] == None assert self.extra_args[self.field_location] == None assert self.extra_args[-1] == True d_state = dl.Function( self.Vh[STATE] ).vector() dd_state = dl.Function( self.Vh[STATE] ).vector() [state_fun, m_fun] = [vector2Function(sm[ii], self.Vh[ii]) for ii in range(2)] dm_fun = vector2Function(dm, self.Vh[PARAMETER]) e_mean_fun =vector2Function(self.field.e_mean, self.Vh[FIELD]) test = dl.TestFunction(self.Vh[STATE]) trial = dl.TrialFunction(self.Vh[STATE]) self.extra_args[self.parameter_location] = m_fun self.extra_args[self.field_location] = e_mean_fun res_form = self.model.residual(state_fun, test, *self.extra_args) J_form = dl.derivative(res_form, state_fun, trial) b1_form = dl.derivative(res_form, m_fun, dm_fun) J, b1 = dl.assemble_system(J_form, b1_form, bcs = self.bcs0, form_compiler_parameters = self.fcp) Jsolver = dl.PETScLUSolver() Jsolver.set_operator(J) Jsolver.solve(d_state, -b1) d_state_fun = vector2Function(d_state, self.Vh[STATE]) b2_form = dl.derivative( dl.derivative(res_form, state_fun, d_state_fun), state_fun, d_state_fun ) \ + dl.Constant(2.)*dl.derivative( dl.derivative(res_form, state_fun, d_state_fun), m_fun, dm_fun ) \ + dl.derivative( dl.derivative(res_form, m_fun, dm_fun), m_fun, dm_fun ) b2 = dl.assemble(b2_form, form_compiler_parameters=self.fcp) [bc.apply(b2) for bc in self.bcs0] Jsolver.solve(dd_state, -b2) self.extra_args[self.parameter_location] = None self.extra_args[self.field_location] = None return d_state, dd_state
def harmonic_interpolation_simple(mesh, points, values): # Laplace equation V = dolfin.FunctionSpace(mesh, "CG", 1) u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) a = dolfin.inner(dolfin.grad(u), dolfin.grad(v)) * dolfin.dx L = dolfin.Constant(0.) * v * dolfin.dx(domain=mesh) # Point-wise boundary condition bc = PointBC(V, points, values) # Assemble, apply bc and solve A, b = dolfin.assemble_system(a, L) bc.apply(A) bc.apply(b) u = dolfin.Function(V) dolfin.solve(A, u.vector(), b, "cg", "hypre_amg") return u
def solve_krylov( a, L, bcs, u: df.Function, verbose: bool = False, ksp_type="cg", ksp_norm_type="unpreconditioned", ksp_atol=1e-15, ksp_rtol=1e-10, ksp_max_it=10000, ksp_error_if_not_converged=False, pc_type="hypre", ) -> df.PETScKrylovSolver: pc_hypre_type = "boomeramg" ksp_monitor = verbose ksp_view = verbose pc_view = verbose solver = df.PETScKrylovSolver() df.PETScOptions.set("ksp_type", ksp_type) df.PETScOptions.set("ksp_norm_type", ksp_norm_type) df.PETScOptions.set("ksp_atol", ksp_atol) df.PETScOptions.set("ksp_rtol", ksp_rtol) df.PETScOptions.set("ksp_max_it", ksp_max_it) df.PETScOptions.set("ksp_error_if_not_converged", ksp_error_if_not_converged) if ksp_monitor: df.PETScOptions.set("ksp_monitor") if ksp_view: df.PETScOptions.set("ksp_view") df.PETScOptions.set("pc_type", pc_type) df.PETScOptions.set("pc_hypre_type", pc_hypre_type) if pc_view: df.PETScOptions.set("pc_view") solver.set_from_options() A, b = df.assemble_system(a, L, bcs) solver.set_operator(A) solver.solve(u.vector(), b) df.info("Sucessfully solved using Krylov solver") return solver
def assemble(self, ff, gs = [], hs = [], *, mesh = None, facets = None): if mesh is None: mesh = self.mesh space = self.getSpace(mesh) if facets is None: facets = self.facets dx = dolfin.Measure('dx', domain = mesh) ds = dolfin.ds if facets is None else dolfin.Measure('ds', domain = mesh, subdomain_data = facets) test = dolfin.TestFunction(space) trial = dolfin.TrialFunction(space) kk = dolfin.inner(self.sigma(trial), self.epsilon(test))*dx ll = dolfin.inner(ff, test)*dx for hh, domain in hs: ll += dolfin.inner(hh, test)*ds(domain) bcs = [] for gg, domain in gs: bcs.append(dolfin.DirichletBC(space, gg, facets, domain)) AA, bb = dolfin.assemble_system(kk, ll, bcs) return AA, bb
def solveAdj(self, adj, x, adj_rhs, tol): """ Solve the linear adjoint problem: Given :math:`m, u`; find :math:`p` such that .. math:: \\delta_u F(u, m, p;\\hat{u}) = 0, \\quad \\forall \\hat{u}. """ if self.solver is None: self.solver = self._createLUSolver() u = vector2Function(x[STATE], self.Vh[STATE]) m = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.Function(self.Vh[ADJOINT]) du = dl.TestFunction(self.Vh[STATE]) dp = dl.TrialFunction(self.Vh[ADJOINT]) varf = self.varf_handler(u, m, p) adj_form = dl.derivative( dl.derivative(varf, u, du), p, dp ) Aadj, dummy = dl.assemble_system(adj_form, dl.inner(u,du)*dl.dx, self.bc0) self.solver.set_operator(Aadj) self.solver.solve(adj, adj_rhs)
def linearize(self, inputs, outputs, partials): # print('linearize') residual_form = self.options['residual'](self.unfiltered_density, self.filtered_density, C=self.filter_strength) J = df.derivative(residual_form, self.filtered_density) self.A, b = df.assemble_system(J, - residual_form) self.unfiltered_density.vector().set_local(inputs['density_unfiltered']) self.filtered_density.vector().set_local(outputs['density']) dR_dstate = self.compute_derivative('dR_dstate', self.filtered_density) dR_dinput = self.compute_derivative('dR_dinput', self.unfiltered_density) self.dR_du_sparse = df.as_backend_type(self.A).mat() partials['density','density'] = dR_dstate.data partials['density','density_unfiltered'] = dR_dinput.data
def solve(self, results_file=None): if self.solver is None: logger.warning("The solver has to be set.") if self.load_integrals is not None: L_terms = [] for contrib_list in self.load_integrals.values(): L_terms += contrib_list L = sum(L_terms) else: zero = fe.Constant(np.zeros(shape=self.v.ufl_shape)) L = fe.dot(zero, self.v) * self.measures[self.part.dim] logger.info("Assembling system...") K, res = fe.assemble_system(self.a, L, self.Dirichlet_bc) logger.info("Assembling system : done") self.u_sol = fe.Function(self.displ_fspace) logger.info("Solving system...") self.solver.solve(K, self.u_sol.vector(), res) logger.info("Solving system : done") logger.info("Computing strain solution...") eps = mat.epsilon(self.u_sol) self.eps_sol = local_project(eps, self.strain_fspace, solver_method="LU") logger.info("Saving results...") if results_file is not None: try: if results_file.suffix != ".xdmf": results_file = results_file.with_suffix(".xdmf") except AttributeError: results_file = Path(results_file).with_suffix(".xdmf") with fe.XDMFFile(results_file.as_posix()) as ofile: ofile.parameters["flush_output"] = False ofile.parameters["functions_share_mesh"] = True self.u_sol.rename("displacement", "displacement solution, full scale problem") self.eps_sol.rename("strain", "strain solution, full scale problem") ofile.write(self.u_sol, 0.0) ofile.write(self.eps_sol, 0.0) return self.u_sol
def _assemble_and_solve_adj_eq(self, dFdu_form, dJdu): dJdu_copy = dJdu.copy() bcs = self._homogenize_bcs() solver = self.block_helper.adjoint_solver if solver is None: adj_sol = df.Function(self.function_space) adjoint_problem = pf.BlockProblem(dFdu_form, dJdu, adj_sol, bcs=bcs) for key, value in self.block_field.items(): adjoint_problem.field(key, value[1], solver=value[2]) for key, value in self.block_split.items(): adjoint_problem.split(key, value[0], solver=value[1]) solver = pf.LinearBlockSolver(adjoint_problem) self.block_helper.adjoint_solver = solver ############ ## Assemble ## rhs_bcs_form = df.inner(df.Function(self.function_space), dFdu_form.arguments()[0]) * df.dx A_, _ = df.assemble_system(dFdu_form, rhs_bcs_form, bcs) A = df.as_backend_type(A_) solver.linear_solver.set_operators(A, A) solver.linear_solver.init_solver_options() [bc.apply(dJdu) for bc in bcs] b = df.as_backend_type(dJdu) ## Actual solve ## its = solver.linear_solver.solve(adj_sol.vector(), b) ########### adj_sol_bdy = dfa.compat.function_from_vector( self.function_space, dJdu_copy - dfa.compat.assemble_adjoint_value(df.action(dFdu_form, adj_sol))) return adj_sol, adj_sol_bdy
def solveFwd(self, state, x, tol): """ Solve the possibly nonlinear Fwd Problem: Given a, find u such that \delta_p F(u,a,p;\hat_p) = 0 \for all \hat_p""" if self.is_fwd_linear: u = dl.TrialFunction(self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, a, p) A_form = dl.lhs(res_form) b_form = dl.rhs(res_form) A, b = dl.assemble_system(A_form, b_form, bcs=self.bc) solver = dl.PETScLUSolver() solver.set_operator(A) solver.solve(state, b) else: u = vector2Function(x[STATE], self.Vh[STATE]) a = vector2Function(x[PARAMETER], self.Vh[PARAMETER]) p = dl.TestFunction(self.Vh[ADJOINT]) res_form = self.varf_handler(u, a, p) dl.solve(res_form == 0, u, self.bc) state.zero() state.axpy(1., u.vector())
def solve(selfmat, var, b): if selfmat.adjoint: operators = transpose_operators(selfmat.operators) else: operators = selfmat.operators # Fetch/construct the solver if var.type in ['ADJ_FORWARD', 'ADJ_TLM']: solver = petsc_krylov_solvers[idx] need_to_set_operator = self._need_to_reset_operator else: if adj_petsc_krylov_solvers[idx] is None: need_to_set_operator = True adj_petsc_krylov_solvers[idx] = PETScKrylovSolver(*solver_parameters) adj_ksp = adj_petsc_krylov_solvers[idx].ksp() fwd_ksp = petsc_krylov_solvers[idx].ksp() adj_ksp.setOptionsPrefix(fwd_ksp.getOptionsPrefix()) adj_ksp.setType(fwd_ksp.getType()) adj_ksp.pc.setType(fwd_ksp.pc.getType()) adj_ksp.setFromOptions() else: need_to_set_operator = self._need_to_reset_operator solver = adj_petsc_krylov_solvers[idx] # FIXME: work around DOLFIN bug #583 try: solver.parameters.convergence_norm_type except: solver.parameters.convergence_norm_type = "preconditioned" # end FIXME solver.parameters.update(parameters) self._need_to_reset_operator = False if selfmat.adjoint: (nsp_, tnsp_) = (tnsp, nsp) else: (nsp_, tnsp_) = (nsp, tnsp) x = dolfin.Function(fn_space) if selfmat.initial_guess is not None and var.type == 'ADJ_FORWARD': x.vector()[:] = selfmat.initial_guess.vector() if b.data is None: dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: selfmat.bcs = [utils.homogenize(bc) for bc in selfmat.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in selfmat.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)] # This is really hideous. Sorry. if isinstance(b.data, dolfin.Function): rhs = b.data.vector().copy() [bc.apply(rhs) for bc in selfmat.bcs] if need_to_set_operator: if assemble_system: # if we called assemble_system, rather than assemble v = dolfin.TestFunction(fn_space) (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, selfmat.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, selfmat.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) [bc.apply(A) for bc in selfmat.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in selfmat.bcs] solver.set_operators(A, P) else: solver.set_operator(A) else: if assemble_system: # if we called assemble_system, rather than assemble (A, rhs) = dolfin.assemble_system(operators[0], b.data, selfmat.bcs) if need_to_set_operator: if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, selfmat.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) rhs = dolfin.assemble(b.data) [bc.apply(A) for bc in selfmat.bcs] [bc.apply(rhs) for bc in selfmat.bcs] if need_to_set_operator: if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in selfmat.bcs] solver.set_operators(A, P) else: solver.set_operator(A) if need_to_set_operator: print "|A|: %.6e" % A.norm("frobenius") # Set the nullspace for the linear operator if nsp_ is not None and need_to_set_operator: dolfin.as_backend_type(A).set_nullspace(nsp_) # (Possibly override the user in) orthogonalize # the right-hand-side if tnsp_ is not None: tnsp_.orthogonalize(rhs) print "%s: |b|: %.6e" % (var, rhs.norm("l2")) solver.solve(x.vector(), rhs) return adjlinalg.Vector(x)
def solve(self, var, b): if self.adjoint: operators = transpose_operators(self.operators) else: operators = self.operators # Fetch/construct the solver if var.type in ['ADJ_FORWARD', 'ADJ_TLM']: solver = krylov_solvers[idx] need_to_set_operator = False else: if adj_krylov_solvers[idx] is None: need_to_set_operator = True adj_krylov_solvers[idx] = KrylovSolver(*solver_parameters) else: need_to_set_operator = False solver = adj_krylov_solvers[idx] solver.parameters.update(parameters) if self.adjoint: (nsp_, tnsp_) = (tnsp, nsp) else: (nsp_, tnsp_) = (nsp, tnsp) x = dolfin.Function(fn_space) if self.initial_guess is not None and var.type == 'ADJ_FORWARD': x.vector()[:] = self.initial_guess.vector() if b.data is None: dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)] # This is really hideous. Sorry. if isinstance(b.data, dolfin.Function): rhs = b.data.vector().copy() [bc.apply(rhs) for bc in self.bcs] if need_to_set_operator: if assemble_system: # if we called assemble_system, rather than assemble v = dolfin.TestFunction(fn_space) (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) [bc.apply(A) for bc in self.bcs] if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) else: if assemble_system: # if we called assemble_system, rather than assemble (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs) if need_to_set_operator: if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) rhs = dolfin.assemble(b.data) [bc.apply(A) for bc in self.bcs] [bc.apply(rhs) for bc in self.bcs] if need_to_set_operator: if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) # Set the nullspace for the linear operator if nsp_ is not None and need_to_set_operator: dolfin.as_backend_type(A).set_nullspace(nsp_) # (Possibly override the user in) orthogonalize # the right-hand-side if tnsp_ is not None: tnsp_.orthogonalize(rhs) solver.solve(x.vector(), rhs) return adjlinalg.Vector(x)
f = dfn.Expression( '500.0 * exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)', degree=1) L = v * f * dfn.dx # Define Dirichlet boundary (x = 0 or x = 1) class DirichletBoundary(dfn.SubDomain): def inside(self, x, on_boundary): return x[0] < dfn.DOLFIN_EPS or x[0] > 1.0 - dfn.DOLFIN_EPS u0 = dfn.Constant(0.0) bc = dfn.DirichletBC(V, u0, DirichletBoundary()) A, rhs = dfn.assemble_system(a, L, bcs=bc) ############################################################ ############################################################ # Part II: Solve with PyAMG Asp = dfn.as_backend_type(A).sparray() b = dfn.as_backend_type(rhs).array_view() ml = pyamg.smoothed_aggregation_solver(Asp, max_coarse=10) residuals = [] x = ml.solve(b, tol=1e-10, accel='cg', residuals=residuals) residuals = residuals / residuals[0] print(ml) ############################################################
def solve(self, var, b): if self.adjoint: operators = transpose_operators(self.operators) else: operators = self.operators solver = dolfin.LinearSolver(*solver_parameters) solver.parameters.update(parameters) x = dolfin.Function(fn_space) if self.initial_guess is not None and var.type == 'ADJ_FORWARD': x.vector()[:] = self.initial_guess.vector() if b.data is None: dolfin.info_red("Warning: got zero RHS for the solve associated with variable %s" % var) return adjlinalg.Vector(x) if var.type in ['ADJ_TLM', 'ADJ_ADJOINT']: self.bcs = [utils.homogenize(bc) for bc in self.bcs if isinstance(bc, dolfin.cpp.DirichletBC)] + [bc for bc in self.bcs if not isinstance(bc, dolfin.cpp.DirichletBC)] # This is really hideous. Sorry. if isinstance(b.data, dolfin.Function): rhs = b.data.vector().copy() [bc.apply(rhs) for bc in self.bcs] if assemble_system: # if we called assemble_system, rather than assemble v = dolfin.TestFunction(fn_space) (A, rhstmp) = dolfin.assemble_system(operators[0], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], dolfin.inner(b.data, v)*dolfin.dx, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) [bc.apply(A) for bc in self.bcs] # Set nullspace if nsp: dolfin.as_backend_type(A).set_nullspace(nsp) nsp.orthogonalize(b); if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) else: if assemble_system: # if we called assemble_system, rather than assemble (A, rhs) = dolfin.assemble_system(operators[0], b.data, self.bcs) if has_preconditioner: (P, rhstmp) = dolfin.assemble_system(operators[1], b.data, self.bcs) solver.set_operators(A, P) else: solver.set_operator(A) else: # we called assemble A = dolfin.assemble(operators[0]) rhs = dolfin.assemble(b.data) [bc.apply(A) for bc in self.bcs] [bc.apply(rhs) for bc in self.bcs] # Set nullspace if nsp: dolfin.as_backend_type(A).set_nullspace(nsp) nsp.orthogonalize(rhs); if has_preconditioner: P = dolfin.assemble(operators[1]) [bc.apply(P) for bc in self.bcs] solver.set_operators(A, P) else: solver.set_operator(A) solver.solve(x.vector(), rhs) return adjlinalg.Vector(x)
np.set_printoptions(formatter={'all': lambda x: '%.5E' % x}) def copy_to_vector(U, U_array): assert U.size() == len(U_array) U.set_local(U_array) U.apply('') # Get the forms # a, L, V, bc, Z = neumann_poisson_data() a, L, V, bc, Z = neumann_elasticity_data() # Turn to dolfin.la objects parameters.linear_algebra_backend = 'uBLAS' # this one provides Matrix.data A, b = Matrix(), Vector() assemble_system(a, L, A_tensor=A, b_tensor=b) # Turn to scipy objects rows, cols, values = A.data() AA = csr_matrix((values, cols, rows)) bb = np.array(b.array()) # Okay, first claim is that CG solver can't solve the problem Ax=b if the # rhs is not perpendicular to the nullspace ZZ = [np.array(Zi.array()) for Zi in Z] for ZZi in ZZ: print '<b, Zi> =', ZZi.dot(bb) x, info = la.cg(AA, bb)
def solve(W, P, mu, u_bcs, p_bcs, f, verbose=True, tol=1.0e-10 ): # Some initial sanity checks. assert mu > 0.0 WP = MixedFunctionSpace([W, P]) # Translate the boundary conditions into the product space. # This conditional loop is able to deal with conditions of the kind # # DirichletBC(W.sub(1), 0.0, right_boundary) # new_bcs = [] for k, bcs in enumerate([u_bcs, p_bcs]): for bc in bcs: space = bc.function_space() C = space.component() if len(C) == 0: new_bcs.append(DirichletBC(WP.sub(k), bc.value(), bc.domain_args[0])) elif len(C) == 1: new_bcs.append(DirichletBC(WP.sub(k).sub(int(C[0])), bc.value(), bc.domain_args[0])) else: raise RuntimeError('Illegal number of subspace components.') # Define variational problem (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) # Build system. # The sign of the div(u)-term is somewhat arbitrary since the right-hand # side is 0 here. We can either make the system symmetric or positive- # definite. # On a second note, we have # # \int grad(p).v = - \int p * div(v) + \int_\Gamma p n.v. # # Since, we have either p=0 or n.v=0 on the boundary, we could as well # replace the term dot(grad(p), v) by -p*div(v). # a = mu * inner(grad(u), grad(v))*dx \ - p * div(v) * dx \ - q * div(u) * dx #a = mu * inner(grad(u), grad(v))*dx + dot(grad(p), v) * dx \ # - div(u) * q * dx L = dot(f, v)*dx A, b = assemble_system(a, L, new_bcs) if has_petsc(): # For an assortment of preconditioners, see # # Performance and analysis of saddle point preconditioners # for the discrete steady-state Navier-Stokes equations; # H.C. Elman, D.J. Silvester, A.J. Wathen; # Numer. Math. (2002) 90: 665-688; # <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.3554>. # # Set up field split. W = SubSpace(WP, 0) P = SubSpace(WP, 1) u_dofs = W.dofmap().dofs() p_dofs = P.dofmap().dofs() prec = PETScPreconditioner() prec.set_fieldsplit([u_dofs, p_dofs], ['u', 'p']) PETScOptions.set('pc_type', 'fieldsplit') PETScOptions.set('pc_fieldsplit_type', 'additive') PETScOptions.set('fieldsplit_u_pc_type', 'lu') PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') ## <http://scicomp.stackexchange.com/questions/7288/which-preconditioners-and-solver-in-petsc-for-indefinite-symmetric-systems-sho> #PETScOptions.set('pc_type', 'fieldsplit') ##PETScOptions.set('pc_fieldsplit_type', 'schur') ##PETScOptions.set('pc_fieldsplit_schur_fact_type', 'upper') #PETScOptions.set('pc_fieldsplit_detect_saddle_point') ##PETScOptions.set('fieldsplit_u_pc_type', 'lsc') ##PETScOptions.set('fieldsplit_u_ksp_type', 'preonly') #PETScOptions.set('pc_type', 'fieldsplit') #PETScOptions.set('fieldsplit_u_pc_type', 'hypre') #PETScOptions.set('fieldsplit_u_ksp_type', 'preonly') #PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') #PETScOptions.set('fieldsplit_p_ksp_type', 'preonly') ## From PETSc/src/ksp/ksp/examples/tutorials/ex42-fsschur.opts: #PETScOptions.set('pc_type', 'fieldsplit') #PETScOptions.set('pc_fieldsplit_type', 'SCHUR') #PETScOptions.set('pc_fieldsplit_schur_fact_type', 'UPPER') #PETScOptions.set('fieldsplit_p_ksp_type', 'preonly') #PETScOptions.set('fieldsplit_u_pc_type', 'bjacobi') ## From ## ## Composable Linear Solvers for Multiphysics; ## J. Brown, M. Knepley, D.A. May, L.C. McInnes, B. Smith; ## <http://www.computer.org/csdl/proceedings/ispdc/2012/4805/00/4805a055-abs.html>; ## <http://www.mcs.anl.gov/uploads/cels/papers/P2017-0112.pdf>. ## #PETScOptions.set('pc_type', 'fieldsplit') #PETScOptions.set('pc_fieldsplit_type', 'schur') #PETScOptions.set('pc_fieldsplit_schur_factorization_type', 'upper') ## #PETScOptions.set('fieldsplit_u_ksp_type', 'cg') #PETScOptions.set('fieldsplit_u_ksp_rtol', 1.0e-6) #PETScOptions.set('fieldsplit_u_pc_type', 'bjacobi') #PETScOptions.set('fieldsplit_u_sub_pc_type', 'cholesky') ## #PETScOptions.set('fieldsplit_p_ksp_type', 'fgmres') #PETScOptions.set('fieldsplit_p_ksp_constant_null_space') #PETScOptions.set('fieldsplit_p_pc_type', 'lsc') ## #PETScOptions.set('fieldsplit_p_lsc_ksp_type', 'cg') #PETScOptions.set('fieldsplit_p_lsc_ksp_rtol', 1.0e-2) #PETScOptions.set('fieldsplit_p_lsc_ksp_constant_null_space') ##PETScOptions.set('fieldsplit_p_lsc_ksp_converged_reason') #PETScOptions.set('fieldsplit_p_lsc_pc_type', 'bjacobi') #PETScOptions.set('fieldsplit_p_lsc_sub_pc_type', 'icc') # Create Krylov solver with custom preconditioner. solver = PETScKrylovSolver('gmres', prec) solver.set_operator(A) else: # Use the preconditioner as recommended in # <http://fenicsproject.org/documentation/dolfin/dev/python/demo/pde/stokes-iterative/python/documentation.html>, # # prec = inner(grad(u), grad(v))*dx - p*q*dx # # although it doesn't seem to be too efficient. # The sign on the last term doesn't matter. prec = mu * inner(grad(u), grad(v))*dx \ - p*q*dx M, _ = assemble_system(prec, L, new_bcs) #solver = KrylovSolver('tfqmr', 'amg') solver = KrylovSolver('gmres', 'amg') solver.set_operators(A, M) solver.parameters['monitor_convergence'] = verbose solver.parameters['report'] = verbose solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = 500 # Solve up = Function(WP) solver.solve(up.vector(), b) # Get sub-functions u, p = up.split() return u, p
plt.show() # Final test with some real example from fenics import dolfin as df mesh = df.UnitSquareMesh(20, 20) V = df.FunctionSpace(mesh, 'CG', 1) u = df.TrialFunction(V) v = df.TestFunction(V) f = df.Expression('sin(pi*x[0])*sin(2*pi*x[1])') a = df.inner(df.grad(u), df.grad(v))*df.dx L = df.inner(f, v)*df.dx bc = df.DirichletBC(V, df.Constant(0), 'on_boundary') A, b = df.assemble_system(a, L, bc) uh = df.Function(V) iters = df.solve(A, uh.vector(), b, 'cg') A_, b_ = A.array(), b.array() x0 = np.zeros(b.size()) x0, my_iters = solve(A_, b_, x0) print 'DOLFIN, Conjugate grad finished in', iters print 'My Conjugate grad finished in', my_iters # Compare error e = uh.vector()[:] - x0[:] print 'Error betwween DOLFIN and CG', la.norm(e)
def ab2tr_step0(u0, P, f, # right-hand side rho, mu, dudt_bcs=[], p_bcs=[], eps=1.0e-4, # relative error tolerance verbose=True ): # Make sure that the initial velocity is divergence-free. alpha = norm(u0, 'Hdiv0') if abs(alpha) > DOLFIN_EPS: warn('Initial velocity not divergence-free (||u||_div = %e).' % alpha ) # Get the initial u0' and p0 by solving the linear equation system # # [M C] [u0'] [f0 - (K+N(u0)u0)] # [C^T 0] [p0 ] = [ g0' ], # # i.e., # # rho u0' + nabla(p0) = f0 + mu\Delta(u0) - rho u0.nabla(u0), # div(u0') = 0. # W = u0.function_space() WP = W*P # Translate the boundary conditions into product space. See # <http://fenicsproject.org/qa/703/boundary-conditions-in-product-space>. dudt_bcs_new = [] for dudt_bc in dudt_bcs: dudt_bcs_new.append(DirichletBC(WP.sub(0), dudt_bc.value(), dudt_bc.user_sub_domain())) p_bcs_new = [] for p_bc in p_bcs: p_bcs_new.append(DirichletBC(WP.sub(1), p_bc.value(), p_bc.user_sub_domain())) new_bcs = dudt_bcs_new + p_bcs_new (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) #a = rho * dot(u, v) * dx + dot(grad(p), v) * dx \ a = rho * inner(u, v) * dx - p * div(v) * dx \ - div(u) * q * dx L = _rhs_weak(u0, v, f, rho, mu) A, b = assemble_system(a, L, new_bcs) # Similar preconditioner as for the Stokes problem. # TODO implement something better! prec = rho * inner(u, v) * dx \ - p*q*dx M, _ = assemble_system(prec, L, new_bcs) solver = KrylovSolver('gmres', 'amg') solver.parameters['monitor_convergence'] = verbose solver.parameters['report'] = verbose solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = 1.0e-6 solver.parameters['maximum_iterations'] = 10000 # Associate operator (A) and preconditioner matrix (M) solver.set_operators(A, M) #solver.set_operator(A) # Solve up = Function(WP) solver.solve(up.vector(), b) # Get sub-functions dudt0, p0 = up.split() # Choosing the first step size for the trapezoidal rule can be tricky. # Chapters 2.7.4a, 2.7.4e of the book # # Incompressible flow and the finite element method, # volume 1: advection-diffusion; # P.M. Gresho, R.L. Sani, # # give some hints. # # eps ... relative error tolerance # tau ... estimate of the initial 'time constant' tau = None if tau: dt0 = tau * eps**(1.0/3.0) else: # Choose something 'reasonably small'. dt0 = 1.0e-3 # Alternative: # Use a dissipative scheme like backward Euler or BDF2 for the first # couple of steps. This makes sure that noisy initial data is damped # out. return dudt0, p0, dt0
# Nonlinear coefficient 2 q2 = ufl.operators.exp(a * u2) for k in range(10): # Two parts of the weak form F1 = (u1.dx(0) * v1.dx(0) + a * u1.dx(0) * q2 * v1) * df.dx F2 = (u2.dx(0) * v2.dx(0) - a * q1 * u2.dx(0) * v2) * df.dx F = F1 + F2 # Compute Jacobian dF = df.derivative(F, u, du) # Assemble matrix and load vector A, b = df.assemble_system(dF, -F, bch) # Compute Newton update df.solve(A, u_inc.vector(), b) # Update solution u.vector()[:] += u_inc.vector() # Evaluate solution ug = u.compute_vertex_values() # partition into u1 and u2 U = np.reshape(ug, (2, nel + 1)) plt.plot(xg, U[0, :]) plt.plot(xg, U[1, :])
def test_stokes_noflow(gamma, Re, nu_interp, postprocessor): #set_log_level(WARNING) basename = postprocessor.basename label = "{}_{}_gamma_{}_Re_{:.0e}".format(basename, nu_interp, gamma, Re) c = postprocessor.get_coefficients() c[r"\nu_1"] = c[r"\rho_1"] / Re c[r"\nu_2"] = c[r"r_visc"] * c[r"\nu_1"] c[r"\nu_1"] /= c[r"\rho_0"] * c[r"V_0"] * c[r"L_0"] c[r"\nu_2"] /= c[r"\rho_0"] * c[r"V_0"] * c[r"L_0"] cc = wrap_coeffs_as_constants(c) nu = eval("nu_" + nu_interp) # choose viscosity interpolation for level in range(1, 4): mesh, boundary_markers, pinpoint, periodic_bnd = create_domain(level) periodic_bnd = None W = create_mixed_space(mesh, periodic_boundary=periodic_bnd) bcs = create_bcs(W, boundary_markers, periodic_boundary=periodic_bnd, pinpoint=pinpoint) phi = create_fixed_vfract(mesh, c) # Create forms a, L = create_forms(W, rho(phi, cc), nu(phi, cc), c[r"g_a"], boundary_markers, gamma) # Solve problem w = df.Function(W) A, b = df.assemble_system(a, L, bcs) solver = df.LUSolver("mumps") df.PETScOptions.set("fieldsplit_u_mat_mumps_icntl_14", 500) solver.set_operator(A) try: solver.solve(w.vector(), b) except: df.warning("Ooops! Something went wrong: {}".format( sys.exc_info()[0])) continue # Pre-process results v, p = w.split(True) v.rename("v", "velocity") p.rename("p", "pressure") V_dv = df.FunctionSpace(mesh, "DG", W.sub(0).ufl_element().degree() - 1) div_v = df.project(df.div(v), V_dv) div_v.rename("div_v", "velocity-divergence") D_22 = df.project(v.sub(1).dx(1), V_dv) p_h = create_hydrostatic_pressure(mesh, cc) #p_ref = df.project(p_h, W.sub(1).ufl_element()) p_ref = df.project( p_h, df.FunctionSpace(mesh, df.FiniteElement("CG", mesh.ufl_cell(), 4))) v_errL2, v_errH10, div_errL2, p_errL2 = compute_errornorms( v, div_v, p, p_ref) if nu_interp[:2] == "PW": V_nu = df.FunctionSpace(mesh, "DG", phi.ufl_element().degree()) else: V_nu = phi.function_space() nu_0 = df.project(nu(phi, cc), V_nu) T_22 = df.project(2.0 * nu(phi, cc) * v.sub(1).dx(1), V_nu) # Save results make_cut = postprocessor._make_cut rs = dict(ndofs=W.dim(), level=level, h=mesh.hmin(), r_dens=c[r"r_dens"], r_visc=c[r"r_visc"], gamma=gamma, Re=Re, nu_interp=nu_interp) rs[r"$v_2$"] = make_cut(v.sub(1)) rs[r"$p$"] = make_cut(p) rs[r"$\phi$"] = make_cut(phi) rs[r"$D_{22}$"] = make_cut(D_22) rs[r"$T_{22}$"] = make_cut(T_22) rs[r"$\nu$"] = make_cut(nu_0) rs[r"$||\mathbf{v} - \mathbf{v}_h||_{L^2}$"] = v_errL2 rs[r"$||\nabla (\mathbf{v} - \mathbf{v}_h)||_{L^2}$"] = v_errH10 rs[r"$||\mathrm{div} \mathbf{v}_h||_{L^2}$"] = div_errL2 rs[r"$||\mathbf{p} - \mathbf{p}_h||_{L^2}$"] = p_errL2 print(label, level) # Send to posprocessor comm = mesh.mpi_comm() rank = df.MPI.rank(comm) postprocessor.add_result(rank, rs) # Plot results obtained in the last round outdir = os.path.join(postprocessor.outdir, "XDMFoutput") with df.XDMFFile(os.path.join(outdir, "v.xdmf")) as file: file.write(v, 0.0) with df.XDMFFile(os.path.join(outdir, "p.xdmf")) as file: file.write(p, 0.0) with df.XDMFFile(os.path.join(outdir, "phi.xdmf")) as file: file.write(phi, 0.0) with df.XDMFFile(os.path.join(outdir, "div_v.xdmf")) as file: file.write(div_v, 0.0) # Save results into a binary file filename = "results_{}.pickle".format(label) postprocessor.save_results(filename) # Flush plots as we now have data for all level values postprocessor.pop_items(["level", "h"]) postprocessor.flush_plots() # Cleanup df.set_log_level(df.INFO) gc.collect()
def get_1d_matrices(mesh_, N, root=''): '''Given mesh construct 1d matrices for GEVP.''' if not isinstance(N, (int, float)): assert root return all([get_1d_matrices(mesh_, n, root) == 0 for n in N]) mesh_dir = '../plate-beam/py/fem_new/meshes' # Zig zag mesh if mesh_ == 'nonuniform': mesh = 'Pb_zig_zag_bif' mesh2d = '%s/%s_%d.xml.gz' % (mesh_dir, mesh, N) # mesh1d = '%s/%s_%d_facet_region.xml.gz' % (mesh_dir, mesh, N) mesh2d = Mesh(mesh2d) # Constructing facet function can be too expensive so here's and # alternative # mesh1d = get_marked_facets(mesh1d) # Structured meshes elif mesh_ == 'uniform': mesh = mesh_ N = int(N) mesh2d = UnitSquareMesh(N, N) # mesh1d = EdgeFunction('size_t', mesh2d, 0) # Beam at y = 0.5 # CompiledSubDomain('near(x[1], 0.5, 1E-10)').mark(mesh1d, 1) # Use the above here as well # from dolfin import SubsetIterator # mesh1d = [e.index() for e in SubsetIterator(mesh1d, 1)] mesh1d = '%s/%s_%d_edgelist' % (mesh_dir, mesh, N) mesh1d = map(int, np.loadtxt(mesh1d)) print FunctionSpace(mesh2d, 'CG', 1).dim() # Extract 1d import sys; sys.setrecursionlimit(20000); mesh = interval_mesh_from_edge_f(mesh2d, mesh1d, 1)[0].pop() # Assemble V = FunctionSpace(mesh, 'CG', 1) u = TrialFunction(V) v = TestFunction(V) bc = DirichletBC(V, Constant(0), 'on_boundary') a = inner(grad(u), grad(v))*dx m = inner(u, v)*dx L = inner(Constant(0), v)*dx A, _ = assemble_system(a, L, bc) M, _ = assemble_system(m, L, bc) A, M = A.array(), M.array() if root: dA = np.diagonal(A, 0) uA = np.r_[np.diagonal(A, 1), 0] A = np.c_[dA, uA] dM = np.diagonal(M, 0) uM = np.r_[np.diagonal(M, 1), 0] M = np.c_[dM, uM] header = 'main and upper diagonals of A, M' f = '_'.join([mesh_, str(N)]) import os f = os.path.join(root, f) np.savetxt(f, np.c_[A, M], header=header) return 0 else: return A, M
def _assemble_system(a, L, bcs, facet_function): return assemble_system(a, L, bcs, exterior_facet_domains=facet_function)
def boundary_D(x, on_boundary): return on_boundary and (near(x[0], 0, tol) or near(x[0], 1.0, tol)) bc = DirichletBC(V, u_D, boundary_D) u = TrialFunction(V) v = TestFunction(V) f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2) \ + pow(x[2] - 0.5, 2)) / 0.02)", degree=6) g = Expression("sin(5.0*x[0])*sin(5.0*x[1])", degree=6) a = dot(grad(u), grad(v)) * dx L = f * v * dx + g * v * ds A = PETScMatrix() b = PETScVector() assemble_system(a, L, bc, A_tensor=A, b_tensor=b) A = A.mat() b = b.vec() # ========================================================================= # Construct the alist for systems on levels from fine to coarse # construct the transfer operators first ruse = [None] * (nl - 1) Alist = [None] * (nl) ruse[0] = Mat() puse[0].transpose(ruse[0]) Alist[0] = A
'500.0 * exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)', degree=1) L = v * f * dfn.dx # Define Dirichlet boundary (x = 0 or x = 1) class DirichletBoundary(dfn.SubDomain): def inside(self, x, on_boundary): return x[0] < dfn.DOLFIN_EPS or x[0] > 1.0 - dfn.DOLFIN_EPS u0 = dfn.Constant(0.0) bc = dfn.DirichletBC(V, u0, DirichletBoundary()) A, rhs = dfn.assemble_system(a, L, bcs=bc) ############################################################ ############################################################ # Part II: Solve with PyAMG Asp = dfn.as_backend_type(A).sparray() b = dfn.as_backend_type(rhs).array_view() ml = pyamg.smoothed_aggregation_solver(Asp, max_coarse=10) residuals = [] x = ml.solve(b, tol=1e-10, accel='cg', residuals=residuals) residuals = residuals / residuals[0] print(ml) ############################################################
def solve_linear(self, d_outputs, d_residuals, mode): linear_solver_ = self.options['linear_solver_'] pde_problem = self.options['pde_problem'] state_name = self.options['state_name'] state_function = pde_problem.states_dict[state_name]['function'] residual_form = pde_problem.states_dict[state_name]['residual_form'] if state_name == 'density': print('this is a variational density filter') A, _ = df.assemble_system(self.derivative_form, -residual_form) else: A, _ = df.assemble_system(self.derivative_form, -residual_form, pde_problem.bcs_list) def report(xk): frame = inspect.currentframe().f_back if linear_solver_ == 'fenics_direct': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) df.solve(AT, dR.vector(), rhs_.vector()) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'scipy_splu': if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) lu = splu(ATm_csr.tocsc()) d_residuals[state_name] = lu.solve(d_outputs[state_name], trans='T') elif linear_solver_ == 'scipy_cg': if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() ATm_csr = csr_matrix(ATm.getValuesCSR()[::-1], shape=Am.size) # lu = splu(ATm_csr.tocsc()) b = d_outputs[state_name] x, info = splinalg.cg(ATm_csr, b, tol=1e-8, callback=report) print('the residual is:') print(info) d_residuals[state_name] = x elif linear_solver_ == 'fenics_krylov': rhs_ = df.Function(state_function.function_space()) dR = df.Function(state_function.function_space()) rhs_.vector().set_local(d_outputs[state_name]) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ATm = Am.transpose() AT = df.PETScMatrix(ATm) solver = df.KrylovSolver('gmres', 'ilu') prm = solver.parameters prm["maximum_iterations"] = 1000000 prm["divergence_limit"] = 1e2 solver.solve(AT, dR.vector(), rhs_.vector()) # print('solve'+iter) d_residuals[state_name] = dR.vector().get_local() elif linear_solver_ == 'petsc_gmres_ilu': ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.GMRES) ksp.setTolerances(rtol=5e-17) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ksp.setOperators(Am) ksp.setFromOptions() pc = ksp.getPC() pc.setType("lu") size = state_function.function_space().dim() dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals[state_name]) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs[state_name]) du.setUp() if mode == 'fwd': ksp.solve(dR, du) d_outputs[state_name] = du.getValues(range(size)) else: ksp.solveTranspose(du, dR) d_residuals[state_name] = dR.getValues(range(size)) elif linear_solver_ == 'petsc_cg_ilu': ksp = PETSc.KSP().create() ksp.setType(PETSc.KSP.Type.CG) ksp.setTolerances(rtol=5e-15) if state_name != 'density': for bc in pde_problem.bcs_list: bc.apply(A) Am = df.as_backend_type(A).mat() ksp.setOperators(Am) ksp.setFromOptions() pc = ksp.getPC() pc.setType("lu") size = state_function.function_space().dim() dR = PETSc.Vec().create() dR.setSizes(size) dR.setType('seq') dR.setValues(range(size), d_residuals[state_name]) dR.setUp() du = PETSc.Vec().create() du.setSizes(size) du.setType('seq') du.setValues(range(size), d_outputs[state_name]) du.setUp() if mode == 'fwd': ksp.solve(dR, du) d_outputs[state_name] = du.getValues(range(size)) else: ksp.solveTranspose(du, dR) d_residuals[state_name] = dR.getValues(range(size))
def stokes_solve( up_out, mu, u_bcs, p_bcs, f, dx=dx, verbose=True, tol=1.0e-10, maxiter=1000 ): # Some initial sanity checks. assert mu > 0.0 WP = up_out.function_space() # Translate the boundary conditions into the product space. new_bcs = [] for k, bcs in enumerate([u_bcs, p_bcs]): for bc in bcs: space = bc.function_space() C = space.component() if len(C) == 0: new_bcs.append(DirichletBC(WP.sub(k), bc.value(), bc.domain_args[0])) elif len(C) == 1: new_bcs.append(DirichletBC(WP.sub(k).sub(int(C[0])), bc.value(), bc.domain_args[0])) else: raise RuntimeError('Illegal number of subspace components.') # TODO define p*=-1 and reverse sign in the end to get symmetric system? # Define variational problem (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) r = Expression('x[0]', degree=1, domain=WP.mesh()) print("mu = %e" % mu) # build system a = mu * inner(r * grad(u), grad(v)) * 2 * pi * dx \ - ((r * v[0]).dx(0) + (r * v[1]).dx(1)) * p * 2 * pi * dx \ + ((r * u[0]).dx(0) + (r * u[1]).dx(1)) * q * 2 * pi * dx #- div(r*v)*p* 2*pi*dx \ #+ q*div(r*u)* 2*pi*dx L = inner(f, v) * 2 * pi * r * dx A, b = assemble_system(a, L, new_bcs) mode = 'lu' if mode == 'lu': solve(A, up_out.vector(), b, 'lu') elif mode == 'gmres': # For preconditioners for the Stokes system, see # # Fast iterative solvers for discrete Stokes equations; # J. Peters, V. Reichelt, A. Reusken. # prec = mu * inner(r * grad(u), grad(v)) * 2 * pi * dx \ - p * q * 2 * pi * r * dx P, btmp = assemble_system(prec, L, new_bcs) solver = KrylovSolver('tfqmr', 'amg') #solver = KrylovSolver('gmres', 'amg') solver.set_operators(A, P) solver.parameters['monitor_convergence'] = verbose solver.parameters['report'] = verbose solver.parameters['absolute_tolerance'] = 0.0 solver.parameters['relative_tolerance'] = tol solver.parameters['maximum_iterations'] = maxiter # Solve solver.solve(up_out.vector(), b) elif mode == 'fieldsplit': raise NotImplementedError('Fieldsplit solver not yet implemented.') # For an assortment of preconditioners, see # # Performance and analysis of saddle point preconditioners # for the discrete steady-state Navier-Stokes equations; # H.C. Elman, D.J. Silvester, A.J. Wathen; # Numer. Math. (2002) 90: 665-688; # <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.3554>. # # Set up field split. W = SubSpace(WP, 0) P = SubSpace(WP, 1) u_dofs = W.dofmap().dofs() p_dofs = P.dofmap().dofs() prec = PETScPreconditioner() prec.set_fieldsplit([u_dofs, p_dofs], ['u', 'p']) PETScOptions.set('pc_type', 'fieldsplit') PETScOptions.set('pc_fieldsplit_type', 'additive') PETScOptions.set('fieldsplit_u_pc_type', 'lu') PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') # Create Krylov solver with custom preconditioner. solver = PETScKrylovSolver('gmres', prec) solver.set_operator(A) return
def __init__( self, Q, kappa, rho, cp, convection, source, dirichlet_bcs=None, neumann_bcs=None, robin_bcs=None, my_dx=dx, my_ds=ds, stabilization=None, ): super(Heat, self).__init__() self.Q = Q dirichlet_bcs = dirichlet_bcs or [] neumann_bcs = neumann_bcs or {} robin_bcs = robin_bcs or {} self.convection = convection u = TrialFunction(Q) v = TestFunction(Q) # If there are sharp temperature gradients, numerical oscillations may # occur. This happens because the resulting matrix is not an M-matrix, # caused by the fact that A1 puts positive elements in places other # than the main diagonal. To prevent that, it is suggested by # Großmann/Roos to use a vertex-centered discretization for the mass # matrix part. # Check # https://bitbucket.org/fenics-project/ffc/issues/145/uflacs-error-for-vertex-quadrature-scheme # self.M = assemble( u * v * dx, form_compiler_parameters={ "representation": "quadrature", "quadrature_rule": "vertex", }, ) mesh = Q.mesh() r = SpatialCoordinate(mesh)[0] self.F0 = F( u, v, kappa, rho, cp, convection, source, r, neumann_bcs, robin_bcs, my_dx, my_ds, stabilization, ) self.dirichlet_bcs = dirichlet_bcs self.A, self.b = assemble_system(-lhs(self.F0), rhs(self.F0)) return
def stokes_solve(up_out, mu, u_bcs, p_bcs, f, my_dx=dx): # Some initial sanity checks. assert mu > 0.0 WP = up_out.function_space() # Translate the boundary conditions into the product space. new_bcs = helpers.dbcs_to_productspace(WP, [u_bcs, p_bcs]) # TODO define p*=-1 and reverse sign in the end to get symmetric system? # Define variational problem (u, p) = TrialFunctions(WP) (v, q) = TestFunctions(WP) mesh = WP.mesh() r = SpatialCoordinate(mesh)[0] # build system f = F(u, p, v, q, f, r, mu, my_dx) a = lhs(f) L = rhs(f) A, b = assemble_system(a, L, new_bcs) mode = "lu" assert mode == "lu" solve(A, up_out.vector(), b, "lu") # TODO Krylov solver for Stokes # assert mode == 'gmres' # # For preconditioners for the Stokes system, see # # # # Fast iterative solvers for discrete Stokes equations; # # J. Peters, V. Reichelt, A. Reusken. # # # prec = mu * inner(r * grad(u), grad(v)) * 2 * pi * my_dx \ # - p * q * 2 * pi * r * my_dx # P, _ = assemble_system(prec, L, new_bcs) # solver = KrylovSolver('tfqmr', 'hypre_amg') # # solver = KrylovSolver('gmres', 'hypre_amg') # solver.set_operators(A, P) # solver.parameters['monitor_convergence'] = verbose # solver.parameters['report'] = verbose # solver.parameters['absolute_tolerance'] = 0.0 # solver.parameters['relative_tolerance'] = tol # solver.parameters['maximum_iterations'] = maxiter # # Solve # solver.solve(up_out.vector(), b) # elif mode == 'fieldsplit': # # For an assortment of preconditioners, see # # # # Performance and analysis of saddle point preconditioners # # for the discrete steady-state Navier-Stokes equations; # # H.C. Elman, D.J. Silvester, A.J. Wathen; # # Numer. Math. (2002) 90: 665-688; # # <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.145.3554>. # # # # Set up field split. # W = SubSpace(WP, 0) # P = SubSpace(WP, 1) # u_dofs = W.dofmap().dofs() # p_dofs = P.dofmap().dofs() # prec = PETScPreconditioner() # prec.set_fieldsplit([u_dofs, p_dofs], ['u', 'p']) # PETScOptions.set('pc_type', 'fieldsplit') # PETScOptions.set('pc_fieldsplit_type', 'additive') # PETScOptions.set('fieldsplit_u_pc_type', 'lu') # PETScOptions.set('fieldsplit_p_pc_type', 'jacobi') # # Create Krylov solver with custom preconditioner. # solver = PETScKrylovSolver('gmres', prec) # solver.set_operator(A) return