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 rotation_matrix_2d(angle): """ Rotation matrix associated with some ``angle``, as a UFL matrix. """ return ufl.as_matrix( [[ufl.cos(angle), -ufl.sin(angle)], [ufl.sin(angle), ufl.cos(angle)]] )
def test_matvec(compile_args): """Test evaluation of linear rank-0 form. Evaluates expression c * A_ij * f_j where c is a Constant, A_ij is a user specified constant matrix and f_j is j-th component of user specified vector-valued finite element function (in P1 space). """ e = ufl.VectorElement("P", "triangle", 1) mesh = ufl.Mesh(e) V = ufl.FunctionSpace(mesh, e) f = ufl.Coefficient(V) a_mat = np.array([[1.0, 2.0], [1.0, 1.0]]) a = ufl.as_matrix(a_mat) expr = ufl.Constant(mesh) * ufl.dot(a, f) points = np.array([[0.0, 0.0], [1.0, 0.0], [0.0, 1.0]]) obj, module = ffcx.codegeneration.jit.compile_expressions( [(expr, points)], cffi_extra_compile_args=compile_args) ffi = cffi.FFI() kernel = obj[0][0] c_type, np_type = float_to_type("double") A = np.zeros((3, 2), dtype=np_type) f_mat = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]) # Coefficient storage XYXYXY w = np.array(f_mat.T.flatten(), dtype=np_type) c = np.array([0.5], dtype=np_type) # Coords storage XYXYXY coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) kernel.tabulate_expression( 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)) # Check the computation against correct NumPy value assert np.allclose(A, 0.5 * np.dot(a_mat, f_mat).T) # Prepare NumPy array of points attached to the expression length = kernel.num_points * kernel.topological_dimension points_kernel = np.frombuffer( ffi.buffer(kernel.points, length * ffi.sizeof("double")), np.double) points_kernel = points_kernel.reshape(points.shape) assert np.allclose(points, points_kernel) # Check the value shape attached to the expression value_shape = np.frombuffer( ffi.buffer(kernel.value_shape, kernel.num_components * ffi.sizeof("int")), np.intc) assert np.allclose(expr.ufl_shape, value_shape)
def eps(self, u): if self.model_type == "2D": return ufl.sym(ufl.grad(u)) if self.model_type == "plane-strain": return ufl.sym( ufl.as_matrix([ [u[0].dx(0), u[0.].dx(1), 0], [u[1].dx(0), u[1].dx(1), 0], [0, 0, 0], ]))
def test_invariants_eigenstate(A, squaremesh_5): dx = ufl.dx(squaremesh_5) A_ = ufl.as_matrix(dolfinx.fem.Constant(squaremesh_5, A)) [e0, e1, e2], [E0, E1, E2] = dolfiny.invariants.eigenstate(A_) e_num = np.sort(np.linalg.eigvals(A)) e_sym = dolfiny.expression.assemble(ufl.as_vector([e0, e1, e2]), dx) assert np.isclose(e_num, e_sym, atol=1e-14).all() As = dolfiny.expression.assemble(e0 * E0 + e1 * E1 + e2 * E2, dx) assert np.isclose(A, As).all()
def solve(self, it=0): if self.group_GS: self.solve_group_GS(it) else: super(EllipticSNFluxModule, self).solve(it) self.slns_mg = split(self.sln) i,p,q,k1,k2 = ufl.indices(5) sol_timer = Timer("-- Complete solution") aux_timer = Timer("---- SOL: Computing angular flux + adjoint") # TODO: Move to Discretization V11 = FunctionSpace(self.DD.mesh, "CG", self.DD.parameters["p"]) for gto in range(self.DD.G): self.PD.get_xs('D', self.D, gto) form = self.D * ufl.diag_vector(ufl.as_matrix(self.DD.ordinates_matrix[i,p]*self.slns_mg[gto][q].dx(i), (p,q))) for gfrom in range(self.DD.G): pres_Ss = False # TODO: Enlarge self.S and self.C to (L+1)^2 (or 1./2.*(L+1)*(L+2) in 2D) to accomodate for anisotropic # scattering (lines below using CC, SS are correct only for L = 0, when the following inner loop runs only # once. for l in range(self.L+1): for m in range(-l, l+1): if self.DD.angular_quad.get_D() == 2 and divmod(l+m, 2)[1] == 0: continue pres_Ss |= self.PD.get_xs('Ss', self.S[l], gto, gfrom, l) self.PD.get_xs('C', self.C[l], gto, gfrom, l) if pres_Ss: Cd = ufl.diag(self.C) CC = self.tensors.Y[p,k1] * Cd[k1,k2] * self.tensors.Qt[k2,q,i] form += ufl.as_vector(CC[p,q,i] * self.slns_mg[gfrom][q].dx(i), p) # project(form, self.DD.Vpsi1, function=self.aux_slng, preconditioner_type="petsc_amg") # FASTER, but requires form compilation for each dir.: for pp in range(self.DD.M): assign(self.aux_slng.sub(pp), project(form[pp], V11, preconditioner_type="petsc_amg")) self.psi_mg[gto].assign(self.slns_mg[gto] + self.aux_slng) self.adj_psi_mg[gto].assign(self.slns_mg[gto] - self.aux_slng)
def __init__(self, problem, SN_order, verbosity=0): super(SNDiscretization, self).__init__(problem, verbosity) if self.verb > 1: print0("Obtaining angular discretization data") t_ordinates = Timer("Angular discretization data") from transport_data import ordinates_ext_module, quadrature_file from common import check_sn_order self.angular_quad = ordinates_ext_module.OrdinatesData(SN_order, self.mesh.topology().dim(), quadrature_file) self.M = self.angular_quad.get_M() self.N = check_sn_order(SN_order) ord_mat = [self.angular_quad.get_xi().tolist(), self.angular_quad.get_eta().tolist()] if self.angular_quad.get_D() == 3: ord_mat.append(self.angular_quad.get_mu().tolist()) self.ordinates_matrix = as_matrix(ord_mat) if self.verb > 2: self.angular_quad.print_info()
def test_diff_then_integrate(): # Define 1D geometry n = 21 mesh = UnitIntervalMesh(MPI.comm_world, n) # Shift and scale mesh x0, x1 = 1.5, 3.14 mesh.coordinates()[:] *= (x1 - x0) mesh.coordinates()[:] += x0 x = SpatialCoordinate(mesh)[0] xs = 0.1 + 0.8 * x / x1 # scaled to be within [0.1,0.9] # 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-ffc-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([x**x]) reg([x**(x**2)], 8) reg([x**(x**3)], 6) reg([x**(x**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) try: import scipy except ImportError: scipy = None if hasattr(math, 'erf') or scipy is not None: reg([erf(xs)]) else: print( "Warning: skipping test of erf, old python version and no scipy.") # if 0: # print("Warning: skipping tests of bessel functions, doesn't build on all platforms.") # elif scipy is None: # print("Warning: skipping tests of bessel functions, missing scipy.") # else: # for nu in (0, 1, 2): # # Many of these are possibly more accurately integrated, # # but 4 covers all and is sufficient for this test # reg([bessel_J(nu, xs), bessel_Y(nu, xs), bessel_I(nu, xs), bessel_K(nu, xs)], 4) # 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]]) x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4]) cc = as_matrix([[2, 3], [4, 5]]) reg2([xx]) 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 * xx, 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 for F, acc in F_list: # Apply UFL differentiation f = diff(F, SpatialCoordinate(mesh))[..., 0] if debug: print(F) print(x) print(f) # Apply integration with DOLFIN # (also passes through form compilation and jit) M = f * dx f_integral = assemble_scalar(M) # noqa f_integral = MPI.sum(mesh.mpi_comm(), f_integral) # Compute integral of f manually from anti-derivative F # (passes through PyDOLFIN interface and uses UFL evaluation) F_diff = F((x1, )) - F((x0, )) # Compare results. Using custom relative delta instead # of decimal digits here because some numbers are >> 1. delta = min(abs(f_integral), abs(F_diff)) * 10**-acc assert f_integral - F_diff <= delta
def test_div_grad_then_integrate_over_cells_and_boundary(): # Define 2D geometry n = 10 mesh = RectangleMesh(Point(0.0, 0.0), Point(2.0, 3.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-ffc-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, Vh, covariance, mean=None): """ Constructor Inputs: - :code:`Vh`: Finite element space on which the prior is defined. Must be the Real space with one global degree of freedom - :code:`covariance`: The covariance of the prior. Must be a :code:`numpy.ndarray` of appropriate size - :code:`mean`(optional): Mean of the prior distribution. Must be of type `dolfin.Vector()` """ self.Vh = Vh if Vh.dim() != covariance.shape[0] or Vh.dim() != covariance.shape[1]: raise ValueError( "Covariance incompatible with Finite Element space") if not np.issubdtype(covariance.dtype, np.floating): raise TypeError("Covariance matrix must be a float array") self.covariance = covariance #np.linalg.cholesky automatically provides more error checking, #so use those self.chol = np.linalg.cholesky(self.covariance) self.chol_inv = scila.solve_triangular(self.chol, np.identity(Vh.dim()), lower=True) self.precision = np.dot(self.chol_inv.T, self.chol_inv) trial = dl.TrialFunction(Vh) test = dl.TestFunction(Vh) domain_measure = dl.assemble(dl.Constant(1.) * ufl.dx(Vh.mesh())) domain_measure_inv = dl.Constant(1.0 / domain_measure) #Identity mass matrix self.M = dl.assemble(domain_measure_inv * ufl.inner(trial, test) * ufl.dx) self.Msolver = Operator2Solver(self.M) if mean: self.mean = mean else: tmp = dl.Vector() self.M.init_vector(tmp, 0) tmp.zero() self.mean = tmp if Vh.dim() == 1: trial = ufl.as_matrix([[trial]]) test = ufl.as_matrix([[test]]) #Create form matrices covariance_op = ufl.as_matrix(list(map(list, self.covariance))) precision_op = ufl.as_matrix(list(map(list, self.precision))) chol_op = ufl.as_matrix(list(map(list, self.chol))) chol_inv_op = ufl.as_matrix(list(map(list, self.chol_inv))) #variational for the regularization operator, or the precision matrix var_form_R = domain_measure_inv \ * ufl.inner(test, ufl.dot(precision_op, trial)) * ufl.dx #variational for the inverse regularization operator, or the covariance #matrix var_form_Rinv = domain_measure_inv \ * ufl.inner(test, ufl.dot(covariance_op, trial)) * ufl.dx #variational form for the square root of the regularization operator var_form_R_sqrt = domain_measure_inv \ * ufl.inner(test, ufl.dot(chol_inv_op.T, trial)) * ufl.dx #variational form for the square root of the inverse regularization #operator var_form_Rinv_sqrt = domain_measure_inv \ * ufl.inner(test, ufl.dot(chol_op, trial)) * ufl.dx self.R = dl.assemble(var_form_R) self.RSolverOp = dl.assemble(var_form_Rinv) self.Rsolver = Operator2Solver(self.RSolverOp) self.sqrtR = dl.assemble(var_form_R_sqrt) self.sqrtRinv = dl.assemble(var_form_Rinv_sqrt)
dolfiny.interpolation.interpolate(gξ, n0i) # ---------------------------------------------------------------------------- # Orthogonal projection operator (assumes sufficient geometry approximation) P = ufl.Identity(mesh.geometry.dim) - ufl.outer(n0i, n0i) # Thickness variable X = dolfinx.FunctionSpace(mesh, ("DG", q)) ξ = dolfinx.Function(X, name='ξ') # Undeformed configuration: director d0 and placement b0 d0 = n0i # normal of manifold mesh, interpolated b0 = x0 + ξ * d0 # Deformed configuration: director d and placement b, assumed kinematics, director uses rotation matrix d = ufl.as_matrix([[ufl.cos(r), 0, ufl.sin(r)], [0, 1, 0], [-ufl.sin(r), 0, ufl.cos(r)]]) * d0 b = x0 + ufl.as_vector([u, 0, w]) + ξ * d # Configuration gradient, undeformed configuration J0 = ufl.grad(b0) - ufl.outer(d0, d0) # = P * ufl.grad(x0) + ufl.grad(ξ * d0) J0 = ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(J0) J0 = ufl.algorithms.apply_derivatives.apply_derivatives(J0) J0 = ufl.replace(J0, {ufl.grad(ξ): d0}) # Configuration gradient, deformed configuration J = ufl.grad(b) - ufl.outer( d0, d0) # = P * ufl.grad(x0) + ufl.grad(ufl.as_vector([u, 0, w]) + ξ * d) J = ufl.algorithms.apply_algebra_lowering.apply_algebra_lowering(J) J = ufl.algorithms.apply_derivatives.apply_derivatives(J) J = ufl.replace(J, {ufl.grad(ξ): d0})