def set_poisson_eq_2d(n=8): ''' Basic example where only the mesh refinement is controlled. ''' # mesh mesh = UnitSquareMesh(n, n) # function space V = FunctionSpace(mesh, 'P', 1) # bcs u_D = Expression('1 + x[0]*x[0] + 2*x[1]*x[1]', degree=2) def boundary(x, on_boundary): return on_boundary bc = DirichletBC(V, u_D, boundary) # variational problem u = TrialFunction(V) v = TestFunction(V) f = Constant(-6.0) a = dot(grad(u), grad(v)) * dx L = f * v * dx # define unknown u = Function(V) return a, L, u, bc
def test_linear_pde(): """Test Newton solver for a linear PDE""" # Create mesh and function space mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 12) V = dolfin.function.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfin.function.Function(V) v = function.TestFunction(V) F = inner(10.0, v) * dx - inner(grad(u), grad(v)) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[:, 0] < 1.0e-8, x[:, 0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector().set(1.0) u_bc.vector().update_ghosts() bc = fem.DirichletBC(V, u_bc, boundary) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve solver = dolfin.cpp.nls.NewtonSolver(dolfin.MPI.comm_world) n, converged = solver.solve(problem, u.vector()) assert converged assert n == 1
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and int(round(self.actual_time * 1000)) % 1000 == 0: self.isWholeSecond = True seconds = int(round(self.actual_time)) self.second_list.append(seconds) self.N1 = seconds*self.stepsInSecond self.N0 = (seconds-1)*self.stepsInSecond else: self.isWholeSecond = False # Update boundary condition self.tc.start('updateBC') if not self.ic == 'correct': self.v_in.t = self.actual_time self.tc.end('updateBC') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and int(round(self.actual_time * 1000)) % 1000 == 0: self.isWholeSecond = True seconds = int(round(self.actual_time)) self.second_list.append(seconds) self.N1 = seconds*self.stepsInSecond self.N0 = (seconds-1)*self.stepsInSecond else: self.isWholeSecond = False self.solution = self.assemble_solution(self.actual_time) # Update boundary condition self.tc.start('updateBC') self.v_in.assign(self.solution) self.tc.end('updateBC') # construct analytic pressure (used for computing pressure and force errors) self.tc.start('analyticP') analytic_pressure = womersleyBC.analytic_pressure(self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.tc.end('analyticP') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def get_inner_products(W, for_): # Test and trial functions block_v = BlockTestFunction(W) v, q = block_split(block_v) block_u = BlockTrialFunction(W) u, p = block_split(block_u) # Inner products assert for_ in ("POD", "L2 projection") if for_ == "POD": # x = { # "u": [[inner(grad(u), grad(v)) * dx]] # } x = { "u": [[inner(grad(u), grad(v)) * dx, 0], [0, 0]], "p": [[0, 0], [0, inner(p, q) * dx]] } elif for_ == "L2 projection": # x = { # "u": [[inner(u, v) * dx]] # } x = { "u": [[inner(u, v) * dx, 0], [0, 0]], "p": [[0, 0], [0, inner(p, q) * dx]] } return {c: block_assemble(x[c]) for c in components}
def nonlinearity(function): if self.use_ema: return 2*inner(dot(sym(grad(function)), u_ext), v1) * dx + inner(div(function)*u_ext, v1) * dx # return 2*inner(dot(sym(grad(function)), u_ext), v) * dx + inner(div(u_ext)*function, v) * dx # QQ implement this way? else: return inner(dot(grad(function), u_ext), v1) * dx
def test_physically_mapped_facet(): mesh = Mesh(VectorElement("P", triangle, 1)) # set up variational problem U = FiniteElement("Morley", mesh.ufl_cell(), 2) V = FiniteElement("P", mesh.ufl_cell(), 1) R = FiniteElement("P", mesh.ufl_cell(), 1) Vv = VectorElement(BrokenElement(V)) Qhat = VectorElement(BrokenElement(V[facet])) Vhat = VectorElement(V[facet]) Z = FunctionSpace(mesh, MixedElement(U, Vv, Qhat, Vhat, R)) z = Coefficient(Z) u, d, qhat, dhat, lam = split(z) s = FacetNormal(mesh) trans = as_matrix([[1, 0], [0, 1]]) mat = trans*grad(grad(u))*trans + outer(d, d) * u J = (u**2*dx + u**3*dx + u**4*dx + inner(mat, mat)*dx + inner(grad(d), grad(d))*dx + dot(s, d)**2*ds) L_match = inner(qhat, dhat - d) L = J + inner(lam, inner(d, d)-1)*dx + (L_match('+') + L_match('-'))*dS + L_match*ds compile_form(L)
def test_assemble_manifold(): """Test assembly of poisson problem on a mesh with topological dimension 1 but embedded in 2D (gdim=2). """ points = numpy.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0], [0.8, 0.0], [1.0, 0.0]], dtype=numpy.float64) cells = numpy.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]], dtype=numpy.int32) cell = ufl.Cell("interval", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) assert mesh.geometry.dim == 2 assert mesh.topology.dim == 1 U = dolfinx.FunctionSpace(mesh, ("P", 1)) u, v = ufl.TrialFunction(U), ufl.TestFunction(U) w = dolfinx.Function(U) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh) L = ufl.inner(1.0, v) * ufl.dx(mesh) bcdofs = dolfinx.fem.locate_dofs_geometrical( U, lambda x: numpy.isclose(x[0], 0.0)) bcs = [dolfinx.DirichletBC(w, bcdofs)] A = dolfinx.fem.assemble_matrix(a, bcs) A.assemble() b = dolfinx.fem.assemble_vector(L) dolfinx.fem.apply_lifting(b, [a], [bcs]) dolfinx.fem.set_bc(b, bcs) assert numpy.isclose(b.norm(), 0.41231) assert numpy.isclose(A.norm(), 25.0199)
def compute_err(self, is_tent, velocity, t): super(Problem, self).compute_err(is_tent, velocity, t) er_list_H1w = self.listDict['u2H1w' if is_tent else 'u_H1w']['list'] errorH1wall = sqrt(assemble((inner(grad(velocity - self.solution), grad(velocity - self.solution)) + inner(velocity - self.solution, velocity - self.solution)) * self.dsWall)) er_list_H1w.append(errorH1wall) print(' Relative H1wall error:', errorH1wall / self.analytic_v_norm_H1w)
def hyperelasticity(domain, q, p, nf=0): # Based on https://github.com/firedrakeproject/firedrake-bench/blob/experiments/forms/firedrake_forms.py V = ufl.FunctionSpace(domain, ufl.VectorElement('P', domain.ufl_cell(), q)) P = ufl.FunctionSpace(domain, ufl.VectorElement('P', domain.ufl_cell(), p)) v = ufl.TestFunction(V) du = ufl.TrialFunction(V) # Incremental displacement u = ufl.Coefficient(V) # Displacement from previous iteration B = ufl.Coefficient(V) # Body force per unit mass # Kinematics I = ufl.Identity(domain.ufl_cell().topological_dimension()) F = I + ufl.grad(u) # Deformation gradient C = F.T*F # Right Cauchy-Green tensor E = (C - I)/2 # Euler-Lagrange strain tensor E = ufl.variable(E) # Material constants mu = ufl.Constant(domain) # Lame's constants lmbda = ufl.Constant(domain) # Strain energy function (material model) psi = lmbda/2*(ufl.tr(E)**2) + mu*ufl.tr(E*E) S = ufl.diff(psi, E) # Second Piola-Kirchhoff stress tensor PK = F*S # First Piola-Kirchoff stress tensor # Variational problem it = ufl.inner(PK, ufl.grad(v)) - ufl.inner(B, v) f = [ufl.Coefficient(P) for _ in range(nf)] return ufl.derivative(reduce(ufl.inner, list(map(ufl.div, f)) + [it])*ufl.dx, u, du)
def tn_reg(lmda, mu, dx, R_lmda=1, R_mu=1): grad_lamda = grad(lmda) grad_mu = grad(mu) reg = 0.5 * R_lmda * inner(grad_lamda, grad_lamda) * dx + \ 0.5 * R_mu * inner(grad_mu, grad_mu) * dx Reg = assemble(reg) return Reg
def test_linear_pde(): """Test Newton solver for a linear PDE""" # Create mesh and function space mesh = dolfin.generation.UnitSquareMesh(dolfin.MPI.comm_world, 12, 12) V = functionspace.FunctionSpace(mesh, ("Lagrange", 1)) u = function.Function(V) v = function.TestFunction(V) F = inner(10.0, v) * dx - inner(grad(u), grad(v)) * dx def boundary(x): """Define Dirichlet boundary (x = 0 or x = 1).""" return np.logical_or(x[:, 0] < 1.0e-8, x[:, 0] > 1.0 - 1.0e-8) u_bc = function.Function(V) u_bc.vector.set(1.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) bc = fem.DirichletBC(V, u_bc, boundary) # Create nonlinear problem problem = NonlinearPDEProblem(F, u, bc) # Create Newton solver and solve solver = dolfin.cpp.nls.NewtonSolver(dolfin.MPI.comm_world) n, converged = solver.solve(problem, u.vector) assert converged assert n == 1 # Increment boundary condition and solve again u_bc.vector.set(2.0) u_bc.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) n, converged = solver.solve(problem, u.vector) assert converged assert n == 1
def compute_err(self, is_tent, velocity, t): if self.doErrControl: er_list_L2 = self.listDict['u2L2' if is_tent else 'u_L2']['list'] er_list_H1 = self.listDict['u2H1' if is_tent else 'u_H1']['list'] self.tc.start('errorV') # assemble is faster than errornorm errorL2_sq = assemble(inner(velocity - self.solution, velocity - self.solution) * dx) errorH1seminorm_sq = assemble(inner(grad(velocity - self.solution), grad(velocity - self.solution)) * dx) info(' H1 seminorm error: %f' % sqrt(errorH1seminorm_sq)) errorL2 = sqrt(errorL2_sq) errorH1 = sqrt(errorL2_sq + errorH1seminorm_sq) info(" Relative L2 error in velocity = %f" % (errorL2 / self.analytic_v_norm_L2)) self.last_error = errorH1 / self.analytic_v_norm_H1 self.last_status_functional = self.last_error info(" Relative H1 error in velocity = %f" % self.last_error) er_list_L2.append(errorL2) er_list_H1.append(errorH1) self.tc.end('errorV') if self.testErrControl: er_list_test_H1 = self.listDict['u2H1test' if is_tent else 'u_H1test']['list'] er_list_test_L2 = self.listDict['u2L2test' if is_tent else 'u_L2test']['list'] self.tc.start('errorVtest') er_list_test_L2.append(errornorm(velocity, self.solution, norm_type='L2', degree_rise=0)) er_list_test_H1.append(errornorm(velocity, self.solution, norm_type='H1', degree_rise=0)) self.tc.end('errorVtest') # stopping criteria for detecting diverging solution if self.last_error > self.divergence_treshold: raise RuntimeError('STOPPED: Failed divergence test!')
def test_expression_assemble(V1, vV1, squaremesh_5): u1, u2 = dolfinx.fem.Function(V1), dolfinx.fem.Function(vV1) dx = ufl.dx(squaremesh_5) u1.vector.set(3.0) u2.vector.set(2.0) u1.vector.ghostUpdate() u2.vector.ghostUpdate() # check assembled shapes assert numpy.shape(dolfiny.expression.assemble(1.0, dx)) == () assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u1), dx)) == (2, ) assert numpy.shape(dolfiny.expression.assemble(ufl.grad(u2), dx)) == (2, 2) # check assembled values assert numpy.isclose(dolfiny.expression.assemble(1.0, dx), 1.0) assert numpy.isclose(dolfiny.expression.assemble(u1, dx), 3.0) assert numpy.isclose(dolfiny.expression.assemble(u2, dx), 2.0).all() assert numpy.isclose(dolfiny.expression.assemble(u1 * u2, dx), 6.0).all() assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u1), dx), 0.0).all() assert numpy.isclose(dolfiny.expression.assemble(ufl.grad(u2), dx), 0.0).all()
def test_helmholtz_form_2d(mode, expected_result, compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) if mode == "double": k = 1.0 elif mode == "double complex": k = ufl.constantvalue.ComplexValue(1j) else: raise RuntimeError("Unknown mode type") a = (ufl.inner(ufl.grad(u), ufl.grad(v)) - ufl.inner(k * u, v)) * ufl.dx forms = [a] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) for f, compiled_f in zip(forms, compiled_forms): assert compiled_f.rank == len(f.arguments()) form0 = compiled_forms[0][0].create_cell_integral(-1) c_type, np_type = float_to_type(mode) A = np.zeros((3, 3), dtype=np_type) w = np.array([], dtype=np_type) c = np.array([], dtype=np_type) ffi = cffi.FFI() coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) assert np.allclose(A, expected_result)
def test_laplace_bilinear_form_3d(mode, expected_result, compile_args): cell = ufl.tetrahedron element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx forms = [a] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) for f, compiled_f in zip(forms, compiled_forms): assert compiled_f.rank == len(f.arguments()) form0 = compiled_forms[0][0].create_cell_integral(-1) c_type, np_type = float_to_type(mode) A = np.zeros((4, 4), dtype=np_type) w = np.array([], dtype=np_type) c = np.array([], dtype=np_type) ffi = cffi.FFI() coords = np.array([0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) assert np.allclose(A, expected_result)
def test_cache_modes(compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx forms = [a] # Load form from /tmp compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, cffi_extra_compile_args=compile_args) tmpname = module.__name__ tmpfile = module.__file__ print(tmpname, tmpfile) del sys.modules[tmpname] # Load form from cache compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, cache_dir="./compile-cache", cffi_extra_compile_args=compile_args) newname = module.__name__ newfile = module.__file__ print(newname, newfile) assert (newname == tmpname) assert (newfile != tmpfile)
def laplace_coeff_action_forms(mesh, el, coeff_el): Q = dolfin.function.functionspace.FunctionSpace(mesh, el) u = dolfin.function.argument.TrialFunction(Q) v = dolfin.function.argument.TestFunction(Q) """ def boundary(x): return np.sum(np.logical_or(x < DOLFIN_EPS, x > 1.0 - DOLFIN_EPS), axis=1) > 0 """ # u_bc = dolfin.function.constant.Constant(50.0) # bc = dolfin.fem.dirichletbc.DirichletBC(Q, u_bc, boundary) c = dolfin.function.expression.Expression("3.14*x[0]", element=coeff_el) f = dolfin.function.expression.Expression("0.4*x[1]*x[2]", element=el) a = inner(c * grad(u), grad(v)) * dx L = f * v * dx w = dolfin.Function(Q) w.vector().set(1.2) L = ufl.action(a, w) return None, L, None
def update_time(self, actual_time, step_number): super(Problem, self).update_time(actual_time, step_number) if self.actual_time > 0.5 and abs(math.modf(actual_time)[0]) < 0.5*self.metadata['dt']: self.second_list.append(int(round(self.actual_time))) self.solution = self.assemble_solution(self.actual_time) # Update boundary condition self.tc.start('updateBC') self.v_in.assign(self.onset_factor * self.solution) self.tc.end('updateBC') # construct analytic pressure (used for computing pressure and force errors) self.tc.start('analyticP') analytic_pressure = womersleyBC.analytic_pressure(self.factor, self.actual_time) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.tc.end('analyticP') self.tc.start('analyticVnorms') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) self.listDict['av_norm_L2']['list'].append(self.analytic_v_norm_L2) self.listDict['av_norm_H1']['list'].append(self.analytic_v_norm_H1) self.listDict['av_norm_H1w']['list'].append(self.analytic_v_norm_H1w) self.tc.end('analyticVnorms')
def tv_reg(lmda, mu, dx, R_lmda=1, R_mu=1, eps=1e-10): grad_lamda = grad(lmda) grad_mu = grad(mu) integrand_lmda = R_lmda * sqrt(inner(grad_lamda, grad_lamda) + eps) * dx integrand_mu = R_mu * sqrt(inner(grad_mu, grad_mu) + eps) * dx return assemble(integrand_lmda + integrand_mu)
def fenics_solve(f): u = fa.Function(V, name="State") v = fn.TestFunction(V) F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f * v) * ufl.dx bcs = [fa.DirichletBC(V, 0.0, "on_boundary")] fa.solve(F == 0, u, bcs) return u
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 solve_equation(): mesh = UnitSquareMesh(32, 32) V = FunctionSpace(mesh, "Lagrange", 1) def boundary(x, on_boundary): return on_boundary u0 = Expression("cos(10 * x[0])", degree=2) bc = DirichletBC(V, u0, boundary) u = TrialFunction(V) v = TestFunction(V) f = Expression("(x[0] - 0.5)*(x[0] - 0.5)", degree=2) a = inner(grad(u), grad(v)) * dx L = f * v * dx u = Function(V) solve(a == L, u, bc) # Plot solution at current time step fig = plt.figure() plot(u, fig=fig) plt.show() print("The norm of u is {}".format(u.vector().norm("l2")))
def initialize(self, V, Q, PS, D): super(Problem, self).initialize(V, Q, PS, D) print("IC type: " + self.ic) print("Velocity scale factor = %4.2f" % self.factor) reynolds = 728.761 * self.factor print("Computing with Re = %f" % reynolds) # set constants for self.area = assemble(interpolate(Expression("1.0"), Q) * self.dsIn) # inflow area self.solution = interpolate(Expression(("0.0", "0.0", "factor*(1081.48-43.2592*(x[0]*x[0]+x[1]*x[1]))"), factor=self.factor), self.vSpace) analytic_pressure = womersleyBC.average_analytic_pressure_expr(self.factor) self.sol_p = interpolate(analytic_pressure, self.pSpace) self.analytic_gradient = womersleyBC.average_analytic_pressure_grad(self.factor) self.analytic_pressure_norm = norm(self.sol_p, norm_type='L2') self.analytic_v_norm_L2 = norm(self.solution, norm_type='L2') self.analytic_v_norm_H1 = norm(self.solution, norm_type='H1') self.analytic_v_norm_H1w = sqrt(assemble((inner(grad(self.solution), grad(self.solution)) + inner(self.solution, self.solution)) * self.dsWall)) print("Prepared analytic solution.") self.pg_normalization_factor.append(womersleyBC.average_analytic_pressure_grad(self.factor)) self.p_normalization_factor.append(self.analytic_pressure_norm) self.vel_normalization_factor.append(norm(self.solution, norm_type='L2')) print('Normalisation factors (vel, p, pg):', self.vel_normalization_factor[0], self.p_normalization_factor[0], self.pg_normalization_factor[0]) one = (interpolate(Expression('1.0'), Q)) self.outflow_area = assemble(one*self.dsOut) print('Outflow area:', self.outflow_area)
def run_scalar_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx # Get quadrature degree for bilinear form integrand (ignores effect of non-affine map) a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1}) a.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) a = form(a) # Source term x = SpatialCoordinate(mesh) u_exact = x[1]**degree f = -div(grad(u_exact)) # Set quadrature degree for linear form integrand (ignores effect of non-affine map) L = inner(f, v) * dx(metadata={"quadrature_degree": -1}) L.integrals()[0].metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) L = form(L) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition facetdim = mesh.topology.dim - 1 mesh.topology.create_connectivity(facetdim, mesh.topology.dim) bndry_facets = np.where( np.array(compute_boundary_facets(mesh.topology)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) bc = dirichletbc(u_bc, bdofs) b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) a = form(a) A = assemble_matrix(a, bcs=[bc]) A.assemble() # Create LU linear solver solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A) uh = Function(V) solver.solve(b, uh.vector) uh.x.scatter_forward() M = (u_exact - uh)**2 * dx M = form(M) error = mesh.comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def monolithic_solve(): """Monolithic (interleaved) solver""" P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2) P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) TH = P2_el * P1_el W = FunctionSpace(mesh, TH) (u, p) = ufl.TrialFunctions(W) (v, q) = ufl.TestFunctions(W) a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx a01 = ufl.inner(p, ufl.div(v)) * dx a10 = ufl.inner(ufl.div(u), q) * dx a = a00 + a01 + a10 p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx p11 = ufl.inner(p, q) * dx p_form = p00 + p11 f = Function(W.sub(0).collapse()[0]) p_zero = Function(W.sub(1).collapse()[0]) L0 = inner(f, v) * dx L1 = inner(p_zero, q) * dx L = L0 + L1 a, p_form, L = form(a), form(p_form), form(L) bdofsW0_P2_0 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets0) bdofsW0_P2_1 = locate_dofs_topological(W.sub(0), facetdim, bndry_facets1) bc0 = dirichletbc(bc_value, bdofsW0_P2_0, W.sub(0)) bc1 = dirichletbc(bc_value, bdofsW0_P2_1, W.sub(0)) A = assemble_matrix(a, bcs=[bc0, bc1]) A.assemble() P = assemble_matrix(p_form, bcs=[bc0, bc1]) P.assemble() b = assemble_vector(L) apply_lifting(b, [a], bcs=[[bc0, bc1]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc0, bc1]) ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A, P) ksp.setType("minres") pc = ksp.getPC() pc.setType('lu') def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = A.createVecRight() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), A.norm(), P.norm()
def eval_cost_fem(w, rho): u, _ = fenics.split(w) J_form = ( 0.5 * ufl.inner(alpha(rho) * u, u) * ufl.dx + mu * ufl.inner(ufl.grad(u), ufl.grad(u)) * ufl.dx ) J = fenics_adjoint.assemble(J_form) return J
def rP(self, u, alpha, v, beta): w_1 = self.w(1) a = self.a sigma = self.sigma eps = self.eps return inner(sqrt(a(alpha))*sigma(v) + diff(a(alpha), alpha)/sqrt(a(alpha))*sigma(u)*beta, sqrt(a(alpha))*eps(v) + diff(a(alpha), alpha)/sqrt(a(alpha))*eps(u)*beta) + \ 2*w_1*self.ell ** 2 * dot(grad(beta), grad(beta))
def helmholtz(domain, q, p, nf=0): # Based on https://github.com/firedrakeproject/firedrake-bench/blob/experiments/forms/firedrake_forms.py V = ufl.FunctionSpace(domain, ufl.FiniteElement('P', domain.ufl_cell(), q)) P = ufl.FunctionSpace(domain, ufl.FiniteElement('P', domain.ufl_cell(), p)) u = ufl.TrialFunction(V) v = ufl.TestFunction(V) f = [ufl.Coefficient(P) for _ in range(nf)] it = ufl.dot(ufl.grad(v), ufl.grad(u)) + 1.0*v*u return reduce(ufl.inner, f + [it])*ufl.dx
def solve_system(N): fenics_mesh = dolfinx.UnitCubeMesh(fenicsx_comm, N, N, N) fenics_space = dolfinx.FunctionSpace(fenics_mesh, ("CG", 1)) u = ufl.TrialFunction(fenics_space) v = ufl.TestFunction(fenics_space) k = 2 # print(u*v*ufl.ds) form = (ufl.inner(ufl.grad(u), ufl.grad(v)) - k**2 * ufl.inner(u, v)) * ufl.dx # locate facets on the cube boundary facets = locate_entities_boundary( fenics_mesh, 2, lambda x: np.logical_or( np.logical_or( np.logical_or(np.isclose(x[2], 0.0), np.isclose(x[2], 1.0)), np.logical_or(np.isclose(x[1], 0.0), np.isclose(x[1], 1.0))), np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0)))) facets.sort() # alternative - more general approach boundary = entities_to_geometry( fenics_mesh, fenics_mesh.topology.dim - 1, exterior_facet_indices(fenics_mesh), True, ) # print(len(facets) assert len(facets) == len(exterior_facet_indices(fenics_mesh)) u0 = fem.Function(fenics_space) with u0.vector.localForm() as u0_loc: u0_loc.set(0) # solution vector bc = DirichletBC(u0, locate_dofs_topological(fenics_space, 2, facets)) A = 1 + 1j f = Function(fenics_space) f.interpolate(lambda x: A * k**2 * np.cos(k * x[0]) * np.cos(k * x[1])) L = ufl.inner(f, v) * ufl.dx u0.name = "u" problem = fem.LinearProblem(form, L, u=u0, petsc_options={ "ksp_type": "preonly", "pc_type": "lu" }) # problem = fem.LinearProblem(form, L, bcs=[bc], u=u0, petsc_options={"ksp_type": "preonly", "pc_type": "lu"}) start_time = time.time() soln = problem.solve() if world_rank == 0: print("--- fenics solve done in %s seconds ---" % (time.time() - start_time))
def velocity_expression(theta_k, theta_kp1, dt): theta_avg = avg(theta_k, theta_kp1, implicitness=.5) velocity_form_ = ( (theta_kp1 - theta_k) / dt / ufl.sqrt(inner(grad(theta_avg), grad(theta_avg)) + DOLFIN_EPS) ) return velocity_form_
def test_mini(): m = Mesh(VectorElement('CG', triangle, 1)) P1 = FiniteElement('Lagrange', triangle, 1) B = FiniteElement("Bubble", triangle, 3) V = FunctionSpace(m, VectorElement(P1 + B)) u = TrialFunction(V) v = TestFunction(V) a = inner(grad(u), grad(v)) * dx count_flops(a)
def forms(arguments, coefficients): v, u = arguments c, f = coefficients n = FacetNormal(triangle) a = u * v * dx L = f * v * dx b = u * v * dx(0) + inner(c * grad(u), grad(v)) * \ dx(1) + dot(n, grad(u)) * v * ds + f * v * dx return (a, L, b)
def sqrt_precision_varf_handler(trial, test): if Theta == None: varfL = ufl.inner(ufl.grad(trial), ufl.grad(test)) * ufl.dx else: varfL = ufl.inner(Theta * ufl.grad(trial), ufl.grad(test)) * ufl.dx varfM = ufl.inner(trial, test) * ufl.dx varfmo = mfun * ufl.inner(trial, test) * ufl.dx return dl.Constant(gamma) * varfL + dl.Constant( delta) * varfM + dl.Constant(pen) * varfmo
def test_compute_form_adjoint(self): cell = triangle element = FiniteElement('Lagrange', cell, 1) u = TrialFunction(element) v = TestFunction(element) a = inner(grad(u), grad(v)) * dx assert compute_form_adjoint(a) == conj(inner(grad(v), grad(u))) * dx
def compute_err(self, is_tent, velocity, t): super(Problem, self).compute_err(is_tent, velocity, t) er_list_H1w = self.listDict['u2H1w' if is_tent else 'u_H1w']['list'] errorH1wall = sqrt(assemble((inner(grad(velocity - self.solution), grad(velocity - self.solution)) + inner(velocity - self.solution, velocity - self.solution)) * self.dsWall)) er_list_H1w.append(errorH1wall) print(' Relative H1wall error:', errorH1wall / self.analytic_v_norm_H1w) if self.isWholeSecond: self.listDict['u2H1w' if is_tent else 'u_H1w']['slist'].append( sqrt(sum([i*i for i in er_list_H1w[self.N0:self.N1]])/self.stepsInSecond))
def HodgeLaplaceGradCurl(element, felement): tau, v = TestFunctions(element) sigma, u = TrialFunctions(element) f = Coefficient(felement) a = (inner(tau, sigma) - inner(grad(tau), u) + inner(v, grad(sigma)) + inner(curl(v), curl(u))) * dx L = inner(v, f) * dx return a, L
def a(u_k, u_kp1, v, control_k, vhc, kappa, cooling_bc, laser_bc, dt, implicitness, x, ds): u_avg = avg(u_k, u_kp1, implicitness) a_ = vhc(u_k) * (u_kp1 - u_k) * v * x[0] * dx\ + dt * inner(kappa(u_k) * grad(u_avg), grad(v)) * x[0] * dx\ - dt * laser_bc(control_k) * v * x[0] * ds(1)\ - dt * cooling_bc(u_avg) * v * x[0] * (ds(1) + ds(2) + ds(4)) return a_
def test_conditional(mode, compile_args): cell = ufl.triangle element = ufl.FiniteElement("Lagrange", cell, 1) u, v = ufl.TrialFunction(element), ufl.TestFunction(element) x = ufl.SpatialCoordinate(cell) condition = ufl.Or(ufl.ge(ufl.real(x[0] + x[1]), 0.1), ufl.ge(ufl.real(x[1] + x[1]**2), 0.1)) c1 = ufl.conditional(condition, 2.0, 1.0) a = c1 * ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx x1x2 = ufl.real(x[0] + ufl.as_ufl(2) * x[1]) c2 = ufl.conditional(ufl.ge(x1x2, 0), 6.0, 0.0) b = c2 * ufl.conj(v) * ufl.dx forms = [a, b] compiled_forms, module = ffcx.codegeneration.jit.compile_forms( forms, parameters={'scalar_type': mode}, cffi_extra_compile_args=compile_args) form0 = compiled_forms[0][0].create_cell_integral(-1) form1 = compiled_forms[1][0].create_cell_integral(-1) ffi = cffi.FFI() c_type, np_type = float_to_type(mode) A1 = np.zeros((3, 3), dtype=np_type) w1 = np.array([1.0, 1.0, 1.0], dtype=np_type) c = np.array([], dtype=np.float64) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form0.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w1.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.array([[2, -1, -1], [-1, 1, 0], [-1, 0, 1]], dtype=np_type) assert np.allclose(A1, expected_result) A2 = np.zeros(3, dtype=np_type) w2 = np.array([1.0, 1.0, 1.0], dtype=np_type) coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) form1.tabulate_tensor( ffi.cast('{type} *'.format(type=c_type), A2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), w2.ctypes.data), ffi.cast('{type} *'.format(type=c_type), c.ctypes.data), ffi.cast('double *', coords.ctypes.data), ffi.NULL, ffi.NULL, 0) expected_result = np.ones(3, dtype=np_type) assert np.allclose(A2, expected_result)
def save_vel(self, is_tent, field, t): self.vFunction.assign(field) self.fileDict['u2' if is_tent else 'u']['file'] << self.vFunction if self.doSaveDiff: self.vFunction.assign((1.0 / self.vel_normalization_factor[0]) * (field - self.solution)) self.fileDict['u2D' if is_tent else 'uD']['file'] << self.vFunction if self.args.ldsg: # info(div(2.*sym(grad(field))-grad(field)).ufl_shape) form = div(2.*sym(grad(field))-grad(field)) self.pFunction.assign(project(sqrt_ufl(inner(form, form)), self.pSpace)) self.fileDict['ldsg2' if is_tent else 'ldsg']['file'] << self.pFunction
def diffusion(fce): if self.useLaplace: return nu * inner(grad(fce), grad(v1)) * dx else: form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx if self.bcv == 'CDN': return form if self.bcv == 'LAP': return form - inner(nu * dot(grad(fce).T, n), v1) * problem.get_outflow_measure_form() if self.bcv == 'DDN': return form # additional term must be added to non-constant part
def test_gradient_error(cell, degree): """Test that tabulating gradient evaluations of the trace element triggers `gem.Failure` to raise the TraceError exception. """ trace_element = FiniteElement("HDiv Trace", cell, degree) lambdar = TrialFunction(trace_element) gammar = TestFunction(trace_element) with pytest.raises(TraceError): compile_form(inner(grad(lambdar('+')), grad(gammar('+'))) * dS)
def norm(v, norm_type="L2", mesh=None): """Compute the norm of ``v``. :arg v: a :class:`.Function` to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ assert isinstance(v, function.Function) typ = norm_type.lower() mesh = v.function_space().mesh() dx = mesh._dx if typ == 'l2': form = inner(v, v)*dx elif typ == 'h1': form = inner(v, v)*dx + inner(grad(v), grad(v))*dx elif typ == "hdiv": form = inner(v, v)*dx + div(v)*div(v)*dx elif typ == "hcurl": form = inner(v, v)*dx + inner(curl(v), curl(v))*dx else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return sqrt(solving.assemble(form))
def diffusion(fce): if self.useLaplace: return nu*inner(grad(fce), grad(v1)) * dx else: form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx if self.bcv == 'CDN': # IMP will work only if p=0 on output, or we must add term # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer return form if self.bcv == 'LAP': return form - inner(nu*dot(grad(fce).T, n), v1) * problem.get_outflow_measure_form() if self.bcv == 'DDN': # IMP will work only if p=0 on output, or we must add term # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer return form # additional term must be added to non-constant part
def norm(v, norm_type="L2", mesh=None): """Compute the norm of ``v``. :arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: * L2 .. math:: ||v||_{L^2}^2 = \int (v, v) \mathrm{d}x * H1 .. math:: ||v||_{H^1}^2 = \int (v, v) + (\\nabla v, \\nabla v) \mathrm{d}x * Hdiv .. math:: ||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\\nabla\cdot v, \\nabla \cdot v) \mathrm{d}x * Hcurl .. math:: ||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\\nabla \wedge v, \\nabla \wedge v) \mathrm{d}x """ typ = norm_type.lower() if typ == 'l2': form = inner(v, v)*dx elif typ == 'h1': form = inner(v, v)*dx + inner(grad(v), grad(v))*dx elif typ == "hdiv": form = inner(v, v)*dx + div(v)*div(v)*dx elif typ == "hcurl": form = inner(v, v)*dx + inner(curl(v), curl(v))*dx else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return sqrt(assemble(form))
def compute_functionals(self, velocity, pressure, t): if self.args.wss: info('Computing stress tensor') I = Identity(velocity.geometric_dimension()) T = TensorFunctionSpace(self.mesh, 'Lagrange', 1) stress = project(-pressure*I + 2*sym(grad(velocity)), T) info('Generating boundary mesh') wall_mesh = BoundaryMesh(self.mesh, 'exterior') # wall_mesh = SubMesh(self.mesh, self.facet_function, 1) # QQ why does not work? # plot(wall_mesh, interactive=True) info(' Boundary mesh geometric dim: %d' % wall_mesh.geometry().dim()) info(' Boundary mesh topologic dim: %d' % wall_mesh.topology().dim()) info('Projecting stress to boundary mesh') Tb = TensorFunctionSpace(wall_mesh, 'Lagrange', 1) stress_b = interpolate(stress, Tb) self.fileDict['wss']['file'] << stress_b if False: # does not work info('Computing WSS') n = FacetNormal(wall_mesh) info(stress_b, True) # wss = stress_b*n - inner(stress_b*n, n)*n wss = dot(stress_b, n) - inner(dot(stress_b, n), n)*n # equivalent Vb = VectorFunctionSpace(wall_mesh, 'Lagrange', 1) Sb = FunctionSpace(wall_mesh, 'Lagrange', 1) # wss_func = project(wss, Vb) wss_norm = project(sqrt(inner(wss, wss)), Sb) plot(wss_norm, interactive=True)
def test_latex_formatting_of_derivatives(): xx = ufl.SpatialCoordinate(ufl.triangle) x = xx[0] # Test derivatives of basic operators assert expr2latex(x.dx(0)) == "1" assert expr2latex(x.dx(1)) == "0" assert expr2latex(ufl.grad(xx)[0, 0]) == "1" assert expr2latex(ufl.grad(xx)[0, 1]) == "0" assert expr2latex(ufl.sin(x).dx(0)) == r"\cos(x_0)" # Test derivatives of form arguments V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2latex(f.dx(0)) == r"\overset{0}{w}_{, 0}" v = ufl.Argument(V, number=3) assert expr2latex(v.dx(1)) == r"\overset{3}{v}_{, 1}"
def test_cpp_formatting_of_derivatives(): xx = ufl.SpatialCoordinate(ufl.triangle) x, y = xx # Test derivatives of basic operators assert expr2cpp(x.dx(0)) == "1" assert expr2cpp(x.dx(1)) == "0" assert expr2cpp(ufl.grad(xx)[0, 0]) == "1" assert expr2cpp(ufl.grad(xx)[0, 1]) == "0" assert expr2cpp(ufl.sin(x).dx(0)) == "cos(x[0])" # Test derivatives of target specific test fakes V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2cpp(f.dx(0)) == "d1_w0[0]" v = ufl.Argument(V, number=3) assert expr2cpp(v.dx(1)) == "d1_v3[1]" # NOT renumbered to 0...
def compute_functionals(self, velocity, pressure, t, step): if self.args.wss == 'all' or \ (step >= self.stepsInCycle and self.args.wss == 'peak' and (self.distance_from_chosen_steps < 0.5 * self.metadata['dt'])): # TODO check if choosing time steps works properly # QQ might skip step? change 0.5 to 0.51? self.tc.start('WSS') begin('WSS (%dth step)' % step) if self.args.wss_method == 'expression': stress = project(self.nu*2*sym(grad(velocity)), self.T) # pressure is not used as it contributes only to the normal component stress.set_allow_extrapolation(True) # need because of some inaccuracies in BoundaryMesh coordinates stress_b = interpolate(stress, self.Tb) # restrict stress to boundary mesh # self.fileDict['stress']['file'].write(stress_b, self.actual_time) # info('Saved stress tensor') info('Computing WSS') wss = dot(stress_b, self.nb) - inner(dot(stress_b, self.nb), self.nb)*self.nb wss_func = project(wss, self.Vb) wss_norm = project(sqrt_ufl(inner(wss, wss)), self.Sb) info('Saving WSS') self.fileDict['wss']['file'].write(wss_func, self.actual_time) self.fileDict['wss_norm']['file'].write(wss_norm, self.actual_time) if self.args.wss_method == 'integral': wss_norm = Function(self.SDG) mS = TestFunction(self.SDG) scaling = 1/FacetArea(self.mesh) stress = self.nu*2*sym(grad(velocity)) wss = dot(stress, self.normal) - inner(dot(stress, self.normal), self.normal)*self.normal wss_norm_form = scaling*mS*sqrt_ufl(inner(wss, wss))*ds # ds is integral over exterior facets only assemble(wss_norm_form, tensor=wss_norm.vector()) self.fileDict['wss_norm']['file'].write(wss_norm, self.actual_time) # to get vector WSS values: # NT this works, but in ParaView for (DG,1)-vector space glyphs are displayed in cell centers # wss_vector = [] # for i in range(3): # wss_component = Function(self.SDG) # wss_vector_form = scaling*wss[i]*mS*ds # assemble(wss_vector_form, tensor=wss_component.vector()) # wss_vector.append(wss_component) # wss_func = project(as_vector(wss_vector), self.VDG) # self.fileDict['wss']['file'].write(wss_func, self.actual_time) self.tc.end('WSS') end()
def test_latex_formatting_of_variables(): x, y = ufl.SpatialCoordinate(ufl.triangle) # Test user-provided C variables for subexpressions # we can use variables for x[0], and sum, and power assert expr2latex(x**2 + y**2, variables={x**2: 'x2', y**2: 'y2'}) == "x2 + y2" assert expr2latex(x**2 + y**2, variables={x: 'z', y**2: 'y2'}) == r"{z}^{2} + y2" assert expr2latex(x**2 + y**2, variables={x**2 + y**2: 'q'}) == "q" # we can use variables in conditionals if 0: assert expr2latex(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8), variables={ufl.eq(x, 2): 'c1', ufl.ne(y, 4): 'c2'}) == "c1 || c2 ? 7: 8" # we can replace coefficients (formatted by user provided code) V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2latex(f, variables={f: 'f'}) == "f" assert expr2latex(f**3, variables={f: 'f'}) == r"{f}^{3}" # variables do not replace derivatives of variable expressions assert expr2latex(f.dx(0), variables={f: 'f'}) == r"\overset{0}{w}_{, 0}" # variables do replace variable expressions that are themselves derivatives assert expr2latex(f.dx(0), variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df" assert expr2latex(ufl.grad(f)[0], variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df"
def split_vector_laplace(cell, degree): m = Mesh(VectorElement('CG', cell, 1)) if cell.cellname() in ['interval * interval', 'quadrilateral']: hcurl_element = FiniteElement('RTCE', cell, degree) elif cell.cellname() == 'triangle * interval': U0 = FiniteElement('RT', triangle, degree) U1 = FiniteElement('CG', triangle, degree) V0 = FiniteElement('CG', interval, degree) V1 = FiniteElement('DG', interval, degree - 1) Wa = HCurlElement(TensorProductElement(U0, V0)) Wb = HCurlElement(TensorProductElement(U1, V1)) hcurl_element = EnrichedElement(Wa, Wb) elif cell.cellname() == 'quadrilateral * interval': hcurl_element = FiniteElement('NCE', cell, degree) RT = FunctionSpace(m, hcurl_element) CG = FunctionSpace(m, FiniteElement('Q', cell, degree)) sigma = TrialFunction(CG) u = TrialFunction(RT) tau = TestFunction(CG) v = TestFunction(RT) return [dot(u, grad(tau))*dx, dot(grad(sigma), v)*dx, dot(curl(u), curl(v))*dx]
def test_expand_indices(): element = FiniteElement("Lagrange", triangle, 2) v = TestFunction(element) u = TrialFunction(element) def evaluate(form): return form.cell_integral()[0].integrand()((), {v: 3, u: 5}) # TODO: How to define values of derivatives? a = div(grad(v)) * u * dx # a1 = evaluate(a) a = expand_derivatives(a) # a2 = evaluate(a) a = expand_indices(a)
def norm(v, norm_type="L2", mesh=None): r"""Compute the norm of ``v``. :arg v: a ufl expression (:class:`~.ufl.classes.Expr`) to compute the norm of :arg norm_type: the type of norm to compute, see below for options. :arg mesh: an optional mesh on which to compute the norm (currently ignored). Available norm types are: - Lp :math:`||v||_{L^p} = (\int |v|^p)^{\frac{1}{p}} \mathrm{d}x` - H1 :math:`||v||_{H^1}^2 = \int (v, v) + (\nabla v, \nabla v) \mathrm{d}x` - Hdiv :math:`||v||_{H_\mathrm{div}}^2 = \int (v, v) + (\nabla\cdot v, \nabla \cdot v) \mathrm{d}x` - Hcurl :math:`||v||_{H_\mathrm{curl}}^2 = \int (v, v) + (\nabla \wedge v, \nabla \wedge v) \mathrm{d}x` """ typ = norm_type.lower() p = 2 if typ == 'l2': expr = inner(v, v) elif typ.startswith('l'): try: p = int(typ[1:]) if p < 1: raise ValueError except ValueError: raise ValueError("Don't know how to interpret %s-norm" % norm_type) expr = inner(v, v) elif typ == 'h1': expr = inner(v, v) + inner(grad(v), grad(v)) elif typ == "hdiv": expr = inner(v, v) + div(v)*div(v) elif typ == "hcurl": expr = inner(v, v) + inner(curl(v), curl(v)) else: raise RuntimeError("Unknown norm type '%s'" % norm_type) return assemble((expr**(p/2))*dx)**(1/p)
def test_cpp_formatting_with_variables(): x, y = ufl.SpatialCoordinate(ufl.triangle) # Test user-provided C variables for subexpressions # we can use variables for x[0], and sum, and power assert expr2cpp(x**2 + y**2, variables={x**2: 'x2', y**2: 'y2'}) == "x2 + y2" assert expr2cpp(x**2 + y**2, variables={x: 'z', y**2: 'y2'}) == "pow(z, 2) + y2" assert expr2cpp(x**2 + y**2, variables={x**2 + y**2: 'q'}) == "q" # we can use variables in conditionals assert expr2cpp(ufl.conditional(ufl.Or(ufl.eq(x, 2), ufl.ne(y, 4)), 7, 8), variables={ufl.eq(x, 2): 'c1', ufl.ne(y, 4): 'c2'}) == "c1 || c2 ? 7: 8" # we can replace coefficients (formatted by user provided code) V = ufl.FiniteElement("CG", ufl.triangle, 1) f = ufl.Coefficient(V, count=0) assert expr2cpp(f, variables={f: 'f'}) == "f" assert expr2cpp(f**3, variables={f: 'f'}) == "pow(f, 3)" # variables do not replace derivatives of variable expressions assert expr2cpp(f.dx(0), variables={f: 'f'}) == "d1_w0[0]" # This test depends on which differentiation algorithm is in use # in UFL, representing derivatives as SpatialDerivative or Grad: # variables do replace variable expressions that are themselves derivatives assert expr2cpp(f.dx(0), variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df" assert expr2cpp(ufl.grad(f)[0], variables={f.dx(0): 'df', ufl.grad(f)[0]: 'df'}) == "df"
def solve(self, problem): self.problem = problem doSave = problem.doSave save_this_step = False onlyVel = problem.saveOnlyVel dt = self.metadata['dt'] nu = Constant(self.problem.nu) # TODO check proper use of watches self.tc.init_watch('init', 'Initialization', True, count_to_percent=False) self.tc.init_watch('rhs', 'Assembled right hand side', True, count_to_percent=True) self.tc.init_watch('updateBC', 'Updated velocity BC', True, count_to_percent=True) self.tc.init_watch('applybc1', 'Applied velocity BC 1st step', True, count_to_percent=True) self.tc.init_watch('applybc3', 'Applied velocity BC 3rd step', True, count_to_percent=True) self.tc.init_watch('applybcP', 'Applied pressure BC or othogonalized rhs', True, count_to_percent=True) self.tc.init_watch('assembleMatrices', 'Initial matrix assembly', False, count_to_percent=True) self.tc.init_watch('solve 1', 'Running solver on 1st step', True, count_to_percent=True) self.tc.init_watch('solve 2', 'Running solver on 2nd step', True, count_to_percent=True) self.tc.init_watch('solve 3', 'Running solver on 3rd step', True, count_to_percent=True) self.tc.init_watch('solve 4', 'Running solver on 4th step', True, count_to_percent=True) self.tc.init_watch('assembleA1', 'Assembled A1 matrix (without stabiliz.)', True, count_to_percent=True) self.tc.init_watch('assembleA1stab', 'Assembled A1 stabilization', True, count_to_percent=True) self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True) self.tc.init_watch('saveVel', 'Saved velocity', True) self.tc.start('init') # Define function spaces (P2-P1) mesh = self.problem.mesh self.V = VectorFunctionSpace(mesh, "Lagrange", 2) # velocity self.Q = FunctionSpace(mesh, "Lagrange", 1) # pressure self.PS = FunctionSpace(mesh, "Lagrange", 2) # partial solution (must be same order as V) self.D = FunctionSpace(mesh, "Lagrange", 1) # velocity divergence space if self.bc == 'lagrange': L = FunctionSpace(mesh, "R", 0) QL = self.Q*L problem.initialize(self.V, self.Q, self.PS, self.D) # Define trial and test functions u = TrialFunction(self.V) v = TestFunction(self.V) if self.bc == 'lagrange': (pQL, rQL) = TrialFunction(QL) (qQL, lQL) = TestFunction(QL) else: p = TrialFunction(self.Q) q = TestFunction(self.Q) n = FacetNormal(mesh) I = Identity(u.geometric_dimension()) # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure [u1, u0, p0] = self.problem.get_initial_conditions([{'type': 'v', 'time': -dt}, {'type': 'v', 'time': 0.0}, {'type': 'p', 'time': 0.0}]) if doSave: problem.save_vel(False, u0, 0.0) problem.save_vel(True, u0, 0.0) u_ = Function(self.V) # current tentative velocity u_cor = Function(self.V) # current corrected velocity if self.bc == 'lagrange': p_QL = Function(QL) # current pressure or pressure help function from rotation scheme pQ = Function(self.Q) # auxiliary function for conversion between QL.sub(0) and Q else: p_ = Function(self.Q) # current pressure or pressure help function from rotation scheme p_mod = Function(self.Q) # current modified pressure from rotation scheme # Define coefficients k = Constant(self.metadata['dt']) f = Constant((0, 0, 0)) # Define forms # step 1: Tentative velocity, solve to u_ u_ext = 1.5*u0 - 0.5*u1 # extrapolation for convection term # Stabilisation h = CellSize(mesh) # CBC delta: if self.cbcDelta: delta = Constant(self.stabCoef)*h/(sqrt(inner(u_ext, u_ext))+h) else: delta = Constant(self.stabCoef)*h**2/(2*nu*k + k*h*inner(u_ext, u_ext)+h**2) if self.use_full_SUPG: v1 = v + delta*0.5*k*dot(grad(v), u_ext) parameters['form_compiler']['quadrature_degree'] = 6 else: v1 = v def nonlinearity(function): if self.use_ema: return 2*inner(dot(sym(grad(function)), u_ext), v1) * dx + inner(div(function)*u_ext, v1) * dx # return 2*inner(dot(sym(grad(function)), u_ext), v) * dx + inner(div(u_ext)*function, v) * dx # QQ implement this way? else: return inner(dot(grad(function), u_ext), v1) * dx def diffusion(fce): if self.useLaplace: return nu*inner(grad(fce), grad(v1)) * dx else: form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx if self.bcv == 'CDN': # IMP will work only if p=0 on output, or we must add term # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer return form if self.bcv == 'LAP': return form - inner(nu*dot(grad(fce).T, n), v1) * problem.get_outflow_measure_form() if self.bcv == 'DDN': # IMP will work only if p=0 on output, or we must add term # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer return form # additional term must be added to non-constant part def pressure_rhs(): if self.useLaplace or self.bcv == 'LAP': return inner(p0, div(v1)) * dx - inner(p0*n, v1) * problem.get_outflow_measure_form() # NT term inner(inner(p, n), v) is 0 when p=0 on outflow else: return inner(p0, div(v1)) * dx a1_const = (1./k)*inner(u, v1)*dx + diffusion(0.5*u) a1_change = nonlinearity(0.5*u) if self.bcv == 'DDN': # IMP Problem: Does not penalize influx for current step, only for the next one # IMP this can lead to oscilation: DDN correct next step, but then u_ext is OK so in next step DDN is not used, leading to new influx... # u and u_ext cannot be switched, min_value is nonlinear function a1_change += -0.5*min_value(Constant(0.), inner(u_ext, n))*inner(u, v1)*problem.get_outflow_measure_form() # IMP works only with uflacs compiler L1 = (1./k)*inner(u0, v1)*dx - nonlinearity(0.5*u0) - diffusion(0.5*u0) + pressure_rhs() if self.bcv == 'DDN': L1 += 0.5*min_value(0., inner(u_ext, n))*inner(u0, v1)*problem.get_outflow_measure_form() # Non-consistent SUPG stabilisation if self.stabilize and not self.use_full_SUPG: # a1_stab = delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx a1_stab = 0.5*delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6}) # NT optional: use Crank Nicolson in stabilisation term: change RHS # L1 += -0.5*delta*inner(dot(grad(u0), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6}) outflow_area = Constant(problem.outflow_area) need_outflow = Constant(0.0) if self.useRotationScheme: # Rotation scheme if self.bc == 'lagrange': F2 = inner(grad(pQL), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx else: F2 = inner(grad(p), grad(q))*dx + (1./k)*q*div(u_)*dx else: # Projection, solve to p_ if self.bc == 'lagrange': F2 = inner(grad(pQL - p0), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx else: if self.forceOutflow and problem.can_force_outflow: info('Forcing outflow.') F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx for m in problem.get_outflow_measures(): F2 += (1./k)*(1./outflow_area)*need_outflow*q*m else: F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx a2, L2 = system(F2) # step 3: Finalize, solve to u_ if self.useRotationScheme: # Rotation scheme if self.bc == 'lagrange': F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0)), v)*dx else: F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_), v)*dx else: if self.bc == 'lagrange': F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0) - p0), v)*dx else: F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_ - p0), v)*dx a3, L3 = system(F3) if self.useRotationScheme: # Rotation scheme: modify pressure if self.bc == 'lagrange': pr = TrialFunction(self.Q) qr = TestFunction(self.Q) F4 = (pr - p0 - p_QL.sub(0) + nu*div(u_))*qr*dx else: F4 = (p - p0 - p_ + nu*div(u_))*q*dx # TODO zkusit, jestli to nebude rychlejsi? nepocitat soustavu, ale p.assign(...), nutno project(div(u),Q) coz je pocitani podobne soustavy # TODO zkusit v project zadat solver_type='lu' >> primy resic by mel byt efektivnejsi a4, L4 = system(F4) # Assemble matrices self.tc.start('assembleMatrices') A1_const = assemble(a1_const) # need to be here, so A1 stays one Python object during repeated assembly A1_change = A1_const.copy() # copy to get matrix with same sparse structure (data will be overwriten) if self.stabilize and not self.use_full_SUPG: A1_stab = A1_const.copy() # copy to get matrix with same sparse structure (data will be overwriten) A2 = assemble(a2) A3 = assemble(a3) if self.useRotationScheme: A4 = assemble(a4) self.tc.end('assembleMatrices') if self.solvers == 'direct': self.solver_vel_tent = LUSolver('mumps') self.solver_vel_cor = LUSolver('mumps') self.solver_p = LUSolver('umfpack') if self.useRotationScheme: self.solver_rot = LUSolver('umfpack') else: # NT not needed, chosen not to use hypre_parasails # if self.prec_v == 'hypre_parasails': # in FEniCS 1.6.0 inaccessible using KrylovSolver class # self.solver_vel_tent = PETScKrylovSolver('gmres') # PETSc4py object # self.solver_vel_tent.ksp().getPC().setType('hypre') # PETScOptions.set('pc_hypre_type', 'parasails') # # this is global setting, but preconditioners for pressure solvers are set by their constructors # else: self.solver_vel_tent = KrylovSolver('gmres', self.prec_v) # nonsymetric > gmres # IMP cannot use 'ilu' in parallel (choose different default option) self.solver_vel_cor = KrylovSolver('cg', 'hypre_amg') # nonsymetric > gmres self.solver_p = KrylovSolver('cg', self.prec_p) # symmetric > CG if self.useRotationScheme: self.solver_rot = KrylovSolver('cg', self.prec_p) solver_options = {'monitor_convergence': True, 'maximum_iterations': 1000, 'nonzero_initial_guess': True} # 'nonzero_initial_guess': True with solver.solbe(A, u, b) means that # Solver will use anything stored in u as an initial guess # Get the nullspace if there are no pressure boundary conditions foo = Function(self.Q) # auxiliary vector for setting pressure nullspace if self.bc in ['nullspace', 'nullspace_s']: null_vec = Vector(foo.vector()) self.Q.dofmap().set(null_vec, 1.0) null_vec *= 1.0/null_vec.norm('l2') self.null_space = VectorSpaceBasis([null_vec]) if self.bc == 'nullspace': as_backend_type(A2).set_nullspace(self.null_space) # apply global options for Krylov solvers self.solver_vel_tent.parameters['relative_tolerance'] = 10 ** (-self.precision_rel_v_tent) self.solver_vel_tent.parameters['absolute_tolerance'] = 10 ** (-self.precision_abs_v_tent) self.solver_vel_cor.parameters['relative_tolerance'] = 10E-12 self.solver_vel_cor.parameters['absolute_tolerance'] = 10E-4 self.solver_p.parameters['relative_tolerance'] = 10**(-self.precision_p) self.solver_p.parameters['absolute_tolerance'] = 10E-10 if self.useRotationScheme: self.solver_rot.parameters['relative_tolerance'] = 10**(-self.precision_p) self.solver_rot.parameters['absolute_tolerance'] = 10E-10 if self.solvers == 'krylov': for solver in [self.solver_vel_tent, self.solver_vel_cor, self.solver_p, self.solver_rot] if \ self.useRotationScheme else [self.solver_vel_tent, self.solver_vel_cor, self.solver_p]: for key, value in solver_options.items(): try: solver.parameters[key] = value except KeyError: info('Invalid option %s for KrylovSolver' % key) return 1 solver.parameters['preconditioner']['structure'] = 'same' # matrices A2-A4 do not change, so we can reuse preconditioners self.solver_vel_tent.parameters['preconditioner']['structure'] = 'same_nonzero_pattern' # matrix A1 changes every time step, so change of preconditioner must be allowed if self.bc == 'lagrange': fa = FunctionAssigner(self.Q, QL.sub(0)) # boundary conditions bcu, bcp = problem.get_boundary_conditions(self.bc == 'outflow', self.V, self.Q) self.tc.end('init') # Time-stepping info("Running of Incremental pressure correction scheme n. 1") ttime = self.metadata['time'] t = dt step = 1 while t < (ttime + dt/2.0): info("t = %f" % t) self.problem.update_time(t, step) if self.MPI_rank == 0: problem.write_status_file(t) if doSave: save_this_step = problem.save_this_step # DDN debug # u_ext_in = assemble(inner(u_ext, n)*problem.get_outflow_measure_form()) # DDN_triggered = assemble(min_value(Constant(0.), inner(u_ext, n))*problem.get_outflow_measure_form()) # print('DDN: u_ext*n dSout = ', u_ext_in) # print('DDN: negative part of u_ext*n dSout = ', DDN_triggered) # assemble matrix (it depends on solution) self.tc.start('assembleA1') assemble(a1_change, tensor=A1_change) # assembling into existing matrix is faster than assembling new one A1 = A1_const.copy() # we dont want to change A1_const A1.axpy(1, A1_change, True) self.tc.end('assembleA1') self.tc.start('assembleA1stab') if self.stabilize and not self.use_full_SUPG: assemble(a1_stab, tensor=A1_stab) # assembling into existing matrix is faster than assembling new one A1.axpy(1, A1_stab, True) self.tc.end('assembleA1stab') # Compute tentative velocity step begin("Computing tentative velocity") self.tc.start('rhs') b = assemble(L1) self.tc.end('rhs') self.tc.start('applybc1') [bc.apply(A1, b) for bc in bcu] self.tc.end('applybc1') try: self.tc.start('solve 1') self.solver_vel_tent.solve(A1, u_.vector(), b) self.tc.end('solve 1') if save_this_step: self.tc.start('saveVel') problem.save_vel(True, u_, t) self.tc.end('saveVel') if save_this_step and not onlyVel: problem.save_div(True, u_) problem.compute_err(True, u_, t) problem.compute_div(True, u_) except RuntimeError as inst: problem.report_fail(t) return 1 end() # DDN debug # u_ext_in = assemble(inner(u_, n)*problem.get_outflow_measure_form()) # DDN_triggered = assemble(min_value(Constant(0.), inner(u_, n))*problem.get_outflow_measure_form()) # print('DDN: u_tent*n dSout = ', u_ext_in) # print('DDN: negative part of u_tent*n dSout = ', DDN_triggered) if self.useRotationScheme: begin("Computing tentative pressure") else: begin("Computing pressure") if self.forceOutflow and problem.can_force_outflow: out = problem.compute_outflow(u_) info('Tentative outflow: %f' % out) n_o = -problem.last_inflow-out info('Needed outflow: %f' % n_o) need_outflow.assign(n_o) self.tc.start('rhs') b = assemble(L2) self.tc.end('rhs') self.tc.start('applybcP') [bc.apply(A2, b) for bc in bcp] if self.bc in ['nullspace', 'nullspace_s']: self.null_space.orthogonalize(b) self.tc.end('applybcP') try: self.tc.start('solve 2') if self.bc == 'lagrange': self.solver_p.solve(A2, p_QL.vector(), b) else: self.solver_p.solve(A2, p_.vector(), b) self.tc.end('solve 2') except RuntimeError as inst: problem.report_fail(t) return 1 if self.useRotationScheme: foo = Function(self.Q) if self.bc == 'lagrange': fa.assign(pQ, p_QL.sub(0)) foo.assign(pQ + p0) else: foo.assign(p_+p0) problem.averaging_pressure(foo) if save_this_step and not onlyVel: problem.save_pressure(True, foo) else: if self.bc == 'lagrange': fa.assign(pQ, p_QL.sub(0)) problem.averaging_pressure(pQ) if save_this_step and not onlyVel: problem.save_pressure(False, pQ) else: # we do not want to change p=0 on outflow, it conflicts with do-nothing conditions foo = Function(self.Q) foo.assign(p_) problem.averaging_pressure(foo) if save_this_step and not onlyVel: problem.save_pressure(False, foo) end() begin("Computing corrected velocity") self.tc.start('rhs') b = assemble(L3) self.tc.end('rhs') if not self.B: self.tc.start('applybc3') [bc.apply(A3, b) for bc in bcu] self.tc.end('applybc3') try: self.tc.start('solve 3') self.solver_vel_cor.solve(A3, u_cor.vector(), b) self.tc.end('solve 3') problem.compute_err(False, u_cor, t) problem.compute_div(False, u_cor) except RuntimeError as inst: problem.report_fail(t) return 1 if save_this_step: self.tc.start('saveVel') problem.save_vel(False, u_cor, t) self.tc.end('saveVel') if save_this_step and not onlyVel: problem.save_div(False, u_cor) end() # DDN debug # u_ext_in = assemble(inner(u_cor, n)*problem.get_outflow_measure_form()) # DDN_triggered = assemble(min_value(Constant(0.), inner(u_cor, n))*problem.get_outflow_measure_form()) # print('DDN: u_cor*n dSout = ', u_ext_in) # print('DDN: negative part of u_cor*n dSout = ', DDN_triggered) if self.useRotationScheme: begin("Rotation scheme pressure correction") self.tc.start('rhs') b = assemble(L4) self.tc.end('rhs') try: self.tc.start('solve 4') self.solver_rot.solve(A4, p_mod.vector(), b) self.tc.end('solve 4') except RuntimeError as inst: problem.report_fail(t) return 1 problem.averaging_pressure(p_mod) if save_this_step and not onlyVel: problem.save_pressure(False, p_mod) end() # compute functionals (e. g. forces) problem.compute_functionals(u_cor, p_mod if self.useRotationScheme else (pQ if self.bc == 'lagrange' else p_), t) # Move to next time step self.tc.start('next') u1.assign(u0) u0.assign(u_cor) u_.assign(u_cor) # use corretced velocity as initial guess in first step if self.useRotationScheme: p0.assign(p_mod) else: if self.bc == 'lagrange': p0.assign(pQ) else: p0.assign(p_) t = round(t + dt, 6) # round time step to 0.000001 step += 1 self.tc.end('next') info("Finished: Incremental pressure correction scheme n. 1") problem.report() return 0
u_tent = TrialFunction(V) v = TestFunction(V) # U_ = 1.5*u0 - 0.5*u1 # nonlinearity = inner(dot(0.5 * (u_tent.dx(0) + u0.dx(0)), U_), v) * dx # F_tent = (1./dt)*inner(u_tent - u0, v) * dx + nonlinearity\ # + nu*inner(0.5 * (u_tent.dx(0) + u0.dx(0)), v.dx(0)) * dx + inner(p0.dx(0), v) * dx\ # - inner(f, v)*dx # solve to u_ # using explicite scheme: so LHS has interpretation as heat equation, RHS are sources F_tent = (1./dt)*inner(u_tent - u0, v)*dx + inner(dot(u0.dx(0), u0), v)*dx + nu*inner((u_tent.dx(0) + u0.dx(0)), v.dx(0)) * dx + inner(p0.dx(0), v) * dx\ - inner(f, v)*dx # solve to u_ a_tent, L_tent = system(F_tent) # step 2 u_tent_computed = Function(V) p = TrialFunction(Q) q = TestFunction(Q) F_p = inner(grad(p-p0), grad(q))*dx + (1./dt)*u_tent_computed.dx(0)*q*dx # + 2*p.dx(0)*q*ds(1) # tried to force dp/dn=0 on inflow # TEST: prescribe Neumann outflow BC # F_p = inner(grad(p-p0), grad(q))*dx + (1./dt)*u_tent_computed.dx(0)*q*dx + (1./dt)*(v_in_expr-u_tent_computed)*q*ds(2) a_p, L_p = system(F_p) A_p = assemble(a_p) as_backend_type(A_p).set_nullspace(null_space) print(A_p.array()) # step 2 rotation # F_p_rot = inner(grad(p), grad(q))*dx + (1./dt)*u_tent_computed.dx(0)*q*dx + (1./dt)*(v_in_expr-u_tent_computed)*q*ds(2) F_p_rot = inner(grad(p), grad(q))*dx + (1./dt)*u_tent_computed.dx(0)*q*dx a_p_rot, L_p_rot = system(F_p_rot) A_p_rot = assemble(a_p_rot) as_backend_type(A_p_rot).set_nullspace(null_space) # step 3 p_computed = Function(Q) u_cor = TrialFunction(V)
# plot_matrix(A_diffusion_1D) # plot_matrix(A_diffusion_1D) a_convection_1D = inner(dot(u.dx(0), u_ext), v)*dx A_convection_1D = assemble(a_convection_1D) # plot_matrix(A_convection_1D) u_exts = [interpolate(Expression(('1.', '1.')), V2D), interpolate(Expression(('1.', '1.', '1.')), V3D)] Qspaces = [Q2D, Q3D] Vspaces = [V2D, V3D] names = ['2D', '3D'] for i in [0, 1]: Qspace = Qspaces[i] Vspace = Vspaces[i] u = TrialFunction(Vspace) v = TestFunction(Vspace) a_mass = inner(u, v)*dx A_mass = assemble(a_mass) a_diffusion = inner(grad(u), grad(v))*dx A_diffusion = assemble(a_diffusion) a_convection = inner(dot(grad(u), u_exts[i]), v)*dx A_convection = assemble(a_convection) plot_matrix(A_mass, 'mass' + names[i]) plot_matrix(A_diffusion, 'diff' + names[i]) plot_matrix(A_convection, 'conv' + names[i]) show()
def norm(v, norm_type="L2", mesh=None): """ Return the norm of a given vector or function. *Arguments* v a :py:class:`Vector <dolfin.cpp.Vector>` or a :py:class:`Function <dolfin.functions.function.Function>`. norm_type see below for alternatives. mesh optional :py:class:`Mesh <dolfin.cpp.Mesh>` on which to compute the norm. If the norm type is not specified, the standard :math:`L^2` -norm is computed. Possible norm types include: *Vectors* ================ ================= ================ Norm Usage ================ ================= ================ :math:`l^2` norm(x, 'l2') Default :math:`l^1` norm(x, 'l1') :math:`l^\infty` norm(x, 'linf') ================ ================= ================ *Functions* ================ ================= ================================= Norm Usage Includes the :math:`L^2` -term ================ ================= ================================= :math:`L^2` norm(v, 'L2') Yes :math:`H^1` norm(v, 'H1') Yes :math:`H^1_0` norm(v, 'H10') No :math:`H` (div) norm(v, 'Hdiv') Yes :math:`H` (div) norm(v, 'Hdiv0') No :math:`H` (curl) norm(v, 'Hcurl') Yes :math:`H` (curl) norm(v, 'Hcurl0') No ================ ================= ================================= *Examples of usage* .. code-block:: python v = Function(V) x = v.vector() print norm(x, 'linf') # print the infinity norm of vector x n = norm(v) # compute L^2 norm of v print norm(v, 'Hdiv') # print H(div) norm of v n = norm(v, 'H1', mesh) # compute H^1 norm of v on given mesh """ if not isinstance(v, (GenericVector, GenericFunction)): raise TypeError, "expected a GenericVector or GenericFunction" # Check arguments if not isinstance(norm_type, str): cpp.dolfin_error("norms.py", "compute norm", "Norm type must be a string, not " + str(type(norm_type))) if mesh is not None and not isinstance(mesh, Mesh): cpp.dolfin_error("norms.py", "compute norm", "Expecting a Mesh, not " + str(type(mesh))) # Select norm type if isinstance(v, GenericVector): return v.norm(norm_type.lower()) elif (isinstance(v, Coefficient) and isinstance(v, GenericFunction)): if norm_type.lower() == "l2": M = inner(v, v)*dx() elif norm_type.lower() == "h1": M = inner(v, v)*dx() + inner(grad(v), grad(v))*dx() elif norm_type.lower() == "h10": M = inner(grad(v), grad(v))*dx() elif norm_type.lower() == "hdiv": M = inner(v, v)*dx() + div(v)*div(v)*dx() elif norm_type.lower() == "hdiv0": M = div(v)*div(v)*dx() elif norm_type.lower() == "hcurl": M = inner(v, v)*dx() + inner(curl(v), curl(v))*dx() elif norm_type.lower() == "hcurl0": M = inner(curl(v), curl(v))*dx() else: cpp.dolfin_error("norms.py", "compute norm", "Unknown norm type (\"%s\") for functions" % str(norm_type)) else: cpp.dolfin_error("norms.py", "compute norm", "Unknown object type. Must be a vector or a function") # Get mesh if isinstance(v, Function) and mesh is None: mesh = v.function_space().mesh() # Assemble value r = assemble(M, mesh=mesh, form_compiler_parameters={"representation": "quadrature"}) # Check value if r < 0.0: cpp.dolfin_error("norms.py", "compute norm", "Square of norm is negative, might be a round-off error") elif r == 0.0: return 0.0 else: return sqrt(r)
def T(p, v): return -p * I + 2.0 * self.nu * sym(grad(v))