Exemplo n.º 1
0
def solve_initial_pressure(w_NSp, p, q, u, v, bcs_NSp, M_, g_, phi_, rho_,
                           rho_e_, V_, drho, sigma_bar, eps, grav, dveps,
                           enable_PF, enable_EC):
    V = u.function_space()
    grad_p = df.TrialFunction(V)
    grad_p_out = df.Function(V)
    F_grad_p = (df.dot(grad_p, v) * df.dx - rho_ * df.dot(grav, v) * df.dx)
    if enable_PF:
        F_grad_p += -drho * M_ * df.inner(df.grad(u), df.outer(df.grad(g_),
                                                               v)) * df.dx
        F_grad_p += -sigma_bar * eps * df.inner(
            df.outer(df.grad(phi_), df.grad(phi_)), df.grad(v)) * df.dx
    if enable_EC and rho_e_ != 0:
        F_grad_p += rho_e_ * df.dot(df.grad(V_), v) * df.dx
    if enable_PF and enable_EC:
        F_grad_p += dveps * df.dot(df.grad(phi_), v) * df.dot(
            df.grad(V_), df.grad(V_)) * df.dx

    info_red("Solving initial grad_p...")
    df.solve(df.lhs(F_grad_p) == df.rhs(F_grad_p), grad_p_out)

    F_p = (df.dot(df.grad(q), df.grad(p)) * df.dx -
           df.dot(df.grad(q), grad_p_out) * df.dx)
    info_red("Solving initial p...")
    df.solve(df.lhs(F_p) == df.rhs(F_p), w_NSp, bcs_NSp)
Exemplo n.º 2
0
def wedge(a, b):
    '''
    Calculates the wedge product of vectors a and b

    .. math::

        a \wedge b : = a \otimes b - b\otimes a

    '''
    return outer(a, b) - outer(b, a)
Exemplo n.º 3
0
    def forms_theta_nlinear_np(self, v0, v_int, Ubar0, dt, theta_map=Constant(1.0),
                               theta_L=Constant(1.0), duh0=Constant((0., 0.)),
                               duh00=Constant((0., 0)), h=Constant((0., 0.)),
                               neumann_idx=99):

        '''
        No particles in mass matrix
        '''

        # Define trial test functions
        (v, lamb, vbar) = self.__trial_functions()
        (w, tau, wbar) = self.__test_functions()

        (zero_vec, h, duh0, duh00) = self.__check_geometric_dimension(h, duh0, duh00)

        beta_map = self.beta_map
        n = self.n
        facet_integral = self.facet_integral

        # Define v_star
        v_star = v0 + (1-theta_L) * duh00 + theta_L * duh0

        Udiv = v0 + duh0
        outer_v_a = outer(w, Udiv)
        outer_v_a_o = outer(v_star, Udiv)
        outer_ubar_a = outer(vbar, Ubar0)

        # Switch to detect in/outflow boundary
        gamma = conditional(ge(dot(Udiv, n), 0), 0, 1)

        # LHS contribution s
        N_a = dot(v, w) * dx + facet_integral(beta_map*dot(v, w))
        G_a = dot(lamb, w)/dt * dx - theta_map*inner(outer_v_a, grad(lamb))*dx \
            + theta_map * (1-gamma) * dot(outer_v_a * n,
                                          lamb) * self.ds(neumann_idx)

        L_a = -facet_integral(beta_map * dot(vbar, w))
        H_a = facet_integral(dot(outer_ubar_a*n, tau)) \
            - dot(outer_ubar_a*n, tau) * self.ds(neumann_idx)
        B_a = facet_integral(beta_map * dot(vbar, wbar))

        # RHS contributions
        Q_a = dot(v_int, w) * dx
        R_a = dot(v_star, tau)/dt * dx \
            + (1-theta_map)*inner(outer_v_a_o, grad(tau))*dx \
            - gamma * dot(h, tau) * self.ds(neumann_idx)
        S_a = facet_integral(dot(Constant(zero_vec), wbar))

        return self.__fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
Exemplo n.º 4
0
def test_is_zero_with_nabla():
    mesh = UnitSquareMesh(4, 4)
    V1 = FunctionSpace(mesh, 'CG', 1)
    V2 = VectorFunctionSpace(mesh, 'CG', 1)
    v1 = TestFunction(V1)
    v2 = TrialFunction(V2)
    n = Constant([1, 1])
    nn = dolfin.outer(n, n)
    vv = dolfin.outer(v2, v2)

    check_is_zero(dot(n, grad(v1)), 1)
    check_is_zero(dolfin.div(v2), 1)
    check_is_zero(dot(dolfin.div(nn), n), 0)
    check_is_zero(dot(dolfin.div(vv), n), 1)
    check_is_zero(dolfin.inner(nn, grad(v2)), 1)
    def blocks(self):
        aa, ff = super(FormulationMinimallyConstrained, self).blocks()

        n = df.FacetNormal(self.mesh)
        ds = df.Measure('ds', self.mesh)

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

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

        ff.append(0)

        return [aa, ff]
Exemplo n.º 6
0
    def __init__(self, parameters, domain):
        rho = Constant(parameters["density [kg/m3]"])
        mu = Constant(parameters["viscosity [Pa*s]"])
        dt = Constant(parameters["dt [s]"])
        u, u_1, u_k, vu = domain.u, domain.u_1, domain.u_k, domain.vu
        p_1 = domain.p_1

        n = FacetNormal(domain.mesh)
        acceleration = rho*inner((u-u_1)/dt, vu) * dx
        convection = dot(div(rho*outer(u_k, u)), vu) * dx
        convection = rho*dot(dot(u_k, nabla_grad(u)), vu) * dx
        pressure = (inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds)
        diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx)  # good
        # diffusion = (-inner(mu * (grad(u) + grad(u).T), grad(vu))*dx
        #               + dot(mu * (grad(u) + grad(u).T)*n, vu)*ds)  # very slow!

        # F_impl = acceleration + convection + pressure + diffusion

        # dot(u_1, nabla_grad(u_1)) works
        # dot(u, nabla_grad(u_1)) does not change!
        u_mid = (u + u_1) / 2.0
        F_impl = rho*dot((u - u_1) / dt, vu)*dx \
            + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \
            + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \
            + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds

        self.a, self.L = lhs(F_impl), rhs(F_impl)
        self.domain = domain
        self.A = assemble(self.a)
        [bc.apply(self.A) for bc in domain.bcu]
        return
Exemplo n.º 7
0
    def SecondPiolaStress(self, F, p=None, deviatoric=False):
        import dolfin
        from pulse import kinematics
        material = self.material
        I = kinematics.SecondOrderIdentity(F)

        f0 = material.f0
        f0f0 = dolfin.outer(f0, f0)

        I1 = dolfin.variable(material.active.I1(F))
        I4f = dolfin.variable(material.active.I4(F))

        Fe = material.active.Fe(F)
        Fa = material.active.Fa
        Ce = Fe.T * Fe

        # fe = Fe*f0
        # fefe = dolfin.outer(fe, fe)

        # Elastic volume ratio
        J = dolfin.variable(dolfin.det(Fe))
        # Active volume ration
        Ja = dolfin.det(Fa)

        dim = self.geometry.dim()
        Ce_bar = pow(J, -2.0 / float(dim)) * Ce

        w1 = material.W_1(I1, diff=1, dim=dim)
        w4f = material.W_4(I4f, diff=1)

        # Total Stress
        S_bar = Ja * (2 * w1 * I + 2 * w4f * f0f0) * dolfin.inv(Fa).T

        if material.is_isochoric:

            # Deviatoric
            Dev_S_bar = S_bar - (1.0 / 3.0) * dolfin.inner(
                S_bar, Ce_bar) * dolfin.inv(Ce_bar)

            S_mat = J**(-2.0 / 3.0) * Dev_S_bar
        else:
            S_mat = S_bar

        # Volumetric
        if p is None or deviatoric:
            S_vol = dolfin.zero((dim, dim))
        else:
            psi_vol = material.compressibility(p, J)
            S_vol = J * dolfin.diff(psi_vol, J) * dolfin.inv(Ce)

        # Active stress
        wactive = material.active.Wactive(F, diff=1)
        eta = material.active.eta

        S_active = wactive * (f0f0 + eta * (I - f0f0))

        S = S_mat + S_vol + S_active

        return S
Exemplo n.º 8
0
def setup_NS(w_NS, u, p, v, q, p0, q0,
             dx, ds, normal,
             dirichlet_bcs_NS, neumann_bcs, boundary_to_mark,
             u_1, rho_, rho_1, mu_, c_1, grad_g_c_,
             dt, grav,
             enable_EC,
             trial_functions,
             use_iterative_solvers,
             p_lagrange,
             mesh,
             q_rhs,
             density_per_concentration,
             K,
             **namespace):
    """ Set up the Navier-Stokes subproblem. """
    mom_1 = rho_1 * u_1
    if enable_EC and density_per_concentration is not None:
        for drhodci, ci_1, grad_g_ci_, Ki in zip(
                density_per_concentration, c_1, grad_g_c_, K):
            if drhodci > 0.:
                mom_1 += -drhodci*Ki*ci_1*grad_g_ci_

    F = (1./dt * rho_1 * df.dot(u - u_1, v) * dx
         + df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx
         + 2*mu_*df.inner(df.sym(df.nabla_grad(u)),
                          df.sym(df.nabla_grad(v))) * dx
         + 0.5*(
             1./dt * (rho_ - rho_1) * df.inner(u, v)
             - df.inner(mom_1, df.nabla_grad(df.dot(u, v)))) * dx
         - p * df.div(v) * dx
         - q * df.div(u) * dx
         - rho_ * df.dot(grav, v) * dx)

    for boundary_name, pressure in neumann_bcs["p"].iteritems():
        F += pressure * df.inner(
            normal, v) * ds(boundary_to_mark[boundary_name])

    if enable_EC:
        F += sum([ci_1*df.dot(grad_g_ci_, v)*dx
                  for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_)])

    if p_lagrange:
        F += (p*q0 + q*p0)*dx

    if "u" in q_rhs:
        F += -df.dot(q_rhs["u"], v)*dx

    a, L = df.lhs(F), df.rhs(F)
    if not use_iterative_solvers:
        problem = df.LinearVariationalProblem(a, L, w_NS, dirichlet_bcs_NS)
        solver = df.LinearVariationalSolver(problem)

    else:
        solver = df.LUSolver("mumps")
        # solver.set_operator(A)
        return solver, a, L, dirichlet_bcs_NS

    return solver
def setup_NSu(w_NSu, u, v, dx, ds, normal, dirichlet_bcs_NSu, neumann_bcs,
              boundary_to_mark, u_, p_, u_1, p_1, rho_, rho_1, mu_, c_1,
              grad_g_c_, dt, grav, enable_EC, trial_functions,
              use_iterative_solvers, mesh, density_per_concentration,
              viscosity_per_concentration, K, **namespace):
    """ Set up the Navier-Stokes velocity subproblem. """
    solvers = dict()

    mom_1 = rho_1 * u_1
    if enable_EC and density_per_concentration is not None:
        for drhodci, ci_1, grad_g_ci_, Ki in zip(density_per_concentration,
                                                 c_1, grad_g_c_, K):
            if drhodci > 0.:
                mom_1 += -drhodci * Ki * ci_1 * grad_g_ci_

    F_predict = (
        1. / dt * rho_1 * df.dot(u - u_1, v) * dx +
        df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2 * mu_ *
        df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx +
        0.5 * (1. / dt * (rho_ - rho_1) * df.dot(u, v) -
               df.inner(mom_1, df.grad(df.dot(u, v)))) * dx -
        p_1 * df.div(v) * dx - rho_ * df.dot(grav, v) * dx)

    for boundary_name, pressure in neumann_bcs["p"].iteritems():
        F_predict += pressure * df.inner(normal, v) * ds(
            boundary_to_mark[boundary_name])

    if enable_EC:
        F_predict += sum([
            ci_1 * df.dot(grad_g_ci_, v) * dx
            for ci_1, grad_g_ci_ in zip(c_1, grad_g_c_)
        ])

    a_predict, L_predict = df.lhs(F_predict), df.rhs(F_predict)
    #    if not use_iterative_solvers:
    problem_predict = df.LinearVariationalProblem(a_predict, L_predict, w_NSu,
                                                  dirichlet_bcs_NSu)
    solvers["predict"] = df.LinearVariationalSolver(problem_predict)
    if use_iterative_solvers:
        solvers["predict"].parameters["linear_solver"] = "bicgstab"
        solvers["predict"].parameters["preconditioner"] = "amg"

    F_correct = (rho_ * df.inner(u - u_, v) * dx - dt *
                 (p_ - p_1) * df.div(v) * dx)
    a_correct, L_correct = df.lhs(F_correct), df.rhs(F_correct)
    problem_correct = df.LinearVariationalProblem(a_correct, L_correct, w_NSu,
                                                  dirichlet_bcs_NSu)
    solvers["correct"] = df.LinearVariationalSolver(problem_correct)

    if use_iterative_solvers:
        solvers["correct"].parameters["linear_solver"] = "bicgstab"
        solvers["correct"].parameters["preconditioner"] = "amg"
    #else:
    #    solver = df.LUSolver("mumps")
    #    # solver.set_operator(A)
    #    return solver, a, L, dirichlet_bcs_NS

    return solvers
Exemplo n.º 10
0
    def forms_theta_nlinear_multiphase(self, rho, rho0, rho00, rhobar, v0, Ubar0, dt, theta_map,
                                       theta_L=Constant(1.0), duh0=Constant((0., 0.)),
                                       duh00=Constant((0., 0)),
                                       h=Constant((0., 0.)), neumann_idx=99):

        (v, lamb, vbar) = self.__trial_functions()
        (w, tau, wbar) = self.__test_functions()

        (zero_vec, h, duh0, duh00) = self.__check_geometric_dimension(h, duh0, duh00)

        beta_map = self.beta_map
        n = self.n
        facet_integral = self.facet_integral

        # FIXME: To be deprecated
        rhov_star = rho0*(v0 + theta_L * duh0) + rho00 * (1-theta_L) * duh00

        Udiv = v0 + duh0
        outer_v_a = outer(rho * w, Udiv)
        outer_v_a_o = outer(rho0 * Udiv, Udiv)
        outer_ubar_a = outer(rhobar * vbar, Ubar0)

        # Switch to detect in/outflow boundary
        gamma = conditional(ge(dot(Udiv, n), 0), 0, 1)

        # LHS contribution
        N_a = facet_integral(beta_map*dot(v, w))
        G_a = dot(lamb, rho * w)/dt * dx - theta_map*inner(outer_v_a, grad(lamb))*dx \
            + theta_map * (1-gamma) * dot(outer_v_a * n,
                                          lamb) * self.ds(neumann_idx)

        L_a = -facet_integral(beta_map * dot(vbar, w))
        H_a = facet_integral(dot(outer_ubar_a*n, tau)) \
            - dot(outer_ubar_a*n, tau) * self.ds(neumann_idx)
        B_a = facet_integral(beta_map * dot(vbar, wbar))

        # RHS contribution
        Q_a = dot(zero_vec, w) * dx
        R_a = dot(rhov_star, tau)/dt*dx  \
            + (1-theta_map)*inner(outer_v_a_o, grad(tau))*dx \
            + gamma * dot(h, tau) * self.ds(neumann_idx)
        S_a = facet_integral(dot(zero_vec, wbar))
        return self.__fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
Exemplo n.º 11
0
    def Fa(self):

        f0 = self.f0
        d = get_dimesion(f0)
        f0f0 = dolfin.outer(f0, f0)
        I = kinematics.SecondOrderIdentity(f0f0)

        mgamma = self._mgamma
        Fa = mgamma * f0f0 + pow(mgamma, -1.0 / float(d - 1)) * (I - f0f0)

        return Fa
Exemplo n.º 12
0
    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()
Exemplo n.º 13
0
    def Fa(self):

        if self.model == ActiveModels.active_stress:
            return dolfin.Identity(self.dim)

        f0 = self.f0
        f0f0 = dolfin.outer(f0, f0)
        Id = dolfin.Identity(self.dim)

        mgamma = 1 - self.activation_field
        Fa = mgamma * f0f0 + pow(mgamma,
                                 -1.0 / float(self.dim - 1)) * (Id - f0f0)

        return Fa
Exemplo n.º 14
0
    def projectAGG(self,
                   a=Constant(0.0),
                   g=Constant(0.0),
                   gamma=Constant([0, 0, 1])):
        """ Calculate and project growth function from given :math:`a`, :math:`g` and :math:`\gamma` values
		"""
        self.a.project(a)
        self.g.project(g)
        self.gamma.project(gamma / sqrt(inner(gamma, gamma)))

        g0 = g * (1 - a)
        g1 = g * (1 + 2 * a)

        self.project(Identity(3) * g0 + (g1 - g0) * outer(gamma, gamma))
Exemplo n.º 15
0
    def set_model(self):

        measures = [self.dx, self.ds, self.dS]
        # import pdb; pdb.set_trace()
        if self.parameters['material']['p'] == 'zero':
            from plate_lib import ActuationOverNematicFoundation
            actuation = ActuationOverNematicFoundation(self.z, self.mesh,
                                                       self.parameters,
                                                       measures)
        elif self.parameters['material']['p'] == 'neg':
            from plate_lib import ActuationOverNematicFoundationPneg
            actuation = ActuationOverNematicFoundationPneg(
                self.z, self.mesh, self.parameters, measures)
        else:
            raise NotImplementedError

        x = Expression(['x[0]', 'x[1]', '0.'], degree=0)
        self.load = Expression('s', s=1., degree=0)

        e1 = Constant([1, 0, 0])
        e3 = Constant([0, 0, 1])

        # self.n = Expression('sin(theta)*_e1 + cos(theta)*_e3',
        # _e1 = e1, _e3 = e3, theta = 0., degree = 0)

        self.n = Expression(['sin(theta)', 0, 'cos(theta)'], theta=0, degree=0)
        # import pdb; pdb.set_trace()
        # print('Nematic: {}'.format(self.parameters["material"]["nematic"]))
        if self.parameters["material"]["nematic"] == 'e1':
            n = e1
        elif self.parameters["material"]["nematic"] == 'e3':
            n = e3
        elif self.parameters["material"]["nematic"] == 'tilt':
            n = (e1 - e3) / np.sqrt(2)
        else:
            raise NotImplementedError

        Qn = outer(self.n, self.n) - 1. / 3. * Identity(3)

        actuation.Q0n = self.load * Qn
        self.Q0 = actuation.Q0n
        actuation.define_variational_equation()

        self.F = actuation.F
        self.J = actuation.jacobian
        self.energy_mem = actuation.energy_mem
        self.energy_ben = actuation.energy_ben
        self.energy_nem = actuation.energy_nem
        self.work = actuation.work
Exemplo n.º 16
0
def setup_NSu(u, v, u_, p_, bcs_NSu, u_1, p_1, phi_, rho_, rho_1, g_, M_, nu_,
              rho_e_, V_, dt, drho, sigma_bar, eps, dveps, grav, enable_PF,
              enable_EC):
    """ Set up the Navier-Stokes subproblem. """
    # Crank-Nicolson velocity
    # u_CN = 0.5*(u_1 + u)

    F_predict = (
        1. / dt * df.sqrt(rho_) *
        df.dot(df.sqrt(rho_) * u - df.sqrt(rho_1) * u_1, v) * df.dx
        # + rho_*df.inner(df.grad(u), df.outer(u_1, v))*df.dx
        # + 2*nu_*df.inner(df.sym(df.grad(u)), df.grad(v))*df.dx
        # - p_1 * df.div(v)*df.dx
        # + df.div(u)*q*df.dx
        + rho_ * df.dot(df.dot(u_1, df.nabla_grad(u)), v) * df.dx +
        2 * nu_ * df.inner(df.sym(df.grad(u)), df.sym(df.grad(v))) * df.dx -
        p_1 * df.div(v) * df.dx - df.dot(rho_ * grav, v) * df.dx)

    phi_filtered = unit_interval_filter(phi_)
    if enable_PF:
        F_predict += -drho * M_ * df.dot(
            df.dot(df.nabla_grad(g_), df.nabla_grad(u)), v) * df.dx
        F_predict += -sigma_bar * eps * df.inner(
            df.outer(df.grad(phi_filtered), df.grad(phi_filtered)),
            df.grad(v)) * df.dx
    if enable_EC and rho_e_ != 0:
        F_predict += rho_e_ * df.dot(df.grad(V_), v) * df.dx
    if enable_PF and enable_EC:
        F_predict += dveps * df.dot(df.grad(phi_filtered), v) * df.dot(
            df.grad(V_), df.grad(V_)) * df.dx

    # a1, L1 = df.lhs(F_predict), df.rhs(F_predict)

    F_correct = (df.inner(u - u_, v) * df.dx +
                 dt / rho_ * df.inner(df.grad(p_ - p_1), v) * df.dx)
    # a3 = df.dot(u, v)*df.dx
    # L3 = df.dot(u_, v)*df.dx - dt*df.dot(df.grad(p_), v)*df.dx
    # a3, L3 = df.lhs(F_correct), df.rhs(F_correct)

    solver = dict()
    # solver["a1"] = a1
    # solver["L1"] = L1
    solver["Fu"] = F_predict
    solver["Fu_corr"] = F_correct
    # solver["a3"] = a3
    # solver["L3"] = L3
    solver["bcs"] = bcs_NSu
    return solver
Exemplo n.º 17
0
    def __init__(self, parameters, domain):
        rho = Constant(parameters["density [kg/m3]"])
        mu = Constant(parameters["viscosity [Pa*s]"])
        dt = Constant(parameters["dt [s]"])
        u, u_1, p_1, vu = domain.u, domain.u_1, domain.p_1, domain.vu

        n = FacetNormal(domain.mesh)
        acceleration = rho*inner((u-u_1)/dt, vu) * dx
        convection = dot(div(rho*outer(u_1, u)), vu) * dx
        diffusion = (-inner(mu * (grad(u_1) + grad(u_1).T), grad(vu))*dx
                     + dot(mu * (grad(u_1) + grad(u_1).T)*n, vu)*ds)
        pressure = inner(p_1, div(vu))*dx - dot(p_1*n, vu)*ds  # int. by parts
        # TODO: what is better?
        # convection = rho*dot(dot(u_1, nabla_grad(u_k)), vu) * dx
        # diffusion = (mu*inner(grad(u_1), grad(vu))*dx
        #              - mu*dot(nabla_grad(u_1)*n, vu)*ds)  # int. by parts
        F_impl = - acceleration - convection + diffusion + pressure
        self.a, self.L = lhs(F_impl), rhs(F_impl)
        self.domain = domain
        self.A = assemble(self.a)
        [bc.apply(self.A) for bc in domain.bcu]
        return
Exemplo n.º 18
0
    def forms_theta_nlinear_multiphase(
        self,
        rho,
        rho0,
        rho00,
        rhobar,
        v0,
        Ubar0,
        dt,
        theta_map,
        theta_L=Constant(1.0),
        duh0=Constant((0.0, 0.0)),
        duh00=Constant((0.0, 0)),
        h=Constant((0.0, 0.0)),
        neumann_idx=99,
    ):
        """
        Set PDEMap forms for a non-linear (but linearized) advection problem
        including density.

        Parameters
        ----------
        rho: dolfin.Function
            Current density field
        rho0: dolfin.Function
            Density field at previous time step.
        rho00: dolfin.Function
            Density field at second last time step
        rhobar: dolfin.Function
            Density field at facets
        v0: dolfin.Function
            Specific momentum at old time level
        Ubar0: dolfin.Function
            Advective field at old time level
        dt: Constant
            Time step
        theta_map: Constant
            Theta value for time stepping in PDE-projection according to
            theta-method
            **NOTE** theta only affects solution for Lagrange multiplier
            space polynomial order >= 1
        theta_L: Constant, optional
            Theta value for reconstructing intermediate field from
            the previous solution and old increments.
        duh0: dolfin.Function, optional
            Increment from previous time step.
        duh00: dolfin.Function, optional
            Increment from second last time step
        h: Constant, dolfin.Function, optional
            Expression or Function for non-homogenous Neumann BC.
            Defaults to Constant(0.
        neumann_idx: int, optional
            Integer to use for marking Neumann boundaries.
            Defaults to value 99

        Returns
        -------
        dict
            Dict with forms
        """
        (v, lamb, vbar) = self._trial_functions()
        (w, tau, wbar) = self._test_functions()

        (zero_vec, h, duh0, duh00) = self._check_geometric_dimension(h, duh0, duh00)

        beta_map = self.beta_map
        n = self.n
        facet_integral = self.facet_integral

        # FIXME: To be deprecated
        rhov_star = rho0 * (v0 + theta_L * duh0) + rho00 * (1 - theta_L) * duh00

        Udiv = v0 + duh0
        outer_v_a = outer(rho * w, Udiv)
        outer_v_a_o = outer(rho0 * Udiv, Udiv)
        outer_ubar_a = outer(rhobar * vbar, Ubar0)

        # Switch to detect in/outflow boundary
        gamma = conditional(ge(dot(Udiv, n), 0), 0, 1)

        # LHS contribution
        N_a = facet_integral(beta_map * dot(v, w))
        G_a = (
            dot(lamb, rho * w) / dt * dx
            - theta_map * inner(outer_v_a, grad(lamb)) * dx
            + theta_map * (1 - gamma) * dot(outer_v_a * n, lamb) * self.ds(neumann_idx)
        )

        L_a = -facet_integral(beta_map * dot(vbar, w))
        H_a = facet_integral(dot(outer_ubar_a * n, tau)) - dot(outer_ubar_a * n, tau) * self.ds(
            neumann_idx
        )
        B_a = facet_integral(beta_map * dot(vbar, wbar))

        # RHS contribution
        Q_a = dot(zero_vec, w) * dx
        R_a = (
            dot(rhov_star, tau) / dt * dx
            + (1 - theta_map) * inner(outer_v_a_o, grad(tau)) * dx
            + gamma * dot(h, tau) * self.ds(neumann_idx)
        )
        S_a = facet_integral(dot(zero_vec, wbar))
        return self._fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
Exemplo n.º 19
0
    def forms_theta_nlinear_np(
        self,
        v0,
        v_int,
        Ubar0,
        dt,
        theta_map=Constant(1.0),
        theta_L=Constant(1.0),
        duh0=Constant((0.0, 0.0)),
        duh00=Constant((0.0, 0)),
        h=Constant((0.0, 0.0)),
        neumann_idx=99,
    ):
        """
        Set PDEMap forms for a non-linear (but linearized) advection problem,
        assumes however that the mass matrix can be obtained from the mesh
        (and not from particles)

        **NOTE** Documentation upcoming.
        """

        # Define trial test functions
        (v, lamb, vbar) = self._trial_functions()
        (w, tau, wbar) = self._test_functions()

        (zero_vec, h, duh0, duh00) = self._check_geometric_dimension(h, duh0, duh00)

        beta_map = self.beta_map
        n = self.n
        facet_integral = self.facet_integral

        # Define v_star
        v_star = v0 + (1 - theta_L) * duh00 + theta_L * duh0

        Udiv = v0 + duh0
        outer_v_a = outer(w, Udiv)
        outer_v_a_o = outer(v_star, Udiv)
        outer_ubar_a = outer(vbar, Ubar0)

        # Switch to detect in/outflow boundary
        gamma = conditional(ge(dot(Udiv, n), 0), 0, 1)

        # LHS contribution s
        N_a = dot(v, w) * dx + facet_integral(beta_map * dot(v, w))
        G_a = (
            dot(lamb, w) / dt * dx
            - theta_map * inner(outer_v_a, grad(lamb)) * dx
            + theta_map * (1 - gamma) * dot(outer_v_a * n, lamb) * self.ds(neumann_idx)
        )

        L_a = -facet_integral(beta_map * dot(vbar, w))
        H_a = facet_integral(dot(outer_ubar_a * n, tau)) - dot(outer_ubar_a * n, tau) * self.ds(
            neumann_idx
        )
        B_a = facet_integral(beta_map * dot(vbar, wbar))

        # RHS contributions
        Q_a = dot(v_int, w) * dx
        R_a = (
            dot(v_star, tau) / dt * dx
            + (1 - theta_map) * inner(outer_v_a_o, grad(tau)) * dx
            - gamma * dot(h, tau) * self.ds(neumann_idx)
        )
        S_a = facet_integral(dot(Constant(zero_vec), wbar))

        return self._fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
Exemplo n.º 20
0
    def forms_theta_nlinear(
        self,
        v0,
        Ubar0,
        dt,
        theta_map=Constant(1.0),
        theta_L=Constant(1.0),
        duh0=Constant((0.0, 0.0)),
        duh00=Constant((0.0, 0)),
        h=Constant((0.0, 0.0)),
        neumann_idx=99,
    ):
        """
        Set PDEMap forms for a non-linear (but linearized) advection problem,

        Parameters
        ----------
        v0: dolfin.Function
            dolfin.Function storing solution from previous step
        Ubar0: dolfin.Function
            Advective velocity at facets
        dt: Constant
            Time step
        theta_map: Constant, optional
            Theta value for time stepping in PDE-projection according to
            theta-method. Defaults to Constant(1.)
            **NOTE** theta only affects solution for Lagrange multiplier
            space polynomial order >= 1
        theta_L: Constant, optional
            Theta value for reconstructing intermediate field from
            the previous solution and old increments. Defaults to Constant(1.)
        duh0: dolfin.Function, optional
            Increment function from last time step
        duh00: dolfin.Function, optional
            Increment function from second last time step
        h: Constant, dolfin.Function, optional
            Expression or Function for non-homogenous Neumann BC.
            Defaults to Constant(0.)
        neumann_idx: int, optional
            Integer to use for marking Neumann boundaries.
            Defaults to value 99
        Returns
        -------
        dict
            Dictionary with forms
        """

        # Define trial test functions
        (v, lamb, vbar) = self._trial_functions()
        (w, tau, wbar) = self._test_functions()

        (zero_vec, h, duh0, duh00) = self._check_geometric_dimension(h, duh0, duh00)

        beta_map = self.beta_map
        n = self.n
        facet_integral = self.facet_integral

        # Define v_star
        v_star = v0 + (1 - theta_L) * duh00 + theta_L * duh0

        Udiv = v0 + duh0
        outer_v_a = outer(w, Udiv)
        outer_v_a_o = outer(v_star, Udiv)
        outer_ubar_a = outer(vbar, Ubar0)

        # Switch to detect in/outflow boundary
        gamma = conditional(ge(dot(Udiv, n), 0), 0, 1)

        # LHS contribution s
        N_a = facet_integral(beta_map * dot(v, w))
        G_a = (
            dot(lamb, w) / dt * dx
            - theta_map * inner(outer_v_a, grad(lamb)) * dx
            + theta_map * (1 - gamma) * dot(outer_v_a * n, lamb) * self.ds(neumann_idx)
        )

        L_a = -facet_integral(beta_map * dot(vbar, w))
        H_a = facet_integral(dot(outer_ubar_a * n, tau)) - dot(outer_ubar_a * n, tau) * self.ds(
            neumann_idx
        )
        B_a = facet_integral(beta_map * dot(vbar, wbar))

        # RHS contributions
        Q_a = dot(zero_vec, w) * dx
        R_a = (
            dot(v_star, tau) / dt * dx
            + (1 - theta_map) * inner(outer_v_a_o, grad(tau)) * dx
            - gamma * dot(h, tau) * self.ds(neumann_idx)
        )
        S_a = facet_integral(dot(zero_vec, wbar))

        return self._fem_forms(N_a, G_a, L_a, H_a, B_a, Q_a, R_a, S_a)
Exemplo n.º 21
0
def NSPFEC_action(u_, u_1, phi_, phi_1, c_, c_1, u, p, phi, g, c, V, v, q, psi,
                  h, b, U, rho, M, nu, rho_e, K, veps, drho, grav, sigma_bar,
                  eps, dveps, dbeta, z, per_tau, enable_NS, enable_PF,
                  enable_EC):
    # The setup of the Navier-Stokes part of F
    F = []
    if enable_NS:
        F_NS = (per_tau * rho * df.dot(u_ - u_1, v) * df.dx + df.inner(
            df.grad(u), df.outer(rho * u - drho * M * df.grad(g), v)) * df.dx +
                2 * nu * df.inner(df.sym(df.grad(u)), df.grad(v)) * df.dx -
                p * df.div(v) * df.dx + df.div(u) * q * df.dx -
                df.dot(rho * grav, v) * df.dx)
        if enable_PF:
            F_NS += -sigma_bar * eps * df.inner(
                df.outer(df.grad(phi), df.grad(phi)), df.grad(v)) * df.dx
        if enable_EC and rho_e != 0:
            F_NS += rho_e * df.dot(df.grad(V), v) * df.dx
        if enable_PF and enable_EC:
            F_NS += dveps * df.dot(df.grad(phi), v) * df.dot(
                df.grad(V), df.grad(V)) * df.dx
        F.append(F_NS)

    # The setup of the Phase feild equations
    if enable_PF:
        F_PF_phi = (per_tau * (phi_ - phi_1) * psi * df.dx +
                    M * df.dot(df.grad(g), df.grad(psi)) * df.dx)
        if enable_NS:
            F_PF_phi += df.dot(u, df.grad(phi)) * psi * df.dx

        F_PF_g = (g * h * df.dx -
                  sigma_bar * eps * df.dot(df.grad(phi), df.grad(h)) * df.dx -
                  sigma_bar / eps * diff_pf_potential(phi) * h * df.dx)
        if enable_EC:
            F_PF_g += (-sum(
                [dbeta_i * ci * h * df.dx for dbeta_i, ci in zip(dbeta, c)]) +
                       dveps * df.dot(df.grad(V), df.grad(V)) * h * df.dx)
        F_PF = F_PF_phi + F_PF_g
        F.append(F_PF)

    # The setup of the Electrochemistry
    if enable_EC:
        F_E_c = []
        for ci, ci_, ci_1, bi, Ki, zi in zip(c, c_, c_1, b, K, z):
            F_E_ci = (per_tau * (ci_ - ci_1) * bi * df.dx +
                      Ki * df.dot(df.grad(ci), df.grad(bi)) * df.dx)
            if zi != 0:
                F_E_ci += Ki * zi * ci * df.dot(df.grad(V),
                                                df.grad(bi)) * df.dx
            if enable_NS:
                F_E_ci += df.dot(u, df.grad(ci)) * bi * df.dx
            F_E_c.append(F_E_ci)
        F_E_V = veps * df.dot(df.grad(V), df.grad(U)) * df.dx
        if rho_e != 0:
            F_E_V += -rho_e * U * df.dx
        F_E = sum(F_E_c) + F_E_V
        F.append(F_E)

    F = sum(F)
    J = df.derivative(F, w_NSPFEC)

    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
Exemplo n.º 22
0
    def define_coupled_equation(self):
        """
        Setup the coupled Navier-Stokes equation

        This implementation assembles the full LHS and RHS each time they are needed
        """
        sim = self.simulation
        mpm = sim.multi_phase_model
        mesh = sim.data['mesh']
        Vcoupled = sim.data['Vcoupled']
        u_conv = sim.data['u_conv']

        # Unpack the coupled trial and test functions
        uc = dolfin.TrialFunction(Vcoupled)
        vc = dolfin.TestFunction(Vcoupled)
        ulist = []
        vlist = []
        sigmas, taus = [], []
        for d in range(sim.ndim):
            ulist.append(uc[d])
            vlist.append(vc[d])
            indices = list(
                range(1 + sim.ndim * (d + 1), 1 + sim.ndim * (d + 2)))
            sigmas.append([uc[i] for i in indices])
            taus.append([vc[i] for i in indices])

        u = dolfin.as_vector(ulist)
        v = dolfin.as_vector(vlist)
        p = uc[sim.ndim]
        q = vc[sim.ndim]
        sigma = dolfin.as_tensor(sigmas)
        tau = dolfin.as_tensor(taus)

        c1, c2, c3 = sim.data['time_coeffs']
        dt = sim.data['dt']
        g = sim.data['g']
        n = dolfin.FacetNormal(mesh)
        h = dolfin.FacetArea(mesh)

        # Fluid properties
        rho = mpm.get_density(0)
        mu = mpm.get_laminar_dynamic_viscosity(0)

        # Upwind and downwind velocities
        w_nU = (dot(u_conv, n) + abs(dot(u_conv, n))) / 2.0
        w_nD = (dot(u_conv, n) - abs(dot(u_conv, n))) / 2.0
        u_uw_s = dolfin.conditional(dolfin.gt(dot(u_conv, n), 0.0), 1.0,
                                    0.0)('+')
        u_uw = u_uw_s * u('+') + (1 - u_uw_s) * u('-')

        # LDG penalties
        # kappa_0 = Constant(4.0)
        # kappa = mu*kappa_0/h
        C11 = avg(mu / h)
        D11 = avg(h / mu)
        C12 = 0.2 * n('+')
        D12 = 0.2 * n('+')

        def ojump(v, n):
            return outer(v, n)('+') + outer(v, n)('-')

        # Interior facet fluxes
        # u_hat_dS = avg(u)
        # sigma_hat_dS = avg(sigma) - avg(kappa)*ojump(u, n)
        # p_hat_dS = avg(p)
        u_hat_s_dS = avg(u) + dot(ojump(u, n), C12)
        u_hat_p_dS = avg(u) + D11 * jump(p, n) + D12 * jump(u, n)
        sigma_hat_dS = avg(sigma) - C11 * ojump(u, n) - outer(
            jump(sigma, n), C12)
        p_hat_dS = avg(p) - dot(D12, jump(p, n))

        # Time derivative
        up = sim.data['up']
        upp = sim.data['upp']
        eq = rho * dot(c1 * u + c2 * up + c3 * upp, v) / dt * dx

        # LDG equation 1
        eq += inner(sigma, tau) * dx
        eq += dot(u, div(mu * tau)) * dx
        eq -= dot(u_hat_s_dS, jump(mu * tau, n)) * dS

        # LDG equation 2
        eq += (inner(sigma, grad(v)) - p * div(v)) * dx
        eq -= (inner(sigma_hat_dS, ojump(v, n)) - p_hat_dS * jump(v, n)) * dS
        eq -= dot(u, div(outer(v, rho * u_conv))) * dx
        eq += rho('+') * dot(u_conv('+'), n('+')) * dot(u_uw, v('+')) * dS
        eq += rho('-') * dot(u_conv('-'), n('-')) * dot(u_uw, v('-')) * dS
        momentum_sources = sim.data['momentum_sources'] + [rho * g]
        eq -= dot(sum(momentum_sources), v) * dx

        # LDG equation 3
        eq -= dot(u, grad(q)) * dx
        eq += dot(u_hat_p_dS, jump(q, n)) * dS

        # Dirichlet boundary
        dirichlet_bcs = get_collected_velocity_bcs(sim, 'dirichlet_bcs')
        for ds, u_bc in dirichlet_bcs.items():
            # sigma_hat_ds = sigma - kappa*outer(u, n)
            sigma_hat_ds = sigma - C11 * outer(u - u_bc, n)
            u_hat_ds = u_bc
            p_hat_ds = p

            # LDG equation 1
            eq -= dot(u_hat_ds, dot(mu * tau, n)) * ds

            # LDG equation 2
            eq -= (inner(sigma_hat_ds, outer(v, n)) -
                   p_hat_ds * dot(v, n)) * ds
            eq += rho * w_nU * dot(u, v) * ds
            eq += rho * w_nD * dot(u_bc, v) * ds

            # LDG equation 3
            eq += dot(u_hat_ds, q * n) * ds

        # Neumann boundary
        neumann_bcs = get_collected_velocity_bcs(sim, 'neumann_bcs')
        assert not neumann_bcs
        for ds, du_bc in neumann_bcs.items():
            # Divergence free criterion
            if self.use_grad_q_form:
                eq += q * dot(u, n) * ds
            else:
                eq -= q * dot(u, n) * ds

            # Convection
            eq += rho * w_nU * dot(u, v) * ds

            # Diffusion
            u_hat_ds = u
            sigma_hat_ds = outer(du_bc, n) / mu
            eq -= dot(u_hat_ds, dot(mu * tau, n)) * ds
            eq -= inner(sigma_hat_ds, outer(v, n)) * ds

            # Pressure
            if not self.use_grad_p_form:
                eq += p * dot(v, n) * ds

        a, L = dolfin.system(eq)
        self.form_lhs = a
        self.form_rhs = L
        self.tensor_lhs = None
        self.tensor_rhs = None
Exemplo n.º 23
0
def solve_initial_pressure(w_NSp,
                           p,
                           q,
                           u,
                           v,
                           dx,
                           ds,
                           dirichlet_bcs_NSp,
                           neumann_bcs,
                           boundary_to_mark,
                           M_,
                           g_,
                           phi_,
                           rho_,
                           rho_e_,
                           V_,
                           drho,
                           sigma_bar,
                           eps,
                           grav,
                           dveps,
                           enable_PF,
                           enable_EC,
                           use_iterative_solvers,
                           solve_initial=True):
    if solve_initial:
        V = u.function_space()
        grad_p = df.TrialFunction(V)
        grad_p_out = df.Function(V)
        F_grad_p = (df.dot(grad_p, v) * dx - rho_ * df.dot(grav, v) * dx)
        if enable_PF:
            F_grad_p += -drho * M_ * df.inner(df.grad(u),
                                              df.outer(df.grad(g_), v)) * dx
            F_grad_p += -sigma_bar * eps * df.inner(
                df.outer(df.grad(phi_), df.grad(phi_)), df.grad(v)) * dx
        if enable_EC and rho_e_ != 0:
            F_grad_p += rho_e_ * df.dot(df.grad(V_), v) * dx
        if enable_PF and enable_EC:
            F_grad_p += 0.5 * dveps * df.dot(df.grad(phi_), v) * df.dot(
                df.grad(V_), df.grad(V_)) * dx

        info_red("Solving initial grad_p...")
        problem_grad_p = df.LinearVariationalProblem(df.lhs(F_grad_p),
                                                     df.rhs(F_grad_p),
                                                     grad_p_out)
        # df.solve(df.lhs(F_grad_p) == df.rhs(F_grad_p), grad_p_out)
        solver_grad_p = df.LinearVariationalSolver(problem_grad_p)
        if use_iterative_solvers:
            solver_grad_p.parameters["linear_solver"] = "gmres"
            solver_grad_p.parameters["preconditioner"] = "amg"
        solver_grad_p.solve()

        F_p = (df.dot(df.grad(q), df.grad(p)) * dx -
               df.dot(df.grad(q), grad_p_out) * dx)
        info_red("Solving initial p...")
        problem_p = df.LinearVariationalProblem(df.lhs(F_p), df.rhs(F_p),
                                                w_NSp, dirichlet_bcs_NSp)
        # df.solve(df.lhs(F_p) == df.rhs(F_p), w_NSp, dirichlet_bcs_NSp)
        solver_p = df.LinearVariationalSolver(problem_p)
        if use_iterative_solvers:
            solver_p.parameters["linear_solver"] = "gmres"
            solver_p.parameters["preconditioner"] = "amg"
        solver_p.solve()

    info_red("Done with the initials.")
Exemplo n.º 24
0
def setup_NS(w_NS, u, p, v, q, p0, q0, dx, ds, normal, dirichlet_bcs,
             neumann_bcs, boundary_to_mark, u_1, phi_, rho_, rho_1, g_, M_,
             mu_, rho_e_, c_, V_, c_1, V_1, dbeta, solutes, per_tau, drho,
             sigma_bar, eps, dveps, grav, fric, u_comoving, enable_PF,
             enable_EC, use_iterative_solvers, use_pressure_stabilization,
             p_lagrange, q_rhs):
    """ Set up the Navier-Stokes subproblem. """
    # F = (
    #     per_tau * rho_ * df.dot(u - u_1, v)*dx
    #     + rho_*df.inner(df.grad(u), df.outer(u_1, v))*dx
    #     + 2*mu_*df.inner(df.sym(df.grad(u)), df.grad(v))*dx
    #     - p * df.div(v)*dx
    #     + df.div(u)*q*dx
    #     - df.dot(rho_*grav, v)*dx
    # )
    mom_1 = rho_1 * (u_1 + u_comoving)
    if enable_PF:
        mom_1 += -M_ * drho * df.nabla_grad(g_)

    F = (per_tau * rho_1 * df.dot(u - u_1, v) * dx +
         fric * mu_ * df.dot(u + u_comoving, v) * dx + 2 * mu_ *
         df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx -
         p * df.div(v) * dx + q * df.div(u) * dx +
         df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 0.5 *
         (per_tau * (rho_ - rho_1) * df.dot(u, v) -
          df.dot(mom_1, df.nabla_grad(df.dot(u, v)))) * dx -
         rho_ * df.dot(grav, v) * dx -
         mu_ * df.dot(df.nabla_grad(u) * normal, v) * df.ds)
    for boundary_name, slip_length in neumann_bcs["u"].items():
        F += 1./slip_length * \
             df.dot(u, v) * ds(boundary_to_mark[boundary_name])

    for boundary_name, pressure in neumann_bcs["p"].items():
        F += pressure * df.dot(normal, v) * ds(boundary_to_mark[boundary_name])
    #          - 2*mu_*df.dot(df.dot(df.sym(df.nabla_grad(u)), v),
    #                         normal)) * ds(boundary_to_mark[boundary_name])

    if enable_PF:
        F += phi_ * df.dot(df.nabla_grad(g_), v) * dx

    if enable_EC:
        for ci_, ci_1, dbetai, solute in zip(c_, c_1, dbeta, solutes):
            zi = solute[1]
            F += df.dot(df.grad(ci_), v)*dx \
                + zi*ci_1*df.dot(df.grad(V_), v)*dx
            if enable_PF:
                F += ci_ * dbetai * df.dot(df.grad(phi_), v) * dx

    if p_lagrange:
        F += (p * q0 + q * p0) * dx

    if "u" in q_rhs:
        F += -df.dot(q_rhs["u"], v) * dx

    a, L = df.lhs(F), df.rhs(F)

    problem = df.LinearVariationalProblem(a, L, w_NS, dirichlet_bcs)
    solver = df.LinearVariationalSolver(problem)

    if use_iterative_solvers and use_pressure_stabilization:
        solver.parameters["linear_solver"] = "gmres"
        #solver.parameters["preconditioner"] = "jacobi"
        #solver.parameters["preconditioner"] = "ilu"

    return solver
    #
    total_mass = assemble(rho * dx)
    mass_change_noflux = assemble((rho - rho0) * dx)
    mass_change_flux = assemble((rho - rho0) * dx +
                                dt * dot(ubar0_a, n) * rhobar * ds(98))

    mx_change_noflux = assemble(
        (rho * dot(ustar, ex) - dot(rho0 * Uh.sub(0), ex)) * dx)
    my_change_noflux = assemble(
        (rho * dot(ustar, ey) - dot(rho0 * Uh.sub(0), ey)) * dx)
    mt_change_noflux = mx_change_noflux + my_change_noflux

    # Check (global) momentum conservation
    mx_change = assemble(
        (rho * dot(ustar, ex) - dot(rho0 * Uh.sub(0), ex)) * dx +
        dt * dot(outer(rhobar * ustar_bar, ubar0_a) * n, ex) * ds)
    my_change = assemble(
        (rho * dot(ustar, ey) - dot(rho0 * Uh.sub(0), ey)) * dx +
        dt * dot(outer(rhobar * ustar_bar, ubar0_a) * n, ey) * ds)
    mt_change = mx_change + my_change

    # Compute Rho_min and Rho_max
    rho_proc_0 = rho.vector().gather_on_zero()

    if comm.rank == 0:
        rho_min = np.amin(rho_proc_0)
        rho_max = np.amax(rho_proc_0)

        with open(conservation_data, "a") as write_file:
            data = [
                t, total_mass, mass_change_flux, mass_change_noflux, mt_change,
Exemplo n.º 26
0
    def __ufl_forms(self, nu, f):
        (w, q, wbar, qbar) = self.__test_functions()
        (u, p, ubar, pbar) = self.__trial_functions()

        # Infer geometric dimension
        zero_vec = np.zeros(self.gdim)

        ds = self.ds
        n = self.n
        he = self.he
        alpha = self.alpha
        h_d = self.h_d
        beta_stab = self.beta_stab
        facet_integral = self.facet_integral

        pI = p * Identity(
            self.mixedL.sub(1).ufl_cell().topological_dimension())
        pbI = pbar * \
            Identity(self.mixedL.sub(1).ufl_cell().topological_dimension())

        # Upper left block
        # Contribution comes from local momentum balance
        AB = inner(2*nu*sym(grad(u)), grad(w))*dx \
            + facet_integral(dot(-2*nu*sym(grad(u))*n
                                 + (2*nu*alpha/he)*u, w)) \
            + facet_integral(dot(-2*nu*u, sym(grad(w))*n)) \
            - inner(pI, grad(w))*dx
        # Contribution comes from local mass balance
        BtF = -dot(q, div(u))*dx - \
            facet_integral(beta_stab*he/(nu+1)*dot(p, q))
        A_S = AB + BtF

        # Upper right block
        # Contribution from local momentum
        CD = facet_integral(-alpha/he*2*nu*inner(ubar, w)) \
            + facet_integral(2*nu*inner(ubar, sym(grad(w))*n)) \
            + facet_integral(dot(pbI*n, w))
        H = facet_integral(beta_stab * he / (nu + 1) * dot(pbar, q))
        G_S = CD + H

        # Transpose block
        CDT = facet_integral(- alpha/he*2*nu*inner(wbar, u)) \
            + facet_integral(2*nu*inner(wbar, sym(grad(u))*n)) \
            + facet_integral(qbar * dot(u, n))
        HT = facet_integral(beta_stab * he / (nu + 1) * dot(p, qbar))
        G_ST = CDT + HT

        # Lower right block, penalty on ds(98) approximates free-slip
        KL = facet_integral(alpha/he * 2 * nu*dot(ubar, wbar)) \
            - facet_integral(dot(pbar*n, wbar)) \
            + Constant(1E12)/he * inner(outer(ubar, wbar), outer(n, n)) * ds(98)
        LtP = - facet_integral(dot(ubar, n)*qbar) \
            - facet_integral(beta_stab*he/(nu+1) * pbar * qbar)
        B_S = KL + LtP

        # Righthandside
        Q_S = dot(f, w) * dx
        S_S = facet_integral(dot(Constant(zero_vec), wbar))
        S_S += dot(h_d[0], wbar) * ds(99) + dot(h_d[1], wbar) * ds(
            100)  #Neumann BC
        return {
            'A_S': A_S,
            'G_S': G_S,
            'G_ST': G_ST,
            'B_S': B_S,
            'Q_S': Q_S,
            'S_S': S_S
        }
Exemplo n.º 27
0
    def ufl_forms(self, nu, f):
        (w, q, wbar, qbar) = self.test_functions()
        (u, p, ubar, pbar) = self.trial_functions()

        # Infer geometric dimension
        zero_vec = np.zeros(self.gdim)

        ds = self.ds
        n = self.n
        he = self.he
        alpha = self.alpha
        beta_stab = self.beta_stab
        facet_integral = self.facet_integral

        pI = p * Identity(self.mixedL.sub(1).ufl_cell().topological_dimension())
        pbI = pbar * Identity(self.mixedL.sub(1).ufl_cell().topological_dimension())

        # Upper left block
        # Contribution comes from local momentum balance
        AB = (
            inner(2 * nu * sym(grad(u)), grad(w)) * dx
            + facet_integral(dot(-2 * nu * sym(grad(u)) * n + (2 * nu * alpha / he) * u, w))
            + facet_integral(dot(-2 * nu * u, sym(grad(w)) * n))
            - inner(pI, grad(w)) * dx
        )
        # Contribution comes from local mass balance
        BtF = -dot(q, div(u)) * dx - facet_integral(beta_stab * he / (nu + 1) * dot(p, q))
        A_S = AB + BtF

        # Upper right block
        # Contribution from local momentum
        CD = (
            facet_integral(-alpha / he * 2 * nu * inner(ubar, w))
            + facet_integral(2 * nu * inner(ubar, sym(grad(w)) * n))
            + facet_integral(dot(pbI * n, w))
        )
        H = facet_integral(beta_stab * he / (nu + 1) * dot(pbar, q))
        G_S = CD + H

        # Transpose block
        CDT = (
            facet_integral(-alpha / he * 2 * nu * inner(wbar, u))
            + facet_integral(2 * nu * inner(wbar, sym(grad(u)) * n))
            + facet_integral(qbar * dot(u, n))
        )
        HT = facet_integral(beta_stab * he / (nu + 1) * dot(p, qbar))
        G_ST = CDT + HT

        # Lower right block, penalty on ds(98) approximates free-slip
        KL = (
            facet_integral(alpha / he * 2 * nu * dot(ubar, wbar))
            - facet_integral(dot(pbar * n, wbar))
            + Constant(1e12) / he * inner(outer(ubar, wbar), outer(n, n)) * ds(98)
        )
        LtP = -facet_integral(dot(ubar, n) * qbar) - facet_integral(
            beta_stab * he / (nu + 1) * pbar * qbar
        )
        B_S = KL + LtP

        # Righthandside
        Q_S = dot(f, w) * dx
        S_S = facet_integral(dot(Constant(zero_vec), wbar))
        return {"A_S": A_S, "G_S": G_S, "G_ST": G_ST, "B_S": B_S, "Q_S": Q_S, "S_S": S_S}
Exemplo n.º 28
0
 def ojump(v, n):
     return outer(v, n)('+') + outer(v, n)('-')
Exemplo n.º 29
0
def setup_NSPFEC(w_NSPFEC, w_1NSPFEC,
                 dirichlet_bcs_NSPFEC,
                 neumann_bcs,
                 boundary_to_mark,
                 dx, ds, normal,
                 v, q, q0, psi, h, b, U,
                 u_, p_, p0_, phi_, g_, c_, V_,
                 u_1, p_1, p0_1, phi_1, g_1, c_1, V_1,
                 M_, nu_, veps_, rho_, K_, beta_, rho_e_,
                 dbeta, dveps, drho,
                 per_tau, sigma_bar, eps, grav, z,
                 solutes,
                 enable_NS, enable_PF, enable_EC,
                 use_iterative_solvers,
                 p_lagrange,
                 q_rhs):
    """ The full problem of electrohydrodynamics in two phases.
    Note that it is possible to turn off the different parts at will.
    """
    # Setup of the Navier-Stokes part of F
    mom_ = rho_*u_
    if enable_PF:
        mom_ += -M_*drho * df.nabla_grad(g_)
    
    F = []
    if enable_NS:
        F_NS = (per_tau * rho_ * df.dot(u_ - u_1, v) * dx
                + df.inner(df.nabla_grad(u_), df.outer(mom_, v)) * dx
                + 2*nu_*df.inner(df.sym(df.nabla_grad(u_)),
                                 df.sym(df.nabla_grad(v))) * dx
                - p_ * df.div(v) * dx
                - df.div(u_) * q * dx
                - df.dot(rho_ * grav, v) * dx)
        # if enable_PF:
        #     F_NS += - sigma_bar*eps*df.inner(
        #         df.outer(df.grad(phi_),
        #                  df.grad(phi_)), df.grad(v)) * dx
        # if enable_EC and rho_e_ != 0:
        #     F_NS += rho_e_*df.dot(df.grad(V_), v) * dx
        # if enable_PF and enable_EC:
        #     F_NS += dveps*df.dot(
        #         df.grad(phi_), v)*df.dot(df.grad(V_),
        #                                  df.grad(V_)) * dx

        if enable_PF:
            F_NS += phi_*df.dot(df.grad(g_), v) * dx

        if enable_EC:
            for ci_, dbetai, solute in zip(c_, dbeta, solutes):
                zi = solute[1]
                F_NS += df.dot(df.grad(ci_), v) * dx \
                        + ci_*dbetai*df.dot(df.grad(phi_), v) * dx \
                        + zi*ci_*df.dot(df.grad(V_), v) * dx

        # Slip boundary condition
        for boundary_name, slip_length in neumann_bcs["u"].items():
            F_NS += 1./slip_length * \
                    df.dot(u_, v) * ds(boundary_to_mark[boundary_name])

        # Pressure boundary condition
        for boundary_name, pressure in neumann_bcs["p"].items():
            F_NS += pressure * df.inner(
                normal, v) * ds(boundary_to_mark[boundary_name])

        # Lagrange pressure
        if p_lagrange:
            F_NS += (p_*q0 + q*p0_)*dx

        # RHS source terms
        if "u" in q_rhs:
            F_NS += -df.dot(q_rhs["u"], v)*dx

        F.append(F_NS)

    # Setup of the phase-field equations
    if enable_PF:
        phi_1_flt = unit_interval_filter(phi_1)
        F_PF_phi = (per_tau*(phi_-phi_1_flt)*psi*df.dx +
                    M_*df.dot(df.grad(g_), df.grad(psi)) * dx)
        if enable_NS:
            F_PF_phi += df.dot(u_, df.grad(phi_)) * psi * dx

        F_PF_g = (g_ * h * dx
                  - sigma_bar*eps*df.dot(df.grad(phi_), df.grad(h)) * dx
                  - sigma_bar/eps*diff_pf_potential(phi_) * h * dx)
        if enable_EC:
            F_PF_g += (-sum([dbeta_i * ci_ * h * dx
                             for dbeta_i, ci_ in zip(dbeta, c_)])
                       + dveps * df.dot(df.grad(V_), df.grad(V_)) * h * dx)

        # Contact angle boundary condtions
        for boundary_name, costheta in neumann_bcs["phi"].items():
            fw_prime = diff_pf_contact(phi_)
            F_PF_g += sigma_bar * costheta * fw_prime * h * ds(
                boundary_to_mark[boundary_name])

        # RHS source terms
        if "phi" in q_rhs:
            F_PF_phi += -q_rhs["phi"]*psi*dx

        F_PF = F_PF_phi + F_PF_g
        F.append(F_PF)

    # Setup of the electrochemistry
    if enable_EC:
        F_E_c = []
        for ci_, ci_1, bi, Ki_, zi, dbetai, solute in zip(
                c_, c_1, b, K_, z, dbeta, solutes):
            ci_1_flt = max_value(ci_1, 0.)
            F_E_ci = (per_tau*(ci_-ci_1_flt)*bi*df.dx
                       + Ki_*df.dot(df.grad(ci_), df.grad(bi))*df.dx)
            if zi != 0:
                F_E_ci += Ki_*zi*ci_*df.dot(df.grad(V_),
                                             df.grad(bi))*df.dx
            if enable_NS:
                F_E_ci += df.dot(u_, df.grad(ci_))*bi*df.dx

            if enable_PF:
                F_E_ci += Ki_*ci_*dbetai*df.dot(df.grad(phi_),
                                                df.grad(bi)) * dx

            if solute[0] in q_rhs:
                F_E_ci += - q_rhs[solute[0]] * bi * dx

            F_E_c.append(F_E_ci)

        F_E_V = veps_*df.dot(df.grad(V_), df.grad(U))*df.dx

        if rho_e_ != 0:
            F_E_V += -rho_e_*U*df.dx

        # Surface charge boundary condition
        for boundary_name, sigma_e in neumann_bcs["V"].items():
            F_E_V += -sigma_e*U*ds(boundary_to_mark[boundary_name])

        # RHS source terms
        if "V" in q_rhs:
            F_E_V += q_rhs["V"]*U*dx

        F_E = sum(F_E_c) + F_E_V

        F.append(F_E)

    F = sum(F)

    J = df.derivative(F, w_NSPFEC)
    problem_NSPFEC = df.NonlinearVariationalProblem(F, w_NSPFEC, dirichlet_bcs_NSPFEC, J)
    solver_NSPFEC = df.NonlinearVariationalSolver(problem_NSPFEC)
    if use_iterative_solvers:
        solver_NSPFEC.parameters['newton_solver']['linear_solver'] = 'gmres'
        solver_NSPFEC.parameters['newton_solver']['preconditioner'] = 'ilu'

    return solver_NSPFEC
Exemplo n.º 30
0
def setup_NSu(w_NSu, u, v, dx, ds, normal, dirichlet_bcs_NSu, neumann_bcs,
              boundary_to_mark, u_, u_1, p_, p_1, phi_, phi_1, rho_, rho_1, g_,
              g_1, c_, c_1, M_, M_1, mu_, mu_1, rho_e_, rho_e_1, V_, dt, drho,
              sigma_bar, eps, dveps, grav, dbeta, z, enable_PF, enable_EC,
              use_iterative_solvers, **namespace):
    """ Set up the Navier-Stokes velocity subproblem. """
    mom_1 = rho_1 * u_1
    if enable_PF:
        mom_1 += -drho * M_1 * df.grad(g_1)

    F_predict = (
        1. / dt * rho_1 * df.dot(u - u_1, v) * dx +
        df.inner(df.nabla_grad(u), df.outer(mom_1, v)) * dx + 2 * mu_ *
        df.inner(df.sym(df.nabla_grad(u)), df.sym(df.nabla_grad(v))) * dx -
        p_1 * df.div(v) * dx - rho_ * df.dot(grav, v) * dx + 0.5 *
        (1. / dt *
         (rho_ - rho_1) - df.inner(mom_1, df.grad(df.dot(u, v)))) * dx)
    if enable_PF:
        F_predict += phi_1 * df.dot(df.grad(g_), v) * dx

    for boundary_name, pressure in neumann_bcs["p"].items():
        F_predict += pressure * df.inner(normal, v) * ds(
            boundary_to_mark[boundary_name])

    if enable_EC:
        for ci_, ci_1_ in zip(c_, c_1):
            # F_predict += df.dot(df.nabla_grad(ci_), v) * dx
            pass

    #if enable_EC and rho_e_ != 0:
    #    F += rho_e_1 * df.dot(df.nabla_grad(V_), v) * dx
    #if enable_PF and enable_EC:
    #    # Not clear how to discretize this term!
    #    # F += dveps * df.dot(df.grad(phi_), v)*df.dot(df.grad(V_),
    #    #                                              df.grad(V_))*dx
    #    F_c = []
    #    for ci_, ci_1, zi, dbetai in zip(c_, c_1, z, dbeta):
    #        F_ci = ci_1*dbetai*df.dot(df.grad(phi_), v)*dx
    #        F_c.append(F_ci)
    #    F += sum(F_c)

    solvers = dict()

    a_predict, L_predict = df.lhs(F_predict), df.rhs(F_predict)

    problem_predict = df.LinearVariationalProblem(a_predict, L_predict, w_NSu,
                                                  dirichlet_bcs_NSu)
    solvers["predict"] = df.LinearVariationalSolver(problem_predict)

    if use_iterative_solvers:
        solvers["predict"].parameters["linear_solver"] = "bicgstab"
        solvers["predict"].parameters["preconditioner"] = "jacobi"  # "amg"

    F_correct = (rho_ * df.inner(u - u_, v) * dx - dt *
                 (p_ - p_1) * df.div(v) * dx)
    a_correct, L_correct = df.lhs(F_correct), df.rhs(F_correct)
    problem_correct = df.LinearVariationalProblem(a_correct, L_correct, w_NSu,
                                                  dirichlet_bcs_NSu)
    solvers["correct"] = df.LinearVariationalSolver(problem_correct)

    if use_iterative_solvers:
        solvers["correct"].parameters["linear_solver"] = "cg"  # "bicgstab"
        solvers["correct"].parameters["preconditioner"] = "jacobi"  # "amg"

    return solvers