def __init__(self, V, fixed_dims=[], direct_solve=False): if isinstance(fixed_dims, int): fixed_dims = [fixed_dims] self.V = V self.fixed_dims = fixed_dims self.direct_solve = direct_solve self.zero = fd.Constant(V.mesh().topological_dimension() * (0, )) u = fd.TrialFunction(V) v = fd.TestFunction(V) self.zero_fun = fd.Function(V) self.a = 1e-2 * \ fd.inner(u, v) * fd.dx + fd.inner(fd.sym(fd.grad(u)), fd.sym(fd.grad(v))) * fd.dx self.bc_fun = fd.Function(V) if len(self.fixed_dims) == 0: bcs = [fd.DirichletBC(self.V, self.bc_fun, "on_boundary")] else: bcs = [] for i in range(self.V.mesh().topological_dimension()): if i in self.fixed_dims: bcs.append(fd.DirichletBC(self.V.sub(i), 0, "on_boundary")) else: bcs.append( fd.DirichletBC(self.V.sub(i), self.bc_fun.sub(i), "on_boundary")) self.A_ext = fd.assemble(self.a, bcs=bcs, mat_type="aij") self.ls_ext = fd.LinearSolver(self.A_ext, solver_parameters=self.get_params()) self.A_adj = fd.assemble(self.a, bcs=fd.DirichletBC(self.V, self.zero, "on_boundary"), mat_type="aij") self.ls_adj = fd.LinearSolver(self.A_adj, solver_parameters=self.get_params())
def dirichlet_boundary_conditions(sim): W = sim.solution_space return [ fe.DirichletBC(W.sub(0), fe.Constant((0., 0.)), (1, 2, 3)), fe.DirichletBC(W.sub(0), fe.Constant((1., 0.)), 4) ]
def dirichlet_boundary_conditions(self): return [ fe.DirichletBC(self.solution_subspaces["u"], fe.Constant((0., 0.)), (1, 2, 3)), fe.DirichletBC(self.solution_subspaces["u"], fe.Constant((1., 0.)), 4) ]
def dirichlet_boundary_conditions(sim): W = sim.function_space return [ fe.DirichletBC(W.sub(1), (0., 0.), "on_boundary"), fe.DirichletBC(W.sub(2), sim.hot_wall_temperature, 1), fe.DirichletBC(W.sub(2), sim.cold_wall_temperature, 2) ]
def dirichlet_boundary_conditions(sim): W = sim.solution_space return [ fe.DirichletBC(sim.solution_subspaces["u"], fe.Constant((0, 0)), (1, 2, 3)), fe.DirichletBC(sim.solution_subspaces["u"], fe.Constant((1, 0)), 4) ]
def dirichlet_boundary_conditions(self): W = self.solution_space return [ fe.DirichletBC(W.sub(1), (0., 0.), "on_boundary"), fe.DirichletBC(W.sub(2), 0.5, 1), fe.DirichletBC(W.sub(2), -0.5, 2) ]
def temperature_solver(T, t, beta, PeInv, solver_parameters, *, t1, INLET1, t2, INLET2): F_T = AdvectionDiffusionGLS(T, beta, t, PeInv=PeInv) bc1 = fd.DirichletBC(T, t1, INLET1) bc2 = fd.DirichletBC(T, t2, INLET2) bcs = [bc1, bc2] problem_T = fd.NonlinearVariationalProblem(F_T, t, bcs=bcs) return fd.NonlinearVariationalSolver(problem_T, solver_parameters=solver_parameters)
def dirichlet_boundary_conditions(sim, manufactured_solution): """Apply velocity and temperature Dirichlet BC's on every boundary. Do not apply Dirichlet BC's on the pressure. """ _, u, T = manufactured_solution return [ fe.DirichletBC(sim.solution_subspaces["u"], u, "on_boundary"), fe.DirichletBC(sim.solution_subspaces["T"], T, "on_boundary")]
def dirichlet_boundary_conditions(self): W = self.solution_space return [ fe.DirichletBC(W.sub(1), (0., ) * self.mesh.geometric_dimension(), "on_boundary"), fe.DirichletBC(W.sub(2), self.hotwall_temperature, 1), fe.DirichletBC(W.sub(2), self.initial_temperature, 2) ]
def dirichlet_boundary_conditions(sim): W = sim.function_space dim = sim.mesh.geometric_dimension() return [ fe.DirichletBC(W.sub(1), (0., ) * dim, "on_boundary"), fe.DirichletBC(W.sub(2), sim.hot_wall_temperature, 1), fe.DirichletBC(W.sub(2), sim.cold_wall_temperature, 2) ]
def dirichlet_boundary_conditions(self): W = self.solution.function_space() d = self.solution.function_space().mesh().geometric_dimension() return [ fe.DirichletBC(W.sub(1), (0., ) * d, "on_boundary"), fe.DirichletBC(W.sub(2), self.hotwall_temperature, self.hotwall_id), fe.DirichletBC(W.sub(2), self.coldwall_temperature, self.coldwall_id) ]
def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (1, 4)), # top-bottom and cylinder fd.DirichletBC(self.V['u'], ((4.0 * 1.5 * y * (0.41 - y) / 0.41**2), 0), 2) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 3)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']]
def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (10, 12)), # top-bottom fd.DirichletBC(self.V['u'], ((1.0 * (y - 1) * (2 - y)) / (0.5**2), 0), 9) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 11)] # outflow self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']]
def __init__(self, mesh_m, viscosity): super().__init__() self.mesh_m = mesh_m self.failed_to_solve = False # when self.solver.solve() fail # Setup problem, Taylor-Hood finite elements self.V = fd.VectorFunctionSpace(self.mesh_m, "CG", 2) \ * fd.FunctionSpace(self.mesh_m, "CG", 1) # Preallocate solution variables for state equation self.solution = fd.Function(self.V, name="State") self.testfunction = fd.TestFunction(self.V) # Define viscosity parameter self.viscosity = viscosity # Weak form of incompressible Navier-Stokes equations z = self.solution u, p = fd.split(z) test = self.testfunction v, q = fd.split(test) nu = self.viscosity # shorten notation self.F = nu*fd.inner(fd.grad(u), fd.grad(v))*fd.dx - p*fd.div(v)*fd.dx\ + fd.inner(fd.dot(fd.grad(u), u), v)*fd.dx + fd.div(u)*q*fd.dx # Dirichlet Boundary conditions X = fd.SpatialCoordinate(self.mesh_m) dim = self.mesh_m.topological_dimension() if dim == 2: uin = 4 * fd.as_vector([(1 - X[1]) * X[1], 0]) elif dim == 3: rsq = X[0]**2 + X[1]**2 # squared radius = 0.5**2 = 1/4 uin = fd.as_vector([0, 0, 1 - 4 * rsq]) else: raise NotImplementedError self.bcs = [ fd.DirichletBC(self.V.sub(0), 0., [12, 13]), fd.DirichletBC(self.V.sub(0), uin, [10]) ] # PDE-solver parameters self.nsp = None self.params = { "snes_max_it": 10, "mat_type": "aij", "pc_type": "lu", "pc_factor_mat_solver_type": "superlu_dist", # "snes_monitor": None, "ksp_monitor": None, }
def setup(self, **kwargs): for name, field in kwargs.items(): if name in self._fields.keys(): self._fields[name].assign(field) else: self._fields[name] = utilities.copy(field) # Create homogeneous BCs for the Dirichlet part of the boundary u = self._fields.get('velocity', self._fields.get('u')) V = u.function_space() bcs = firedrake.DirichletBC(V, u, self._dirichlet_ids) if not self._dirichlet_ids: bcs = None # Find the numeric IDs for the ice front boundary_ids = u.ufl_domain().exterior_facets.unique_markers ice_front_ids_comp = set(self._dirichlet_ids + self._side_wall_ids) ice_front_ids = list(set(boundary_ids) - ice_front_ids_comp) # Create the action and scale functionals _kwargs = { 'side_wall_ids': self._side_wall_ids, 'ice_front_ids': ice_front_ids } action = self._model.action(**self._fields, **_kwargs) F = firedrake.derivative(action, u) degree = self._model.quadrature_degree(**self._fields) params = {'form_compiler_parameters': {'quadrature_degree': degree}} problem = firedrake.NonlinearVariationalProblem(F, u, bcs, **params) self._solver = firedrake.NonlinearVariationalSolver( problem, solver_parameters=self._solver_parameters)
def __init__(self, mesh_m): super().__init__() self.mesh_m = mesh_m # Setup problem self.V = fd.FunctionSpace(self.mesh_m, "CG", 1) # Preallocate solution variables for state and adjoint equations self.solution = fd.Function(self.V, name="State") # Weak form of Poisson problem u = self.solution v = fd.TestFunction(self.V) self.f = fd.Constant(4.) self.F = (fd.inner(fd.grad(u), fd.grad(v)) - self.f * v) * fd.dx self.bcs = fd.DirichletBC(self.V, 0., "on_boundary") # PDE-solver parameters self.params = { "ksp_type": "cg", "mat_type": "aij", "pc_type": "hypre", "pc_factor_mat_solver_package": "boomerang", "ksp_rtol": 1e-11, "ksp_atol": 1e-11, "ksp_stol": 1e-15, } stateproblem = fd.NonlinearVariationalProblem(self.F, self.solution, bcs=self.bcs) self.solver = fd.NonlinearVariationalSolver( stateproblem, solver_parameters=self.params)
def get_mu(self, V): W = fd.FunctionSpace(V.mesh(), "CG", 1) bcs = [] if len(self.fixed_bids): bcs.append(fd.DirichletBC(W, 1, self.fixed_bids)) if len(self.free_bids): bcs.append(fd.DirichletBC(W, 10, self.free_bids)) if len(bcs) == 0: bcs = None u = fd.TrialFunction(W) v = fd.TestFunction(W) a = fd.inner(fd.grad(u), fd.grad(v)) * fd.dx b = fd.inner(fd.Constant(0.), v) * fd.dx mu = fd.Function(W) fd.solve(a == b, mu, bcs=bcs) return mu
def __init__(self, mesh_m): super().__init__() # Setup problem V = fd.FunctionSpace(mesh_m, "CG", 1) # Weak form of Poisson problem u = fd.Function(V, name="State") v = fd.TestFunction(V) f = fd.Constant(4.) self.F = (fd.inner(fd.grad(u), fd.grad(v)) - f * v) * fd.dx self.bcs = fd.DirichletBC(V, 0., "on_boundary") # PDE-solver parameters self.params = { "ksp_type": "cg", "mat_type": "aij", "pc_type": "hypre", "pc_factor_mat_solver_package": "boomerang", "ksp_rtol": 1e-11, "ksp_atol": 1e-11, "ksp_stol": 1e-15, } self.solution = u
def setup_bcs(self): x, y = fd.SpatialCoordinate(self.mesh) c0 = fd.exp(x * y * self.t) bcu = [ fd.DirichletBC(self.V['u'], fd.Constant((0, 0)), (10, 12)), # top-bottom and cylinder fd.DirichletBC(self.V['u'], ((1.0 * (y - 1) * (2 - y)) / (0.5**2), 0), 9) ] # inflow bcp = [fd.DirichletBC(self.V['p'], fd.Constant(0), 11)] # outflow bcc1 = [fd.DirichletBC(self.V['c'].sub(0), c0, 'on_boundary')] self.bc['u'][0] = [bcu, None, None, None, 'fixed'] self.bc['p'] = [[bcp, None, None, None, 'fixed']] self.bc['c'][0] = [bcc1, c0, 'on_boundary', 0, 'update']
def _newton_solve(z, E, scale, tolerance=1e-6, armijo=1e-4, max_iterations=50): F = derivative(E, z) H = derivative(F, z) Q = z.function_space() bc = firedrake.DirichletBC(Q, 0, 'on_boundary') p = firedrake.Function(Q) for iteration in range(max_iterations): firedrake.solve(H == -F, p, bc, solver_parameters={'ksp_type': 'preonly', 'pc_type': 'lu'}) dE_dp = assemble(action(F, p)) α = 1.0 E0 = assemble(E) Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p})) while (Ez > E0 + armijo * α * dE_dp) or np.isnan(Ez): α /= 2 Ez = assemble(replace(E, {z: z + firedrake.Constant(α) * p})) z.assign(z + firedrake.Constant(α) * p) if abs(dE_dp) < tolerance * assemble(scale): return z raise ValueError("Newton solver failed to converge after {0} iterations" .format(max_iterations))
def get_boundary_conditions(self): """Impose Dirichlet boundary conditions.""" dim = self.mesh_m.cell_dimension() if dim == 2: zerovector = fd.Constant((0.0, 0.0)) elif dim == 3: zerovector = fd.Constant((0.0, 0.0, 0.0)) bcs = [] if len(self.inflow_bids) is not None: bcs.append( fd.DirichletBC(self.V.sub(0), self.inflow_expr, self.inflow_bids)) if len(self.noslip_bids) > 0: bcs.append( fd.DirichletBC(self.V.sub(0), zerovector, self.noslip_bids)) return bcs
def setup(self, **kwargs): for name, field in kwargs.items(): if name in self._fields.keys(): self._fields[name].assign(field) else: if isinstance(field, firedrake.Constant): self._fields[name] = firedrake.Constant(field) elif isinstance(field, firedrake.Function): self._fields[name] = field.copy(deepcopy=True) else: raise TypeError( "Input %s field has type %s, must be Constant or Function!" % (name, type(field)) ) # Create homogeneous BCs for the Dirichlet part of the boundary u = self._fields["velocity"] V = u.function_space() # NOTE: This will have to change when we do Stokes! if hasattr(V._ufl_element, "_sub_element"): bcs = firedrake.DirichletBC(V, Constant((0, 0)), self._dirichlet_ids) else: bcs = firedrake.DirichletBC(V, Constant(0), self._dirichlet_ids) if not self._dirichlet_ids: bcs = None # Find the numeric IDs for the ice front boundary_ids = u.ufl_domain().exterior_facets.unique_markers ice_front_ids_comp = set(self._dirichlet_ids + self._side_wall_ids) ice_front_ids = list(set(boundary_ids) - ice_front_ids_comp) # Create the action and scale functionals _kwargs = {"side_wall_ids": self._side_wall_ids, "ice_front_ids": ice_front_ids} action = self._model.action(**self._fields, **_kwargs) scale = self._model.scale(**self._fields, **_kwargs) # Set up a minimization problem and solver quadrature_degree = self._model.quadrature_degree(**self._fields) params = {"quadrature_degree": quadrature_degree} problem = MinimizationProblem(action, scale, u, bcs, params) self._solver = NewtonSolver( problem, self._tolerance, solver_parameters=self._solver_parameters, max_iterations=self._max_iterations, )
def __init__(self, function_space, state, boundary): self.state = state.clone() self.values = fire.Function(function_space) self.dofs = function_space.boundary_nodes(boundary, "topological") self.dirichlet = fire.DirichletBC(function_space, self.values, boundary, method="topological")
def dirichlet_boundary_conditions(sim, manufactured_solution): """Apply velocity Dirichlet BC's on every boundary.""" p, u = manufactured_solution return [fe.DirichletBC( sim.solution_subspaces["u"], u, "on_boundary"),]
def dirichlet_boundary_conditions(sim, manufactured_solution): """Apply velocity Dirichlet BC's on every boundary.""" W = sim.solution_space u, p = manufactured_solution return [ fe.DirichletBC(W.sub(0), u, "on_boundary"), ]
def test_solver_no_flow_region(): mesh = fd.Mesh("./2D_mesh.msh") no_flow = [2] no_flow_markers = [1] mesh = mark_no_flow_regions(mesh, no_flow, no_flow_markers) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) (v, q) = fd.TestFunctions(W) # Stokes 1 w_sol1 = fd.Function(W) nu = fd.Constant(0.05) F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0) x, y = fd.SpatialCoordinate(mesh) u_mms = fd.as_vector( [sin(2.0 * pi * x) * sin(pi * y), sin(pi * x) * sin(2.0 * pi * y)]) p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2) f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) - 2.0 * nu * div(sym(grad(u_mms)))) f_mms_p = div(u_mms) F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary") bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary") bc_no_flow = InteriorBC(W.sub(0), fd.Constant((0.0, 0.0)), no_flow_markers) solver_parameters = {"ksp_max_it": 500, "ksp_monitor": None} problem1 = fd.NonlinearVariationalProblem(F, w_sol1, bcs=[bc1, bc2, bc_no_flow]) solver1 = NavierStokesBrinkmannSolver( problem1, options_prefix="navier_stokes", solver_parameters=solver_parameters, ) solver1.solve() u_sol, _ = w_sol1.split() u_mms_func = fd.interpolate(u_mms, W.sub(0)) error = fd.errornorm(u_sol, u_mms_func) assert error < 0.07
def run_solver(r): mesh = fd.UnitSquareMesh(2**r, 2**r) P2 = fd.VectorElement("CG", mesh.ufl_cell(), 1) P1 = fd.FiniteElement("CG", mesh.ufl_cell(), 1) TH = P2 * P1 W = fd.FunctionSpace(mesh, TH) (v, q) = fd.TestFunctions(W) # Stokes 1 w_sol1 = fd.Function(W) nu = fd.Constant(0.05) F = NavierStokesBrinkmannForm(W, w_sol1, nu, beta_gls=2.0) from firedrake import sin, grad, pi, sym, div, inner x, y = fd.SpatialCoordinate(mesh) u_mms = fd.as_vector( [sin(2.0 * pi * x) * sin(pi * y), sin(pi * x) * sin(2.0 * pi * y)]) p_mms = -0.5 * (u_mms[0]**2 + u_mms[1]**2) f_mms_u = (grad(u_mms) * u_mms + grad(p_mms) - 2.0 * nu * div(sym(grad(u_mms)))) f_mms_p = div(u_mms) F += -inner(f_mms_u, v) * dx - f_mms_p * q * dx bc1 = fd.DirichletBC(W.sub(0), u_mms, "on_boundary") bc2 = fd.DirichletBC(W.sub(1), p_mms, "on_boundary") solver_parameters = {"ksp_max_it": 200} problem1 = fd.NonlinearVariationalProblem(F, w_sol1, bcs=[bc1, bc2]) solver1 = NavierStokesBrinkmannSolver( problem1, options_prefix="navier_stokes", solver_parameters=solver_parameters, ) solver1.solve() u_sol, _ = w_sol1.split() fd.File("test_u_sol.pvd").write(u_sol) u_mms_func = fd.interpolate(u_mms, W.sub(0)) error = fd.errornorm(u_sol, u_mms_func) print(f"Error: {error}") return error
def mms_dirichlet_boundary_conditions(sim, manufactured_solution): W = sim.function_space if type(sim.element) is fe.FiniteElement: w = (manufactured_solution, ) else: w = manufactured_solution return [fe.DirichletBC(V, g, "on_boundary") for V, g in zip(W, w)]
def coarsen_bcs(fbcs): cbcs = [] for bc in fbcs: cV_ = cV for index in bc._indices: cV_ = cV_.sub(index) cbc_value = self.coarsen_bc_value(bc, cV_) if type(bc) == firedrake.DirichletBC: cbcs.append(firedrake.DirichletBC(cV_, cbc_value, bc.sub_domain)) else: raise NotImplementedError("Unsupported BC type, please get in touch if you need this") return cbcs
def default_mms_dirichlet_boundary_conditions(sim, manufactured_solution): """Apply Dirichlet BC's to every component on every boundary.""" W = sim.solution_space if type(W.ufl_element()) is fe.FiniteElement: w = (manufactured_solution, ) else: w = manufactured_solution return [fe.DirichletBC(V, g, "on_boundary") for V, g in zip(W, w)]