Esempio n. 1
0
 def adaptive(self, mesh, eigv, eigf):
     """Refine mesh based on residual errors."""
     fraction = 0.1
     C = FunctionSpace(mesh, "DG", 0)  # constants on triangles
     w = TestFunction(C)
     h = CellSize(mesh)
     n = FacetNormal(mesh)
     marker = CellFunction("bool", mesh)
     print len(marker)
     indicators = np.zeros(len(marker))
     for e, u in zip(eigv, eigf):
         errform = avg(h) * jump(grad(u), n) ** 2 * avg(w) * dS \
             + h * (inner(grad(u), n) - Constant(e) * u) ** 2 * w * ds
         if self.degree > 1:
             errform += h ** 2 * div(grad(u)) ** 2 * w * dx
         indicators[:] += assemble(errform).array()  # errors for each cell
     print "Residual error: ", sqrt(sum(indicators) / len(eigv))
     cutoff = sorted(
         indicators, reverse=True)[
         int(len(indicators) * fraction) - 1]
     marker.array()[:] = indicators > cutoff  # mark worst errors
     mesh = refine(mesh, marker)
     return mesh
Esempio n. 2
0
    def _evaluateLocalEstimator(cls, mu, w, coeff_field, pde, f, quadrature_degree, epsilon=1e-5):
        """Evaluation of patch local equilibrated estimator."""

        # prepare numerical flux and f
        sigma_mu, f_mu = evaluate_numerical_flux(w, mu, coeff_field, f)

        # ###################
        # ## MIXED PROBLEM ##
        # ###################

        # get setup data for mixed problem
        V = w[mu]._fefunc.function_space()
        mesh = V.mesh()
        mesh.init()
        degree = element_degree(w[mu]._fefunc)

        # data for nodal bases
        V_dm = V.dofmap()
        V_dofs = dict([(i, V_dm.cell_dofs(i)) for i in range(mesh.num_cells())])
        V1 = FunctionSpace(mesh, 'CG', 1)   # V1 is to define nodal base functions
        phi_z = Function(V1)
        phi_coeffs = np.ndarray(V1.dim())
        vertex_dof_map = V1.dofmap().vertex_to_dof_map(mesh)
        # vertex_dof_map = vertex_to_dof_map(V1)
        dof_list = vertex_dof_map.tolist()
        # DG0 localisation
        DG0 = FunctionSpace(mesh, 'DG', 0)
        DG0_dofs = dict([(c.index(),DG0.dofmap().cell_dofs(c.index())[0]) for c in cells(mesh)])
        dg0 = TestFunction(DG0)
        # characteristic function of patch
        xi_z = Function(DG0)
        xi_coeffs = np.ndarray(DG0.dim())
        # mesh data
        h = CellSize(mesh)
        n = FacetNormal(mesh)
        cf = CellFunction('size_t', mesh)
        # setup error estimator vector
        eq_est = np.zeros(DG0.dim())

        # setup global equilibrated flux vector
        DG = VectorFunctionSpace(mesh, "DG", degree)
        DG_dofmap = DG.dofmap()

        # define form functions
        tau = TrialFunction(DG)
        v = TestFunction(DG)

        # define global tau
        tau_global = Function(DG)
        tau_global.vector()[:] = 0.0

        # iterate vertices
        for vertex in vertices(mesh):
            # get patch cell indices
            vid = vertex.index()
            patch_cid, FF_inner, FF_boundary = get_vertex_patch(vid, mesh, layers=1)

            # set nodal base function
            phi_coeffs[:] = 0
            phi_coeffs[dof_list.index(vid)] = 1
            phi_z.vector()[:] = phi_coeffs

            # set characteristic function and mark patch
            cf.set_all(0)
            xi_coeffs[:] = 0
            for cid in patch_cid:
                xi_coeffs[DG0_dofs[int(cid)]] = 1
                cf[int(cid)] = 1
            xi_z.vector()[:] = xi_coeffs

            # determine local dofs
            lDG_cell_dofs = dict([(cid, DG_dofmap.cell_dofs(cid)) for cid in patch_cid])
            lDG_dofs = [cd.tolist() for cd in lDG_cell_dofs.values()]
            lDG_dofs = list(iter.chain(*lDG_dofs))

            # print "\nlocal DG subspace has dimension", len(lDG_dofs), "degree", degree, "cells", len(patch_cid), patch_cid
            # print "local DG_cell_dofs", lDG_cell_dofs
            # print "local DG_dofs", lDG_dofs

            # create patch measures
            dx = Measure('dx')[cf]
            dS = Measure('dS')[FF_inner]

            # define forms
            alpha = Constant(1 / epsilon) / h
            a = inner(tau,v) * phi_z * dx(1) + alpha * div(tau) * div(v) * dx(1) + avg(alpha) * jump(tau,n) * jump(v,n) * dS(1)\
                + avg(alpha) * jump(xi_z * tau,n) * jump(v,n) * dS(2)
            L = -alpha * (div(sigma_mu) + f) * div(v) * phi_z * dx(1)\
                - avg(alpha) * jump(sigma_mu,n) * jump(v,n) * avg(phi_z)*dS(1)

    #        print "L2 f + div(sigma)", assemble((f + div(sigma)) * (f + div(sigma)) * dx(0))

            # assemble forms
            lhs = assemble(a, form_compiler_parameters={'quadrature_degree': quadrature_degree})
            rhs = assemble(L, form_compiler_parameters={'quadrature_degree': quadrature_degree})

            # convert DOLFIN representation to scipy sparse arrays
            rows, cols, values = lhs.data()
            lhsA = sps.csr_matrix((values, cols, rows)).tocoo()

            # slice sparse matrix and solve linear problem
            lhsA = coo_submatrix_pull(lhsA, lDG_dofs, lDG_dofs)
            lx = spsolve(lhsA, rhs.array()[lDG_dofs])
            # print ">>> local solution lx", type(lx), lx
            local_tau = Function(DG)
            local_tau.vector()[lDG_dofs] = lx
            # print "div(tau)", assemble(inner(div(local_tau),div(local_tau))*dx(1))

            # add up local fluxes
            tau_global.vector()[lDG_dofs] += lx

        # evaluate estimator
        # maybe TODO: re-define measure dx
        eq_est = assemble( inner(tau_global, tau_global) * dg0 * (dx(0)+dx(1)),\
                           form_compiler_parameters={'quadrature_degree': quadrature_degree})

        # reorder according to cell ids
        eq_est = eq_est[DG0_dofs.values()].array()
        global_est = np.sqrt(np.sum(eq_est))
        # eq_est_global = assemble( inner(tau_global, tau_global) * (dx(0)+dx(1)), form_compiler_parameters={'quadrature_degree': quadrature_degree} )
        # global_est2 = np.sqrt(np.sum(eq_est_global))
        return global_est, FlatVector(np.sqrt(eq_est))#, tau_global
Esempio n. 3
0
    def _evaluateResidualEstimator(cls, mu, w, coeff_field, pde, f, quadrature_degree):
        """Evaluate the residual error according to EGSZ (5.7) which consists of volume terms (5.3) and jump terms (5.5).

            .. math:: \eta_{\mu,T}(w_N) &:= h_T || \overline{a}^{-1/2} (f\delta_{\mu,0} + \nabla\overline{a}\cdot\nabla w_{N,\mu}
                                + \sum_{m=1}^\infty \nabla a_m\cdot\nabla( \alpha^m_{\mu_m+1}\Pi_\mu^{\mu+e_m} w_{N,\mu+e_m}
                                - \alpha_{\mu_m}^m w_{N,\mu} + \alpha_{\mu_m-1}^m\Pi_\mu^{\mu_m-e_m} w_{N,\mu-e_m} ||_{L^2(T)}\\
          \eta_{\mu,S}(w_N) &:= h_S^{-1/2} || \overline{a}^{-1/2} [(\overline{a}\nabla w_{N,\mu} + \sum_{m=1}^\infty a_m\nabla
                                  ( \alpha_{\mu_m+1}^m\Pi_\mu^{\mu+e_m} w_{N,\mu+e_m} - \alpha_{\mu_m}^m w_{N,\mu}
                                  + \alpha_{\mu_m-1}^m\Pi_\mu^{\mu-e_m} w_{N,\mu-e_m})\cdot\nu] ||_{L^2(S)}\\
        """
        # set quadrature degree
        quadrature_degree_old = parameters["form_compiler"]["quadrature_degree"]
        parameters["form_compiler"]["quadrature_degree"] = quadrature_degree
        logger.debug("residual quadrature order = " + str(quadrature_degree))
    
        # get pde residual terms
        r_T = pde.volume_residual
        r_E = pde.edge_residual
        r_Nb = pde.neumann_residual
        
        # get mean field of coefficient
        a0_f = coeff_field.mean_func

        # prepare some FEM variables
        V = w[mu]._fefunc.function_space()
        mesh = V.mesh()
        nu = FacetNormal(mesh)

        # initialise volume and edge residual with deterministic part
#        R_T = dot(nabla_grad(a0_f), nabla_grad(w[mu]._fefunc))
        R_T = r_T(a0_f, w[mu]._fefunc)
        if not mu:
            R_T = R_T + f
#        R_E = a0_f * dot(nabla_grad(w[mu]._fefunc), nu)
        R_E = r_E(a0_f, w[mu]._fefunc, nu)
        # get Neumann residual
        homogeneousNBC = False if mu.order == 0 else True
        R_Nb = r_Nb(a0_f, w[mu]._fefunc, nu, mesh, homogeneous=homogeneousNBC)

        # iterate m
        Lambda = w.active_indices()
        maxm = w.max_order
        if len(coeff_field) < maxm:
            logger.warning("insufficient length of coefficient field for MultiVector (%i < %i)", len(coeff_field), maxm)
            maxm = len(coeff_field)
            #        assert coeff_field.length >= maxm        # ensure coeff_field expansion is sufficiently long
        for m in range(maxm):
            am_f, am_rv = coeff_field[m]

            # prepare polynom coefficients
            beta = am_rv.orth_polys.get_beta(mu[m])

            # mu
            res = -beta[0] * w[mu]

            # mu+1
            mu1 = mu.inc(m)
            if mu1 in Lambda:
                w_mu1 = w.get_projection(mu1, mu)
                res += beta[1] * w_mu1

            # mu-1
            mu2 = mu.dec(m)
            if mu2 in Lambda:
                w_mu2 = w.get_projection(mu2, mu)
                res += beta[-1] * w_mu2

            # add volume contribution for m
#            r_t = dot(nabla_grad(am_f), nabla_grad(res._fefunc))
            R_T = R_T + r_T(am_f, res._fefunc)
            # add edge contribution for m
#            r_e = am_f * dot(nabla_grad(res._fefunc), nu)
            R_E = R_E + r_E(am_f, res._fefunc, nu)

        # prepare more FEM variables for residual assembly
        DG = FunctionSpace(mesh, "DG", 0)
        s = TestFunction(DG)
        h = CellSize(mesh)

        # scaling of residual terms and definition of residual form
        a0_s = a0_f[0] if isinstance(a0_f, tuple) else a0_f     # required for elasticity parameters
        res_form = (h ** 2 * (1 / a0_s) * dot(R_T, R_T) * s * dx
                    + avg(h) * dot(avg(R_E) / avg(a0_s), avg(R_E)) * 2 * avg(s) * dS)
        
        resT = h ** 2 * (1 / a0_s) * dot(R_T, R_T) * s * dx
        resE = 0 * s * dx + avg(h) * dot(avg(R_E) / avg(a0_s), avg(R_E)) * 2 * avg(s) * dS
        resNb = 0 * s * dx
        
        # add Neumann residuals
        if R_Nb is not None:
            for rj, dsj in R_Nb:
                res_form = res_form + h * (1 / a0_s) * dot(rj, rj) * s * dsj
                resNb += h * (1 / a0_s) * dot(rj, rj) * s * dsj

        # FEM evaluate residual on mesh
        eta = assemble(res_form)
        eta_indicator = np.array([sqrt(e) for e in eta])
        # map DG dofs to cell indices
        dofs = [DG.dofmap().cell_dofs(c.index())[0] for c in cells(mesh)]
        eta_indicator = eta_indicator[dofs]
        global_error = sqrt(sum(e for e in eta))

        # debug ---
        if False:
            etaT = assemble(resT)
            etaT_indicator = etaT #np.array([sqrt(e) for e in etaT])
            etaT = sqrt(sum(e for e in etaT))
            etaE = assemble(resE)
            etaE_indicator = etaE #np.array([sqrt(e) for e in etaE])
            etaE = sqrt(sum(e for e in etaE))
            etaNb = assemble(resNb)
            etaNb_indicator = etaNb #np.array([sqrt(e) for e in etaNb])
            etaNb = sqrt(sum(e for e in etaNb))
        
            print "==========RESIDUAL ESTIMATOR============"
            print "eta", eta
            print "eta_indicator", eta_indicator
            print "global =", global_error
            print "volume =", etaT
            print "edge =", etaE
            print "Neumann =", etaNb

            if False:        
                plot_indicators(((eta, "overall residual"), (etaT_indicator, "volume residual"), (etaE_indicator, "edge residual"), (etaNb_indicator, "Neumann residual")), mesh)
        # ---debug
        
        # restore quadrature degree
        parameters["form_compiler"]["quadrature_degree"] = quadrature_degree_old

        return (FlatVector(eta_indicator), global_error)
Esempio n. 4
0
def solverNeilanSalgadoZhang(P, opt):
    '''
    This function implements the method presented in
    Neilan, Salgado, Zhang (2017), Chapter 4
    Main characteristics:
    - test with piecewise second derivative of test_u
    - no discrete Hessian
    - first-order stabilization necessary
    '''

    assert opt["HessianSpace"] == "CG", 'opt["HessianSpace"] has to be "CG"'
    assert opt[
        "stabilityConstant1"], 'opt["stabilityConstant1"] has to be positive'

    gamma = P.normalizeSystem(opt)

    if isinstance(P.g, list):
        bc_V = []
        for fun, dom in P.g:
            bc_V.append(DirichletBC(P.V, fun, dom))
    else:
        if isinstance(P.g, Function):
            bc_V = DirichletBC(P.V, P.g, 'on_boundary')
        else:
            g = project(P.g, P.V)
            bc_V = DirichletBC(P.V, g, 'on_boundary')

    trial_u = TrialFunction(P.V)
    test_u = TestFunction(P.V)

    # Assemble right-hand side in each case
    f_h = gamma * P.f * div(grad(test_u)) * dx

    # Adjust load vector in case of time-dependent problem
    if P.isTimeDependant:
        f_h = gamma * P.u_np1 * div(grad(test_u)) * dx - P.dt * f_h

    rhs = assemble(f_h)
    if isinstance(bc_V, list):
        for bc_v in bc_V:
            bc_v.apply(rhs)
    else:
        bc_V.apply(rhs)

    repeat_setup = False

    if hasattr(P, 'timeDependentCoefs'):
        if P.timeDependentCoefs:
            repeat_setup = True

    if 'HJB' in str(type(P)):
        repeat_setup = True

    if (not P.isTimeDependant) or (P.iter == 0) or repeat_setup:

        print('Setup bilinear form')

        # Define bilinear form
        a_h = gamma * inner(P.a, grad(grad(trial_u))) * div(grad(test_u)) * dx \
            + opt["stabilityConstant1"] * avg(P.hE)**(-1) * inner(
                jump(grad(trial_u), P.nE), jump(grad(test_u), P.nE)) * dS

        if P.hasDrift:
            a_h += gamma * inner(P.b, grad(trial_u)) * div(grad(test_u)) * dx

        if P.hasPotential:
            a_h += gamma * P.c * trial_u * div(grad(test_u)) * dx

        # Adjust system matrix in case of time-dependent problem
        if P.isTimeDependant:
            a_h = gamma * trial_u * div(grad(test_u)) * dx - P.dt * a_h

        S = assemble(a_h)
        if isinstance(bc_V, list):
            for bc_v in bc_V:
                bc_v.apply(S)
        else:
            bc_V.apply(S)

        P.S = S

    if opt['time_check']:
        t1 = time()

    solve(P.S, P.u.vector(), rhs)

    # tmp = assemble(inner(P.a,grad(grad(trial_u))) * div(grad(test_u)) * dx)
    # A = assemble(a_h)
    # print('Row sum: ', sum(A.array(),1).round(4))
    # print('Col sum: ', sum(A.array(),0).round(4))
    # print('Total sum: ', sum(sum(A.array())).round(4))
    # ipdb.set_trace()
    # solve(a_h == f_h, P.u, bc_V, solver_parameters={'linear_solver': 'mumps'})

    if opt['time_check']:
        print("Solve linear equation system ... %.2fs" % (time() - t1))
        sys.stdout.flush()

    N_iter = 1

    return N_iter
Esempio n. 5
0
# Crank Nicholson parameter
cn = 1.0
Hm = cn * H + (1 - cn) * H0

# Jump and average for DG elements
H_avg = 0.5 * (Hm('+') + Hm('-'))
H_jump = Hm('+') * nhat('+') + Hm('-') * nhat('-')

xsi_avg = 0.5 * (xsi('+') + xsi('-'))
xsi_jump = xsi('+') * nhat('+') + xsi('-') * nhat('-')

uvec = df.as_vector([u, v])
unorm = df.dot(uvec, uvec)**0.5

#Upwind
uH = df.avg(uvec) * H_avg + 0.5 * df.avg(unorm) * H_jump
beff = df.Function(Q_dg)
beff.interpolate(adot())
R_H = ((H - H0) / dt - beff) * xsi * df.dx - df.dot(
    df.grad(xsi), uvec * Hm) * df.dx + df.dot(
        uH, xsi_jump) * df.dS  # + xsi*H*df.dot(uvec,nhat)*df.ds

# Calving relations
k_calving = df.Constant(0.5)
H_calving = (1 + df.Constant(.0)) * d * rho_w / rho
f = Min((H_calving / H), 5)
ucalv = f * uvec

# ALE level set velocity
unorm_c = df.dot(uvec - ucalv, uvec - ucalv)**0.5
Esempio n. 6
0
    def setup_scalar_equation(self):
        sim = self.simulation
        V = sim.data['Vphi']
        mesh = V.mesh()
        P = V.ufl_element().degree()

        # Source term
        source_cpp = sim.input.get_value('solver/source', '0', 'string')
        f = dolfin.Expression(source_cpp, degree=P)

        # Create the solution function
        sim.data['phi'] = dolfin.Function(V)

        # DG elliptic penalty
        penalty = define_penalty(mesh, P, k_min=1.0, k_max=1.0)
        penalty_dS = dolfin.Constant(penalty)
        penalty_ds = dolfin.Constant(penalty * 2)
        yh = dolfin.Constant(1 / (penalty * 2))

        # Define weak form
        u, v = dolfin.TrialFunction(V), dolfin.TestFunction(V)
        a = dot(grad(u), grad(v)) * dx
        L = f * v * dx

        # Symmetric Interior Penalty method for -∇⋅∇φ
        n = dolfin.FacetNormal(mesh)
        a -= dot(n('+'), avg(grad(u))) * jump(v) * dS
        a -= dot(n('+'), avg(grad(v))) * jump(u) * dS

        # Symmetric Interior Penalty coercivity term
        a += penalty_dS * jump(u) * jump(v) * dS

        # Dirichlet boundary conditions
        # Nitsche's (1971) method, see e.g. Epshteyn and Rivière (2007)
        dirichlet_bcs = sim.data['dirichlet_bcs'].get('phi', [])
        for dbc in dirichlet_bcs:
            bcval, dds = dbc.func(), dbc.ds()

            # SIPG for -∇⋅∇φ
            a -= dot(n, grad(u)) * v * dds
            a -= dot(n, grad(v)) * u * dds
            L -= dot(n, grad(v)) * bcval * dds

            # Weak Dirichlet
            a += penalty_ds * u * v * dds
            L += penalty_ds * bcval * v * dds

        # Neumann boundary conditions
        neumann_bcs = sim.data['neumann_bcs'].get('phi', [])
        for nbc in neumann_bcs:
            L += nbc.func() * v * nbc.ds()

        # Robin boundary conditions
        # See Juntunen and Stenberg (2009)
        # n⋅∇φ = (φ0 - φ)/b + g
        robin_bcs = sim.data['robin_bcs'].get('phi', [])
        for rbc in robin_bcs:
            b, rds = rbc.blend(), rbc.ds()
            dval, nval = rbc.dfunc(), rbc.nfunc()

            # From IBP of the main equation
            a -= dot(n, grad(u)) * v * rds

            # Test functions for the Robin BC
            z1 = 1 / (b + yh) * v
            z2 = -yh / (b + yh) * dot(n, grad(v))

            # Robin BC added twice with different test functions
            for z in [z1, z2]:
                a += b * dot(n, grad(u)) * z * rds
                a += u * z * rds
                L += dval * z * rds
                L += b * nval * z * rds

        # Does the system have a null-space?
        self.has_null_space = len(dirichlet_bcs) + len(robin_bcs) == 0

        self.form_lhs = a
        self.form_rhs = L
Esempio n. 7
0
def h_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 sigma_v_freeze, dphi_c_dt):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet"  # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    BDM = FiniteElement("BDM", mesh.ufl_cell(), 1)
    PDG = FiniteElement("DG", mesh.ufl_cell(), 0)

    BDM_F = FunctionSpace(mesh, BDM)
    PDG_F = FunctionSpace(mesh, PDG)

    W = BlockFunctionSpace([BDM_F, PDG_F], restrict=[None, None])

    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc / fc
    h_avg = (vc('+') + vc('-')) / (2 * avg(fc))

    I = Identity(mesh.topology().dim())

    monitor_dt = dt

    p_outlet = 0.1e6
    p_inlet = 1000.0

    M_inv = phi_0 * cf + (alpha - phi_0) / Ks

    # Define variational problem
    trial = BlockTrialFunction(W)
    dv, dp = block_split(trial)

    trial_dot = BlockTrialFunction(W)
    dv_dot, dp_dot = block_split(trial_dot)

    test = BlockTestFunction(W)
    psiv, psip = block_split(test)

    block_w = BlockFunction(W)
    v, p = block_split(block_w)

    block_w_dot = BlockFunction(W)
    v_dot, p_dot = block_split(block_w_dot)

    a_time = Constant(0.0) * inner(v_dot, psiv) * dx  #quasi static

    # k is a function of phi
    #k = perm_update_rutqvist_newton(p,p0,phi0,phi,coeff)
    lhs_a = inner(dot(v, mu * inv(k)), psiv) * dx - p * div(
        psiv
    ) * dx  #+ 6.0*inner(psiv,n)*ds(2)  # - inner(gravity*(rho-rho0), psiv)*dx

    b_time = (M_inv + pow(alpha, 2.) / K) * p_dot * psip * dx

    lhs_b = div(v) * psip * dx  #div(rho*v)*psip*dx #TODO rho

    rhs_v = -p_outlet * inner(psiv, n) * ds(3)

    rhs_p = -alpha / K * sigma_v_freeze * psip * dx - dphi_c_dt * psip * dx

    r_u = [lhs_a, lhs_b]

    j_u = block_derivative(r_u, block_w, trial)

    r_u_dot = [a_time, b_time]

    j_u_dot = block_derivative(r_u_dot, block_w_dot, trial_dot)

    r = [r_u_dot[0] + r_u[0] - rhs_v, \
         r_u_dot[1] + r_u[1] - rhs_p]

    def bc(t):
        #bc_v = [DirichletBC(W.sub(0), (.0, .0), boundaries, 4)]
        v1 = DirichletBC(W.sub(0), (1.e-4 * 2.0, 0.0), boundaries, 1)
        v2 = DirichletBC(W.sub(0), (0.0, 0.0), boundaries, 2)
        v4 = DirichletBC(W.sub(0), (0.0, 0.0), boundaries, 4)
        bc_v = [v1, v2, v4]

        return BlockDirichletBC([bc_v, None])

    # Define problem wrapper
    class ProblemWrapper(object):
        def set_time(self, t):
            pass
            #g.t = t

        # Residual and jacobian functions
        def residual_eval(self, t, solution, solution_dot):
            #print(as_backend_type(assemble(p_time - p_time_error)).vec().norm())
            #print("gravity effect", as_backend_type(assemble(inner(gravity*(rho-rho0), psiv)*dx)).vec().norm())

            return r

        def jacobian_eval(self, t, solution, solution_dot,
                          solution_dot_coefficient):
            return [[Constant(solution_dot_coefficient)*j_u_dot[0, 0] + j_u[0, 0], \
                     Constant(solution_dot_coefficient)*j_u_dot[0, 1] + j_u[0, 1]], \
                    [Constant(solution_dot_coefficient)*j_u_dot[1, 0] + j_u[1, 0], \
                     Constant(solution_dot_coefficient)*j_u_dot[1, 1] + j_u[1, 1]]]

        # Define boundary condition
        def bc_eval(self, t):
            return bc(t)

        # Define initial condition
        def ic_eval(self):
            return solution0

        # Define custom monitor to plot the solution
        def monitor(self, t, solution, solution_dot):
            pass

    # Solve the time dependent problem
    problem_wrapper = ProblemWrapper()
    (solution, solution_dot) = (block_w, block_w_dot)
    solver = TimeStepping(problem_wrapper, solution, solution_dot)
    solver.set_parameters({
        "initial_time": t_start,
        "time_step_size": dt,
        "monitor": {
            "time_step_size": monitor_dt,
        },
        "final_time": T,
        "exact_final_time": "stepover",
        "integrator_type": integrator_type,
        "problem_type": "linear",
        "linear_solver": "mumps",
        "report": True
    })
    export_solution = solver.solve()

    return export_solution, T
    Vx = FunctionSpace(mx, 'CG', 2)
    Vy = FunctionSpace(my, 'CG', 1)

    phi = TrialFunction(Vx)
    psi = TestFunction(Vx)

    v = Function(Vx)
    # We avoid the normalization
    gamma = 1.0
    # Jump penalty term
    stab1 = 2.
    nE = FacetNormal(mx)
    hE = FacetArea(mx)
    test = div(grad(psi))
    S_xx = gamma * inner(ax, grad(grad(phi))) * test * dx(mx) \
        + stab1 * avg(hE)**(-1) * inner(jump(grad(phi), nE),
                                        jump(grad(psi), nE)) * dS(mx)
    S_x = gamma * inner(bx, grad(phi)) * test * dx(mx)
    S_0 = gamma * c * phi * test * dx(mx)

    # This matrix also changes since we are testing the whole equation
    # with div(grad(psi)) instead of psi
    M_ = gamma * phi * test * dx(mx)

    M = assemble(M_)

    # Prepare special treatment of deterministic part and time-derivative.

    # Probably, I'll need here the dof coordinates and the dof list
    xdofs = Vx.tabulate_dof_coordinates().flatten()
    ix = np.argsort(xdofs)
Esempio n. 9
0
def navier_stokes_stabilization_penalties(
    simulation,
    nu,
    velocity_continuity_factor_D12=0,
    pressure_continuity_factor=0,
    no_coeff=False,
):
    """
    Calculate the stabilization parameters needed in the DG scheme
    """
    ndim = simulation.ndim
    mpm = simulation.multi_phase_model
    mesh = simulation.data['mesh']
    use_const = simulation.input.get_value('solver/spatially_constant_penalty',
                                           False, 'bool')

    if no_coeff:
        mu_min = mu_max = 1.0
    else:
        mu_min, mu_max = mpm.get_laminar_dynamic_viscosity_range()

    P = simulation.data['Vu'].ufl_element().degree()
    if use_const:
        simulation.log.info('    Using spatially constant elliptic penalty')
        penalty_dS = define_penalty(mesh,
                                    P,
                                    mu_min,
                                    mu_max,
                                    boost_factor=3,
                                    exponent=1.0)
        penalty_ds = penalty_dS * 2
        simulation.log.info('    DG SIP penalty:  dS %.1f  ds %.1f' %
                            (penalty_dS, penalty_ds))
        penalty_dS = Constant(penalty_dS)
        penalty_ds = Constant(penalty_ds)

    else:
        simulation.log.info('    Using spatially varying elliptic penalties')
        penalty_dS = define_spatially_varying_penalty(simulation,
                                                      P,
                                                      mu_min,
                                                      mu_max,
                                                      boost_factor=3,
                                                      exponent=1.0)
        penalty_ds = penalty_dS * 2
        penalty_dS = dolfin.conditional(
            dolfin.lt(penalty_dS('+'), penalty_dS('-')),
            penalty_dS('-'),
            penalty_dS('+'),
        )

    if velocity_continuity_factor_D12:
        D12 = Constant([velocity_continuity_factor_D12] * ndim)
    else:
        D12 = Constant([0] * ndim)

    if pressure_continuity_factor:
        h = simulation.data['h']
        h = Constant(1.0)
        D11 = avg(h / nu) * Constant(pressure_continuity_factor)
    else:
        D11 = None

    return penalty_dS, penalty_ds, D11, D12
degree = 2
V = MultiMeshFunctionSpace(multimesh, "CG", degree)

# Assign a function to each mesh, such that T and lmb are discontinuous at the
# interface Gamma
T = MultiMeshFunction(V)
lmb = MultiMeshFunction(V)

# Terms for variational form
alpha = 4
beta = 4
h = 2 * Circumradius(multimesh)
h = 0.5 * (h("+") + h("-"))
a1 = inner(grad(T), grad(lmb)) * dX
a2 = -dot(avg(grad(T)), jump(lmb, n)) * dI
a3 = -dot(avg(grad(lmb)), jump(T, n)) * dI
# NOTE: Only adding h to a4 reduced convergence rate
a4 = alpha / h * inner(jump(T), jump(lmb)) * dI
# NOTE: Adding overlap stabilization increases convergence rate to two as it enforces smoothness
a5 = beta * dot(jump(grad(T)), jump(grad(lmb))) * dO
J1 = inner(T, T) * dX


def solve_state():
    a = a1 + a2 + a3 + a4 + a5
    a = replace(a, {lmb: TestFunction(V), T: TrialFunction(V)})
    l = Constant(0) * TestFunction(V) * dX
    a = assemble_multimesh(a)
    L = assemble_multimesh(l)
    bcs = [
Esempio n. 11
0
    def _setup_dg1_projection_2D(self, w, incompressibility_flux_type, D12,
                                 use_bcs):
        """
        Implement the projection where the result is BDM embeded in a DG1 function
        """
        sim = self.simulation
        k = 1
        gdim = 2
        mesh = w[0].function_space().mesh()
        V = VectorFunctionSpace(mesh, 'DG', k)
        W = FunctionSpace(mesh, 'DGT', k)
        n = FacetNormal(mesh)

        v1 = TestFunction(W)
        u = TrialFunction(V)

        # The same fluxes that are used in the incompressibility equation
        if incompressibility_flux_type == 'central':
            u_hat_dS = dolfin.avg(w)
        elif incompressibility_flux_type == 'upwind':
            w_nU = (dot(w, n) + abs(dot(w, n))) / 2.0
            switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0)
            u_hat_dS = switch * w('+') + (1 - switch) * w('-')

        if D12 is not None:
            u_hat_dS += dolfin.Constant([D12, D12]) * dolfin.jump(w, n)

        # Equation 1 - flux through the sides
        a = L = 0
        for R in '+-':
            a += dot(u(R), n(R)) * v1(R) * dS
            L += dot(u_hat_dS, n(R)) * v1(R) * dS

        # Eq. 1 cont. - flux through external boundaries
        a += dot(u, n) * v1 * ds
        if use_bcs:
            for d in range(gdim):
                dirichlet_bcs = sim.data['dirichlet_bcs']['u%d' % d]
                neumann_bcs = sim.data['neumann_bcs'].get('u%d' % d, [])
                robin_bcs = sim.data['robin_bcs'].get('u%d' % d, [])
                outlet_bcs = sim.data['outlet_bcs']

                for dbc in dirichlet_bcs:
                    u_bc = dbc.func()
                    L += u_bc * n[d] * v1 * dbc.ds()

                for nbc in neumann_bcs + robin_bcs + outlet_bcs:
                    if nbc.enforce_zero_flux:
                        pass  # L += 0
                    else:
                        L += w[d] * n[d] * v1 * nbc.ds()

            for sbc in sim.data['slip_bcs'].get('u', []):
                pass  # L += 0
        else:
            L += dot(w, n) * v1 * ds

        # Equation 2 - internal shape   :   empty for DG1
        # Equation 3 - BDM Phi          :   empty for DG1

        return a, L, V
Esempio n. 12
0
    def _setup_projection_nedelec(self, w, incompressibility_flux_type, D12,
                                  use_bcs, pdeg, gdim):
        """
        Implement the BDM-like projection using Nedelec elements in the test function
        """
        sim = self.simulation
        k = pdeg
        mesh = w[0].function_space().mesh()
        V = VectorFunctionSpace(mesh, 'DG', k)
        n = FacetNormal(mesh)

        # The mixed function space of the projection test functions
        e1 = FiniteElement('DGT', mesh.ufl_cell(), k)
        e2 = FiniteElement('N1curl', mesh.ufl_cell(), k - 1)
        em = MixedElement([e1, e2])
        W = FunctionSpace(mesh, em)
        v1, v2 = TestFunctions(W)
        u = TrialFunction(V)

        # The same fluxes that are used in the incompressibility equation
        if incompressibility_flux_type == 'central':
            u_hat_dS = dolfin.avg(w)
        elif incompressibility_flux_type == 'upwind':
            w_nU = (dot(w, n) + abs(dot(w, n))) / 2.0
            switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0)
            u_hat_dS = switch * w('+') + (1 - switch) * w('-')

        if D12 is not None:
            u_hat_dS += dolfin.Constant([D12] * gdim) * dolfin.jump(w, n)

        # Equation 1 - flux through the sides
        a = L = 0
        for R in '+-':
            a += dot(u(R), n(R)) * v1(R) * dS
            L += dot(u_hat_dS, n(R)) * v1(R) * dS

        # Eq. 1 cont. - flux through external boundaries
        a += dot(u, n) * v1 * ds
        if use_bcs:
            for d in range(gdim):
                dirichlet_bcs = sim.data['dirichlet_bcs'].get('u%d' % d, [])
                neumann_bcs = sim.data['neumann_bcs'].get('u%d' % d, [])
                robin_bcs = sim.data['robin_bcs'].get('u%d' % d, [])
                outlet_bcs = sim.data['outlet_bcs']

                for dbc in dirichlet_bcs:
                    u_bc = dbc.func()
                    L += u_bc * n[d] * v1 * dbc.ds()

                for nbc in neumann_bcs + robin_bcs + outlet_bcs:
                    if nbc.enforce_zero_flux:
                        pass  # L += 0
                    else:
                        L += w[d] * n[d] * v1 * nbc.ds()

            for sbc in sim.data['slip_bcs'].get('u', []):
                pass  # L += 0
        else:
            L += dot(w, n) * v1 * ds

        # Equation 2 - internal shape using 'Nedelec 1st kind H(curl)' elements
        a += dot(u, v2) * dx
        L += dot(w, v2) * dx

        return a, L, V
Esempio n. 13
0
    def _setup_dg2_projection_2D(self, w, incompressibility_flux_type, D12,
                                 use_bcs):
        """
        Implement the projection where the result is BDM embeded in a DG2 function
        """
        sim = self.simulation
        k = 2
        gdim = 2
        mesh = w[0].function_space().mesh()
        V = VectorFunctionSpace(mesh, 'DG', k)
        n = FacetNormal(mesh)

        # The mixed function space of the projection test functions
        e1 = FiniteElement('DGT', mesh.ufl_cell(), k)
        e2 = VectorElement('DG', mesh.ufl_cell(), k - 2)
        e3 = FiniteElement('Bubble', mesh.ufl_cell(), 3)
        em = MixedElement([e1, e2, e3])
        W = FunctionSpace(mesh, em)
        v1, v2, v3b = TestFunctions(W)
        u = TrialFunction(V)

        # The same fluxes that are used in the incompressibility equation
        if incompressibility_flux_type == 'central':
            u_hat_dS = dolfin.avg(w)
        elif incompressibility_flux_type == 'upwind':
            w_nU = (dot(w, n) + abs(dot(w, n))) / 2.0
            switch = dolfin.conditional(dolfin.gt(w_nU('+'), 0.0), 1.0, 0.0)
            u_hat_dS = switch * w('+') + (1 - switch) * w('-')

        if D12 is not None:
            u_hat_dS += dolfin.Constant([D12, D12]) * dolfin.jump(w, n)

        # Equation 1 - flux through the sides
        a = L = 0
        for R in '+-':
            a += dot(u(R), n(R)) * v1(R) * dS
            L += dot(u_hat_dS, n(R)) * v1(R) * dS

        # Eq. 1 cont. - flux through external boundaries
        a += dot(u, n) * v1 * ds
        if use_bcs:
            for d in range(gdim):
                dirichlet_bcs = sim.data['dirichlet_bcs']['u%d' % d]
                neumann_bcs = sim.data['neumann_bcs'].get('u%d' % d, [])
                robin_bcs = sim.data['robin_bcs'].get('u%d' % d, [])
                outlet_bcs = sim.data['outlet_bcs']

                for dbc in dirichlet_bcs:
                    u_bc = dbc.func()
                    L += u_bc * n[d] * v1 * dbc.ds()

                for nbc in neumann_bcs + robin_bcs + outlet_bcs:
                    if nbc.enforce_zero_flux:
                        pass  # L += 0
                    else:
                        L += w[d] * n[d] * v1 * nbc.ds()

            for sbc in sim.data['slip_bcs'].get('u', []):
                pass  # L += 0
        else:
            L += dot(w, n) * v1 * ds

        # Equation 2 - internal shape
        a += dot(u, v2) * dx
        L += dot(w, v2) * dx

        # Equation 3 - BDM Phi
        v3 = as_vector([v3b.dx(1), -v3b.dx(0)])  # Curl of [0, 0, v3b]
        a += dot(u, v3) * dx
        L += dot(w, v3) * dx

        return a, L, V