예제 #1
0
def deformation_vector():
    from femorph import VolumeNormal
    n1 = VolumeNormal(multimesh.part(1))
    bc = DirichletBC(VectorFunctionSpace(multimesh.part(1), "CG", 1),
                     Constant((0, 0)), mfs[1], 2)
    bc.apply(n1.vector())
    S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1)
    s = MultiMeshFunction(S)
    s.assign_part(1, n1)
    return s
예제 #2
0
def deformation_vector():
    from femorph import VolumeNormal
    n0 = VolumeNormal(multimesh.part(0))
    S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1)
    s = MultiMeshFunction(S)
    s.assign_part(0, n0)
    return s
예제 #3
0
    def recompute_dJ(self):
        """
        Create gradient expression for deformation algorithm
        """
        # FIXME: probably only works with one obstacle
        # Recalculate barycenter and volume of obstacle
        self.geometric_quantities()
        self.integrand_list = []
        dJ = 0
        solver.dJ_form = []
        for i in range(1, self.N):
            # Integrand of gradient
            x = SpatialCoordinate(self.multimesh.part(i))
            u_i = self.u.part(i)
            dJ_stokes = -inner(grad(u_i), grad(u_i))
            dJ_vol = -Constant(2 * self.vfac) * (self.Vol - self.Vol0)
            dJ_bar = Constant(2 * self.bfac) / self.Vol * (
                (self.bx - x[0]) * self.bxoff + (self.by - x[1]) * self.byoff)
            integrand = dJ_stokes + dJ_vol + dJ_bar
            dDeform = Measure("ds", subdomain_data=self.mfs[i])
            from femorph import VolumeNormal
            n = VolumeNormal(self.multimesh.part(i))
            s = TestFunction(self.S[i])

            self.integrand_list.append(n * integrand)

            dJ = inner(s, n) * integrand * dDeform(self.move_dict[i]["Deform"])
            self.dJ_form.append(dJ)
def deformation_vector(multimesh):
    from femorph import VolumeNormal
    n2 = VolumeNormal(multimesh.part(0))
    S_sm = VectorFunctionSpace(multimesh.part(0), "CG", 1)
    bc = DirichletBC(S_sm, n2, mfs[0], 2)
    bc2 = DirichletBC(S_sm, Constant((0, 0)), mfs[0], 1)
    us, vs = TrialFunction(S_sm), TestFunction(S_sm)
    a_ = inner(grad(us), grad(vs)) * dx + inner(us, vs) * dx
    deformation = Function(S_sm)
    solve(lhs(a_) == rhs(a_), deformation, bcs=[bc, bc2])
    return deformation
def deformation_vector(multimesh):
    from femorph import VolumeNormal
    n0 = VolumeNormal(multimesh.part(0))
    n1 = VolumeNormal(multimesh.part(1))
    S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1)
    mfs = []
    for i in range(2):
        mvc = MeshValueCollection("size_t", multimesh.part(i), 1)
        with XDMFFile("meshes/mf_%d.xdmf" % i) as infile:
            infile.read(mvc, "name_to_read")
        mfs.append(cpp.mesh.MeshFunctionSizet(multimesh.part(i), mvc))
    mf_0 = mfs[0]
    mf_1 = mfs[1]

    bcs = [
        MultiMeshDirichletBC(S, n1, mf_1, 2, 1),
        MultiMeshDirichletBC(S, Constant((0, 0)), mf_0, 1, 0)
    ]  #n1
    n = FacetNormal(multimesh)
    h = 2.0 * Circumradius(multimesh)
    h = (h('+') + h('-')) / 2
    us, vs = TrialFunction(S), TestFunction(S)
    a_s = inner(grad(us), grad(vs)) * dX
    a_IP = (-inner(dot(avg(grad(us)), n("+")), jump(vs)) -
            inner(dot(avg(grad(vs)), n("+")), jump(us)) +
            alpha / h * inner(jump(us), jump(vs))) * dI
    a_O = inner(jump(grad(us)), jump(grad(vs))) * dO
    a = a_s + a_IP + a_O
    L = inner(Constant((0, 0)), vs) * dX
    A = assemble_multimesh(a)
    b = assemble_multimesh(L)
    [bc.apply(A, b) for bc in bcs]
    S.lock_inactive_dofs(A, b)
    perturbation = MultiMeshFunction(S)
    solve(A, perturbation.vector(), b, 'lu')
    plot(perturbation.part(0))
    plot(perturbation.part(1))
    return perturbation
예제 #6
0
def eval_dJ(cable_positions):
    # Update mesh
    eval_J(cable_positions)
    dJ = []
    # Solve adjoint equation
    adj = TrialFunction(V)
    v = TestFunction(V)
    constraint = inner(lmb * grad(adj), grad(v)) * dX - c * v * adj * dX
    # FIXME: Add derivative of alpha in ext bc constraint,only works for alpha=1
    constraint += adj * 1 * v * ds  # alpha_heat_transfer(T)*v*ds
    constraint += - inner(avg(lmb*grad(adj)), jump(v, n))*dI \
                  - inner(avg(lmb*grad(v)), jump(adj, n))*dI \
                  + alpha/h*jump(adj)*jump(v)*dI   \
                  + beta*lmb*inner(jump(grad(adj)), jump(grad(v)))*dO
    constraint += objdT * v * dX
    A, b = assemble_multimesh(lhs(constraint)), assemble_multimesh(
        rhs(constraint))
    V.lock_inactive_dofs(A, b)
    solve(A, adjT.vector(), b, 'lu')

    for i, (cable_mesh, cable_facet, cable_subdomain) in enumerate(
            zip(cable_meshes, cable_facets, cable_subdomains)):
        T_cable = T.part(i + 1, deepcopy=True)
        adjT_cable = adjT.part(i + 1, deepcopy=True)
        lmb_cable = lmb.part(i + 1, deepcopy=True)
        f_cable = f.part(i + 1, deepcopy=True)

        from femorph import VolumeNormal
        normal = VolumeNormal(cable_mesh, [0], cable_facet, [16, 17])
        dJ_Surf = WeakCableShapeGradSurf(T_cable,
                                         adjT_cable,
                                         lmb_cable,
                                         c,
                                         f_cable,
                                         n=normal)
        dSc1 = Measure("dS", subdomain_data=cable_facet, subdomain_id=16)
        dSc2 = Measure("dS", subdomain_data=cable_facet, subdomain_id=17)
        gradx = assemble(normal[0] * dJ_Surf * dSc1 +
                         normal[0] * dJ_Surf * dSc2 + Constant(0) *
                         dx(domain=cable_mesh, subdomain_data=cable_subdomain))
        grady = assemble(normal[1] * dJ_Surf * dSc1 +
                         normal[1] * dJ_Surf * dSc2 + Constant(0) *
                         dx(domain=cable_mesh, subdomain_data=cable_subdomain))

        dJ.append(gradx)
        dJ.append(grady)
    return numpy.array(dJ)
def deformation_vector(mesh, S_sm):
    from femorph import VolumeNormal
    n2 = VolumeNormal(mesh)
    # S_sm = VectorFunctionSpace(mesh, "CG", 1)
    mvc = MeshValueCollection("size_t", mesh, 1)
    with XDMFFile("meshes/mf.xdmf") as infile:
        infile.read(mvc, "name_to_read")
    mf = cpp.mesh.MeshFunctionSizet(mesh, mvc)

    bc = DirichletBC(S_sm, n2, mf, 2)
    bc2 = DirichletBC(S_sm, Constant((0, 0)), mf, 1)

    us, vs = TrialFunction(S_sm), TestFunction(S_sm)
    a_ = inner(grad(us), grad(vs)) * dx + inner(us, vs) * dx
    deformation = Function(S_sm)
    solve(lhs(a_) == rhs(a_), deformation, bcs=[bc, bc2])
    return deformation
예제 #8
0
def deformation_vector():
    from femorph import VolumeNormal
    n1 = VolumeNormal(multimesh.part(1))
    S_sm = VectorFunctionSpace(multimesh.part(1), "CG", 1)
    bcs = [
        DirichletBC(S_sm, Constant((0, 0)), mfs[1], 2),
        DirichletBC(S_sm, n1, mfs[1], 1)
    ]

    u, v = TrialFunction(S_sm), TestFunction(S_sm)
    a = inner(grad(u), grad(v)) * dx
    l = inner(Constant((0., 0.)), v) * dx
    n = Function(S_sm)
    solve(a == l, n, bcs=bcs)
    S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1)
    s = MultiMeshFunction(S)
    s.assign_part(1, n)
    return s
def deformation_vector():
    n1 = (1 + x1[0] * sin(2 * pi * x1[1])) * VolumeNormal(multimesh.part(1))
    S_sm = VectorFunctionSpace(multimesh.part(1), "CG", 1)
    # Note removing 0 dirichlet at dI introduces problems with the change in
    # the cut cell and overlap cell part. We do not have any way of describing
    # this movement
    bcs = [
        DirichletBC(S_sm, n1, mfs[1], 2),
        DirichletBC(S_sm, Constant((0, 0)), mfs[1], 1)
    ]

    u, v = TrialFunction(S_sm), TestFunction(S_sm)
    a = inner(grad(u), grad(v)) * dx
    l = inner(Constant((0., 0.)), v) * dx
    n = Function(S_sm)
    solve(a == l, n, bcs=bcs)
    S = MultiMeshVectorFunctionSpace(multimesh, "CG", 1)
    s = MultiMeshFunction(S)
    s.assign_part(1, n)
    return s
예제 #10
0
    def recompute_dJ(self):
        """
        Create gradient expression for deformation algorithm
        """

        # Recalculate barycenter and volume of obstacle
        self.compute_volume_bary()

        # Integrand of gradient
        x = SpatialCoordinate(mesh)
        dJ_stokes = -inner(grad(self.u), grad(self.u))
        dJ_vol = - Constant(2*self.vfac)*(self.Vol-self.Vol0)
        dJ_bar = Constant(2*self.bfac)/self.Vol*((self.bx-x[0])*self.bx_off
                                                 + (self.by-x[1])*self.by_off)
        self.integrand = dJ_stokes + dJ_vol + dJ_bar
        dDeform = Measure("ds", subdomain_data=self.mf)
        from femorph import VolumeNormal
        n = VolumeNormal(mesh)
        s = TestFunction(self.S)
        dJ = 0
        # Sum up over all moving boundaries
        for marker in self.move_dict["Deform"]:
            dJ += inner(s,n)*self.integrand*dDeform(marker)
        self.dJ_form = dJ
예제 #11
0
    def update_mesh_from_boundary_nodes(self, perturbation):
        """
        Deform mesh with boundary perturbation (a numpy array)
        given as Neumann input in an linear elastic mesh deformation.
        """
        # Reset mesh
        self.mesh.coordinates()[:] = self.backup
        volume_function = Function(self.S)

        for i in self.design_map.keys():
            volume_function.vector()[self.design_map[i]] = perturbation[i]
        u, v = TrialFunction(self.S), TestFunction(self.S)

        def compute_mu(constant=True):
            """
            Compute mu as according to arxiv paper
            https://arxiv.org/pdf/1509.08601.pdf
            """
            mu_min=Constant(1)
            mu_max=Constant(500)
            if constant:
                return mu_max
            else:
                V = FunctionSpace(self.mesh, "CG",1)
                u, v = TrialFunction(V), TestFunction(V)
                a = inner(grad(u),grad(v))*dx
                l = Constant(0)*v*dx
                bcs = []
                for marker in self.move_dict["Fixed"]:
                    bcs.append(DirichletBC(V, mu_min, self.mf, marker))
                for marker in self.move_dict["Deform"]:
                    bcs.append(DirichletBC(V, mu_max, self.mf, marker))
                mu = Function(V)
                solve(a==l, mu, bcs=bcs)
                return mu
        mu = compute_mu(False)
        
        def epsilon(u):
            return sym(grad(u))
        def sigma(u,mu=500, lmb=0):
            return 2*mu*epsilon(u) + lmb*tr(epsilon(u))*Identity(2)
        a = inner(sigma(u,mu=mu), grad(v))*dx
        L = inner(Constant((0,0)), v)*dx

        
        bcs = []
        for marker in self.move_dict["Fixed"]:
            bcs.append(DirichletBC(self.S,
                                   Constant([0]*mesh.geometric_dimension()),
                                   self.mf, marker))
            
        dStress = Measure("ds", subdomain_data=self.mf)
        from femorph import VolumeNormal
        n = VolumeNormal(mesh)

        # Enforcing node movement through elastic stress computation
        # NOTE: This strategy does only work for the first part of the deformation
        for marker in self.move_dict["Deform"]:
            L += inner(volume_function, v)*dStress(marker)
        # Direct control of boundary nodes
        # for marker in self.move_dict["Deform"]:
        #     bcs.append(DirichletBC(self.S, volume_function, self.mf, marker))
        s = Function(self.S)
        solve(a==L, s, bcs=bcs)
        self.perturbation = s
        ALE.move(self.mesh, self.perturbation)