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 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 test_facet_normals(cell_type): """Test that FacetNormal is outward facing""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim V = VectorFunctionSpace(mesh, ("Lagrange", 1)) normal = FacetNormal(mesh) v = Function(V) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # For each facet, check that the inner product of the normal and # the vector that has a positive normal component on only that # facet is positive for i in range(num_facets): if cell_type == CellType.interval: co = mesh.geometry.x[i] v.interpolate(lambda x: x[0] - co[0]) if cell_type == CellType.triangle: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away # from `co` so that there is no normal component on two # edges and the integral over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 2, (x[1] - co[1]) / 2)) elif cell_type == CellType.tetrahedron: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away # from `co` so that there is no normal component on # three faces and the integral over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 3, (x[1] - co[1]) / 3, (x[2] - co[2]) / 3)) elif cell_type == CellType.quadrilateral: # function that is 0 on one edge and points away from # that edge so that there is no normal component on # three edges v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 2 else 0 * x[j] for j in range(2))) elif cell_type == CellType.hexahedron: # function that is 0 on one face and points away from # that face so that there is no normal component on five # faces v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 3 else 0 * x[j] for j in range(3))) # assert that the integrals these functions dotted with the # normal over a face is 1 on one face and 0 on the others ones = 0 for j in range(num_facets): a = inner(v, normal) * ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) if np.isclose(result, 1): ones += 1 else: assert np.isclose(result, 0) assert ones == 1
def __init__(self, mesh, k: int, omega, c, c0, lumped): P = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), k) self.V = FunctionSpace(mesh, P) self.u, self.v = Function(self.V), Function(self.V) self.g1 = Function(self.V) self.g2 = Function(self.V) self.omega = omega self.c = c self.c0 = c0 n = FacetNormal(mesh) # Pieces for plane wave incident field x = ufl.geometry.SpatialCoordinate(mesh) cos_wave = ufl.cos(self.omega / self.c0 * x[0]) sin_wave = ufl.sin(self.omega / self.c0 * x[0]) plane_wave = self.g1 * cos_wave + self.g2 * sin_wave dv, p = TrialFunction(self.V), TestFunction(self.V) self.L1 = - inner(grad(self.u), grad(p)) * dx(degree=k) \ - (1 / self.c) * inner(self.v, p) * ds \ - (1 / self.c**2) * (-self.omega**2) * inner(plane_wave, p) * dx \ - inner(grad(plane_wave), grad(p)) * dx \ + inner(dot(grad(plane_wave), n), p) * ds # Vector to be re-used for assembly self.b = None # TODO: precompile/pre-process Form L self.lumped = lumped if self.lumped: a = (1 / self.c**2) * p * dx(degree=k) self.M = dolfinx.fem.assemble_vector(a) self.M.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) else: a = (1 / self.c**2) * inner(dv, p) * dx(degree=k) M = dolfinx.fem.assemble_matrix(a) M.assemble() self.solver = PETSc.KSP().create(mesh.mpi_comm()) opts = PETSc.Options() opts["ksp_type"] = "cg" opts["ksp_rtol"] = 1.0e-8 self.solver.setFromOptions() self.solver.setOperators(M)
def __init__(self, args, tc, metadata): self.has_analytic_solution = False self.problem_code = 'FACB' super(Problem, self).__init__(args, tc, metadata) self.name = 'test on real mesh' self.status_functional_str = 'not selected' # input parameters self.factor = args.factor self.scale_factor.append(self.factor) self.nu = 0.001 * args.nufactor # kinematic viscosity # Import gmsh mesh self.compatible_meshes = ['bench3D_1', 'bench3D_2', 'bench3D_3'] if args.mesh not in self.compatible_meshes: exit('Bad mesh, should be some from %s' % str(self.compatible_meshes)) self.mesh = Mesh("meshes/" + args.mesh + ".xml") self.cell_function = MeshFunction( "size_t", self.mesh, "meshes/" + args.mesh + "_physical_region.xml") self.facet_function = MeshFunction( "size_t", self.mesh, "meshes/" + args.mesh + "_facet_region.xml") self.dsIn = Measure("ds", subdomain_id=2, subdomain_data=self.facet_function) self.dsOut = Measure("ds", subdomain_id=3, subdomain_data=self.facet_function) self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function) self.dsCyl = Measure("ds", subdomain_id=5, subdomain_data=self.facet_function) self.normal = FacetNormal(self.mesh) print("Mesh name: ", args.mesh, " ", self.mesh) print("Mesh norm max: ", self.mesh.hmax()) print("Mesh norm min: ", self.mesh.hmin()) self.actual_time = None self.v_in = None
def run_dg_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[component]**n, where n is the degree of the Lagrange function space. """ u, v = TrialFunction(V), TestFunction(V) # Exact solution x = SpatialCoordinate(mesh) u_exact = x[1]**degree # Coefficient k = Function(V) k.vector.set(2.0) k.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) # Source term f = -div(k * grad(u_exact)) # Mesh normals and element size n = FacetNormal(mesh) h = CellDiameter(mesh) h_avg = (h("+") + h("-")) / 2.0 # Penalty parameter alpha = 32 dx_ = dx(metadata={"quadrature_degree": -1}) ds_ = ds(metadata={"quadrature_degree": -1}) dS_ = dS(metadata={"quadrature_degree": -1}) a = inner(k * grad(u), grad(v)) * dx_ \ - k("+") * inner(avg(grad(u)), jump(v, n)) * dS_ \ - k("+") * inner(jump(u, n), avg(grad(v))) * dS_ \ + k("+") * (alpha / h_avg) * inner(jump(u, n), jump(v, n)) * dS_ \ - inner(k * grad(u), v * n) * ds_ \ - inner(u * n, k * grad(v)) * ds_ \ + (alpha / h) * inner(k * u, v) * ds_ L = inner(f, v) * dx_ - inner(k * u_exact * n, grad(v)) * ds_ \ + (alpha / h) * inner(k * u_exact, v) * ds_ for integral in a.integrals(): integral.metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree( a) for integral in L.integrals(): integral.metadata( )["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree( L) b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a, []) 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) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) # Calculate error M = (u_exact - uh)**2 * dx M = fem.Form(M) error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def compute(space, epsilon, weakBnd, skeleton, mol=None): u = TrialFunction(space) v = TestFunction(space) n = FacetNormal(space) he = avg(CellVolume(space)) / FacetArea(space) hbnd = CellVolume(space) / FacetArea(space) x = SpatialCoordinate(space) exact = uflFunction(space.gridView, name="exact", order=3, ufl=sin(x[0] * x[1])) uh = space.interpolate(exact, name="solution") # diffusion factor eps = Constant(epsilon, "eps") # transport direction and upwind flux b = as_vector([1, 0]) hatb = (dot(b, n) + abs(dot(b, n))) / 2.0 # characteristic function for left/right boundary dD = conditional((1 + x[0]) * (1 - x[0]) < 1e-10, 1, 0) # penalty parameter beta = Constant(20 * space.order**2, "beta") rhs = -(div(eps * grad(exact) - b * exact)) * v * dx aInternal = dot(eps * grad(u) - b * u, grad(v)) * dx aInternal -= eps * dot(grad(exact), n) * v * (1 - dD) * ds diffSkeleton = eps*beta/he*jump(u)*jump(v)*dS -\ eps*dot(avg(grad(u)),n('+'))*jump(v)*dS -\ eps*jump(u)*dot(avg(grad(v)),n('+'))*dS if weakBnd: diffSkeleton += eps*beta/hbnd*(u-exact)*v*dD*ds -\ eps*dot(grad(exact),n)*v*dD*ds advSkeleton = jump(hatb * u) * jump(v) * dS if weakBnd: advSkeleton += (hatb * u + (dot(b, n) - hatb) * exact) * v * dD * ds if skeleton: form = aInternal + diffSkeleton + advSkeleton else: form = aInternal if weakBnd and skeleton: strongBC = None else: strongBC = DirichletBC(space, exact, dD) if space.storage[0] == "numpy": solver = { "solver": ("suitesparse", "umfpack"), "parameters": { "newton.verbose": True, "newton.linear.verbose": False, "newton.linear.tolerance": 1e-5, } } else: solver = { "solver": "bicgstab", "parameters": { "newton.linear.preconditioning.method": "ilu", "newton.linear.tolerance": 1e-13, "newton.verbose": True, "newton.linear.verbose": False } } if mol == 'mol': scheme = molSolutionScheme([form == rhs, strongBC], **solver) else: scheme = solutionScheme([form == rhs, strongBC], **solver) eoc = [] info = scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error0 = math.sqrt(integrate(gridView, error, order=5)) print(error0, " # output", flush=True) for i in range(3): gridView.hierarchicalGrid.globalRefine(1) uh.interpolate(exact) scheme.solve(target=uh) error = dot(uh - exact, uh - exact) error1 = math.sqrt(integrate(gridView, error, order=5)) eoc += [math.log(error1 / error0) / math.log(0.5)] print(i, error0, error1, eoc, " # output", flush=True) error0 = error1 # print(space.order,epsilon,eoc) if (eoc[-1] - (space.order + 1)) < -0.1: print("ERROR:", space.order, epsilon, eoc) return eoc
has_petsc_complex, solve) from dolfinx.fem.assemble import assemble_scalar from dolfinx.io import XDMFFile from ufl import FacetNormal, TestFunction, TrialFunction, dx, grad, inner # wavenumber k0 = 4 * np.pi # approximation space polynomial degree deg = 1 # number of elements in each direction of mesh n_elem = 128 mesh = UnitSquareMesh(MPI.COMM_WORLD, n_elem, n_elem) n = FacetNormal(mesh) # Source amplitude if has_petsc_complex: A = 1 + 1j else: A = 1 # Test and trial function space V = FunctionSpace(mesh, ("Lagrange", deg)) # Define variational problem u = TrialFunction(V) v = TestFunction(V) f = Function(V) f.interpolate(lambda x: A * k0**2 * np.cos(k0 * x[0]) * np.cos(k0 * x[1]))
# \begin{align*} # u(x) = \left(\frac{1}{2}(x^2 + y^2) - \frac{1}{3}(x^3 - y^3)\right) + 1 # \end{align*} # <codecell> from ufl import TestFunction, TrialFunction from dune.ufl import DirichletBC u = TrialFunction(space) v = TestFunction(space) from ufl import dx, grad, div, grad, dot, inner, sqrt, conditional, FacetNormal, ds a = dot(grad(u), grad(v)) * dx f = -div( grad(exact) ) g_N = grad(exact) n = FacetNormal(space) b = f*v*dx + dot(g_N,n)*conditional(x[0]>=1e-8,1,0)*v*ds dbc = DirichletBC(space,exact,x[0]<=1e-8) # <markdowncell> # With the model described as a ufl form, we can construct a scheme class # that provides the solve method which we can use to compute the solution: # <codecell> from dune.fem import parameter parameter.append({"fem.verboserank": -1}) from dune.fem.scheme import galerkin as solutionScheme scheme = solutionScheme([a == b, dbc], solver='cg') scheme.solve(target = u_h) # <markdowncell>
def b(tau_S, v): n = FacetNormal(mesh) return inner(tau_S, grad(grad(v))) * dx \ - ufl.dot(ufl.dot(tau_S('+'), n('+')), n('+')) * jump(grad(v), n) * dS \ - ufl.dot(ufl.dot(tau_S, n), n) * ufl.dot(grad(v), n) * ds
# Last changed: 2007-07-15 # # The bilinear form a(v, u) and linear form L(v) for # Poisson's equation in a discontinuous Galerkin (DG) # formulation. from ufl import (Coefficient, Constant, FacetNormal, FiniteElement, TestFunction, TrialFunction, avg, dot, dS, ds, dx, grad, inner, jump, triangle) element = FiniteElement("Discontinuous Lagrange", triangle, 1) v = TestFunction(element) u = TrialFunction(element) f = Coefficient(element) n = FacetNormal(triangle) h = Constant(triangle) gN = Coefficient(element) alpha = 4.0 gamma = 8.0 a = inner(grad(v), grad(u)) * dx \ - inner(avg(grad(v)), jump(u, n)) * dS \ - inner(jump(v, n), avg(grad(u))) * dS \ + alpha / h('+') * dot(jump(v, n), jump(u, n)) * dS \ - inner(grad(v), u * n) * ds \ - inner(v * n, grad(u)) * ds \ + gamma / h * v * u * ds
def __init__(self, args, tc, metadata): self.has_analytic_solution = False self.problem_code = 'REAL' super(Problem, self).__init__(args, tc, metadata) self.name = 'test on real mesh' self.status_functional_str = 'outflow/inflow' self.last_inflow = 0 # time settings self.itp_lengths = { 1: 1.0, 2: 0.9375, } self.cycle_length = self.itp_lengths[self.args.itp] # input parameters self.nu = self.args.nu # kinematic viscosity self.factor = args.factor self.metadata['factor'] = self.factor self.scale_factor.append(self.factor) self.tc.start('mesh') # Import mesh try: self.mesh, self.facet_function = super(Problem, self).loadMesh(args.mesh) info("Mesh name: " + args.mesh + " " + str(self.mesh)) f_ini = open('meshes/' + args.mesh + '.ini', 'r') reader = csv.reader(f_ini, delimiter=' ', escapechar='\\') except (EnvironmentError, RuntimeError): print( 'Unable to open mesh.hdf5 or mesh.ini file. Check if the mesh was prepared to be used ' 'with \"real\" problem.') exit(1) # load inflows and outflows (interfaces) from mesh.ini file obj = None self.interfaces = [] for row in reader: if not row: pass elif row[0] == 'volume': self.mesh_volume = float(row[1]) elif row[0] == 'in': if obj is not None: self.interfaces.append(obj) obj = {'inflow': True, 'number': row[1]} elif row[0] == 'out': if obj is not None: self.interfaces.append(obj) obj = {'inflow': False, 'number': row[1]} else: if len(row) == 2: # scalar values obj[row[0]] = row[1] else: # vector values obj[row[0]] = [float(f) for f in row[1:]] self.interfaces.append(obj) f_ini.close() self.tc.end('mesh') # collect inflows and outflows into separate lists self.outflow_area = 0 self.inflows = [] self.outflows = [] for obj in self.interfaces: if not obj['inflow']: self.outflow_area += float(obj['S']) self.outflows.append(obj) else: self.inflows.append(obj) info('Outflow area: %f' % self.outflow_area) # self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function) self.normal = FacetNormal(self.mesh) # generate measures, collect measure lists self.inflow_measures = [] for obj in self.interfaces: obj['measure'] = Measure("ds", subdomain_id=int(obj['number']), subdomain_data=self.facet_function) if obj['inflow']: self.inflow_measures.append(obj['measure']) else: self.outflow_measures.append(obj['measure']) self.listDict.update({ 'outflow': { 'list': [], 'name': 'outflow rate', 'abrev': 'OUT', 'slist': [] }, 'inflow': { 'list': [], 'name': 'inflow rate', 'abrev': 'IN', 'slist': [] }, 'oiratio': { 'list': [], 'name': 'outflow/inflow ratio (mass conservation)', 'abrev': 'O/I', 'slist': [] }, }) for obj in self.outflows: n = obj['number'] self.listDict.update({ 'outflow' + n: { 'list': [], 'name': 'outflow rate ' + n, 'abrev': 'OUT' + n, 'slist': [] } }) self.can_force_outflow = True
# # Author: Marie Rognes # Modified by: Martin Sandve Alnes # Date: 2009-02-12 # from ufl import (FacetNormal, FiniteElement, TestFunctions, TrialFunctions, div, dot, ds, dx, tetrahedron) cell = tetrahedron RT = FiniteElement("Raviart-Thomas", cell, 1) DG = FiniteElement("DG", cell, 0) MX = RT * DG (u, p) = TrialFunctions(MX) (v, q) = TestFunctions(MX) n = FacetNormal(cell) a0 = (dot(u, v) + div(u) * q + div(v) * p) * dx a1 = (dot(u, v) + div(u) * q + div(v) * p) * dx - p * dot(v, n) * ds forms = [a0, a1]
def model(space, epsilon, weakBnd, skeleton, useMol): u = TrialFunction(space) v = TestFunction(space) n = FacetNormal(space) he = avg(CellVolume(space)) / FacetArea(space) hbnd = CellVolume(space) / FacetArea(space) x = SpatialCoordinate(space) #exact = sin(x[0]*x[1]) # atan(1*x[1]) exact = uflFunction(space.gridView, name="exact", order=3, ufl=sin(x[0] * x[1])) # diffusion factor eps = 1 # Constant(epsilon,"eps") # transport direction and upwind flux b = as_vector([1, 0]) hatb = (dot(b, n) + abs(dot(b, n))) / 2.0 # characteristic function for left/right boundary dD = conditional((1 + x[0]) * (1 - x[0]) < 1e-10, 1, 0) # penalty parameter beta = Constant(10 * space.order**2 if space.order > 0 else 1, "beta") rhs = (-div(eps * grad(exact) - b * exact) + exact) * v * dx aInternal = (dot(eps * grad(u) - b * u, grad(v)) + dot(u, v)) * dx diffSkeleton = eps*beta/he*jump(u)*jump(v)*dS -\ eps*dot(avg(grad(u)),n('+'))*jump(v)*dS -\ eps*jump(u)*dot(avg(grad(v)),n('+'))*dS diffSkeleton -= eps * dot(grad(exact), n) * v * (1 - dD) * ds if weakBnd: diffSkeleton += eps*beta/hbnd*(u-exact)*v*dD*ds -\ eps*dot(grad(exact),n)*v*dD*ds advSkeleton = jump(hatb * u) * jump(v) * dS if weakBnd: advSkeleton += (hatb * u + (dot(b, n) - hatb) * exact) * v * dD * ds if skeleton: form = aInternal + diffSkeleton + advSkeleton else: form = aInternal if weakBnd and skeleton: strongBC = None else: strongBC = None # DirichletBC(space,exact,dD) if space.storage[0] == "fem": solver = {"solver": ("suitesparse", "umfpack")} else: solver = { "solver": "bicgstab", "parameters": { "newton.linear.preconditioning.method": "jacobi", "newton.linear.tolerance": 1e-13 } } if useMol: scheme = solutionMolScheme([form == rhs, strongBC], **solver) else: scheme = solutionScheme([form == rhs, strongBC], **solver) uh = space.interpolate(exact, name="solution") A = linear(scheme) return scheme, uh, A, exact
def test_div_grad_then_integrate_over_cells_and_boundary(): # Define 2D geometry n = 10 mesh = RectangleMesh( [numpy.array([0.0, 0.0, 0.0]), numpy.array([2.0, 3.0, 0.0])], 2 * n, 3 * n) x, y = SpatialCoordinate(mesh) xs = 0.1 + 0.8 * x / 2 # scaled to be within [0.1,0.9] # ys = 0.1 + 0.8 * y / 3 # scaled to be within [0.1,0.9] n = FacetNormal(mesh) # Define list of expressions to test, and configure accuracies # these expressions are known to pass with. The reason some # functions are less accurately integrated is likely that the # default choice of quadrature rule is not perfect F_list = [] def reg(exprs, acc=10): for expr in exprs: F_list.append((expr, acc)) # FIXME: 0*dx and 1*dx fails in the ufl-ffcx-jit framework somewhere # reg([Constant(0.0, cell=cell)]) # reg([Constant(1.0, cell=cell)]) monomial_list = [x**q for q in range(2, 6)] reg(monomial_list) reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list]) reg([xs**xs]) reg( [xs**(xs**2)], 8 ) # Note: Accuracies here are from 1D case, not checked against 2D results. reg([xs**(xs**3)], 6) reg([xs**(xs**4)], 2) # Special functions: reg([atan(xs)], 8) reg([sin(x), cos(x), exp(x)], 5) reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3) reg([asin(xs), acos(xs)], 1) reg([tan(xs)], 7) # To handle tensor algebra, make an x dependent input tensor # xx and square all expressions def reg2(exprs, acc=10): for expr in exprs: F_list.append((inner(expr, expr), acc)) xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]]) xxs = as_matrix([[2 * xs**2, 3 * xs**3], [11 * xs**5, 7 * xs**4]]) x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4]) cc = as_matrix([[2, 3], [4, 5]]) reg2( [xx] ) # TODO: Make unit test for UFL from this, results in listtensor with free indices reg2([x3v]) reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))]) reg2([xx.T]) reg2([tr(xx)]) reg2([det(xx)]) reg2([dot(xx, 0.1 * xx)]) reg2([outer(xx, xx.T)]) reg2([dev(xx)]) reg2([sym(xx)]) reg2([skew(xx)]) reg2([elem_mult(7 * xx, cc)]) reg2([elem_div(7 * xx, xx + cc)]) reg2([elem_pow(1e-3 * xxs, 1e-3 * cc)]) reg2([elem_pow(1e-3 * cc, 1e-3 * xx)]) reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2) # pretty inaccurate... # FIXME: Add tests for all UFL operators: # These cause discontinuities and may be harder to test in the # above fashion: # 'inv', 'cofac', # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not', # 'conditional', 'sign', # 'jump', 'avg', # 'LiftingFunction', 'LiftingOperator', # FIXME: Test other derivatives: (but algorithms for operator # derivatives are the same!): # 'variable', 'diff', # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative', # Run through all operators defined above and compare integrals debug = 0 if debug: F_list = F_list[1:] for F, acc in F_list: if debug: print('\n', "F:", str(F)) # Integrate over domain and its boundary int_dx = assemble(div(grad(F)) * dx(mesh)) # noqa int_ds = assemble(dot(grad(F), n) * ds(mesh)) # noqa if debug: print(int_dx, int_ds) # Compare results. Using custom relative delta instead of # decimal digits here because some numbers are >> 1. delta = min(abs(int_dx), abs(int_ds)) * 10**-acc assert int_dx - int_ds <= delta
def __init__(self, args, tc, metadata): self.has_analytic_solution = True self.problem_code = 'WCYL' super(Problem, self).__init__(args, tc, metadata) self.tc.init_watch('assembleSol', 'Assembled analytic solution', True) self.tc.init_watch('analyticP', 'Analytic pressure', True) self.tc.init_watch('analyticVnorms', 'Computed analytic velocity norms', True) self.tc.init_watch('errorP', 'Computed pressure error', True) self.tc.init_watch('errorForce', 'Computed force error', True) self.tc.init_watch('computePG', 'Computed pressure gradient', True) self.name = 'womersley_cylinder' self.status_functional_str = 'last H1 velocity error' # input parameters self.ic = args.ic self.factor = args.factor self.metadata['factor'] = self.factor self.scale_factor.append(self.factor) # fixed parameters (used in analytic solution and in BC) self.nu = 3.71 * self.args.nufactor # kinematic viscosity self.R = 5.0 # cylinder radius self.mesh_volume = pi * 25. * 20. # Import gmsh mesh self.tc.start('mesh') self.mesh, self.facet_function = super(Problem, self).loadMesh(args.mesh) self.dsIn = Measure("ds", subdomain_id=2, subdomain_data=self.facet_function) self.dsOut = Measure("ds", subdomain_id=3, subdomain_data=self.facet_function) self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function) self.normal = FacetNormal(self.mesh) print("Mesh name: ", args.mesh, " ", self.mesh) print("Mesh norm max: ", self.mesh.hmax()) print("Mesh norm min: ", self.mesh.hmin()) self.tc.end('mesh') self.sol_p = None self.last_analytic_pressure_norm = None self.v_in = None self.area = None choose_note = {1.0: '', 0.1: 'nuL10', 0.01: 'nuL100', 10.0: 'nuH10'} self.precomputed_filename = args.mesh + choose_note[self.args.nufactor] print('chosen filename for precomputed solution', self.precomputed_filename) # partial Bessel functions and coefficients self.bessel_parabolic = None self.bessel_real = [] self.bessel_complex = [] self.coefs_exp = [-8, -6, -4, -2, 2, 4, 6, 8] self.listDict.update({ 'u_H1w': { 'list': [], 'name': 'corrected velocity H1 error on wall', 'abrev': 'CE_H1w', 'scale': self.scale_factor, 'relative': 'av_norm_H1w', 'slist': [] }, 'u2H1w': { 'list': [], 'name': 'tentative velocity H1 error on wall', 'abrev': 'TE_H1w', 'scale': self.scale_factor, 'relative': 'av_norm_H1w', 'slist': [] }, 'av_norm_H1w': { 'list': [], 'name': 'analytic velocity H1 norm on wall', 'abrev': 'AVN_H1w' }, 'a_force_wall': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AF' }, 'a_force_wall_normal': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AFN' }, 'a_force_wall_shear': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AFS' }, 'force_wall': { 'list': [], 'name': 'force error on wall', 'abrev': 'FE', 'relative': 'a_force_wall', 'slist': [] }, 'force_wall_normal': { 'list': [], 'name': 'normal force error on wall', 'abrev': 'FNE', 'relative': 'a_force_wall', 'slist': [] }, 'force_wall_shear': { 'list': [], 'name': 'shear force error on wall', 'abrev': 'FSE', 'relative': 'a_force_wall', 'slist': [] }, })
def _compileUFL(integrands, form, *args, tempVars=True): if isinstance(form, Equation): form = form.lhs - form.rhs if not isinstance(form, Form): raise ValueError("ufl.Form or ufl.Equation expected.") # added for dirichlet treatment same as conservationlaw model dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)] uflExpr = [form] + [bc.ufl_value for bc in dirichletBCs] if len(form.arguments()) < 2: raise ValueError( "Integrands model requires form with at least two arguments.") x = SpatialCoordinate(form.ufl_cell()) n = FacetNormal(form.ufl_cell()) cellVolume = CellVolume(form.ufl_cell()) maxCellEdgeLength = MaxCellEdgeLength(form.ufl_cell()) minCellEdgeLength = MinCellEdgeLength(form.ufl_cell()) facetArea = FacetArea(form.ufl_cell()) maxFacetEdgeLength = MaxFacetEdgeLength(form.ufl_cell()) minFacetEdgeLength = MinFacetEdgeLength(form.ufl_cell()) phi, u = form.arguments() ubar = Coefficient(u.ufl_function_space()) derivatives = gatherDerivatives(form, [phi, u]) derivatives_phi = derivatives[0] derivatives_u = derivatives[1] derivatives_ubar = map_expr_dags(Replacer({u: ubar}), derivatives_u) try: integrands.field = u.ufl_function_space().field except AttributeError: pass integrals = splitForm(form, [phi]) dform = apply_derivatives(derivative(action(form, ubar), ubar, u)) linearizedIntegrals = splitForm(dform, [phi, u]) if not set( integrals.keys()) <= {'cell', 'exterior_facet', 'interior_facet'}: raise Exception('unknown integral encountered in ' + str(set(integrals.keys())) + '.') if 'cell' in integrals.keys(): arg = Variable(integrands.domainValueTuple, 'u') predefined = { derivatives_u[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) integrands.predefineCoefficients(predefined, False) integrands.interior = generateUnaryCode(predefined, derivatives_phi, integrals['cell'], tempVars=tempVars) predefined = { derivatives_ubar[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) integrands.predefineCoefficients(predefined, False) integrands.linearizedInterior = generateUnaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('cell'), tempVars=tempVars) if 'exterior_facet' in integrals.keys(): arg = Variable(integrands.domainValueTuple, 'u') predefined = { derivatives_u[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[n] = integrands.facetNormal('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, False) integrands.boundary = generateUnaryCode(predefined, derivatives_phi, integrals['exterior_facet'], tempVars=tempVars) predefined = { derivatives_ubar[i]: arg[i] for i in range(len(derivatives_u)) } predefined[x] = integrands.spatialCoordinate('x') predefined[n] = integrands.facetNormal('x') predefined[cellVolume] = integrands.cellVolume() predefined[maxCellEdgeLength] = maxEdgeLength( integrands.cellGeometry()) predefined[minCellEdgeLength] = minEdgeLength( integrands.cellGeometry()) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, False) integrands.linearizedBoundary = generateUnaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('exterior_facet'), tempVars=tempVars) if 'interior_facet' in integrals.keys(): argIn = Variable(integrands.domainValueTuple, 'uIn') argOut = Variable(integrands.domainValueTuple, 'uOut') predefined = { derivatives_u[i](s): arg[i] for i in range(len(derivatives_u)) for s, arg in (('+', argIn), ('-', argOut)) } predefined[x] = integrands.spatialCoordinate('xIn') predefined[n('+')] = integrands.facetNormal('xIn') predefined[cellVolume('+')] = integrands.cellVolume('Side::in') predefined[cellVolume('-')] = integrands.cellVolume('Side::out') predefined[maxCellEdgeLength('+')] = maxEdgeLength( integrands.cellGeometry('Side::in')) predefined[maxCellEdgeLength('-')] = maxEdgeLength( integrands.cellGeometry('Side::out')) predefined[minCellEdgeLength('+')] = minEdgeLength( integrands.cellGeometry('Side::in')) predefined[minCellEdgeLength('-')] = minEdgeLength( integrands.cellGeometry('Side::out')) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, True) integrands.skeleton = generateBinaryCode(predefined, derivatives_phi, integrals['interior_facet'], tempVars=tempVars) predefined = { derivatives_ubar[i](s): arg[i] for i in range(len(derivatives_u)) for s, arg in (('+', argIn), ('-', argOut)) } predefined[x] = integrands.spatialCoordinate('xIn') predefined[n('+')] = integrands.facetNormal('xIn') predefined[cellVolume('+')] = integrands.cellVolume('Side::in') predefined[cellVolume('-')] = integrands.cellVolume('Side::out') predefined[maxCellEdgeLength('+')] = maxEdgeLength( integrands.cellGeometry('Side::in')) predefined[maxCellEdgeLength('-')] = maxEdgeLength( integrands.cellGeometry('Side::out')) predefined[minCellEdgeLength('+')] = minEdgeLength( integrands.cellGeometry('Side::in')) predefined[minCellEdgeLength('-')] = minEdgeLength( integrands.cellGeometry('Side::out')) predefined[facetArea] = integrands.facetArea() predefined[maxFacetEdgeLength] = maxEdgeLength( integrands.facetGeometry()) predefined[minFacetEdgeLength] = minEdgeLength( integrands.facetGeometry()) integrands.predefineCoefficients(predefined, True) integrands.linearizedSkeleton = generateBinaryLinearizedCode( predefined, derivatives_phi, derivatives_u, linearizedIntegrals.get('interior_facet'), tempVars=tempVars) if dirichletBCs: integrands.hasDirichletBoundary = True predefined = {} # predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )') predefined[x] = UnformattedExpression( 'auto', 'intersection.geometry().center( )') integrands.predefineCoefficients(predefined, False) maxId = 0 codeDomains = [] bySubDomain = dict() neuman = [] wholeDomain = None for bc in dirichletBCs: if bc.subDomain in bySubDomain: raise Exception( 'Multiply defined Dirichlet boundary for subdomain ' + str(bc.subDomain)) if not isinstance(bc.functionSpace, (FunctionSpace, FiniteElementBase)): raise Exception( 'Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement' ) if isinstance(bc.functionSpace, FunctionSpace) and ( bc.functionSpace != u.ufl_function_space()): raise Exception( 'Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet' ) if isinstance(bc.functionSpace, FiniteElementBase) and ( bc.functionSpace != u.ufl_element()): raise Exception( 'Cannot handle boundary conditions on subspaces, yet') if isinstance(bc.value, list): neuman = [i for i, x in enumerate(bc.value) if x == None] else: neuman = [] value = ExprTensor(u.ufl_shape) for key in value.keys(): value[key] = Indexed( bc.ufl_value, MultiIndex(tuple(FixedIndex(k) for k in key))) if bc.subDomain is None: wholeDomain = value, neuman elif isinstance(bc.subDomain, int): bySubDomain[bc.subDomain] = value, neuman maxId = max(maxId, bc.subDomain) else: domain = ExprTensor(()) for key in domain.keys(): domain[key] = Indexed( bc.subDomain, MultiIndex(tuple(FixedIndex(k) for k in key))) codeDomains.append((value, neuman, domain)) defaultCode = [] if len(codeDomains) > 0: defaultCode.append(Declaration(Variable('int', 'domainId'))) # defaultCode.append(Declaration(Variable('auto', 'x'), # initializer=UnformattedExpression('auto','intersection.geometry().center()'))) for i, v in enumerate(codeDomains): block = Block() block.append( generateDirichletDomainCode(predefined, v[2], tempVars=tempVars)) block.append('if (domainId)') ifBlock = UnformattedBlock() ifBlock.append( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId + i + 2) + ' );') if len(v[1]) > 0: [ ifBlock.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1] ] ifBlock.append('return true;') block.append(ifBlock) defaultCode.append(block) if wholeDomain is not None: block = UnformattedBlock() block.append( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId + 1) + ' );') if len(wholeDomain[1]) > 0: [ block.append('dirichletComponent[' + str(c) + '] = 0;') for c in wholeDomain[1] ] block.append('return true;') defaultCode.append(block) defaultCode.append(return_(False)) bndId = Variable('const int', 'bndId') getBndId = UnformattedExpression( 'int', 'BoundaryIdProviderType::boundaryId( ' + integrands.arg_i.name + ' )') # getBndId = UnformattedExpression('int', 'boundaryIdGetter_.boundaryId( ' + integrands.arg_i.name + ' )') switch = SwitchStatement(bndId, default=defaultCode) for i, v in bySubDomain.items(): code = [] if len(v[1]) > 0: [ code.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1] ] code.append(return_(True)) switch.append(i, code) integrands.isDirichletIntersection = [ Declaration(bndId, initializer=getBndId), UnformattedBlock( 'std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + bndId.name + ' );'), switch ] predefined[x] = UnformattedExpression( 'auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )') if wholeDomain is None: defaultCode = assign(integrands.arg_r, construct("RRangeType", 0)) else: defaultCode = generateDirichletCode(predefined, wholeDomain[0], tempVars=tempVars) switch = SwitchStatement(integrands.arg_bndId, default=defaultCode) for i, v in bySubDomain.items(): switch.append( i, generateDirichletCode(predefined, v[0], tempVars=tempVars)) for i, v in enumerate(codeDomains): switch.append( i + maxId + 2, generateDirichletCode(predefined, v[0], tempVars=tempVars)) integrands.dirichlet = [switch] return integrands
def __init__(self, args, tc, metadata): self.has_analytic_solution = True self.problem_code = 'SCYL' super(Problem, self).__init__(args, tc, metadata) self.tc.init_watch('errorP', 'Computed pressure error', True) self.tc.init_watch('errorV', 'Computed velocity error', True) self.tc.init_watch('errorForce', 'Computed force error', True) self.tc.init_watch('errorVtest', 'Computed velocity error test', True) self.tc.init_watch('computePG', 'Computed pressure gradient', True) self.name = 'steady_cylinder' self.status_functional_str = 'last H1 velocity error' # input parameters self.ic = args.ic self.factor = args.factor self.metadata['factor'] = self.factor self.scale_factor.append(self.factor) # fixed parameters (used in analytic solution and in BC) self.nu = 3.71 # kinematic viscosity self.R = 5.0 # cylinder radius self.mesh_volume = pi * 25. * 20. # Import gmsh mesh self.tc.start('mesh') self.mesh, self.facet_function = super(Problem, self).loadMesh(args.mesh) self.dsIn = Measure("ds", subdomain_id=2, subdomain_data=self.facet_function) self.dsOut = Measure("ds", subdomain_id=3, subdomain_data=self.facet_function) self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function) self.normal = FacetNormal(self.mesh) print("Mesh name: ", args.mesh, " ", self.mesh) print("Mesh norm max: ", self.mesh.hmax()) print("Mesh norm min: ", self.mesh.hmin()) self.tc.end('mesh') self.sol_p = None self.analytic_gradient = None self.analytic_pressure_norm = None self.v_in = None self.area = None self.analytic_v_norm_L2 = None self.analytic_v_norm_H1 = None self.analytic_v_norm_H1w = None self.listDict.update({ 'u_H1w': { 'list': [], 'name': 'corrected velocity H1 error on wall', 'abrev': 'CE_H1w', 'scale': self.scale_factor, 'relative': 'av_norm_H1w', 'slist': [] }, 'u2H1w': { 'list': [], 'name': 'tentative velocity H1 error on wall', 'abrev': 'TE_H1w', 'scale': self.scale_factor, 'relative': 'av_norm_H1w', 'slist': [] }, 'av_norm_H1w': { 'list': [], 'name': 'analytic velocity H1 norm on wall', 'abrev': 'AVN_H1w' }, 'a_force_wall': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AF' }, 'a_force_wall_normal': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AFN' }, 'a_force_wall_shear': { 'list': [], 'name': 'analytic force on wall', 'abrev': 'AFS' }, 'force_wall': { 'list': [], 'name': 'force error on wall', 'abrev': 'FE', 'relative': 'a_force_wall', 'slist': [] }, 'force_wall_normal': { 'list': [], 'name': 'normal force error on wall', 'abrev': 'FNE', 'relative': 'a_force_wall', 'slist': [] }, 'force_wall_shear': { 'list': [], 'name': 'shear force error on wall', 'abrev': 'FSE', 'relative': 'a_force_wall', 'slist': [] }, })
def readin_mesh(self): if self.meshfile_type=='ASCII': encoding = XDMFFile.Encoding.ASCII elif self.meshfile_type=='HDF5': encoding = XDMFFile.Encoding.HDF5 else: raise NameError('Choose either ASCII or HDF5 as meshfile_type, or add a different encoding!') # read in xdmf mesh - domain with XDMFFile(self.comm, self.mesh_domain, 'r', encoding=encoding) as infile: self.mesh = infile.read_mesh(name="Grid") self.mt_d = infile.read_meshtags(self.mesh, name="Grid") # read in xdmf mesh - boundary # here, we define b1 BCs as BCs associated to a topology one dimension less than the problem (most common), # b2 BCs two dimensions less, and b3 BCs three dimensions less # for a 3D problem - b1: surface BCs, b2: edge BCs, b3: point BCs # for a 2D problem - b1: edge BCs, b2: point BCs # 1D problems not supported (currently...) if self.mesh.topology.dim == 3: try: self.mesh.topology.create_connectivity(2, self.mesh.topology.dim) with XDMFFile(self.comm, self.mesh_boundary, 'r', encoding=encoding) as infile: self.mt_b1 = infile.read_meshtags(self.mesh, name="Grid") except: pass try: self.mesh.topology.create_connectivity(1, self.mesh.topology.dim) with XDMFFile(self.comm, self.mesh_boundary, 'r', encoding=encoding) as infile: self.mt_b2 = infile.read_meshtags(self.mesh, name="Grid_b2") except: pass try: self.mesh.topology.create_connectivity(0, self.mesh.topology.dim) with XDMFFile(self.comm, self.mesh_boundary, 'r', encoding=encoding) as infile: self.mt_b3 = infile.read_meshtags(self.mesh, name="Grid_b3") except: pass elif self.mesh.topology.dim == 2: try: self.mesh.topology.create_connectivity(1, self.mesh.topology.dim) with XDMFFile(self.comm, self.mesh_boundary, 'r', encoding=encoding) as infile: self.mt_b1 = infile.read_meshtags(self.mesh, name="Grid") except: pass try: self.mesh.topology.create_connectivity(0, self.mesh.topology.dim) with XDMFFile(self.comm, self.mesh_boundary, 'r', encoding=encoding) as infile: self.mt_b2 = infile.read_meshtags(self.mesh, name="Grid_b2") except: pass else: raise AttributeError("Your mesh seems to be 1D! Not supported!") # useful fields: # facet normal self.n0 = FacetNormal(self.mesh) # cell diameter self.h0 = CellDiameter(self.mesh)