Exemplo n.º 1
0
 def compute_force(self, velocity, pressure, t):
     self.tc.start('errorForce')
     I = Identity(3)  # Identity tensor
     def T(p, v):
         return -p * I + 2.0 * self.nu * sym(grad(v))
     error_force = sqrt(
             assemble(inner((T(pressure, velocity) - T(self.sol_p, self.solution)) * self.normal,
                            (T(pressure, velocity) - T(self.sol_p, self.solution)) * self.normal) * self.dsWall))
     an_force = sqrt(assemble(inner(T(self.sol_p, self.solution) * self.normal,
                                         T(self.sol_p, self.solution) * self.normal) * self.dsWall))
     an_f_normal = sqrt(assemble(inner(inner(T(self.sol_p, self.solution) * self.normal, self.normal),
                                            inner(T(self.sol_p, self.solution) * self.normal, self.normal)) * self.dsWall))
     error_f_normal = sqrt(
             assemble(inner(inner((T(self.sol_p, self.solution) - T(pressure, velocity)) * self.normal, self.normal),
                            inner((T(self.sol_p, self.solution) - T(pressure, velocity)) * self.normal, self.normal)) * self.dsWall))
     an_f_shear = sqrt(
             assemble(inner((I - outer(self.normal, self.normal)) * T(self.sol_p, self.solution) * self.normal,
                            (I - outer(self.normal, self.normal)) * T(self.sol_p, self.solution) * self.normal) * self.dsWall))
     error_f_shear = sqrt(
             assemble(inner((I - outer(self.normal, self.normal)) *
                            (T(self.sol_p, self.solution) - T(pressure, velocity)) * self.normal,
                            (I - outer(self.normal, self.normal)) *
                            (T(self.sol_p, self.solution) - T(pressure, velocity)) * self.normal) * self.dsWall))
     self.listDict['a_force_wall']['list'].append(an_force)
     self.listDict['a_force_wall_normal']['list'].append(an_f_normal)
     self.listDict['a_force_wall_shear']['list'].append(an_f_shear)
     self.listDict['force_wall']['list'].append(error_force)
     self.listDict['force_wall_normal']['list'].append(error_f_normal)
     self.listDict['force_wall_shear']['list'].append(error_f_shear)
     if self.isWholeSecond:
         self.listDict['force_wall']['slist'].append(
             sqrt(sum([i*i for i in self.listDict['force_wall']['list'][self.N0:self.N1]])/self.stepsInSecond))
     print('  Relative force error:', error_force/an_force)
     self.tc.end('errorForce')
Exemplo n.º 2
0
    def compute_force(self, velocity, pressure, t):
        self.tc.start('errorForce')
        I = Identity(3)  # Identity tensor

        def T(p, v):
            return -p * I + 2.0 * self.nu * sym(grad(v))

        error_force = sqrt(
            assemble(
                inner((T(pressure, velocity) - T(self.sol_p, self.solution)) *
                      self.normal,
                      (T(pressure, velocity) - T(self.sol_p, self.solution)) *
                      self.normal) * self.dsWall))
        an_force = sqrt(
            assemble(
                inner(
                    T(self.sol_p, self.solution) * self.normal,
                    T(self.sol_p, self.solution) * self.normal) * self.dsWall))
        an_f_normal = sqrt(
            assemble(
                inner(
                    inner(
                        T(self.sol_p, self.solution) * self.normal,
                        self.normal),
                    inner(
                        T(self.sol_p, self.solution) * self.normal,
                        self.normal)) * self.dsWall))
        error_f_normal = sqrt(
            assemble(
                inner(
                    inner(
                        (T(self.sol_p, self.solution) - T(pressure, velocity))
                        * self.normal, self.normal),
                    inner(
                        (T(self.sol_p, self.solution) - T(pressure, velocity))
                        * self.normal, self.normal)) * self.dsWall))
        an_f_shear = sqrt(
            assemble(
                inner(
                    (I - outer(self.normal, self.normal)) *
                    T(self.sol_p, self.solution) * self.normal,
                    (I - outer(self.normal, self.normal)) *
                    T(self.sol_p, self.solution) * self.normal) * self.dsWall))
        error_f_shear = sqrt(
            assemble(
                inner((I - outer(self.normal, self.normal)) *
                      (T(self.sol_p, self.solution) - T(pressure, velocity)) *
                      self.normal, (I - outer(self.normal, self.normal)) *
                      (T(self.sol_p, self.solution) - T(pressure, velocity)) *
                      self.normal) * self.dsWall))
        self.listDict['a_force_wall']['list'].append(an_force)
        self.listDict['a_force_wall_normal']['list'].append(an_f_normal)
        self.listDict['a_force_wall_shear']['list'].append(an_f_shear)
        self.listDict['force_wall']['list'].append(error_force)
        self.listDict['force_wall_normal']['list'].append(error_f_normal)
        self.listDict['force_wall_shear']['list'].append(error_f_shear)
        print('  Relative force error:', error_force / an_force)
        self.tc.end('errorForce')
Exemplo n.º 3
0
def test_physically_mapped_facet():
    mesh = Mesh(VectorElement("P", triangle, 1))

    # set up variational problem
    U = FiniteElement("Morley", mesh.ufl_cell(), 2)
    V = FiniteElement("P", mesh.ufl_cell(), 1)
    R = FiniteElement("P", mesh.ufl_cell(), 1)
    Vv = VectorElement(BrokenElement(V))
    Qhat = VectorElement(BrokenElement(V[facet]))
    Vhat = VectorElement(V[facet])
    Z = FunctionSpace(mesh, MixedElement(U, Vv, Qhat, Vhat, R))

    z = Coefficient(Z)
    u, d, qhat, dhat, lam = split(z)

    s = FacetNormal(mesh)
    trans = as_matrix([[1, 0], [0, 1]])
    mat = trans*grad(grad(u))*trans + outer(d, d) * u
    J = (u**2*dx +
         u**3*dx +
         u**4*dx +
         inner(mat, mat)*dx +
         inner(grad(d), grad(d))*dx +
         dot(s, d)**2*ds)
    L_match = inner(qhat, dhat - d)
    L = J + inner(lam, inner(d, d)-1)*dx + (L_match('+') + L_match('-'))*dS + L_match*ds
    compile_form(L)
Exemplo n.º 4
0
    def blocks(self):
        aa, ff = super(FormulationMinimallyConstrained, self).blocks()

        n = ufl.FacetNormal(self.mesh)
        ds = ufl.Measure("ds", self.mesh)

        u, P = self.uu_[0], self.uu_[2]
        v, Q = self.vv_[0], self.vv_[2]

        aa[0].append(-ufl.inner(P, ufl.outer(v, n)) * ds)
        aa[1].append(0)
        aa.append([-ufl.inner(Q, ufl.outer(u, n)) * ds, 0, 0])

        ff.append(0)

        return [aa, ff]
Exemplo n.º 5
0
    def dtheta_dC(self, u_, p_, ivar, theta_old_, thres, dt):
        
        theta_ = ivar["theta"]
        
        dFg_dtheta = self.F_g(theta_,tang=True)
        
        ktheta = self.res_dtheta_growth(u_, p_, ivar, theta_old_, thres, dt, 'ktheta')
        K_growth = self.res_dtheta_growth(u_, p_, ivar, theta_old_, thres, dt, 'tang')
        
        i, j, k, l = indices(4)
        
        if self.growth_trig == 'volstress':
            
            Cmat = self.S(u_,p_,ivar,tang=True)
            
            # TeX: \frac{\partial \vartheta}{\partial \boldsymbol{C}} = \frac{k(\vartheta) \Delta t}{\frac{\partial r}{\partial \vartheta}}\left(\boldsymbol{S} + \boldsymbol{C} : \frac{1}{2} \check{\mathbb{C}}\right)

            tangdC = (ktheta*dt/K_growth) * (self.S(u_,p_,ivar=ivar) + 0.5*as_tensor(self.kin.C(u_)[i,j]*Cmat[i,j,k,l], (k,l)))
            
        elif self.growth_trig == 'fibstretch':
            
            # TeX: \frac{\partial \vartheta}{\partial \boldsymbol{C}} = \frac{k(\vartheta) \Delta t}{\frac{\partial r}{\partial \vartheta}} \frac{1}{2\lambda_{f}} \boldsymbol{f}_{0}\otimes \boldsymbol{f}_{0}

            tangdC = (ktheta*dt/K_growth) * outer(self.kin.fib_funcs[0],self.kin.fib_funcs[0])/(2.*self.kin.fibstretch(u_,self.kin.fib_funcs[0]))

        else:
            raise NameError("Unkown growth_trig!")
        
        return tangdC
Exemplo n.º 6
0
def test_automatic_simplification(self):
    cell = triangle
    element = FiniteElement("Lagrange", cell, 1)

    v = TestFunction(element)
    u = TrialFunction(element)

    assert inner(u, v) == u * conj(v)
    assert dot(u, v) == u * v
    assert outer(u, v) == conj(u) * v
Exemplo n.º 7
0
def test_apply_algebra_lowering_complex(self):
    cell = triangle
    element = FiniteElement("Lagrange", cell, 1)

    v = TestFunction(element)
    u = TrialFunction(element)

    gv = grad(v)
    gu = grad(u)

    a = dot(gu, gv)
    b = inner(gv, gu)
    c = outer(gu, gv)

    lowered_a = apply_algebra_lowering(a)
    lowered_b = apply_algebra_lowering(b)
    lowered_c = apply_algebra_lowering(c)
    lowered_a_index = lowered_a.index()
    lowered_b_index = lowered_b.index()
    lowered_c_indices = lowered_c.indices()

    assert lowered_a == gu[lowered_a_index] * gv[lowered_a_index]
    assert lowered_b == gv[lowered_b_index] * conj(gu[lowered_b_index])
    assert lowered_c == as_tensor(conj(gu[lowered_c_indices[0]]) * gv[lowered_c_indices[1]], (lowered_c_indices[0],) + (lowered_c_indices[1],))
Exemplo n.º 8
0
def test_diff_then_integrate():

    # Define 1D geometry
    n = 21
    mesh = UnitIntervalMesh(MPI.comm_world, n)

    # Shift and scale mesh
    x0, x1 = 1.5, 3.14
    mesh.coordinates()[:] *= (x1 - x0)
    mesh.coordinates()[:] += x0

    x = SpatialCoordinate(mesh)[0]
    xs = 0.1 + 0.8 * x / x1  # scaled to be within [0.1,0.9]

    # Define list of expressions to test, and configure
    # accuracies these expressions are known to pass with.
    # The reason some functions are less accurately integrated is
    # likely that the default choice of quadrature rule is not perfect
    F_list = []

    def reg(exprs, acc=10):
        for expr in exprs:
            F_list.append((expr, acc))

    # FIXME: 0*dx and 1*dx fails in the ufl-ffc-jit framework somewhere
    # reg([Constant(0.0, cell=cell)])
    # reg([Constant(1.0, cell=cell)])
    monomial_list = [x**q for q in range(2, 6)]
    reg(monomial_list)
    reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list])
    reg([x**x])
    reg([x**(x**2)], 8)
    reg([x**(x**3)], 6)
    reg([x**(x**4)], 2)
    # Special functions:
    reg([atan(xs)], 8)
    reg([sin(x), cos(x), exp(x)], 5)
    reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3)
    reg([asin(xs), acos(xs)], 1)
    reg([tan(xs)], 7)

    try:
        import scipy
    except ImportError:
        scipy = None

    if hasattr(math, 'erf') or scipy is not None:
        reg([erf(xs)])
    else:
        print(
            "Warning: skipping test of erf, old python version and no scipy.")

    # if 0:
    #     print("Warning: skipping tests of bessel functions, doesn't build on all platforms.")
    # elif scipy is None:
    #     print("Warning: skipping tests of bessel functions, missing scipy.")
    # else:
    #     for nu in (0, 1, 2):
    #         # Many of these are possibly more accurately integrated,
    #         # but 4 covers all and is sufficient for this test
    #         reg([bessel_J(nu, xs), bessel_Y(nu, xs), bessel_I(nu, xs), bessel_K(nu, xs)], 4)

    # To handle tensor algebra, make an x dependent input tensor
    # xx and square all expressions
    def reg2(exprs, acc=10):
        for expr in exprs:
            F_list.append((inner(expr, expr), acc))

    xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]])
    x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4])
    cc = as_matrix([[2, 3], [4, 5]])
    reg2([xx])
    reg2([x3v])
    reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))])
    reg2([xx.T])
    reg2([tr(xx)])
    reg2([det(xx)])
    reg2([dot(xx, 0.1 * xx)])
    reg2([outer(xx, xx.T)])
    reg2([dev(xx)])
    reg2([sym(xx)])
    reg2([skew(xx)])
    reg2([elem_mult(7 * xx, cc)])
    reg2([elem_div(7 * xx, xx + cc)])
    reg2([elem_pow(1e-3 * xx, 1e-3 * cc)])
    reg2([elem_pow(1e-3 * cc, 1e-3 * xx)])
    reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2)  # pretty inaccurate...

    # FIXME: Add tests for all UFL operators:
    # These cause discontinuities and may be harder to test in the
    # above fashion:
    # 'inv', 'cofac',
    # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
    # 'conditional', 'sign',
    # 'jump', 'avg',
    # 'LiftingFunction', 'LiftingOperator',

    # FIXME: Test other derivatives: (but algorithms for operator
    # derivatives are the same!):
    # 'variable', 'diff',
    # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative',

    # Run through all operators defined above and compare integrals
    debug = 0
    for F, acc in F_list:
        # Apply UFL differentiation
        f = diff(F, SpatialCoordinate(mesh))[..., 0]
        if debug:
            print(F)
            print(x)
            print(f)

        # Apply integration with DOLFIN
        # (also passes through form compilation and jit)
        M = f * dx
        f_integral = assemble_scalar(M)  # noqa
        f_integral = MPI.sum(mesh.mpi_comm(), f_integral)

        # Compute integral of f manually from anti-derivative F
        # (passes through PyDOLFIN interface and uses UFL evaluation)
        F_diff = F((x1, )) - F((x0, ))

        # Compare results. Using custom relative delta instead
        # of decimal digits here because some numbers are >> 1.
        delta = min(abs(f_integral), abs(F_diff)) * 10**-acc
        assert f_integral - F_diff <= delta
Exemplo n.º 9
0
def test_div_grad_then_integrate_over_cells_and_boundary():

    # Define 2D geometry
    n = 10
    mesh = RectangleMesh(Point(0.0, 0.0), Point(2.0, 3.0), 2 * n, 3 * n)

    x, y = SpatialCoordinate(mesh)
    xs = 0.1 + 0.8 * x / 2  # scaled to be within [0.1,0.9]
    #    ys = 0.1 + 0.8 * y / 3  # scaled to be within [0.1,0.9]
    n = FacetNormal(mesh)

    # Define list of expressions to test, and configure accuracies
    # these expressions are known to pass with.  The reason some
    # functions are less accurately integrated is likely that the
    # default choice of quadrature rule is not perfect
    F_list = []

    def reg(exprs, acc=10):
        for expr in exprs:
            F_list.append((expr, acc))

    # FIXME: 0*dx and 1*dx fails in the ufl-ffc-jit framework somewhere
    # reg([Constant(0.0, cell=cell)])
    # reg([Constant(1.0, cell=cell)])
    monomial_list = [x**q for q in range(2, 6)]
    reg(monomial_list)
    reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list])
    reg([xs**xs])
    reg(
        [xs**(xs**2)], 8
    )  # Note: Accuracies here are from 1D case, not checked against 2D results.
    reg([xs**(xs**3)], 6)
    reg([xs**(xs**4)], 2)
    # Special functions:
    reg([atan(xs)], 8)
    reg([sin(x), cos(x), exp(x)], 5)
    reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3)
    reg([asin(xs), acos(xs)], 1)
    reg([tan(xs)], 7)

    # To handle tensor algebra, make an x dependent input tensor
    # xx and square all expressions
    def reg2(exprs, acc=10):
        for expr in exprs:
            F_list.append((inner(expr, expr), acc))

    xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]])
    xxs = as_matrix([[2 * xs**2, 3 * xs**3], [11 * xs**5, 7 * xs**4]])
    x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4])
    cc = as_matrix([[2, 3], [4, 5]])
    reg2(
        [xx]
    )  # TODO: Make unit test for UFL from this, results in listtensor with free indices
    reg2([x3v])
    reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))])
    reg2([xx.T])
    reg2([tr(xx)])
    reg2([det(xx)])
    reg2([dot(xx, 0.1 * xx)])
    reg2([outer(xx, xx.T)])
    reg2([dev(xx)])
    reg2([sym(xx)])
    reg2([skew(xx)])
    reg2([elem_mult(7 * xx, cc)])
    reg2([elem_div(7 * xx, xx + cc)])
    reg2([elem_pow(1e-3 * xxs, 1e-3 * cc)])
    reg2([elem_pow(1e-3 * cc, 1e-3 * xx)])
    reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2)  # pretty inaccurate...

    # FIXME: Add tests for all UFL operators:
    # These cause discontinuities and may be harder to test in the
    # above fashion:
    # 'inv', 'cofac',
    # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not',
    # 'conditional', 'sign',
    # 'jump', 'avg',
    # 'LiftingFunction', 'LiftingOperator',

    # FIXME: Test other derivatives: (but algorithms for operator
    # derivatives are the same!):
    # 'variable', 'diff',
    # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative',

    # Run through all operators defined above and compare integrals
    debug = 0
    if debug:
        F_list = F_list[1:]

    for F, acc in F_list:
        if debug:
            print('\n', "F:", str(F))

        # Integrate over domain and its boundary
        int_dx = assemble(div(grad(F)) * dx(mesh))  # noqa
        int_ds = assemble(dot(grad(F), n) * ds(mesh))  # noqa

        if debug:
            print(int_dx, int_ds)

        # Compare results. Using custom relative delta instead of
        # decimal digits here because some numbers are >> 1.
        delta = min(abs(int_dx), abs(int_ds)) * 10**-acc
        assert int_dx - int_ds <= delta
Exemplo n.º 10
0
    def crossfiber(self, f0):

        F_g = self.theta * self.I + (1. - self.theta) * outer(f0, f0)

        return F_g
Exemplo n.º 11
0
                                                                  )
source = lambda u1, u2, u3, v: -1 / spiral_eps * u1 * (1 - u2) * (u3 - ustar(v)
                                                                  )

xForm = inner(diffusiveFlux(u, grad(u)), grad(phi)) * dx
xForm += ufl.conditional(uh_n < ustar(vh_n), source(u, uh_n, uh_n, vh_n),
                         source(uh_n, u, uh_n, vh_n)) * phi * dx

# <markdowncell>
# To handle the possible non conforming intersection we add DG type
# skeleton terms:
# <codecell>

penalty = 5 * (order * (order + 1)) * spiral_D
if nonConforming:
    xForm -= ( inner( outer(jump(u), n('+')), avg(diffusiveFlux(u,grad(phi)))) +\
               inner( avg(diffusiveFlux(u,grad(u))), outer(jump(phi), n('+'))) ) * dS
    xForm += penalty / hS * inner(jump(u), jump(phi)) * dS

# <markdowncell>
# After adding the time discretization (a simple backward Euler scheme),
# the model is now completely implemented and the scheme can be created:
# <codecell>

form = (inner(u, phi) - inner(uh_n, phi)) * dx + dt * xForm
solverParameters =\
       {"newton.tolerance": 1e-8,
        "newton.linear.tolerance": 1e-12,
        "newton.linear.preconditioning.method": "amg-ilu",
        "newton.linear.maxiterations":1000,
        "newton.verbose": False,
# Jacobi matrix of map reference -> undeformed
J0 = ufl.geometry.Jacobian(mesh)
# Tangent basis
gs = J0[:, 0]
gη = ufl.as_vector([0, 1, 0])  # unit vector e_y (assume curve in x-z plane)
gξ = ufl.cross(gs, gη)
# Unit tangent basis
gs /= ufl.sqrt(ufl.dot(gs, gs))
gη /= ufl.sqrt(ufl.dot(gη, gη))
gξ /= ufl.sqrt(ufl.dot(gξ, gξ))
# Interpolate normal vector
dolfiny.interpolation.interpolate(gξ, n0i)
# ----------------------------------------------------------------------------

# Orthogonal projection operator (assumes sufficient geometry approximation)
P = ufl.Identity(mesh.geometry.dim) - ufl.outer(n0i, n0i)

# Thickness variable
X = dolfinx.FunctionSpace(mesh, ("DG", q))
ξ = dolfinx.Function(X, name='ξ')

# Undeformed configuration: director d0 and placement b0
d0 = n0i  # normal of manifold mesh, interpolated
b0 = x0 + ξ * d0

# Deformed configuration: director d and placement b, assumed kinematics, director uses rotation matrix
d = ufl.as_matrix([[ufl.cos(r), 0, ufl.sin(r)], [0, 1, 0],
                   [-ufl.sin(r), 0, ufl.cos(r)]]) * d0
b = x0 + ufl.as_vector([u, 0, w]) + ξ * d

# Configuration gradient, undeformed configuration
Exemplo n.º 13
0
a01 = - ufl.inner(p, ufl.div(v)) * ufl.dx
a10 = - ufl.inner(ufl.div(u), q) * ufl.dx
a11 = None

L0 = ufl.inner(f, v) * ufl.dx
L1 = ufl.inner(dolfinx.fem.Constant(mesh, PETSc.ScalarType(0.0)), q) * ufl.dx

# No prescribed shear stress
n = ufl.FacetNormal(mesh)
g_tau = tangential_proj(dolfinx.fem.Constant(
    mesh, PETSc.ScalarType(((0, 0), (0, 0)))) * n, n)
ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=1)

# Terms due to slip condition
# Explained in for instance: https://arxiv.org/pdf/2001.10639.pdf
a00 -= ufl.inner(ufl.outer(n, n) * ufl.dot(2 * mu * sym_grad(u), n), v) * ds
a01 -= ufl.inner(ufl.outer(n, n) * ufl.dot(
    - p * ufl.Identity(u.ufl_shape[0]), n), v) * ds
L0 += ufl.inner(g_tau, v) * ds

a = [[dolfinx.fem.form(a00), dolfinx.fem.form(a01)],
     [dolfinx.fem.form(a10), dolfinx.fem.form(a11)]]
L = [dolfinx.fem.form(L0), dolfinx.fem.form(L1)]

# Assemble LHS matrix and RHS vector
with dolfinx.common.Timer("~Stokes: Assemble LHS and RHS"):
    A = dolfinx_mpc.create_matrix_nest(a, [mpc, mpc_q])
    dolfinx_mpc.assemble_matrix_nest(A, a, [mpc, mpc_q], bcs)
    A.assemble()

    b = dolfinx_mpc.create_vector_nest(L, [mpc, mpc_q])
Exemplo n.º 14
0
f = fem.Constant(mesh, PETSc.ScalarType((0, 0)))
(u, p) = TrialFunctions(W)
(v, q) = TestFunctions(W)
a = (2 * mu * inner(sym_grad(u), sym_grad(v)) - inner(p, div(v)) -
     inner(div(u), q)) * dx
L = inner(f, v) * dx

# No prescribed shear stress
n = FacetNormal(mesh)
g_tau = tangential_proj(
    fem.Constant(mesh, PETSc.ScalarType(((0, 0), (0, 0)))) * n, n)
ds = Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=1)

# Terms due to slip condition
# Explained in for instance: https://arxiv.org/pdf/2001.10639.pdf
a -= inner(outer(n, n) * dot(T(u, p, mu), n), v) * ds
L += inner(g_tau, v) * ds

# Solve linear problem
petsc_options = {
    "ksp_type": "preonly",
    "pc_type": "lu",
    "pc_factor_solver_type": "mumps"
}
problem = LinearProblem(a, L, mpc, bcs=bcs, petsc_options=petsc_options)
U = problem.solve()

# ------------------------------ Output ----------------------------------
u = U.sub(0).collapse()
p = U.sub(1).collapse()
u.name = "u"
Exemplo n.º 15
0
    def active_fiber(self, tau, f0):

        S = tau * outer(f0, f0)

        return S
Exemplo n.º 16
0
    def fiber(self, f0):

        F_g = self.I + (self.theta - 1.) * outer(f0, f0)

        return F_g
Exemplo n.º 17
0
 def tangential_proj(u, n):
     """
     See for instance:
     https://link.springer.com/content/pdf/10.1023/A:1022235512626.pdf
     """
     return (ufl.Identity(u.ufl_shape[0]) - ufl.outer(n, n)) * u
Exemplo n.º 18
0
    def radial(self, f0, s0):

        r0 = cross(f0, s0)
        F_g = self.I + (self.theta - 1.) * outer(r0, r0)

        return F_g
Exemplo n.º 19
0
def test_mixed_element(cell_type, ghost_mode):
    N = 4
    mesh = dolfinx.mesh.create_unit_square(
        MPI.COMM_WORLD, N, N, cell_type=cell_type, ghost_mode=ghost_mode)

    # Inlet velocity Dirichlet BC
    bc_facets = dolfinx.mesh.locate_entities_boundary(
        mesh, mesh.topology.dim - 1, lambda x: np.isclose(x[0], 0.0))
    other_facets = dolfinx.mesh.locate_entities_boundary(
        mesh, mesh.topology.dim - 1, lambda x: np.isclose(x[0], 1.0))
    arg_sort = np.argsort(other_facets)
    mt = dolfinx.mesh.meshtags(mesh, mesh.topology.dim - 1,
                               other_facets[arg_sort], np.full_like(other_facets, 1))

    # Rotate the mesh to induce more interesting slip BCs
    th = np.pi / 4.0
    rot = np.array([[np.cos(th), -np.sin(th)],
                    [np.sin(th), np.cos(th)]])
    gdim = mesh.geometry.dim
    mesh.geometry.x[:, :gdim] = (rot @ mesh.geometry.x[:, :gdim].T).T

    # Create the function space
    Ve = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    Qe = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    V = dolfinx.fem.FunctionSpace(mesh, Ve)
    Q = dolfinx.fem.FunctionSpace(mesh, Qe)
    W = dolfinx.fem.FunctionSpace(mesh, Ve * Qe)

    inlet_velocity = dolfinx.fem.Function(V)
    inlet_velocity.interpolate(
        lambda x: np.zeros((mesh.geometry.dim, x[0].shape[0]), dtype=np.double))
    inlet_velocity.x.scatter_forward()

    # -- Nested assembly
    dofs = dolfinx.fem.locate_dofs_topological(V, 1, bc_facets)
    bc1 = dolfinx.fem.dirichletbc(inlet_velocity, dofs)

    # Collect Dirichlet boundary conditions
    bcs = [bc1]
    mpc_v = dolfinx_mpc.MultiPointConstraint(V)
    n_approx = dolfinx_mpc.utils.create_normal_approximation(V, mt, 1)
    mpc_v.create_slip_constraint(V, (mt, 1), n_approx, bcs=bcs)
    mpc_v.finalize()

    mpc_q = dolfinx_mpc.MultiPointConstraint(Q)
    mpc_q.finalize()

    f = dolfinx.fem.Constant(mesh, PETSc.ScalarType((0, 0)))
    (u, p) = ufl.TrialFunction(V), ufl.TrialFunction(Q)
    (v, q) = ufl.TestFunction(V), ufl.TestFunction(Q)
    a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
    a01 = - ufl.inner(p, ufl.div(v)) * ufl.dx
    a10 = - ufl.inner(ufl.div(u), q) * ufl.dx
    a11 = None

    L0 = ufl.inner(f, v) * ufl.dx
    L1 = ufl.inner(
        dolfinx.fem.Constant(mesh, PETSc.ScalarType(0.0)), q) * ufl.dx

    n = ufl.FacetNormal(mesh)
    g_tau = ufl.as_vector((0.0, 0.0))
    ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=1)

    a00 -= ufl.inner(ufl.outer(n, n) * ufl.dot(ufl.grad(u), n), v) * ds
    a01 -= ufl.inner(ufl.outer(n, n) * ufl.dot(
        - p * ufl.Identity(u.ufl_shape[0]), n), v) * ds
    L0 += ufl.inner(g_tau, v) * ds

    a_nest = dolfinx.fem.form(((a00, a01),
                               (a10, a11)))
    L_nest = dolfinx.fem.form((L0, L1))

    # Assemble MPC nest matrix
    A_nest = dolfinx_mpc.create_matrix_nest(a_nest, [mpc_v, mpc_q])
    dolfinx_mpc.assemble_matrix_nest(A_nest, a_nest, [mpc_v, mpc_q], bcs)
    A_nest.assemble()

    # Assemble original nest matrix
    A_org_nest = dolfinx.fem.petsc.assemble_matrix_nest(a_nest, bcs)
    A_org_nest.assemble()

    # MPC nested rhs
    b_nest = dolfinx_mpc.create_vector_nest(L_nest, [mpc_v, mpc_q])
    dolfinx_mpc.assemble_vector_nest(b_nest, L_nest, [mpc_v, mpc_q])
    dolfinx.fem.petsc.apply_lifting_nest(b_nest, a_nest, bcs)

    for b_sub in b_nest.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)

    bcs0 = dolfinx.fem.bcs_by_block(
        dolfinx.fem.extract_function_spaces(L_nest), bcs)
    dolfinx.fem.petsc.set_bc_nest(b_nest, bcs0)

    # Original dolfinx rhs
    b_org_nest = dolfinx.fem.petsc.assemble_vector_nest(L_nest)
    dolfinx.fem.petsc.apply_lifting_nest(b_org_nest, a_nest, bcs)

    for b_sub in b_org_nest.getNestSubVecs():
        b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD,
                          mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.petsc.set_bc_nest(b_org_nest, bcs0)

    # -- Monolithic assembly
    dofs = dolfinx.fem.locate_dofs_topological((W.sub(0), V), 1, bc_facets)
    bc1 = dolfinx.fem.dirichletbc(inlet_velocity, dofs, W.sub(0))

    bcs = [bc1]

    V, V_to_W = W.sub(0).collapse()
    mpc_vq = dolfinx_mpc.MultiPointConstraint(W)
    n_approx = dolfinx_mpc.utils.create_normal_approximation(V, mt, 1)
    mpc_vq.create_slip_constraint(W.sub(0), (mt, 1), n_approx, bcs=bcs)
    mpc_vq.finalize()

    f = dolfinx.fem.Constant(mesh, PETSc.ScalarType((0, 0)))
    (u, p) = ufl.TrialFunctions(W)
    (v, q) = ufl.TestFunctions(W)
    a = (
        ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx
        - ufl.inner(p, ufl.div(v)) * ufl.dx
        - ufl.inner(ufl.div(u), q) * ufl.dx
    )

    L = ufl.inner(f, v) * ufl.dx + ufl.inner(
        dolfinx.fem.Constant(mesh, PETSc.ScalarType(0.0)), q) * ufl.dx

    # No prescribed shear stress
    n = ufl.FacetNormal(mesh)
    g_tau = ufl.as_vector((0.0, 0.0))
    ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt, subdomain_id=1)

    # Terms due to slip condition
    # Explained in for instance: https://arxiv.org/pdf/2001.10639.pdf
    a -= ufl.inner(ufl.outer(n, n) * ufl.dot(ufl.grad(u), n), v) * ds
    a -= ufl.inner(ufl.outer(n, n) * ufl.dot(
        - p * ufl.Identity(u.ufl_shape[0]), n), v) * ds
    L += ufl.inner(g_tau, v) * ds

    a, L = dolfinx.fem.form(a), dolfinx.fem.form(L)

    # Assemble LHS matrix and RHS vector
    A = dolfinx_mpc.assemble_matrix(a, mpc_vq, bcs)
    A.assemble()
    A_org = dolfinx.fem.petsc.assemble_matrix(a, bcs)
    A_org.assemble()

    b = dolfinx_mpc.assemble_vector(L, mpc_vq)
    b_org = dolfinx.fem.petsc.assemble_vector(L)

    # Set Dirichlet boundary condition values in the RHS
    dolfinx_mpc.apply_lifting(b, [a], [bcs], mpc_vq)
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.petsc.set_bc(b, bcs)
    dolfinx.fem.petsc.apply_lifting(b_org, [a], [bcs])
    b_org.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
    dolfinx.fem.petsc.set_bc(b_org, bcs)

    # -- Verification
    def nest_matrix_norm(A):
        assert A.getType() == "nest"
        nrows, ncols = A.getNestSize()
        sub_A = [A.getNestSubMatrix(row, col)
                 for row in range(nrows) for col in range(ncols)]
        return sum(map(lambda A_: A_.norm()**2 if A_ else 0.0, sub_A))**0.5

    # -- Ensure monolithic and nest matrices are the same
    assert np.isclose(nest_matrix_norm(A_nest), A.norm())