Пример #1
0
    def estimate(self, solution):
        mesh = solution.function_space().mesh()

        # Define cell and facet residuals
        R_T = -(self.rhs_f + div(grad(solution)))
        n = FacetNormal(mesh)
        R_dT = dot(grad(solution), n)

        # Will use space of constants to localize indicator form
        Constants = FunctionSpace(mesh, "DG", 0)
        w = TestFunction(Constants)
        h = CellSize(mesh)

        # Define form for assembling error indicators
        form = (h ** 2 * R_T ** 2 * w * dx + avg(h) * avg(R_dT) ** 2 * 2 * avg(w) * dS)
    #            + h * R_dT ** 2 * w * ds)

        # Assemble error indicators
        indicators = assemble(form)

        # Calculate error
        error_estimate = sqrt(sum(i for i in indicators.array()))

        # Take sqrt of indicators
        indicators = np.array([sqrt(i) for i in indicators])

        # Mark cells for refinement based on maximal marking strategy
        largest_error = max(indicators)
        cell_markers = MeshFunction("bool", mesh, mesh.topology().dim())
        for c in cells(mesh):
            cell_markers[c] = indicators[c.index()] > (self.fraction * largest_error)

        return error_estimate, cell_markers
Пример #2
0
    def circumradius(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        if not domain.is_piecewise_linear_simplex_domain():
            # Don't lower for non-affine cells, instead leave it to
            # form compiler
            warning(
                "Only know how to compute the circumradius of an affine cell.")
            return o

        cellname = domain.ufl_cell().cellname()
        cellvolume = self.cell_volume(CellVolume(domain))

        if cellname == "interval":
            r = 0.5 * cellvolume

        elif cellname == "triangle":
            J = self.jacobian(Jacobian(domain))
            trev = CellEdgeVectors(domain)
            num_edges = 3
            i, j, k = indices(3)
            elen = [
                sqrt((J[i, j] * trev[edge, j]) * (J[i, k] * trev[edge, k]))
                for edge in range(num_edges)
            ]

            r = (elen[0] * elen[1] * elen[2]) / (4.0 * cellvolume)

        elif cellname == "tetrahedron":
            J = self.jacobian(Jacobian(domain))
            trev = CellEdgeVectors(domain)
            num_edges = 6
            i, j, k = indices(3)
            elen = [
                sqrt((J[i, j] * trev[edge, j]) * (J[i, k] * trev[edge, k]))
                for edge in range(num_edges)
            ]

            # elen[3] = length of edge 3
            # la, lb, lc = lengths of the sides of an intermediate triangle
            la = elen[3] * elen[2]
            lb = elen[4] * elen[1]
            lc = elen[5] * elen[0]
            # p = perimeter
            p = (la + lb + lc)
            # s = semiperimeter
            s = p / 2
            # area of intermediate triangle with Herons formula
            triangle_area = sqrt(s * (s - la) * (s - lb) * (s - lc))
            r = triangle_area / (6.0 * cellvolume)

        else:
            error("Unhandled cell type %s." % cellname)

        return r
Пример #3
0
def pseudo_determinant_expr(A):
    """Compute the pseudo-determinant of A."""
    m, n = A.ufl_shape
    if n == 1:
        # Special case 1xm for simpler expression
        i = Index()
        return sqrt(A[i, 0] * A[i, 0])
    elif n == 2 and m == 3:
        # Special case 2x3 for simpler expression
        c = cross_expr(A[:, 0], A[:, 1])
        i = Index()
        return sqrt(c[i] * c[i])
    else:
        # Generic formulation based on A.T*A
        return generic_pseudo_determinant_expr(A)
Пример #4
0
def pseudo_determinant_expr(A):
    """Compute the pseudo-determinant of A."""
    m, n = A.ufl_shape
    if n == 1:
        # Special case 1xm for simpler expression
        i = Index()
        return sqrt(A[i, 0] * A[i, 0])
    elif n == 2 and m == 3:
        # Special case 2x3 for simpler expression
        c = cross_expr(A[:, 0], A[:, 1])
        i = Index()
        return sqrt(c[i] * c[i])
    else:
        # Generic formulation based on A.T*A
        return generic_pseudo_determinant_expr(A)
Пример #5
0
    def _reduce_facet_edge_length(self, o, reduction_op):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if domain.ufl_cell().topological_dimension() < 3:
            error(
                "Facet edge lengths only make sense for topological dimension >= 3."
            )

        elif not domain.ufl_coordinate_element().degree() == 1:
            # Don't lower bendy cells, instead leave it to form compiler
            warning(
                "Only know how to compute facet edge lengths of P1 or Q1 cell."
            )
            return o

        else:
            # P1 tetrahedron or Q1 hexahedron
            edges = FacetEdgeVectors(domain)
            num_edges = edges.ufl_shape[0]
            j = Index()
            elen2 = [edges[e, j] * edges[e, j] for e in range(num_edges)]
            return sqrt(reduce(reduction_op, elen2))
Пример #6
0
    def max_facet_edge_length(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        if not domain.is_piecewise_linear_simplex_domain():
            # Don't lower for non-affine cells, instead leave it to
            # form compiler
            warning(
                "Only know how to compute the max_facet_edge_length of an affine cell."
            )
            return o

        cellname = domain.ufl_cell().cellname()

        if cellname == "triangle":
            return self.facet_area(FacetArea(domain))
        elif cellname == "tetrahedron":
            J = self.jacobian(Jacobian(domain))
            trev = FacetEdgeVectors(domain)
            num_edges = 3
            i, j, k = indices(3)
            elen = [
                sqrt((J[i, j] * trev[edge, j]) * (J[i, k] * trev[edge, k]))
                for edge in range(num_edges)
            ]
            return max_value(elen[0], max_value(elen[1], elen[2]))
        else:
            error("Unhandled cell type %s." % cellname)
Пример #7
0
    def cell_normal(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        gdim = domain.geometric_dimension()
        tdim = domain.topological_dimension()

        if tdim == gdim - 1:  # n-manifold embedded in n-1 space
            i = Index()
            J = self.jacobian(Jacobian(domain))

            if tdim == 2:
                # Surface in 3D
                t0 = as_vector(J[i, 0], i)
                t1 = as_vector(J[i, 1], i)
                cell_normal = cross_expr(t0, t1)
            elif tdim == 1:
                # Line in 2D (cell normal is 'up' for a line pointing
                # to the 'right')
                cell_normal = as_vector((-J[1, 0], J[0, 0]))
            else:
                error("Cell normal not implemented for tdim %d, gdim %d" %
                      (tdim, gdim))

            # Return normalized vector, sign corrected by cell
            # orientation
            co = CellOrientation(domain)
            return co * cell_normal / sqrt(cell_normal[i] * cell_normal[i])
        else:
            error("What do you want cell normal in gdim={0}, tdim={1} to be?".
                  format(gdim, tdim))
Пример #8
0
    def cell_normal(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        gdim = domain.geometric_dimension()
        tdim = domain.topological_dimension()

        if tdim == gdim - 1:  # n-manifold embedded in n-1 space
            i = Index()
            J = self.jacobian(Jacobian(domain))

            if tdim == 2:
                # Surface in 3D
                t0 = as_vector(J[i, 0], i)
                t1 = as_vector(J[i, 1], i)
                cell_normal = cross_expr(t0, t1)
            elif tdim == 1:
                # Line in 2D (cell normal is 'up' for a line pointing
                # to the 'right')
                cell_normal = as_vector((-J[1, 0], J[0, 0]))
            else:
                error("Cell normal not implemented for tdim %d, gdim %d" % (tdim, gdim))

            # Return normalized vector, sign corrected by cell
            # orientation
            co = CellOrientation(domain)
            return co * cell_normal / sqrt(cell_normal[i]*cell_normal[i])
        else:
            error("What do you want cell normal in gdim={0}, tdim={1} to be?".format(gdim, tdim))
Пример #9
0
    def facet_normal(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        tdim = domain.topological_dimension()

        if tdim == 1:
            # Special-case 1D (possibly immersed), for which we say
            # that n is just in the direction of J.
            J = self.jacobian(Jacobian(domain))  # dx/dX
            ndir = J[:, 0]

            gdim = domain.geometric_dimension()
            if gdim == 1:
                nlen = abs(ndir[0])
            else:
                i = Index()
                nlen = sqrt(ndir[i] * ndir[i])

            rn = ReferenceNormal(domain)  # +/- 1.0 here
            n = rn[0] * ndir / nlen
            r = n
        else:
            # Recall that the covariant Piola transform u -> J^(-T)*u
            # preserves tangential components. The normal vector is
            # characterised by having zero tangential component in
            # reference and physical space.
            Jinv = self.jacobian_inverse(JacobianInverse(domain))
            i, j = indices(2)

            rn = ReferenceNormal(domain)
            # compute signed, unnormalised normal; note transpose
            ndir = as_vector(Jinv[j, i] * rn[j], i)

            # normalise
            i = Index()
            n = ndir / sqrt(ndir[i] * ndir[i])
            r = n

        if r.ufl_shape != o.ufl_shape:
            error("Inconsistent dimensions (in=%d, out=%d)." %
                  (o.ufl_shape[0], r.ufl_shape[0]))
        return r
Пример #10
0
    def facet_normal(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()
        tdim = domain.topological_dimension()

        if tdim == 1:
            # Special-case 1D (possibly immersed), for which we say
            # that n is just in the direction of J.
            J = self.jacobian(Jacobian(domain))  # dx/dX
            ndir = J[:, 0]

            gdim = domain.geometric_dimension()
            if gdim == 1:
                nlen = abs(ndir[0])
            else:
                i = Index()
                nlen = sqrt(ndir[i]*ndir[i])

            rn = ReferenceNormal(domain)  # +/- 1.0 here
            n = rn[0] * ndir / nlen
            r = n
        else:
            # Recall that the covariant Piola transform u -> J^(-T)*u
            # preserves tangential components. The normal vector is
            # characterised by having zero tangential component in
            # reference and physical space.
            Jinv = self.jacobian_inverse(JacobianInverse(domain))
            i, j = indices(2)

            rn = ReferenceNormal(domain)
            # compute signed, unnormalised normal; note transpose
            ndir = as_vector(Jinv[j, i] * rn[j], i)

            # normalise
            i = Index()
            n = ndir / sqrt(ndir[i]*ndir[i])
            r = n

        if r.ufl_shape != o.ufl_shape:
            error("Inconsistent dimensions (in=%d, out=%d)." % (o.ufl_shape[0], r.ufl_shape[0]))
        return r
Пример #11
0
    def circumradius(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.is_piecewise_linear_simplex_domain():
            error("Circumradius only makes sense for affine simplex cells")

        cellname = domain.ufl_cell().cellname()
        cellvolume = self.cell_volume(CellVolume(domain))

        if cellname == "interval":
            # Optimization for square interval; no square root needed
            return 0.5 * cellvolume

        # Compute lengths of cell edges
        edges = CellEdgeVectors(domain)
        num_edges = edges.ufl_shape[0]
        j = Index()
        elen = [sqrt(edges[e, j] * edges[e, j]) for e in range(num_edges)]

        if cellname == "triangle":
            return (elen[0] * elen[1] * elen[2]) / (4.0 * cellvolume)

        elif cellname == "tetrahedron":
            # la, lb, lc = lengths of the sides of an intermediate triangle
            # NOTE: Is here some hidden numbering assumption?
            la = elen[3] * elen[2]
            lb = elen[4] * elen[1]
            lc = elen[5] * elen[0]
            # p = perimeter
            p = (la + lb + lc)
            # s = semiperimeter
            s = p / 2
            # area of intermediate triangle with Herons formula
            triangle_area = sqrt(s * (s - la) * (s - lb) * (s - lc))
            return triangle_area / (6.0 * cellvolume)
Пример #12
0
    def circumradius(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.is_piecewise_linear_simplex_domain():
            error("Circumradius only makes sense for affine simplex cells")

        cellname = domain.ufl_cell().cellname()
        cellvolume = self.cell_volume(CellVolume(domain))

        if cellname == "interval":
            # Optimization for square interval; no square root needed
            return 0.5 * cellvolume

        # Compute lengths of cell edges
        edges = CellEdgeVectors(domain)
        num_edges = edges.ufl_shape[0]
        j = Index()
        elen = [sqrt(edges[e, j]*edges[e, j]) for e in range(num_edges)]

        if cellname == "triangle":
            return (elen[0] * elen[1] * elen[2]) / (4.0 * cellvolume)

        elif cellname == "tetrahedron":
            # la, lb, lc = lengths of the sides of an intermediate triangle
            # NOTE: Is here some hidden numbering assumption?
            la = elen[3] * elen[2]
            lb = elen[4] * elen[1]
            lc = elen[5] * elen[0]
            # p = perimeter
            p = (la + lb + lc)
            # s = semiperimeter
            s = p / 2
            # area of intermediate triangle with Herons formula
            triangle_area = sqrt(s * (s - la) * (s - lb) * (s - lc))
            return triangle_area / (6.0 * cellvolume)
Пример #13
0
    def _reduce_facet_edge_length(self, o, reduction_op):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if domain.ufl_cell().topological_dimension() < 3:
            error("Facet edge lengths only make sense for topological dimension >= 3.")

        elif not domain.ufl_coordinate_element().degree() == 1:
            # Don't lower bendy cells, instead leave it to form compiler
            warning("Only know how to compute facet edge lengths of P1 or Q1 cell.")
            return o

        else:
            # P1 tetrahedron or Q1 hexahedron
            edges = FacetEdgeVectors(domain)
            num_edges = edges.ufl_shape[0]
            j = Index()
            elen2 = [edges[e, j]*edges[e, j] for e in range(num_edges)]
            return sqrt(reduce(reduction_op, elen2))
Пример #14
0
    def cell_diameter(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.ufl_coordinate_element().degree() in {1, (1, 1)}:
            # Don't lower bendy cells, instead leave it to form compiler
            warning("Only know how to compute cell diameter of P1 or Q1 cell.")
            return o

        elif domain.is_piecewise_linear_simplex_domain():
            # Simplices
            return self.max_cell_edge_length(MaxCellEdgeLength(domain))

        else:
            # Q1 cells, maximal distance between any two vertices
            verts = CellVertices(domain)
            verts = [verts[v, ...] for v in range(verts.ufl_shape[0])]
            j = Index()
            elen2 = (real((v0 - v1)[j] * conj((v0 - v1)[j])) for v0, v1 in combinations(verts, 2))
            return real(sqrt(reduce(max_value, elen2)))
Пример #15
0
    def cell_diameter(self, o):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.ufl_coordinate_element().degree() == 1:
            # Don't lower bendy cells, instead leave it to form compiler
            warning("Only know how to compute cell diameter of P1 or Q1 cell.")
            return o

        elif domain.is_piecewise_linear_simplex_domain():
            # Simplices
            return self.max_cell_edge_length(MaxCellEdgeLength(domain))

        else:
            # Q1 cells, maximal distance between any two vertices
            verts = CellVertices(domain)
            verts = [verts[v, ...] for v in range(verts.ufl_shape[0])]
            j = Index()
            elen2 = ((v0-v1)[j]*(v0-v1)[j] for v0, v1 in combinations(verts, 2))
            return sqrt(reduce(max_value, elen2))
Пример #16
0
    def _reduce_cell_edge_length(self, o, reduction_op):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.ufl_coordinate_element().degree() == 1:
            # Don't lower bendy cells, instead leave it to form compiler
            warning("Only know how to compute cell edge lengths of P1 or Q1 cell.")
            return o

        elif domain.ufl_cell().cellname() == "interval":
            # Interval optimization, square root not needed
            return self.cell_volume(CellVolume(domain))

        else:
            # Other P1 or Q1 cells
            edges = CellEdgeVectors(domain)
            num_edges = edges.ufl_shape[0]
            j = Index()
            elen2 = [edges[e, j]*edges[e, j] for e in range(num_edges)]
            return sqrt(reduce(reduction_op, elen2))
Пример #17
0
    def _reduce_cell_edge_length(self, o, reduction_op):
        if self._preserve_types[o._ufl_typecode_]:
            return o

        domain = o.ufl_domain()

        if not domain.ufl_coordinate_element().degree() == 1:
            # Don't lower bendy cells, instead leave it to form compiler
            warning("Only know how to compute cell edge lengths of P1 or Q1 cell.")
            return o

        elif domain.ufl_cell().cellname() == "interval":
            # Interval optimization, square root not needed
            return self.cell_volume(CellVolume(domain))

        else:
            # Other P1 or Q1 cells
            edges = CellEdgeVectors(domain)
            num_edges = edges.ufl_shape[0]
            j = Index()
            elen2 = [real(edges[e, j] * conj(edges[e, j])) for e in range(num_edges)]
            return real(sqrt(reduce(reduction_op, elen2)))
Пример #18
0
 def acos(self, f):
     r".. math:: \\frac{d}{dx} f(x) = \frac{d}{dx} \arccos(x) = \frac{-1}{\sqrt{1 - x^2}}"
     x, = f.operands()
     return (-1.0/sqrt(1.0 - x**2),)
Пример #19
0
 def erf(self, o, a):
     f, fp = a
     o = self.reuse_if_possible(o, f)
     op = fp*(2.0/sqrt(pi)*exp(-f**2))
     return (o, op)
Пример #20
0
 def asin(self, o, a):
     f, fp = a
     o = self.reuse_if_possible(o, f)
     op = fp/sqrt(1.0 - f**2)
     return (o, op)
Пример #21
0
 def erf(self, o, fp):
     f, = o.ufl_operands
     return fp * (2.0 / sqrt(pi) * exp(-f**2))
Пример #22
0
 def acos(self, o, fp):
     f, = o.ufl_operands
     return -fp / sqrt(1.0 - f**2)
Пример #23
0
 def asin(self, o, a):
     f, fp = a
     o = self.reuse_if_possible(o, f)
     op = fp / sqrt(1.0 - f**2)
     return (o, op)
Пример #24
0
 def asin(self, o, fp):
     f, = o.ufl_operands
     return fp / sqrt(1.0 - f**2)
Пример #25
0
 def erf(self, f):
     "d/dx erf x = 2/sqrt(pi)*exp(-x^2)"
     x, = f.operands()
     return (2.0/sqrt(pi)*exp(-x**2),)
Пример #26
0
 def erf(self, o, a):
     f, fp = a
     o = self.reuse_if_possible(o, f)
     op = fp * (2.0 / sqrt(pi) * exp(-f**2))
     return (o, op)
Пример #27
0
def generic_pseudo_determinant_expr(A):
    """Compute the pseudo-determinant of A: sqrt(det(A.T*A))."""
    i, j, k = indices(3)
    ATA = as_tensor(A[k, i] * A[k, j], (i, j))
    return sqrt(determinant_expr(ATA))
Пример #28
0
 def asin(self, o, fp):
     f, = o.ufl_operands
     return fp / sqrt(1.0 - f**2)
Пример #29
0
 def asin(self, f):
     "d/dx asin x = 1/sqrt(1 - x^2)"
     x, = f.operands()
     return (1.0/sqrt(1.0 - x**2),)
Пример #30
0
 def acos(self, o, fp):
     f, = o.ufl_operands
     return -fp / sqrt(1.0 - f**2)
Пример #31
0
def generic_pseudo_determinant_expr(A):
    """Compute the pseudo-determinant of A: sqrt(det(A.T*A))."""
    i, j, k = indices(3)
    ATA = as_tensor(A[k, i] * A[k, j], (i, j))
    return sqrt(determinant_expr(ATA))
Пример #32
0
 def erf(self, o, fp):
     f, = o.ufl_operands
     return fp * (2.0 / sqrt(pi) * exp(-f**2))
Пример #33
0
def compute_stress(mesh: Mesh, displacement: Function) -> Function:
    V = FunctionSpace(mesh, 'P', 1)
    s = sigma(displacement) - tr(sigma(displacement)) * Identity(3) / 3
    return project(sqrt(1.5 * inner(s, s)), V)