def solve_state(): a = a1 + a2 + a3 + a4 + a5 a = replace(a, {lmb: TestFunction(V), T: TrialFunction(V)}) l = Constant(0) * TestFunction(V) * dX a = assemble_multimesh(a) L = assemble_multimesh(l) bcs = [ MultiMeshDirichletBC(V, Constant(0), mfs[0], 1, 0), MultiMeshDirichletBC(V, Constant(1), mfs[1], 2, 1) ] [bc.apply(a, L) for bc in bcs] V.lock_inactive_dofs(a, L) solve(a, T.vector(), L)
def project_to_background(s_top): # Projects a function living on the boundary intersecting with the # bottom mesh to the bottom mesh S = s_top.function_space() u, v = TrialFunction(S), TestFunction(S) a = inner(u("+"), v("+")) * dI A = assemble_multimesh(a) A.ident_zeros() l = inner(s_top("-"), v("+")) * dI L = assemble_multimesh(l) S.lock_inactive_dofs(A, L) s_back = MultiMeshFunction(S) solve(A, s_back.vector(), L) return s_back
def solve_adjoint(): a = a1 + a2 + a3 + a4 + a5 a = derivative(a, T, TestFunction(V)) a = replace(a, {lmb: TrialFunction(V)}) l = derivative(-J1, T, TestFunction(V)) a = assemble_multimesh(a) L = assemble_multimesh(l) bcs = [ MultiMeshDirichletBC(V, Constant(0), mfs[0], 1, 0), MultiMeshDirichletBC(V, Constant(0), mfs[1], 2, 1) ] [bc.apply(a, L) for bc in bcs] V.lock_inactive_dofs(a, L) solve(a, lmb.vector(), L)
def eval_J(self): self.geometric_quantities() J_s = assemble_multimesh(inner(grad(self.u), grad(self.u)) * dX) J_v = self.vfac * self.Voloff**2 J_bx = self.bfac * self.bxoff**2 J_by = self.bfac * self.byoff**2 self.J = float(J_s + J_v + J_bx + J_by)
def __init_geometric_quantities(self): """ Helper initializer to compute original volume and barycenter of the obstacle. """ x = SpatialCoordinate(self.multimesh) V = MultiMeshFunctionSpace(self.multimesh, "CG", 1) x = interpolate(Expression("x[0]", degree=1), V) y = interpolate(Expression("x[1]", degree=1), V) fluid_vol = assemble_multimesh( Constant(1) * dx(domain=self.multimesh) + Constant(1) * dC(domain=self.multimesh)) self.Vol0 = Constant(self.length_width[0] * self.length_width[1] - fluid_vol) self.bx0 = Constant( (0.5 * self.length_width[0] - assemble_multimesh(x * dX)) / self.Vol0) self.by0 = Constant( (0.5 * self.length_width[1] - assemble_multimesh(y * dX)) / self.Vol0)
def solve(self): """ Solves the stokes equation with the current multimesh """ (u, p) = TrialFunctions(self.VQ) (v, q) = TestFunctions(self.VQ) n = FacetNormal(self.multimesh) h = 2.0 * Circumradius(self.multimesh) alpha = Constant(6.0) tensor_jump = lambda u: outer(u("+"), n("+")) + outer(u("-"), n("-")) a_s = inner(grad(u), grad(v)) * dX a_IP = - inner(avg(grad(u)), tensor_jump(v))*dI\ - inner(avg(grad(v)), tensor_jump(u))*dI\ + alpha/avg(h) * inner(jump(u), jump(v))*dI a_O = inner(jump(grad(u)), jump(grad(v))) * dO b_s = -div(u) * q * dX - div(v) * p * dX b_IP = jump(u, n) * avg(q) * dI + jump(v, n) * avg(p) * dI l_s = inner(self.f, v) * dX s_C = h*h*inner(-div(grad(u)) + grad(p), -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(-div(grad(u("+"))) + grad(p("+")), -div(grad(v("+"))) + grad(q("+")))*dO l_C = h*h*inner(self.f, -div(grad(v)) - grad(q))*dC\ + h("+")*h("+")*inner(self.f("+"), -div(grad(v("+"))) - grad(q("+")))*dO a = a_s + a_IP + a_O + b_s + b_IP + s_C l = l_s + l_C A = assemble_multimesh(a) L = assemble_multimesh(l) [bc.apply(A, L) for bc in self.bcs] self.VQ.lock_inactive_dofs(A, L) solve(A, self.w.vector(), L, "mumps") self.splitMMF()
def geometric_quantities(self): """ Compute volume and barycenter of obstacle, as long as its offset from original values with current multimesh """ x = SpatialCoordinate(self.multimesh) V = MultiMeshFunctionSpace(self.multimesh, "CG", 1) x = interpolate(Expression("x[0]", degree=1), V) y = interpolate(Expression("x[1]", degree=1), V) fluid_vol = assemble_multimesh( Constant(1) * dx(domain=self.multimesh) + Constant(1) * dC(domain=self.multimesh)) self.Vol = Constant(self.length_width[0] * self.length_width[1] - fluid_vol) self.bx = Constant( (0.5 * self.length_width[0] - assemble_multimesh(x * dX)) / self.Vol) self.by = Constant( (0.5 * self.length_width[1] - assemble_multimesh(y * dX)) / self.Vol) self.Voloff = self.Vol - self.Vol0 self.bxoff = self.bx - self.bx0 self.byoff = self.by - self.by0
def __init__(self, V, inner_product="L2", map_operator=None, inverse="default"): self.V = V if inner_product is not "custom": u = dolfin.TrialFunction(V) v = dolfin.TestFunction(V) if isinstance(V, dolfin.cpp.function.MultiMeshFunctionSpace): default_forms = { "L2": dolfin.inner(u, v) * dolfin.dX, "H0_1": dolfin.inner(dolfin.grad(u), dolfin.grad(v)) * dolfin.dX, "H1": (dolfin.inner(u, v) + dolfin.inner(dolfin.grad(u), dolfin.grad(v))) * dolfin.dX, } else: default_forms = { "L2": dolfin.inner(u, v) * dolfin.dx, "H0_1": dolfin.inner(dolfin.grad(u), dolfin.grad(v)) * dolfin.dx, "H1": (dolfin.inner(u, v) + dolfin.inner(dolfin.grad(u), dolfin.grad(v))) * dolfin.dx, } form = default_forms[inner_product] if hasattr(form.arguments()[0], "_V_multi"): map_operator = dolfin.assemble_multimesh(form) else: map_operator = dolfin.assemble(form) self.map_operator = map_operator if inverse in ("default", "lu"): self.map_solver = dolfin.LUSolver(self.map_operator) elif inverse == "jacobi": self.map_solver = dolfin.PETScKrylovSolver() self.map_solver.set_operator(self.map_operator) self.map_solver.ksp().setType("preonly") self.map_solver.ksp().getPC().setType("jacobi") elif inverse == "sor": self.map_solver = dolfin.PETScKrylovSolver() self.map_solver.set_operator(self.map_operator) self.map_solver.ksp().setType("preonly") self.map_solver.ksp().getPC().setType("sor") elif inverse == "amg": self.map_solver = dolfin.PETScKrylovSolver() self.map_solver.set_operator(self.map_operator) self.map_solver.ksp().setType("preonly") self.map_solver.ksp().getPC().setType("hypre") elif isinstance(inverse, dolfin.GenericMatrix): self.map_solver = dolfin.PETScKrylovSolver() self.map_solver.set_operators(self.map_operator, inverse) self.map_solver.ksp().setType("preonly") self.map_solver.ksp().getPC().setType("mat") else: self.map_solver = inverse self.solver_type = inverse
# Classic shape derivative term da4 = tan_div(s_top("-"), n("-")) * alpha * inner(jump(T), jump(lmb)) * dI # Material derivative of background T da4 += alpha * inner(dot(s_top("-"), grad(T("+"))), jump(lmb)) * dI # Material derivative of background lmb da4 += alpha * inner(jump(T), dot(s_top("-"), grad(lmb("+")))) * dI #----------------------------------------------------------------------------- J1 = inner(T, T) * dX dJ1_top = div(s_top) * inner(T, T) * dX # Classic shape derivative term bottom mesh dJ1_bottom = div(s_bottom) * inner(T, T) * dX # Material derivative of background T dJ1_bottom += 2 * inner(dot(s_bottom, grad(T)), T) * dX J = a1 + J1 + a2 + a3 + a4 dJds = assemble_multimesh(da1_top + da1_bottom + dJ1_top + dJ1_bottom + da2 + da3 + da4) # Do a taylor test for deformation of the top mesh Js = [assemble_multimesh(J)] epsilons = [0.1 * 0.5**i for i in range(5)] errors = {"0": [], "1": []} for eps in epsilons: s_eps = deformation_vector() s_eps.vector()[:] *= eps for i in range(2): plot(multimesh.part(i)) ALE.move(multimesh.part(i), s_eps.part(i)) plot(multimesh.part(i), color="r") show() multimesh.build() multimesh.auto_cover(0, Point(1.25, 0.875))