def setup_mms(): '''Simple MMS problem for UnitSquareMesh''' mesh = UnitSquareMesh(2, 2) # The following labeling of edges will be enforced # 4 # 1 2 # 3 subdomains = {1: CompiledSubDomain('near(x[0], 0)'), 2: CompiledSubDomain('near(x[0], 1)'), 3: CompiledSubDomain('near(x[1], 0)'), 4: CompiledSubDomain('near(x[1], 1)')} x, y = SpatialCoordinate(mesh) u = as_vector((sin(pi*(x+y)), cos(pi*(x-y)))) # LM is defined as -div(u), in addition when specifying bcs Hdiv uses # sigma, so no need for normal p = -div(u) f = -grad(div(u)) + u g_u = [u]*4 to_expr = lambda f: ulfy.Expression(f, degree=4) w = tuple(to_expr(x) for x in (u, p)) return {'solution': w, 'force': to_expr(f), 'u': dict(enumerate(map(to_expr, g_u), 1)), 'subdomains': subdomains}
def mms_solid(parameters): '''Method of manufactured solutions on [0, 1]^2''' mesh = UnitSquareMesh(MPI.comm_self, 2, 2) V = VectorFunctionSpace(mesh, 'CG', 2) # Displacement, Flux Q = FunctionSpace(mesh, 'CG', 2) # Pressure # Coefficient space S = FunctionSpace(mesh, 'DG', 0) kappa, mu, lmbda, alpha, s0 = [Function(S) for _ in range(5)] eta = Function(V) # Displacement p = Function(Q) # Pressure u = -kappa*grad(p) # Define flux pT = -lmbda*div(eta) + alpha*p # Total pressure sigma_p = lambda eta, p: 2*mu*sym(grad(eta)) + lmbda*div(eta)*Identity(len(eta)) - alpha*p*Identity(len(eta)) f1 = -div(sigma_p(eta, p)) # NOTE: we do not have temporal derivative but if we assume eta and p # have foo(x, y)*bar(t) then in mass conservation we will have # [s0*p + alpha*div(eta)]*dbar(t) # What we want to substitute x, y, kappa_, mu_, lmbda_, alpha_, s0_ = sp.symbols('x y kappa mu lmbda alpha s0') time_ = sp.Symbol('time') # Expressions eta_ = sp.Matrix([sp.sin(pi*(x + y)), sp.cos(pi*(x + y))])*sp.exp(1-time_) p_ = sp.cos(pi*(x-y))*sp.exp(1-time_) # - here is dbar(t) f2 = -(s0*p + alpha*div(eta)) + div(u) subs = {eta: eta_, p: p_, kappa: kappa_, mu: mu_, lmbda: lmbda_, alpha: alpha_, s0: s0_} as_expr = lambda t: ulfy.Expression(t, subs=subs, degree=4, kappa=parameters['kappa'], mu=parameters['mu'], lmbda=parameters['lmbda'], alpha=parameters['alpha'], s0=parameters['s0'], time=0.0) # Solution eta_exact, u_exact, p_exact, pT_exact = map(as_expr, (eta, u, p, pT)) # Forcing f1, f2 = as_expr(f1), as_expr(f2) # 4 # 1 2 # 3 so that normals = [Constant((-1, 0)), Constant((1, 0)), Constant((0, -1)), Constant((0, 1))] tractions = [as_expr(dot(sigma_p(eta, p), n)) for n in normals] return {'solution': (eta_exact, u_exact, p_exact, pT_exact), 'force': (f1, f2), 'tractions': tractions}
def setup_mms(parameter_values): '''Manufacture solution for the immersed test case''' mesh = UnitSquareMesh(2, 2, 'crossed') x, y = SpatialCoordinate(mesh) kappa0, kappa1 = Constant(1), Constant(1) u0 = sin(pi*(x-2*y)) u1 = cos(2*pi*(3*x-y)) sigma0 = kappa0*grad(u0) sigma1 = kappa1*grad(u1) f0 = -div(sigma0) f1 = -div(sigma1) # Interface is oriented based on outer normalsI = tuple(map(Constant, ((1, 0), (-1, 0), (0, 1), (0, -1)))) # Neumann and Robin interface data g_n = tuple(dot(sigma0, n) - dot(sigma1, n) for n in normalsI) g_r = tuple(u0 - u1 + dot(sigma0, n) for n in normalsI) # True multiplier value lms = [-dot(sigma0, n) for n in normalsI] # Don't want to trigger compiler on parameter change kappa0_, kappa1_ = sp.symbols('kappa0 kappa1') subs = {kappa0: kappa0_, kappa1: kappa1_} # Check coefs assert parameter_values['kappa0'] > 0 and parameter_values['kappa1'] > 0 to_expr = lambda f: ulfy.Expression(f, degree=4, subs=subs, kappa0=parameter_values['kappa0'], kappa1=parameter_values['kappa1']) # As tagged in utils.immersed_geometry lm_subdomains = { 1: CompiledSubDomain('near(x[0], 0.25) && ((0.25-DOLFIN_EPS < x[1]) && (x[1] < 0.75+DOLFIN_EPS))'), 2: CompiledSubDomain('near(x[0], 0.75) && ((0.25-DOLFIN_EPS < x[1]) && (x[1] < 0.75+DOLFIN_EPS))'), 3: CompiledSubDomain('near(x[1], 0.25) && ((0.25-DOLFIN_EPS < x[0]) && (x[0] < 0.75+DOLFIN_EPS))'), 4: CompiledSubDomain('near(x[1], 0.75) && ((0.25-DOLFIN_EPS < x[0]) && (x[0] < 0.75+DOLFIN_EPS))') } return { 'solution': {'u0': to_expr(u0), 'u1': to_expr(u1), 'lm': PiecewiseExpression(lm_subdomains, dict(enumerate(map(to_expr, lms), 1)))}, 'f0': to_expr(f0), 'f1': to_expr(f1), # Standard boundary data 'dirichlet_0': dict(enumerate(map(to_expr, [u0]*8), 1)), # Interface boundary conditions 'g_n': dict(enumerate(map(to_expr, g_n), 1)), 'g_r': dict(enumerate(map(to_expr, g_r), 1)), # Geometry setup 'get_geometry': immersed_geometry }
def setup_mms(Bop): '''Simple MMS problem for UnitSquareMesh''' mesh = UnitSquareMesh(2, 2) # The following labeling of edges will be enforced # 4 # 1 2 # 3 subdomains = { 1: CompiledSubDomain('near(x[0], 0)'), 2: CompiledSubDomain('near(x[0], 1)'), 3: CompiledSubDomain('near(x[1], 0)'), 4: CompiledSubDomain('near(x[1], 1)') } x, y = SpatialCoordinate(mesh) u = as_vector((sin(pi * (x - 2 * y)), cos(2 * pi * (x + y)))) sigma = sym(grad(u)) f = -div(sigma) + u # For LM We have -sigma.n as LM when Bu = u # -sigma.n.n when Bu = u.n # -sigma.n.t when Bu = u.t normals = (Constant((-1, 0)), Constant((1, 0)), Constant( (0, -1)), Constant((0, 1))) R = Constant(((0, 1), (-1, 0))) lm = [-dot(sigma, n) for n in normals] lm_n = [dot(l, n) for l, n in zip(lm, normals)] lm_t = [dot(l, dot(R, n)) for l, n in zip(lm, normals)] to_expr = lambda f: ulfy.Expression(f, degree=4) # Multiplier is traction if Bop == 'full': lm_ = dict(enumerate(map(to_expr, lm), 1)) # LM is traction components elif Bop == 'normal': lm_ = dict(enumerate(map(to_expr, lm_n), 1)) else: assert Bop == 'tangent' lm_ = dict(enumerate(map(to_expr, lm_t), 1)) up = (to_expr(u), PiecewiseExpression(subdomains, lm_)) return { 'solution': up, 'f': to_expr(f), 'dirichlet': dict(enumerate(map(to_expr, [u] * 4), 1)), # Will select proper component from traction 'neumann': {tag: to_expr(dot(sigma, n)) for tag, n in enumerate(normals, 1)}, 'subdomains': subdomains }
def setup_mms(eps=None): '''Simple MMS problem for UnitSquareMesh''' import sympy as sp import ulfy mesh = UnitSquareMesh(2, 2) V = VectorFunctionSpace(mesh, 'CG', 1) u = Function(V) # Define as function to allow ufly substition S = FunctionSpace(mesh, 'DG', 0) mu = Function(S) lmbda = Function(S) sigma = lambda u: 2 * mu * sym(grad(u)) + lmbda * div(u) * Identity(2) # The form f = -div(sigma(u)) p = lmbda * div(u) # Solid pressure # What we want to substitute x, y, mu_, lambda_ = sp.symbols('x y mu lmbda') # I chose u purposely such that sigma(u).n is zero on the boundary u_ = sp.Matrix([ 0.01 * sp.cos(sp.pi * x * (1 - x) * y * (1 - y)), -0.01 * sp.cos(2 * sp.pi * x * (1 - x) * y * (1 - y)) ]) x_ = sp.Matrix([0, 0]) subs = {u: u_, mu: mu_, lmbda: lambda_} # Function are replaced by symbols # As expressions up = (ulfy.Expression(u_, degree=5), ulfy.Expression(p, subs=subs, degree=4, mu=eps[0], lmbda=eps[1]), ulfy.Expression(x_, degree=1)) # Note lmbda_ being a constant is compiled into constant so errornorm # will complaing about the Expressions's degree being too low fg = (ulfy.Expression(f, subs=subs, degree=4, mu=eps[0], lmbda=eps[1]), ulfy.Expression(u_, degree=4, mu=eps[0], lmbda=eps[1])) # mu, lmbda are are given value return up, fg
def mms_ad(kappa_value): '''Method of manufactured solutions on [0, 1]^2''' mesh = UnitSquareMesh(2, 2) # Dummy V = FunctionSpace(mesh, 'CG', 2) # Coefficient space S = FunctionSpace(mesh, 'DG', 0) kappa, alpha = Function(S), Function(S) # Velocity W = VectorFunctionSpace(mesh, 'CG', 1) velocity = Function(W) c = Function(V) # foo*exp(1-alpha*time) so that d / dt gives us -alpha*foo f = -alpha * c + dot(velocity, grad(c)) - kappa * div(grad(c)) flux = lambda c, n, kappa=kappa: dot(kappa * grad(c), n) # What we want to substitute x, y, kappa_ = sp.symbols('x y kappa') time_, alpha_ = sp.symbols('time alpha') velocity_ = sp.Matrix([-(y - 0.5), (x - 0.5)]) # Expressions c_ = sp.sin(pi * (x + y)) * sp.exp(1 - alpha_ * time_) subs = {c: c_, kappa: kappa_, alpha: alpha_, velocity: velocity_} as_expr = lambda t: ulfy.Expression( t, subs=subs, degree=4, kappa=kappa_value, alpha=2, time=0.) # Solution c_exact, velocity = map(as_expr, (c, velocity)) # Forcing f = as_expr(f) normals = [ Constant((-1, 0)), Constant((1, 0)), Constant((0, -1)), Constant((0, 1)) ] fluxes = [as_expr(flux(c, n)) for n in normals] return { 'solution': c_exact, 'forcing': f, 'fluxes': fluxes, 'velocity': velocity }
def setup_mms(): '''Simple MMS problem for UnitSquareMesh''' mesh = UnitSquareMesh(2, 2) x, y = SpatialCoordinate(mesh) u = cos(pi*x*(1-x)*y*(1-y)) p = Constant(0) f = -div(grad(u)) + u g = u to_expr = lambda f: ulfy.Expression(f, degree=4) up = tuple(to_expr(x) for x in (u, p)) fg = tuple(to_expr(x) for x in (f, g)) return {'solution': up, 'data': fg}
def setup_mms(): '''Simple MMS problem for UnitSquareMesh''' mesh = UnitSquareMesh(2, 2) x, y = SpatialCoordinate(mesh) phi = sin(pi*(x+y)) u = as_vector((phi.dx(1), -phi.dx(0))) p = cos(pi*x)*cos(pi*y) sigma = 2*sym(grad(u)) - p*Identity(2) f = -div(sigma) g_u = u to_expr = lambda f: ulfy.Expression(f, degree=4) w = tuple(to_expr(x) for x in (u, p)) return {'solution': w, 'force': to_expr(f), 'velocity': to_expr(g_u)}
def mms_ale(kappa_value): '''Method of manufactured solutions on [0, 1]^2''' mesh = UnitSquareMesh(2, 2) # Dummy V = VectorFunctionSpace(mesh, 'CG', 2) # Coefficient space S = FunctionSpace(mesh, 'DG', 0) kappa = Function(S) u = Function(V) f = -div(kappa * grad(u)) flux = lambda u, n, kappa=kappa: dot(kappa * grad(u), n) # What we want to substitute x, y, kappa_ = sp.symbols('x y kappa') # Expressions u_ = sp.Matrix([sp.sin(pi * (x + y)), sp.cos(pi * (x + y))]) subs = {u: u_, kappa: kappa_} # Function are replaced by symbols as_expr = lambda t: ulfy.Expression( t, subs=subs, degree=4, kappa=kappa_value) # Solution u_exact = as_expr(u) # Forcing f = as_expr(f) # 4 # 1 2 # 3 so that normals = [ Constant((-1, 0)), Constant((1, 0)), Constant((0, -1)), Constant((0, 1)) ] fluxes = [as_expr(flux(u, n)) for n in normals] return {'solution': u_exact, 'force': f, 'fluxes': fluxes}
from dolfin import * import numpy as np import sympy as sp import ulfy n = 64 mesh = UnitSquareMesh(n, n) V = VectorFunctionSpace(mesh, 'CG', 2) x, y = sp.symbols('x y') u = Function(V) n = Constant((1, 0)) subs = {u: sp.Matrix([sp.sin(x**2 + y**2), sp.cos(x**2 - 3 * y**2)])} displacement = ulfy.Expression(u, subs=subs, degree=2) stress = ulfy.Expression(sym(grad(u)), subs=subs, degree=2) traction = ulfy.Expression(dot(n, sym(grad(u))), subs=subs, degree=2) traction_n = ulfy.Expression(dot(n, dot(n, sym(grad(u)))), subs=subs, degree=2) displacement_n = ulfy.Expression(dot(u, n) * n, subs=subs, degree=2) cell_f = MeshFunction('size_t', mesh, 2, 2) CompiledSubDomain('x[0] < 0.5+DOLFIN_EPS').mark(cell_f, 1) left = EmbeddedMesh(cell_f, 1) left_bdries = MeshFunction('size_t', left, 1, 0) CompiledSubDomain('near(x[0], 0.5)').mark(left_bdries, 1) right = EmbeddedMesh(cell_f, 2)
def setup_mms(params): ''' Simple MMS problem for UnitSquareMesh. Return MMSData. ''' mesh = UnitSquareMesh(mpi_comm_self(), 2, 2) # Dummy V = FunctionSpace(mesh, 'CG', 2) S = FunctionSpace(mesh, 'DG', 0) # Define as function to allow ufly substition kappa, kappa1, eps = Function(S), Function(S), Function(S) u = Function(V) sigma = kappa * grad(u) # Outer normals of inner normals = map(Constant, [(-1, 0), (1, 0), (0, -1), (0, 1)]) # Forcing for first f = -div(sigma) # Second and its forcing u1 = Function(V) sigma1 = kappa1 * grad(u1) f1 = -div(sigma1) # On interface we have difference in us (restricted) gGamma_i = lambda n: u1 - u - eps * dot(sigma, n) hGamma_i = lambda n: -dot(sigma1, n) + dot(sigma, n) # Multiplier is u1| restricted! # What we want to substitute x, y, kappa1_, kappa_, eps_ = sp.symbols('x y kappa1 kappa eps') u_ = sp.sin(pi * (x + y)) #u1_ = u_/kappa1_ + (x-0.25)**2*(x-0.75)**2*(y-0.25)**2*(y-0.75)**2 # u1 - u1 = 0 so simple! u1_ = u_ / kappa1_ + sp.cos(pi * (x - 0.25) * (x - 0.75)) * sp.cos(pi * (y - 0.25) * (y - 0.75)) subs = {u: u_, u1: u1_, kappa: kappa_, kappa1: kappa1_, eps: eps_} as_expression = lambda f: ulfy.Expression( f, subs=subs, degree=4, kappa=1, kappa1=params.kappa, eps=params.eps) # Solutions u_exact = as_expression(u) sigma_exact = as_expression(sigma) u1_exact = as_expression(u1) sigma1_exact = as_expression(sigma1) # Mulltiplier is du on the boundary p_exact = as_expression(u1 - u) I_exact = [as_expression(dot(sigma, n)) for n in normals] # current # Data f = as_expression(f) f1 = as_expression(f1) # Dirichle data for outer boundary (piecewise) gBdry = [u1_exact] * 4 # Temperature jump (piecewise) gGamma = [as_expression(gGamma_i(n)) for n in normals] # Flux jump hGamma = [as_expression(hGamma_i(n)) for n in normals] rhs = (f1, f, gBdry, gGamma, hGamma) # Subdomains for the outerboundary then interfaces then extra/intracelluler inside = [ '(0.25-tol<x[0])', '(x[0] < 0.75+tol)', '(0.25-tol<x[1])', '(x[1] < 0.75+tol)' ] inside = ' && '.join(inside) outside = '!(%s)' % inside subdomains = [('near(x[0], 0.0)', 'near(x[0], 1.0)', 'near(x[1], 0.0)', 'near(x[1], 1.0)'), ('near(x[0], 0.25)', 'near(x[0], 0.75)', 'near(x[1], 0.25)', 'near(x[1], 0.75)'), (outside, inside)] # Solutions for inside and outside return MMSData(solution=[[sigma1_exact, sigma_exact], [u1_exact, u_exact], p_exact, I_exact], rhs=rhs, subdomains=subdomains, normals=[normals, normals])
def foo(n): mesh = UnitSquareMesh(n, n) V = VectorFunctionSpace(mesh, 'CG', 2) x, y = sp.symbols('x y') u = Function(V) n = Constant((1, 0)) subs = {u: sp.Matrix([sp.sin(x**2 + y**2), sp.cos(x**2 - 3 * y**2)])} displacement = ulfy.Expression(u, subs=subs, degree=2) stress = ulfy.Expression(sym(grad(u)), subs=subs, degree=2) traction = ulfy.Expression(dot(n, sym(grad(u))), subs=subs, degree=2) cell_f = MeshFunction('size_t', mesh, 2, 2) CompiledSubDomain('x[0] < 0.5+DOLFIN_EPS').mark(cell_f, 1) left = EmbeddedMesh(cell_f, 1) left_bdries = MeshFunction('size_t', left, 1, 0) CompiledSubDomain('near(x[0], 0.5)').mark(left_bdries, 1) interface = EmbeddedMesh(left_bdries, 1) right = EmbeddedMesh(cell_f, 2) right_bdries = MeshFunction('size_t', right, 1, 0) CompiledSubDomain('near(x[0], 0.5)').mark(right_bdries, 2) # Don't redefine! interface.compute_embedding(right_bdries, 2) # Okay so let's be on left with displacement V = VectorFunctionSpace(left, 'CG', 2) u = interpolate(displacement, V) # Is this a way to compute the stress? Q = VectorFunctionSpace(left, 'DG', 1) q = TestFunction(Q) # Use DG1? n = FacetNormal(left) expr = dot(sym(grad(u)), n) ds_ = Measure('ds', domain=left, subdomain_data=left_bdries) b = assemble(inner(expr, q) * ds_(1)) # This B = VectorFunctionSpace(interface, 'DG', 1) # Match the test function of form MTb = Function(B) trace_matrix(Q, B, interface).mult(b, MTb.vector()) # Now y is in the dual. we need it back x = Function(B) M = assemble(inner(TrialFunction(B), TestFunction(B)) * dx) solve(M, x.vector(), MTb.vector()) # x is now expr|_interface print assemble(inner(x - traction, x - traction) * dx) # What I want to do next is to extend it to right domain so that # if I there perform surface integral over the interface I get close # to what the left boundary said R = VectorFunctionSpace(right, 'DG', 1) extend = Function(R) trace_matrix(R, B, interface).transpmult(x.vector(), extend.vector()) import matplotlib.pyplot as plt xx = np.sort([cell.midpoint().array()[1] for cell in cells(interface)]) yy = np.array([x(0.5, xxi)[0] for xxi in xx]) zz = np.array([traction(0.5, xxi)[0] for xxi in xx]) rr = np.array([extend(0.5, xxi)[0] for xxi in xx]) plt.figure() plt.plot(xx, yy, label='num') plt.plot(xx, zz, label='true') plt.plot(xx, rr, label='rec') plt.legend() plt.show()
def mms_stokes(mu_value, rho_value): '''Method of manufactured solutions on [0, 1]^2''' mesh = UnitSquareMesh(2, 2) # Dummy V = FunctionSpace(mesh, 'CG', 2) # Coefficient space S = FunctionSpace(mesh, 'DG', 0) mu, rho, alpha, time = Function(S), Function(S), Function(S), Function(S) # Auxiliry function for defining Stokes velocity (to make it div-free) phi = Function(V) u = as_vector((phi.dx(1), -phi.dx(0))) * exp(1 - alpha**2 * time) p = Function(V) # Pressure stress = lambda u, p, mu=mu: mu * grad(u) - p * Identity(len(u)) # Forcing for Stokes f = -div(stress(u, p)) / rho + u * (-alpha**2) # We will also need traction on boundaries with normal n traction = lambda u, p, n: dot(stress(u, p), n) # What we want to substitute x, y, mu_, rho_, alpha_, time_ = sp.symbols('x y mu rho alpha time') # Expressions phi_ = sp.sin(pi * (x + y)) p_ = sp.sin(2 * pi * x) * sp.sin(4 * pi * y) subs = { phi: phi_, p: p_, mu: mu_, rho: rho_, alpha: alpha_, time: time_ } # Function are replaced by symbols as_expr = lambda t: ulfy.Expression( t, subs=subs, degree=4, mu=mu_value, rho=rho_value, alpha=0.2, time=0.) # Solution u_exact, p_exact = map(as_expr, (u, p)) # Forcing f = as_expr(f) # With u, p we have things for Dirichlet and pressure boudaries. For # traction assume boundaries labeled in order # 4 # 1 2 # 3 so that normals = [ Constant((-1, 0)), Constant((1, 0)), Constant((0, -1)), Constant((0, 1)) ] tractions = [as_expr(traction(u, p, n)) for n in normals] # Finally tangential part R = Constant(((0, -1), (1, 0))) normal_comps = [as_expr(dot(n, traction(u, p, n))) for n in normals] tangent_comps = [ as_expr(dot(dot(R, n), traction(u, p, n))) for n in normals ] stress_components = zip(normal_comps, tangent_comps) return { 'solution': (u_exact, p_exact), 'force': f, 'tractions': tractions, 'stress_components': stress_components }
def setup_mms(flat_gamma): '''''' mesh = UnitSquareMesh(2, 2) # The following labeling of edges will be enforced # 4 # 1 2 # 3 x, y = SpatialCoordinate(mesh) phi = sin(pi * (x - 2 * y)) # Auxiliary for div free velocity u = as_vector((phi.dx(1), -phi.dx(0))) p = cos(pi * (2 * x - 3 * y)) sigma = 2 * sym(grad(u)) - p * Identity(2) f = -div(sigma) # Normal of gamma and how to construct the mesh then if flat_gamma: normals = (Constant((-1, 0)), ) def get_geometry(i): n = 2 * 2**i mesh = UnitSquareMesh(n, n) facet_f = MeshFunction('size_t', mesh, 1, 0) CompiledSubDomain('near(x[0], 0)').mark(facet_f, 1) CompiledSubDomain('near(x[0], 1)').mark(facet_f, 2) CompiledSubDomain('near(x[1], 0)').mark(facet_f, 3) CompiledSubDomain('near(x[1], 1)').mark(facet_f, 4) return facet_f else: cx, cy, r = Constant(0), Constant(0.5), Constant(0.5) normals = (as_vector(((x - cx) / r, (y - cy) / r)), ) try: import gmshnics, gmsh # We want to define # /------| # ( | # ( | # \------| def get_geometry(i): gmsh.initialize(['', '-clscale', str(1 / 2**i)]) model = gmsh.model factory = model.occ ul = factory.addPoint(0, 1, 0) c = factory.addPoint(0, 0.5, 0) front = factory.addPoint(-0.5, 0.5, 0) ll = factory.addPoint(0, 0, 0) lr = factory.addPoint(1, 0, 0) ur = factory.addPoint(1, 1, 0) arc_top = factory.addCircleArc(ul, c, front) arc_bottom = factory.addCircleArc(front, c, ll) bottom = factory.addLine(ll, lr) right = factory.addLine(lr, ur) top = factory.addLine(ur, ul) loop = factory.addCurveLoop( [arc_top, arc_bottom, bottom, right, top]) domain = factory.addPlaneSurface([loop]) factory.synchronize() model.addPhysicalGroup(2, [domain], 1) model.addPhysicalGroup(1, [arc_top, arc_bottom], 1) model.addPhysicalGroup(1, [right], 2) model.addPhysicalGroup(1, [bottom], 3) model.addPhysicalGroup(1, [top], 4) factory.synchronize() nodes, topologies = gmshnics.msh_gmsh_model(model, 2) mesh, entity_functions = gmshnics.mesh_from_gmsh( nodes, topologies) gmsh.finalize() return entity_functions[1] except ImportError: print('Missing gmshnics module') get_geometry = lambda i: None # The remaining normals normals = normals + (Constant((1, 0)), Constant((0, -1)), Constant((0, 1))) R = Constant(((0, -1), (1, 0))) # In addition to u we will need data for Neumann boundaries and gamma g_dir = [u] * 4 g_neu = [dot(sigma, n) for n in normals] # On LM boundary we have tangential data for velocity ... g_lm_t = [dot(u, dot(R, n)) for n in normals] # ... and also traction data in normal direction g_lm_n = [dot(dot(sigma, n), n) for n in normals] # For multiplier we have a setup in mind where it is defind only on # the left boundary lm, = (-dot(dot(R, n), dot(sigma, n)) for n in normals[:1]) to_expr = lambda f: ulfy.Expression(f, degree=4) solution = tuple(map(to_expr, (u, p, lm))) return { 'solution': solution, 'f': to_expr(f), 'dirichlet': dict(enumerate(map(to_expr, g_dir), 1)), 'neumann': dict(enumerate(map(to_expr, g_neu), 1)), 'lagrange_t': dict(enumerate(map(to_expr, g_lm_t), 1)), 'lagrange_n': dict(enumerate(map(to_expr, g_lm_n), 1)), 'get_geometry': get_geometry }
def mms_solid(parameters): '''Method of manufactured solutions on [0, 1]^2''' mesh = UnitSquareMesh(2, 2) V = VectorFunctionSpace(mesh, 'CG', 2) # Displacement, Flux Q = FunctionSpace(mesh, 'CG', 2) # Pressure # Coefficient space S = FunctionSpace(mesh, 'DG', 0) kappa, mu, lmbda, alpha, s0 = [Function(S) for _ in range(5)] eta = Function(V) # Displacement p = Function(Q) # Pressure u = -kappa * grad(p) # Define flux sigma_p = lambda eta, p: 2 * mu * sym(grad(eta)) + lmbda * div( eta) * Identity(len(eta)) - alpha * p * Identity(len(eta)) f1 = -div(sigma_p(eta, p)) # What we want to substitute x, y, kappa_, mu_, lmbda_, alpha_, s0_ = sp.symbols( 'x y kappa mu lmbda alpha s0') # Expressions eta_ = sp.Matrix([sp.sin(pi * (x + y)), sp.cos(pi * (x + y))]) p_ = sp.cos(pi * (x - y)) f2 = (s0 * p + alpha * div(eta)) + div(u) # Start with stationary first subs = { eta: eta_, p: p_, kappa: kappa_, mu: mu_, lmbda: lmbda_, alpha: alpha_, s0: s0_ } as_expr = lambda t: ulfy.Expression(t, subs=subs, degree=4, kappa=parameters['kappa'], mu=parameters['mu'], lmbda=parameters['lmbda'], alpha=parameters['alpha'], s0=parameters['s0']) # Solution eta_exact, u_exact, p_exact = map(as_expr, (eta, u, p)) # Forcing f1, f2 = as_expr(f1), as_expr(f2) # 4 # 1 2 # 3 so that normals = [ Constant((-1, 0)), Constant((1, 0)), Constant((0, -1)), Constant((0, 1)) ] tractions = [as_expr(dot(sigma_p(eta, p), n)) for n in normals] return { 'solution': (eta_exact, u_exact, p_exact), 'force': (f1, f2), 'tractions': tractions }
def setup_mms(parameter_values): '''Manufacture solution for the immersed test case''' # We take Stokes side as the master for normal orientation mesh = UnitSquareMesh(2, 2, 'crossed') x, y = SpatialCoordinate(mesh) mu, K, alpha = Constant(1), Constant(1), Constant(1) phi = sin(pi*(x-2*y)) uS = as_vector((phi.dx(1), -phi.dx(0))) pS = cos(2*pi*(3*x-y)) pD = sin(2*pi*(x+y)) uD = -K*grad(pD) # Stokes ... sigma = 2*mu*sym(grad(uS)) - pS*Identity(2) fS = -div(sigma) # ... we need for standard boudaries velocity and traction. # NOTE: normals are assumed to be labeled as in immersed_geometry normalsS = tuple(map(Constant, ((1, 0), (-1, 0), (0, 1), (0, -1), (-1, 0), (1, 0), (0, -1), (0, 1)))) traction = tuple(dot(sigma, n) for n in normalsS) # Darcy ... fD = div(uD) # ... we need pD and uD normalsD = tuple(map(Constant, ((-1, 0), (1, 0), (0, -1), (0, 1)))) # Interface normalsI = tuple(map(Constant, ((1, 0), (-1, 0), (0, 1), (0, -1)))) g_u = tuple(dot(uS, n) - dot(uD, n) for n in normalsI) g_n = tuple(-dot(n, dot(sigma, n)) - pD for n in normalsI) g_t = tuple(-dot(rotate(n), dot(sigma, n)) - alpha*dot(rotate(n), uS) for n in normalsI) # Multiplier is -normal part of traction lms = [-dot(n, dot(sigma, n)) for n in normalsI] # Don't want to trigger compiler on parameter change mu_, alpha_, K_ = sp.symbols('mu, alpha, K') subs = {mu: mu_, alpha: alpha_, K: K_} # Check coefs assert parameter_values['mu'] > 0 and parameter_values['K'] > 0 and parameter_values['alpha'] >= 0 to_expr = lambda f: ulfy.Expression(f, degree=4, subs=subs, mu=parameter_values['mu'], K=parameter_values['K'], alpha=parameter_values['alpha']) # As tagged in utils.immersed_geometry lm_subdomains = { 1: CompiledSubDomain('near(x[0], 0.25) && ((0.25-DOLFIN_EPS < x[1]) && (x[1] < 0.75+DOLFIN_EPS))'), 2: CompiledSubDomain('near(x[0], 0.75) && ((0.25-DOLFIN_EPS < x[1]) && (x[1] < 0.75+DOLFIN_EPS))'), 3: CompiledSubDomain('near(x[1], 0.25) && ((0.25-DOLFIN_EPS < x[0]) && (x[0] < 0.75+DOLFIN_EPS))'), 4: CompiledSubDomain('near(x[1], 0.75) && ((0.25-DOLFIN_EPS < x[0]) && (x[0] < 0.75+DOLFIN_EPS))') } return { 'solution': {'uS': to_expr(uS), 'uD': to_expr(uD), 'pS': to_expr(pS), 'pD': to_expr(pD), 'lm': PiecewiseExpression(lm_subdomains, dict(enumerate(map(to_expr, lms), 1)))}, 'fS': to_expr(fS), 'fD': to_expr(fD), # Standard boundary data 'velocity_S': dict(enumerate(map(to_expr, [uS]*len(normalsS)), 1)), 'traction_S': dict(enumerate(map(to_expr, traction), 1)), 'pressure_D': dict(enumerate(map(to_expr, [pD]*len(normalsD)), 1)), 'flux_D': dict(enumerate(map(to_expr, [uD]*len(normalsD)), 1)), # Interface boundary conditions 'g_u': dict(enumerate(map(to_expr, g_u), 1)), 'g_n': dict(enumerate(map(to_expr, g_n), 1)), 'g_t': dict(enumerate(map(to_expr, g_t), 1)), # Geometry setup 'get_geometry': immersed_geometry }