def a(phi): # phi = 1e5*phi n = ufl.grad(phi) / ufl.sqrt(ufl.dot(ufl.grad(phi), ufl.grad(phi)) + 1e-5) theta = ufl.atan_2(n[1], n[0]) n = 1e5 * n + ufl.as_vector([1e-5, 1e-5]) xx = n[1] / n[0] # theta = ufl.asin(xx/ ufl.sqrt(1 + xx**2)) theta = ufl.atan(xx) return 1.0 + epsilon_4 * ufl.cos(m * (theta - theta_0))
def initControl(self): self.controlSpace = [ FunctionSpace(self.mesh, "DG", 1), FunctionSpace(self.mesh, "DG", 1) ] u_x = Dx(self.u, 0) u_y = Dx(self.u, 1) # phi = atan(u_y/u_x) <==> sin(phi) / cos(phi) = u_y / u_x self.gamma = [] phi = ufl.atan_2(u_y, u_x) self.gamma.append(1. / self.alpha * (cos(phi) * u_x + sin(phi) * u_y)) self.gamma.append(phi)
def updateCoefficients(self): x, y = SpatialCoordinate(self.mesh) # Init coefficient matrix self.a = as_matrix([[1., Constant(0.)], [Constant(0.), 1.]]) # Set up explicit solution r = sqrt(x**2 + y**2) phi = atan_2(x, y) self.u_ = r**self.alpha * sin(2. * phi) * (1 - x) * (1 - y) # Init right-hand side self.f = inner(self.a, grad(grad(self.u_))) # Set boundary conditions to exact solution self.g = self.u_
def eigenstate(A): """Eigenvalues and eigenprojectors of the 3x3 (real-valued) tensor A. Provides the spectral decomposition A = sum_{a=0}^{2} λ_a * E_a with (ordered) eigenvalues λ_a and their associated eigenprojectors E_a = n_a^R x n_a^L. Note: Tensor A must not have complex eigenvalues! """ if ufl.shape(A) != (3, 3): raise RuntimeError( f"Tensor A of shape {ufl.shape(A)} != (3, 3) is not supported!") # eps = 3.0e-16 # slightly above 2**-(53 - 1), see https://en.wikipedia.org/wiki/IEEE_754 # A = ufl.variable(A) # # --- determine eigenvalues λ0, λ1, λ2 # I1, I2, I3 = invariants_principal(A) dq = 2 * I1**3 - 9 * I1 * I2 + 27 * I3 # Δx = [ A[0, 1] * A[1, 2] * A[2, 0] - A[0, 2] * A[1, 0] * A[2, 1], A[0, 1]**2 * A[1, 2] - A[0, 1] * A[0, 2] * A[1, 1] + A[0, 1] * A[0, 2] * A[2, 2] - A[0, 2]**2 * A[2, 1], A[0, 0] * A[0, 1] * A[2, 1] - A[0, 1]**2 * A[2, 0] - A[0, 1] * A[2, 1] * A[2, 2] + A[0, 2] * A[2, 1]**2, A[0, 0] * A[0, 2] * A[1, 2] + A[0, 1] * A[1, 2]**2 - A[0, 2]**2 * A[1, 0] - A[0, 2] * A[1, 1] * A[1, 2], A[0, 0] * A[0, 1] * A[1, 2] - A[0, 1] * A[0, 2] * A[1, 0] - A[0, 1] * A[1, 2] * A[2, 2] + A[0, 2] * A[1, 2] * A[2, 1], # noqa: E501 A[0, 0] * A[0, 2] * A[2, 1] - A[0, 1] * A[0, 2] * A[2, 0] + A[0, 1] * A[1, 2] * A[2, 1] - A[0, 2] * A[1, 1] * A[2, 1], # noqa: E501 A[0, 1] * A[1, 0] * A[1, 2] - A[0, 2] * A[1, 0] * A[1, 1] + A[0, 2] * A[1, 0] * A[2, 2] - A[0, 2] * A[1, 2] * A[2, 0], # noqa: E501 A[0, 0]**2 * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 0] - A[0, 0] * A[1, 1] * A[1, 2] - A[0, 0] * A[1, 2] * A[2, 2] + A[0, 1] * A[1, 0] * A[1, 2] + A[0, 2] * A[1, 0] * A[2, 2] + A[1, 1] * A[1, 2] * A[2, 2] - A[1, 2]**2 * A[2, 1], # noqa: E501 A[0, 0]**2 * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 0] - A[0, 0] * A[1, 1] * A[1, 2] - A[0, 0] * A[1, 2] * A[2, 2] + A[0, 2] * A[1, 0] * A[1, 1] + A[0, 2] * A[1, 2] * A[2, 0] + A[1, 1] * A[1, 2] * A[2, 2] - A[1, 2]**2 * A[2, 1], # noqa: E501 A[0, 0] * A[0, 1] * A[1, 1] - A[0, 0] * A[0, 1] * A[2, 2] - A[0, 1]**2 * A[1, 0] + A[0, 1] * A[0, 2] * A[2, 0] - A[0, 1] * A[1, 1] * A[2, 2] + A[0, 1] * A[2, 2]**2 + A[0, 2] * A[1, 1] * A[2, 1] - A[0, 2] * A[2, 1] * A[2, 2], # noqa: E501 A[0, 0] * A[0, 1] * A[1, 1] - A[0, 0] * A[0, 1] * A[2, 2] + A[0, 0] * A[0, 2] * A[2, 1] - A[0, 1]**2 * A[1, 0] - A[0, 1] * A[1, 1] * A[2, 2] + A[0, 1] * A[1, 2] * A[2, 1] + A[0, 1] * A[2, 2]**2 - A[0, 2] * A[2, 1] * A[2, 2], # noqa: E501 A[0, 0] * A[0, 1] * A[1, 2] - A[0, 0] * A[0, 2] * A[1, 1] + A[0, 0] * A[0, 2] * A[2, 2] - A[0, 1] * A[1, 1] * A[1, 2] - A[0, 2]**2 * A[2, 0] + A[0, 2] * A[1, 1]**2 - A[0, 2] * A[1, 1] * A[2, 2] + A[0, 2] * A[1, 2] * A[2, 1], # noqa: E501 A[0, 0] * A[0, 2] * A[1, 1] - A[0, 0] * A[0, 2] * A[2, 2] - A[0, 1] * A[0, 2] * A[1, 0] + A[0, 1] * A[1, 1] * A[1, 2] - A[0, 1] * A[1, 2] * A[2, 2] + A[0, 2]**2 * A[2, 0] - A[0, 2] * A[1, 1]**2 + A[0, 2] * A[1, 1] * A[2, 2], # noqa: E501 A[0, 0]**2 * A[1, 1] - A[0, 0]**2 * A[2, 2] - A[0, 0] * A[0, 1] * A[1, 0] + A[0, 0] * A[0, 2] * A[2, 0] - A[0, 0] * A[1, 1]**2 + A[0, 0] * A[2, 2]**2 + A[0, 1] * A[1, 0] * A[1, 1] - A[0, 2] * A[2, 0] * A[2, 2] + A[1, 1]**2 * A[2, 2] - A[1, 1] * A[1, 2] * A[2, 1] - A[1, 1] * A[2, 2]**2 + A[1, 2] * A[2, 1] * A[2, 2] ] # noqa: E501 Δy = [ A[0, 2] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 2] * A[2, 0], A[1, 0]**2 * A[2, 1] - A[1, 0] * A[1, 1] * A[2, 0] + A[1, 0] * A[2, 0] * A[2, 2] - A[1, 2] * A[2, 0]**2, A[0, 0] * A[1, 0] * A[1, 2] - A[0, 2] * A[1, 0]**2 - A[1, 0] * A[1, 2] * A[2, 2] + A[1, 2]**2 * A[2, 0], A[0, 0] * A[2, 0] * A[2, 1] - A[0, 1] * A[2, 0]**2 + A[1, 0] * A[2, 1]**2 - A[1, 1] * A[2, 0] * A[2, 1], A[0, 0] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 0] * A[2, 0] - A[1, 0] * A[2, 1] * A[2, 2] + A[1, 2] * A[2, 0] * A[2, 1], # noqa: E501 A[0, 0] * A[1, 2] * A[2, 0] - A[0, 2] * A[1, 0] * A[2, 0] + A[1, 0] * A[1, 2] * A[2, 1] - A[1, 1] * A[1, 2] * A[2, 0], # noqa: E501 A[0, 1] * A[1, 0] * A[2, 1] - A[0, 1] * A[1, 1] * A[2, 0] + A[0, 1] * A[2, 0] * A[2, 2] - A[0, 2] * A[2, 0] * A[2, 1], # noqa: E501 A[0, 0]**2 * A[2, 1] - A[0, 0] * A[0, 1] * A[2, 0] - A[0, 0] * A[1, 1] * A[2, 1] - A[0, 0] * A[2, 1] * A[2, 2] + A[0, 1] * A[1, 0] * A[2, 1] + A[0, 1] * A[2, 0] * A[2, 2] + A[1, 1] * A[2, 1] * A[2, 2] - A[1, 2] * A[2, 1]**2, # noqa: E501 A[0, 0]**2 * A[2, 1] - A[0, 0] * A[0, 1] * A[2, 0] - A[0, 0] * A[1, 1] * A[2, 1] - A[0, 0] * A[2, 1] * A[2, 2] + A[0, 1] * A[1, 1] * A[2, 0] + A[0, 2] * A[2, 0] * A[2, 1] + A[1, 1] * A[2, 1] * A[2, 2] - A[1, 2] * A[2, 1]**2, # noqa: E501 A[0, 0] * A[1, 0] * A[1, 1] - A[0, 0] * A[1, 0] * A[2, 2] - A[0, 1] * A[1, 0]**2 + A[0, 2] * A[1, 0] * A[2, 0] - A[1, 0] * A[1, 1] * A[2, 2] + A[1, 0] * A[2, 2]**2 + A[1, 1] * A[1, 2] * A[2, 0] - A[1, 2] * A[2, 0] * A[2, 2], # noqa: E501 A[0, 0] * A[1, 0] * A[1, 1] - A[0, 0] * A[1, 0] * A[2, 2] + A[0, 0] * A[1, 2] * A[2, 0] - A[0, 1] * A[1, 0]**2 - A[1, 0] * A[1, 1] * A[2, 2] + A[1, 0] * A[1, 2] * A[2, 1] + A[1, 0] * A[2, 2]**2 - A[1, 2] * A[2, 0] * A[2, 2], # noqa: E501 A[0, 0] * A[1, 0] * A[2, 1] - A[0, 0] * A[1, 1] * A[2, 0] + A[0, 0] * A[2, 0] * A[2, 2] - A[0, 2] * A[2, 0]**2 - A[1, 0] * A[1, 1] * A[2, 1] + A[1, 1]**2 * A[2, 0] - A[1, 1] * A[2, 0] * A[2, 2] + A[1, 2] * A[2, 0] * A[2, 1], # noqa: E501 A[0, 0] * A[1, 1] * A[2, 0] - A[0, 0] * A[2, 0] * A[2, 2] - A[0, 1] * A[1, 0] * A[2, 0] + A[0, 2] * A[2, 0]**2 + A[1, 0] * A[1, 1] * A[2, 1] - A[1, 0] * A[2, 1] * A[2, 2] - A[1, 1]**2 * A[2, 0] + A[1, 1] * A[2, 0] * A[2, 2], # noqa: E501 A[0, 0]**2 * A[1, 1] - A[0, 0]**2 * A[2, 2] - A[0, 0] * A[0, 1] * A[1, 0] + A[0, 0] * A[0, 2] * A[2, 0] - A[0, 0] * A[1, 1]**2 + A[0, 0] * A[2, 2]**2 + A[0, 1] * A[1, 0] * A[1, 1] - A[0, 2] * A[2, 0] * A[2, 2] + A[1, 1]**2 * A[2, 2] - A[1, 1] * A[1, 2] * A[2, 1] - A[1, 1] * A[2, 2]**2 + A[1, 2] * A[2, 1] * A[2, 2] ] # noqa: E501 Δd = [9, 6, 6, 6, 8, 8, 8, 2, 2, 2, 2, 2, 2, 1] Δ = 0 for i in range(len(Δd)): Δ += Δx[i] * Δd[i] * Δy[i] Δxp = [ A[1, 0], A[2, 0], A[2, 1], -A[0, 0] + A[1, 1], -A[0, 0] + A[2, 2], -A[1, 1] + A[2, 2] ] Δyp = [ A[0, 1], A[0, 2], A[1, 2], -A[0, 0] + A[1, 1], -A[0, 0] + A[2, 2], -A[1, 1] + A[2, 2] ] Δdp = [6, 6, 6, 1, 1, 1] dp = 0 for i in range(len(Δdp)): dp += 1 / 2 * Δxp[i] * Δdp[i] * Δyp[i] # Avoid dp = 0 and disc = 0, both are known with absolute error of ~eps**2 # Required to avoid sqrt(0) derivatives and negative square roots dp += eps**2 Δ += eps**2 phi3 = ufl.atan_2(ufl.sqrt(27) * ufl.sqrt(Δ), dq) # sorted eigenvalues: λ0 <= λ1 <= λ2 λ = [(I1 + 2 * ufl.sqrt(dp) * ufl.cos((phi3 + 2 * ufl.pi * k) / 3)) / 3 for k in range(1, 4)] # # --- determine eigenprojectors E0, E1, E2 # E = [ufl.diff(λk, A).T for λk in λ] return λ, E
# and # # $D_n$ is the anisotropic diffusion using the previous solution $\textbf{u}_n$ to compute the entries. # # First we put in the right hand side which only contains explicit data. # <codecell> from ufl import inner, dx a_ex = (inner(u_h_n, v) - inner(u_h_n[0], v[1])) * dx # <markdowncell> # For the left hand side we have the spatial derivatives and the implicit parts. # <codecell> from ufl import pi, atan, atan_2, tan, grad, as_vector, inner, dot psi = pi / 8.0 + atan_2(grad(u_h_n[0])[1], (grad(u_h_n[0])[0])) Phi = tan(N / 2.0 * psi) beta = (1.0 - Phi * Phi) / (1.0 + Phi * Phi) dbeta_dPhi = -2.0 * N * Phi / (1.0 + Phi * Phi) fac = 1.0 + c * beta diag = fac * fac offdiag = -fac * c * dbeta_dPhi d0 = as_vector([diag, offdiag]) d1 = as_vector([-offdiag, diag]) m = u[0] - 0.5 - kappa1 / pi * atan(kappa2 * u[1]) s = as_vector([dt / tau * u[0] * (1.0 - u[0]) * m, u[0]]) a_im = (alpha * alpha * dt / tau * (inner(dot(d0, grad(u[0])), grad(v[0])[0]) + inner(dot(d1, grad(u[0])), grad(v[0])[1])) + 2.25 * dt * inner(grad(u[1]), grad(v[1])) + inner(u, v) - inner(s, v)) * dx
def eval(self, values, x): values[0] = ufl.atan_2(x[1], x[0])
from dolfin import * import matplotlib.pyplot as plt import ufl mesh = RectangleMesh(Point(-1.0, -1.0), Point(1.0, 1.0), 10, 10) el = FiniteElement("Lagrange", mesh.ufl_cell(), degree=1) V = FunctionSpace(mesh, el) x = SpatialCoordinate(mesh) # Approach 1: Fails with project phi = project(ufl.atan_2(x[1], x[0]), V) # phi = interpolate(ufl.atan_2(x[1], x[0]), V) # fails, no eval() method.. plt.subplot(221) p1 = plot(phi, title="phi1") plt.colorbar(p1) file = File("phi1.pvd") file.write(phi) # Approach 2: Works with interpolate and UserExpression (has eval method) class RadialAngle(UserExpression): def eval(self, values, x): values[0] = ufl.atan_2(x[1], x[0]) phi2 = interpolate(RadialAngle(), V) plt.subplot(222) p2 = plot(phi2, title="phi2") plt.colorbar(p2) file2 = File("phi2.pvd")