V = dolfin.VectorFunctionSpace(mesh, 'CG', FINITE_ELEMENT_DEGREE)

# Displacement field
u = Function(V)

### Dirichlet boundary conditions

bcs = []

Vx, Vy, Vz = V.split()

zero = Constant(0)
zeros = Constant((0, 0, 0))

bcs.append(DirichletBC(Vx, zero, boundary_markers, id_subdomain_fix))
bcs.append(DirichletBC(Vx, uxD_msr, boundary_markers, id_subdomain_msr))

bcs.append(DirichletBC(V, zeros, fixed_vertex_000, "pointwise"))
bcs.append(DirichletBC(Vz, zero, fixed_vertex_010, "pointwise"))

### Define hyperelastic material model

material_parameters = {'E': Constant(1.0), 'nu': Constant(0.0)}

E, nu = material_parameters.values()

d = len(u)  # Displacement dimension

I = dolfin.Identity(d)
F = dolfin.variable(I + dolfin.grad(u))
def solverBHWreduced(P, opt):
    ''' Function to solve the second-order pde in
    nonvariational formulation using gmres '''

    if P.hasDrift:
        raise ValueError('Method currently does not support non-zero drift terms.')
    if P.isTimeDependant:
        raise ValueError('Method currently does not support parabolic problems.')
    if P.hasPotential:
        raise ValueError('Method currently does not support non-zero potential terms.')

    gamma = P.normalizeSystem(opt)

    # Extract local space of tensor space W_h
    W_H_loc = P.mixedSpace.sub(1).extract_sub_space(np.array([0])).collapse()

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

    trial_p = TrialFunction(W_H_loc)
    test_p = TestFunction(W_H_loc)

    # Get number of dofs in V
    N = P.V.dim()
    NW = W_H_loc.dim()

    # Get indices of inner and boundary nodes
    # Calling DirichletBC with actual P.g calls project which is expensive
    bc_V = DirichletBC(P.V, Constant(1), 'on_boundary')
    idx_bnd = list(bc_V.get_boundary_values().keys())
    N_bnd = len(idx_bnd)
    N_in = N - N_bnd

    # Get indices of inner nodes
    idx_inner = np.setdiff1d(range(N), idx_bnd)

    def _i2a(S):
        return S[:, idx_inner]

    def _i2i(S):
        return S[idx_inner, :][:, idx_inner]

    def _b2a(S):
        return S[:, idx_bnd]

    def _b2i(S):
        return S[idx_inner, :][:, idx_bnd]

    # Assemble mass matrix and store LU decomposition
    M_W = spmat(assemble(trial_p * test_p * dx))
    # spy(M_W)

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

    # M_LU = la.splu(M_W)
    M_LU = cgMat(M_W)

    if opt['time_check']:
        print("Compute LU decomposition of M_W ... %.2fs" % (time() - t1))
        sys.stdout.flush()

    # Check for constant zero entries in diffusion matrix

    # The diagonal entries are set up everytime
    nzdiags = [(i, i) for i in range(P.dim())]

    # The off-diagonal entries
    nzs = []
    Asym = True
    for (i, j) in itertools.product(range(P.dim()), range(P.dim())):
        if i == j:
            nzs.append((i, j))
        else:
            is_zero = checkForZero(P.a[i, j])
            if not is_zero:
                Asym = False
                print('Use value ({},{})'.format(i, j))
                nzs.append((i, j))
            else:
                print('Ignore value ({},{})'.format(i, j))

    def emptyMat(d=P.dim()):
        return [[-1e15] * d for i in range(d)]
        # return [[0] * d for i in range(d)]

    # Assemble weighted mass matrices
    B = emptyMat()
    for (i, j) in nzs:
        # ipdb.set_trace()
        this_form = gamma * P.a[i, j] * trial_p * test_p * dx
        B[i][j] = spmat(assemble(this_form))

    # Init array for partial stiffness matrices
    C = emptyMat()

    # Set up the form for partial stiffness matrices
    def C_form(i, j):
        this_form = -trial_u.dx(i) * test_p.dx(j) * \
            dx + trial_u.dx(i) * test_p * P.nE[j] * ds
        if opt["HessianSpace"] == 'DG':
            this_form += avg(trial_u.dx(i)) \
                * (test_p('+') * P.nE[j]('+') + test_p('-') * P.nE[j]('-')) * dS
        return this_form

    # Ensure the diagonal is set up, necessary for the FE Laplacian
    for i in range(P.dim()):
        C[i][i] = spmat(assemble(C_form(i, i)))

    # Assemble the partial stiffness matrices for off-diagonal entries
    # only if a_i,j is non-zero
    for i, j in nzs:
        if i != j:
            C[i][j] = spmat(assemble(C_form(i, j)))

    C_lapl = sum([C[i][j] for i, j in nzdiags])

    # Set up the form for stabilization term
    if opt["stabilizationFlag"] > 0:

        this_form = 0

        # First stabilization term
        if opt["stabilityConstant1"] > 0:
            this_form += opt["stabilityConstant1"] * avg(P.hE)**(-1) * \
                inner(vj(grad(trial_u), P.nE), vj(grad(test_u), P.nE)) * dS

        # Second stabilization term
        if opt["stabilityConstant2"] > 0:
            this_form += opt["stabilityConstant2"] * avg(P.hE)**(+1) * \
                inner(mj(grad(grad(trial_u)), P.nE),
                      mj(grad(grad(test_u)), P.nE)) * dS

        # Assemble stabilization term
        S = spmat(assemble(this_form))

    else:

        # If no stabilization is used, S is zero
        S = sp.csc_matrix((N, N))

    # Set up matrix-vector product for inner nodes
    def S_II_times_u(x):
        Dv = [B[i][j] * M_LU.solve(_i2a(C[i][j]) * x) for i, j in nzs]
        w = M_LU.solve(sum(Dv))
        return (_i2a(C_lapl)).transpose() * w + _i2i(S) * x

    # Set up matrix-vector product for boundary nodes
    def S_IB_times_u(x):
        Dv = [B[i][j] * M_LU.solve(_b2a(C[i][j]) * x) for i, j in nzs]
        w = M_LU.solve(sum(Dv))
        return (_i2a(C_lapl)).transpose() * w + _b2i(S) * x

    # Assemble f_W
    f_W = assemble(gamma * P.f * test_p * dx)

    M_in = la.LinearOperator((N_in, N_in), matvec=lambda x: S_II_times_u(x))
    M_bnd = la.LinearOperator((N_in, N_bnd), matvec=lambda x: S_IB_times_u(x))

    # Set up right-hand side
    try:
        print('Project boundary data with LU')
        G = project(P.g, P.V, solver_type="lu")
    except RuntimeError:
        print('Out of memory error: Switch to projection with CG')
        G = project(P.g, P.V, solver_type="cg")

    # Compute right-hand side
    rhs = (_i2a(C_lapl)).transpose() * M_LU.solve(f_W.get_local())

    Gvec = G.vector()
    g_bc = Gvec.get_local().take(idx_bnd)
    rhs -= M_bnd * g_bc

    M_W_DiagInv = sp.spdiags(1. / M_W.diagonal(), np.array([0]), NW, NW, format='csc')
    D = sum([sp.spdiags(B[i][j].diagonal(), np.array([0]), NW, NW, format='csc')
             * M_W_DiagInv * _i2a(C[i][j]) for i, j in nzs])
    Prec = (_i2a(C_lapl)).transpose().tocsc() * M_W_DiagInv * D + _i2i(S)

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

    # Determine approximate size of LU decomposition in GB
    LU_size = NW**2 / (1024.**3)
    MEM_size = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES') / (1024.**3)

    if LU_size / MEM_size > 0.8:
        if Asym:
            print('Use CG for preconditioning')
            Prec_LU = cgMat(Prec)
        else:
            print('Use GMRES for preconditioning')
            Prec_LU = gmresMat(Prec)
    else:
        try:
            print('Use LU for preconditioning')
            Prec_LU = la.splu(Prec)
        except MemoryError:
            if Asym:
                print('Use CG for preconditioning')
                Prec_LU = cgMat(Prec)
            else:
                print('Use GMRES for preconditioning')
                Prec_LU = gmresMat(Prec)

    PrecLinOp = la.LinearOperator(
        (N_in, N_in), matvec=lambda x: Prec_LU.solve(x))

    # import ipdb
    # ipdb.set_trace()
    # gmres_mode = 1  # LU decomposition of Prec
    # # gmres_mode = 3  # incomplete LU decomposition of Prec
    # # gmres_mode = 4  # aslinearop
    # # Findings during experiments
    # # - LU factorization of prec is fast, high memory demand
    # # - Using only the diag of prec is not suitable
    # # - Solve routine from scipy is slow

    # # 1st variant: determine LU factorization of preconditioner
    # if gmres_mode == 1:
    #     Prec_LU = la.splu(Prec)
    #     PrecLinOp = la.LinearOperator(
    #         (N_in, N_in), matvec=lambda x: Prec_LU.solve(x))

    # # 3rd variant: determine incomplete LU factorization of preconditioner
    # if gmres_mode == 3:
    #     if P.solDofs(opt) < MEM_THRESHOLD:
    #         fill_factor = 20
    #         fill_factor = 30
    #         print('Use incomplete LU with fill factor {} for preconditioning'.format(fill_factor))
    #         Prec_LU = la.spilu(Prec,
    #                            fill_factor=fill_factor,
    #                            drop_tol=1e-4)
    #     else:
    #         print('Use gmres for preconditioning')
    #         Prec_LU = gmresMat(Prec, tol=1e-8)
    #         # print('Use cg for preconditioning')
    #         # Prec_LU = cgMat(Prec)
    #     PrecLinOp = la.LinearOperator(
    #         (N_in, N_in), matvec=lambda x: Prec_LU.solve(x))

    # if gmres_mode == 4:

    #     if P.solDofs(opt) < MEM_THRESHOLD:
    #         Prec_LU = la.splu(Prec)
    #     else:
    #         Prec_LU = gmresMat(Prec)

    #     PrecLinOp = la.LinearOperator(
    #         (N_in, N_in), matvec=lambda x: Prec_LU.solve(x))

    if opt['time_check']:
        t2 = time()
        print("Prepare GMRES (e.g. LU decomp of Prec) ... %.2fs" % (t2 - t1))
        sys.stdout.flush()

    do_savemat = 0
    if do_savemat:
        from scipy.io import savemat
        savemat('M_{}.mat'.format(P.meshLevel),
                mdict={'Prec': Prec,
                       'B': B,
                       'C': C,
                       'S': S,
                       'M': M_W,
                       'f': f_W.get_local(),
                       'g': Gvec.get_local(),
                       'idx_inner': idx_inner,
                       'idx_bnd': idx_bnd,
                       })

    if P.meshLevel == 1 or not opt["gmresWarmStart"]:
        x0 = np.zeros(N_in)
    else:
        tmp = interpolate(P.uold, P.V)
        x0 = tmp.vector().get_local()[idx_inner]

    # Initialize counter for GMRES
    counter = gmres_counter(disp=True)

    # System solve
    (x, gmres_flag) = la.gmres(A=M_in,
                               b=rhs,
                               M=PrecLinOp,
                               x0=x0,
                               maxiter=2000,
                               tol=opt["gmresTolRes"],
                               atol=opt["gmresTolRes"],
                               restart=20,
                               callback=counter)

    if opt['time_check']:
        print("Time for GMRES ... %.2fs" % (time() - t2))
        sys.stdout.flush()

    print('GMRES output flag: {}'.format(gmres_flag))

    N_iter = counter.niter

    u_loc = Function(P.V)
    u_loc.vector()[idx_bnd] = g_bc
    u_loc.vector()[idx_inner] = x

    # Set solution to problem structure
    assign(P.u, u_loc)

    # Compute FE Hessians
    # import ipdb
    # ipdb.set_trace()

    for (i, j) in itertools.product(range(P.dim()), range(P.dim())):
        if (i, j) in nzs:
            Hij = Function(P.W_H.sub(i*P.dim() + j).collapse())
            hij = M_LU.solve(C[i][j] * u_loc.vector())
            Hij.vector()[:] = hij
            assign(P.H.sub(i*P.dim() + j), Hij)

    return N_iter
Esempio n. 3
0
def run_with_params(Tb, mu_value, k_s, path):
    run_time_init = clock()

    mesh = BoxMesh(Point(0.0, 0.0, 0.0),
                   Point(mesh_width, mesh_width, mesh_height), nx, ny, nz)

    pbc = PeriodicBoundary()

    WE = VectorElement('CG', mesh.ufl_cell(), 2)
    SE = FiniteElement('CG', mesh.ufl_cell(), 1)
    WSSS = FunctionSpace(mesh,
                         MixedElement(WE, SE, SE, SE),
                         constrained_domain=pbc)
    # W = FunctionSpace(mesh, WE, constrained_domain=pbc)
    # S = FunctionSpace(mesh, SE, constrained_domain=pbc)
    W = WSSS.sub(0).collapse()
    S = WSSS.sub(1).collapse()

    temperature_vals = [27.0 + 273, Tb + 273, 1300.0 + 273, 1305.0 + 273]
    temp_prof = TemperatureProfile(temperature_vals, element=S.ufl_element())

    mu_a = mu_value  # this was taken from the Blankenbach paper, can change

    Ep = b / temp_prof.delta

    mu_bot = exp(-Ep *
                 (temp_prof.bottom * temp_prof.delta - 1573.0) + cc) * mu_a

    # TODO: verify exponentiation
    Ra = rho_0 * alpha * g * temp_prof.delta * h**3 / (kappa_0 * mu_a)
    w0 = rho_0 * alpha * g * temp_prof.delta * h**2 / mu_a
    tau = h / w0
    p0 = mu_a * w0 / h

    log(mu_a, mu_bot, Ra, w0, p0)

    slip_vx = 1.6E-09 / w0  # Non-dimensional
    slip_velocity = Constant((slip_vx, 0.0, 0.0))
    zero_slip = Constant((0.0, 0.0, 0.0))

    time_step = 3.0E11 / tau * 2

    dt = Constant(time_step)
    t_end = 3.0E15 / tau / 5.0  # Non-dimensional times

    u = Function(WSSS)

    # Instead of TrialFunctions, we use split(u) for our non-linear problem
    v, p, T, Tf = split(u)
    v_t, p_t, T_t, Tf_t = TestFunctions(WSSS)

    T0 = interpolate(temp_prof, S)

    mu_exp = Expression(
        'exp(-Ep * (T_val * dTemp - 1573.0) + cc * x[2] / mesh_height)',
        Ep=Ep,
        dTemp=temp_prof.delta,
        cc=cc,
        mesh_height=mesh_height,
        T_val=T0,
        element=S.ufl_element())

    Tf0 = interpolate(temp_prof, S)

    mu = Function(S)
    v0 = Function(W)

    v_theta = (1.0 - theta) * v0 + theta * v

    T_theta = (1.0 - theta) * T0 + theta * T

    Tf_theta = (1.0 - theta) * Tf0 + theta * Tf

    # TODO: Verify forms

    r_v = (inner(sym(grad(v_t)), 2.0 * mu * sym(grad(v))) - div(v_t) * p -
           T * v_t[2]) * dx

    r_p = p_t * div(v) * dx

    heat_transfer = Constant(k_s) * (Tf_theta - T_theta) * dt

    r_T = (
        T_t *
        ((T - T0) + dt * inner(v_theta, grad(T_theta)))  # TODO: Inner vs dot
        +
        (dt / Ra) * inner(grad(T_t), grad(T_theta)) - T_t * heat_transfer) * dx

    v_melt = Function(W)
    z_hat = Constant((0.0, 0.0, 1.0))

    # TODO: inner -> dot, take out Tf_t
    r_Tf = (Tf_t * ((Tf - Tf0) + dt * inner(v_melt, grad(Tf_theta))) +
            Tf_t * heat_transfer) * dx

    r = r_v + r_p + r_T + r_Tf

    bcv0 = DirichletBC(WSSS.sub(0), zero_slip, top)
    bcv1 = DirichletBC(WSSS.sub(0), slip_velocity, bottom)
    bcv2 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), back)
    bcv3 = DirichletBC(WSSS.sub(0).sub(1), Constant(0.0), front)

    bcp0 = DirichletBC(WSSS.sub(1), Constant(0.0), bottom)
    bct0 = DirichletBC(WSSS.sub(2), Constant(temp_prof.surface), top)
    bct1 = DirichletBC(WSSS.sub(2), Constant(temp_prof.bottom), bottom)
    bctf1 = DirichletBC(WSSS.sub(3), Constant(temp_prof.bottom), bottom)

    bcs = [bcv0, bcv1, bcv2, bcv3, bcp0, bct0, bct1, bctf1]

    t = 0
    count = 0
    files = DefaultDictByKey(partial(create_xdmf, path))

    while t < t_end:
        mu.interpolate(mu_exp)
        rhosolid = rho_0 * (1.0 - alpha * (T0 * temp_prof.delta - 1573.0))
        deltarho = rhosolid - rho_melt
        # TODO: project (accuracy) vs interpolate
        assign(
            v_melt,
            project(
                v0 - darcy * (grad(p) * p0 / h - deltarho * z_hat * g) / w0,
                W))
        # TODO: Written out one step later?
        # v_melt.assign(v0 - darcy * (grad(p) * p0 / h - deltarho * yvec * g) / w0)
        # TODO: use nP after to avoid projection?

        solve(r == 0, u, bcs)
        nV, nP, nT, nTf = u.split()  # TODO: write with Tf, ... etc

        if count % output_every == 0:
            time_left(count, t_end / time_step,
                      run_time_init)  # TODO: timestep vs dt

            # TODO: Make sure all writes are to the same function for each time step
            files['T_fluid'].write(nTf, t)
            files['p'].write(nP, t)
            files['v_solid'].write(nV, t)
            files['T_solid'].write(nT, t)
            files['mu'].write(mu, t)
            files['v_melt'].write(v_melt, t)
            files['gradp'].write(project(grad(nP), W), t)
            files['rho'].write(project(rhosolid, S), t)
            files['Tf_grad'].write(project(grad(Tf), W), t)
            files['advect'].write(project(dt * dot(v_melt, grad(nTf))), t)
            files['ht'].write(project(heat_transfer, S), t)

        assign(T0, nT)
        assign(v0, nV)
        assign(Tf0, nTf)

        t += time_step
        count += 1

    log('Case mu={}, Tb={}, k={} complete. Run time = {:.2f} minutes'.format(
        mu_a, Tb, k_s, (clock() - run_time_init) / 60.0))
Esempio n. 4
0
# ===================================================================
# Scaled variables
E = 1.0e9
nu = 0.3
mu = E / (2.0 * (1.0 + nu))
lambda_ = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))

# Dirichlet boundary condition
tol = 1E-14


def clamped_boundary(x, on_boundary):
    return on_boundary and near(x[0], 0, tol)


bc = DirichletBC(V, Constant((0, 0, 0)), clamped_boundary)


# Define strain and stress
def epsilon(u):
    return 0.5 * (grad(u) + grad(u).T)


def sigma(u):
    return lambda_ * div(u) * Identity(d) + 2 * mu * epsilon(u)


# Mark facets of the mesh and Neumann boundary condition
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
boundaries.set_all(0)
Esempio n. 5
0
# Define function space and basis functions
V = FunctionSpace(mesh, ("CG", 2))
u = TrialFunction(V)
v = TestFunction(V)

u5 = Function(V)
with u5.vector().localForm() as bc_local:
    bc_local.set(5.0)

u0 = Function(V)
with u0.vector().localForm() as bc_local:
    bc_local.set(0.0)

# Define Dirichlet boundary conditions at top and bottom boundaries
bcs = [
    DirichletBC(V, u5, boundaries.where_equal(boundary["TOP"][0])),
    DirichletBC(V, u0, boundaries.where_equal(boundary["BOTTOM"][0])),
]

dx = dx(subdomain_data=domains)
ds = ds(subdomain_data=boundaries)

# Define variational form
F = (inner(a0 * grad(u), grad(v)) * dx(boundary["DOMAIN"][0]) +
     inner(a1 * grad(u), grad(v)) * dx(boundary["OBSTACLE"][0]) -
     g_L * v * ds(boundary["LEFT"][0]) - g_R * v * ds(boundary["RIGHT"][0]) -
     f * v * dx(boundary["DOMAIN"][0]) - f * v * dx(boundary["OBSTACLE"][0]))

# Separate left and right hand sides of equation
a, L = lhs(F), rhs(F)
Esempio n. 6
0
    def test_DoGIP_vs_FEniCS(self):
        print(
            '\n== testing DoGIP vs. FEniCS for problem of weighted projection ===='
        )
        for dim, pol_order in itertools.product([2, 3], [1, 2]):
            print('dim={}; pol_order={}'.format(dim, pol_order))
            N = 2  # no. of elements

            # creating MESH, defining MATERIAL and SOURCE
            if dim == 2:
                mesh = UnitSquareMesh(N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])", degree=4)
                f = Expression("80*x[0]*(0.5-x[0])*(1.-x[0])*x[1]*(1.-x[1])",
                               degree=5)
            elif dim == 3:
                mesh = UnitCubeMesh(N, N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*(1-x[1])*x[2]", degree=4)
                f = Expression("80*x[0]*(0.5-x[0])*(1.-x[0])*x[1]*(1.-x[1])",
                               degree=5)

            mesh.coordinates()[:] += 0.1 * np.random.random(
                mesh.coordinates().shape)  # mesh perturbation

            ## standard approach with FEniCS #############################################
            V = FunctionSpace(mesh, "CG", pol_order)  # original FEM space
            bc = DirichletBC(V, Constant(0.0),
                             lambda x, on_boundary: on_boundary)
            u, v = TrialFunction(V), TestFunction(V)
            u_fenics = Function(V)  # the vector for storing the solution
            solve(m * inner(grad(u), grad(v)) * dx == f * v * dx, u_fenics,
                  bc)  # solution by FEniCS

            ## DoGIP - double-grid integration with interpolation-projection #############
            W = FunctionSpace(mesh, "DG",
                              2 * (pol_order - 1))  # double-grid space
            Wvector = VectorFunctionSpace(
                mesh, "DG",
                2 * (pol_order - 1))  # vector variant of double-grid space
            w = TestFunction(W)
            A_dogip = assemble(
                m * w *
                dx).get_local()  # diagonal matrix of material coefficients
            A_dogip_full = np.einsum(
                'i,jk->ijk', A_dogip,
                np.eye(dim))  # block-diagonal mat. for non-isotropic mat.
            bv = assemble(f * v * dx)
            bc.apply(bv)
            b = bv.get_local()  # vector of right-hand side

            # assembling global interpolation-projection matrix B
            B = get_B(V, Wvector, problem=1)

            # solution to DoGIP problem
            def Afun(x):
                Axd = np.einsum('...jk,...j', A_dogip_full,
                                B.dot(x).reshape((-1, dim)))
                Afunx = B.T.dot(Axd.ravel())
                Afunx[list(bc.get_boundary_values()
                           )] = 0  # application of Dirichlet BC
                return Afunx

            Alinoper = linalg.LinearOperator((b.size, b.size),
                                             matvec=Afun,
                                             dtype=np.float)  # system matrix
            x, info = linalg.cg(Alinoper,
                                b,
                                x0=np.zeros_like(b),
                                tol=1e-8,
                                maxiter=1e2)  # conjugate gradients

            # testing the difference between DoGIP and FEniCS
            self.assertAlmostEqual(
                0, np.linalg.norm(u_fenics.vector().get_local() - x))
            print('...ok')
Esempio n. 7
0
 def dbc(self, subspace, subdomains, mark):
     return DirichletBC(subspace.sub(self.dim),
                        Constant(0.), subdomains, mark)
Esempio n. 8
0
        stab1 = 2.

        nE = FacetNormal(mx)
        hE = FacetArea(mx)

        test = div(grad(psi))
        S_ = gamma * inner(ax, grad(grad(phi))) * test * dx(mx) \
            + stab1 * avg(hE)**(-1) * inner(jump(grad(phi), nE), jump(grad(psi), nE)) * dS(mx) \
            + gamma * inner(bx, grad(phi)) * test * dx(mx) \
            + 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)

        bc_Vx = DirichletBC(Vx, g, 'on_boundary')
        S = assemble(S_)
        M = assemble(M_)

        # Prepare special treatment of deterministic part and time-derivative.
        xdofs = Vx.tabulate_dof_coordinates().flatten()
        ix = np.argsort(xdofs)

        # Since we're using the mesh in the deterministic direction
        # only for temporary purpose, the coordinates are fine here
        ydofs = Vy.tabulate_dof_coordinates().flatten()
        ydofs.sort()
        ydiff = np.diff(ydofs)

        assert np.all(ydiff > 0)
        # Create meshgrid X, Y of shape (ny+1, nx+1)
def test_poisson(k):
    # Polynomial order and mesh resolution
    nx_list = [4, 8, 16]

    # Error list
    error_u_l2, error_u_h1 = [], []

    for nx in nx_list:
        mesh = UnitSquareMesh(nx, nx)

        # Define FunctionSpaces and functions
        V = FunctionSpace(mesh, "DG", k)
        Vbar = FunctionSpace(mesh,
                             FiniteElement("CG", mesh.ufl_cell(), k)["facet"])

        u_soln = Expression("sin(pi*x[0])*sin(pi*x[1])",
                            degree=k + 1,
                            domain=mesh)
        f = Expression("2*pi*pi*sin(pi*x[0])*sin(pi*x[1])", degree=k + 1)
        u, v = Function(V), TestFunction(V)
        ubar, vbar = Function(Vbar), TestFunction(Vbar)

        n = FacetNormal(mesh)
        h = CellDiameter(mesh)
        alpha = Constant(6 * k * k)
        penalty = alpha / h

        def facet_integral(integrand):
            return integrand('-') * dS + integrand('+') * dS + integrand * ds

        u_flux = ubar
        F_v_flux = grad(u) + penalty * outer(u_flux - u, n)

        residual_local = inner(grad(u), grad(v)) * dx
        residual_local += facet_integral(inner(outer(u_flux - u, n), grad(v)))
        residual_local -= facet_integral(inner(F_v_flux, outer(v, n)))
        residual_local -= f * v * dx

        residual_global = facet_integral(inner(F_v_flux, outer(vbar, n)))

        a_ll = derivative(residual_local, u)
        a_lg = derivative(residual_local, ubar)
        a_gl = derivative(residual_global, u)
        a_gg = derivative(residual_global, ubar)

        l_l = -residual_local
        l_g = -residual_global

        bcs = [DirichletBC(Vbar, u_soln, "on_boundary")]

        # Initialize static condensation assembler
        assembler = AssemblerStaticCondensation(a_ll, a_lg, a_gl, a_gg, l_l,
                                                l_g, bcs)

        A_g, b_g = PETScMatrix(), PETScVector()
        assembler.assemble_global_lhs(A_g)
        assembler.assemble_global_rhs(b_g)

        for bc in bcs:
            bc.apply(A_g, b_g)

        solver = PETScKrylovSolver()
        solver.set_operator(A_g)
        PETScOptions.set("ksp_type", "preonly")
        PETScOptions.set("pc_type", "lu")
        PETScOptions.set("pc_factor_mat_solver_type", "mumps")
        solver.set_from_options()

        solver.solve(ubar.vector(), b_g)
        assembler.backsubstitute(ubar._cpp_object, u._cpp_object)

        # Compute L2 and H1 norms
        e_u_l2 = assemble((u - u_soln)**2 * dx)**0.5
        e_u_h1 = assemble(grad(u - u_soln)**2 * dx)**0.5

        if mesh.mpi_comm().rank == 0:
            error_u_l2.append(e_u_l2)
            error_u_h1.append(e_u_h1)

    if mesh.mpi_comm().rank == 0:
        iterator_list = [1.0 / float(nx) for nx in nx_list]
        conv_u_l2 = compute_convergence(iterator_list, error_u_l2)
        conv_u_h1 = compute_convergence(iterator_list, error_u_h1)

        # Optimal rate of k + 1 - tolerance
        assert np.all(conv_u_l2 >= (k + 1.0 - 0.15))
        # Optimal rate of k - tolerance
        assert np.all(conv_u_h1 >= (k - 0.1))
Esempio n. 10
0
def build_clamped_walls(VComplex):
    c0vec = Constant((0.0, 0.0, 0.0, 0.0, 0.0, 0.0))              
    bcs = DirichletBC(VComplex, c0vec, OuterWalls())
    return bcs
def test_unsteady_stokes():
    nx, ny = 15, 15
    k = 1
    nu = Constant(1.E-0)
    dt = Constant(2.5e-2)
    num_steps = 20
    theta0 = 1.0  # Initial theta value
    theta1 = 0.5  # Theta after 1 step
    theta = Constant(theta0)

    mesh = UnitSquareMesh(nx, ny)

    # The 'unsteady version' of the benchmark in the 2012 paper by Labeur&Wells
    u_exact = Expression(("sin(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                           -6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
                          "-sin(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                           - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])"), t=0, degree=7, domain=mesh)
    p_exact = Expression("sin(t) * x[0]*(1.0 - x[0])", t=0, degree=7, domain=mesh)
    du_exact = Expression(("cos(t) * x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                            - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
                           "-cos(t)* x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                            -6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])"), t=0, degree=7, domain=mesh)

    ux_exact = Expression(("x[0]*x[0]*(1.0 - x[0])*(1.0 - x[0])*(2.0*x[1] \
                            - 6.0*x[1]*x[1] + 4.0*x[1]*x[1]*x[1])",
                           "-x[1]*x[1]*(1.0 - x[1])*(1.0 - x[1])*(2.0*x[0] \
                            - 6.0*x[0]*x[0] + 4.0*x[0]*x[0]*x[0])"), degree=7, domain=mesh)

    px_exact = Expression("x[0]*(1.0 - x[0])", degree=7, domain=mesh)

    sin_ext = Expression("sin(t)", t=0, degree=7, domain=mesh)

    f = du_exact + sin_ext * div(px_exact*Identity(2) - 2*sym(grad(ux_exact)))

    Vhigh = VectorFunctionSpace(mesh, "DG", 7)
    Phigh = FunctionSpace(mesh, "DG", 7)

    # New syntax:
    V = VectorElement("DG", mesh.ufl_cell(), k)
    Q = FiniteElement("DG", mesh.ufl_cell(), k-1)
    Vbar = VectorElement("DGT", mesh.ufl_cell(), k)
    Qbar = FiniteElement("DGT", mesh.ufl_cell(), k)

    mixedL = FunctionSpace(mesh, MixedElement([V, Q]))
    mixedG = FunctionSpace(mesh, MixedElement([Vbar, Qbar]))
    V2 = FunctionSpace(mesh, V)

    Uh = Function(mixedL)
    Uhbar = Function(mixedG)
    U0 = Function(mixedL)
    Uhbar0 = Function(mixedG)
    u0, p0 = split(U0)
    ubar0, pbar0 = split(Uhbar0)
    ustar = Function(V2)

    # Then the boundary conditions
    bc0 = DirichletBC(mixedG.sub(0), Constant((0, 0)), Gamma)
    bc1 = DirichletBC(mixedG.sub(1), Constant(0), Corner, "pointwise")
    bcs = [bc0, bc1]

    alpha = Constant(6*k*k)
    forms_stokes = FormsStokes(mesh, mixedL, mixedG, alpha).forms_unsteady(ustar, dt, nu, f)
    ssc = StokesStaticCondensation(mesh,
                                   forms_stokes['A_S'], forms_stokes['G_S'],
                                   forms_stokes['G_ST'], forms_stokes['B_S'],
                                   forms_stokes['Q_S'], forms_stokes['S_S'])

    t = 0.
    step = 0
    for step in range(num_steps):
        step += 1
        t += float(dt)
        if comm.Get_rank() == 0:
            print("Step "+str(step)+" Time "+str(t))

        # Set time level in exact solution
        u_exact.t = t
        p_exact.t = t

        du_exact.t = t - (1-float(theta))*float(dt)
        sin_ext.t = t - (1-float(theta))*float(dt)

        ssc.assemble_global_lhs()
        ssc.assemble_global_rhs()
        for bc in bcs:
            ssc.apply_boundary(bc)

        ssc.solve_problem(Uhbar, Uh, 'none', 'default')
        assign(U0, Uh)
        assign(ustar, U0.sub(0))
        assign(Uhbar0, Uhbar)
        if step == 1:
            theta.assign(theta1)

        udiv_e = sqrt(assemble(div(Uh.sub(0)) * div(Uh.sub(0))*dx))

    u_ex_h = interpolate(u_exact, Vhigh)
    p_ex_h = interpolate(p_exact, Phigh)

    u_error = sqrt(assemble(dot(Uh.sub(0) - u_ex_h, Uh.sub(0) - u_ex_h)*dx))
    p_error = sqrt(assemble(dot(Uh.sub(1) - p_ex_h, Uh.sub(1) - p_ex_h)*dx))

    assert udiv_e < 1e-12
    assert u_error < 1.5e-4
    assert p_error < 1e-2
Esempio n. 12
0
def compute_time_errors(problem, MethodClass, mesh_sizes, Dt):

    mesh_generator, solution, f, mu, rho, cell_type = problem()
    # Translate data into FEniCS expressions.
    sol_u = Expression((sympy.printing.ccode(solution['u']['value'][0]),
                        sympy.printing.ccode(solution['u']['value'][1])),
                       degree=_truncate_degree(solution['u']['degree']),
                       t=0.0,
                       cell=cell_type)
    sol_p = Expression(sympy.printing.ccode(solution['p']['value']),
                       degree=_truncate_degree(solution['p']['degree']),
                       t=0.0,
                       cell=cell_type)

    fenics_rhs0 = Expression((sympy.printing.ccode(
        f['value'][0]), sympy.printing.ccode(f['value'][1])),
                             degree=_truncate_degree(f['degree']),
                             t=0.0,
                             mu=mu,
                             rho=rho,
                             cell=cell_type)
    # Deep-copy expression to be able to provide f0, f1 for the Dirichlet-
    # boundary conditions later on.
    fenics_rhs1 = Expression(fenics_rhs0.cppcode,
                             degree=_truncate_degree(f['degree']),
                             t=0.0,
                             mu=mu,
                             rho=rho,
                             cell=cell_type)
    # Create initial states.
    p0 = Expression(sol_p.cppcode,
                    degree=_truncate_degree(solution['p']['degree']),
                    t=0.0,
                    cell=cell_type)

    # Compute the problem
    errors = {
        'u': numpy.empty((len(mesh_sizes), len(Dt))),
        'p': numpy.empty((len(mesh_sizes), len(Dt)))
    }
    for k, mesh_size in enumerate(mesh_sizes):
        mesh = mesh_generator(mesh_size)
        mesh_area = assemble(1.0 * dx(mesh))
        W = VectorFunctionSpace(mesh, 'CG', 2)
        P = FunctionSpace(mesh, 'CG', 1)
        method = MethodClass(
            W,
            P,
            rho,
            mu,
            theta=1.0,
            # theta=0.5,
            stabilization=None
            # stabilization='SUPG'
        )
        u1 = Function(W)
        p1 = Function(P)
        err_p = Function(P)
        divu1 = Function(P)
        for j, dt in enumerate(Dt):
            # Prepare previous states for multistepping.
            u = [
                Expression(sol_u.cppcode,
                           degree=_truncate_degree(solution['u']['degree']),
                           t=0.0,
                           cell=cell_type),
                # Expression(
                # sol_u.cppcode,
                # degree=_truncate_degree(solution['u']['degree']),
                # t=0.5*dt,
                # cell=cell_type
                # )
            ]
            sol_u.t = dt
            u_bcs = [DirichletBC(W, sol_u, 'on_boundary')]
            sol_p.t = dt
            # p_bcs = [DirichletBC(P, sol_p, 'on_boundary')]
            p_bcs = []
            fenics_rhs0.t = 0.0
            fenics_rhs1.t = dt
            method.step(dt,
                        u1,
                        p1,
                        u,
                        p0,
                        u_bcs=u_bcs,
                        p_bcs=p_bcs,
                        f0=fenics_rhs0,
                        f1=fenics_rhs1,
                        verbose=False,
                        tol=1.0e-10)
            sol_u.t = dt
            sol_p.t = dt
            errors['u'][k][j] = errornorm(sol_u, u1)
            # The pressure is only determined up to a constant which makes
            # it a bit harder to define what the error is. For our
            # purposes, choose an alpha_0\in\R such that
            #
            #    alpha0 = argmin ||e - alpha||^2
            #
            # with  e := sol_p - p.
            # This alpha0 is unique and explicitly given by
            #
            #     alpha0 = 1/(2|Omega|) \int (e + e*)
            #            = 1/|Omega| \int Re(e),
            #
            # i.e., the mean error in \Omega.
            alpha = (+assemble(sol_p * dx(mesh)) - assemble(p1 * dx(mesh)))
            alpha /= mesh_area
            # We would like to perform
            #     p1 += alpha.
            # To avoid creating a temporary function every time, assume
            # that p1 lives in a function space where the coefficients
            # represent actual function values. This is true for CG
            # elements, for example. In that case, we can just add any
            # number to the vector of p1.
            p1.vector()[:] += alpha
            errors['p'][k][j] = errornorm(sol_p, p1)

            show_plots = False
            if show_plots:
                plot(p1, title='p1', mesh=mesh)
                plot(sol_p, title='sol_p', mesh=mesh)
                err_p.vector()[:] = p1.vector()
                sol_interp = interpolate(sol_p, P)
                err_p.vector()[:] -= sol_interp.vector()
                # plot(sol_p - p1, title='p1 - sol_p', mesh=mesh)
                plot(err_p, title='p1 - sol_p', mesh=mesh)
                # r = Expression('x[0]', degree=1, cell=triangle)
                # divu1 = 1 / r * (r * u1[0]).dx(0) + u1[1].dx(1)
                divu1.assign(project(u1[0].dx(0) + u1[1].dx(1), P))
                plot(divu1, title='div(u1)')
    return errors
Esempio n. 13
0
    duh0=duh0,
    duh00=duh00)
pde_u = PDEStaticCondensation(mesh, p, forms_u['N_a'], forms_u['G_a'],
                              forms_u['L_a'], forms_u['H_a'], forms_u['B_a'],
                              forms_u['Q_a'], forms_u['R_a'], forms_u['S_a'],
                              2)

# Set-up Stokes Solve
forms_stokes = FormsStokes(mesh, mixedL, mixedG, alpha,
                           ds=ds).forms_multiphase(rho0, ustar, dt, mu, f)
ssc = StokesStaticCondensation(mesh, forms_stokes['A_S'], forms_stokes['G_S'],
                               forms_stokes['B_S'], forms_stokes['Q_S'],
                               forms_stokes['S_S'])

# Set pressure in upper left corner to zero
bc1 = DirichletBC(mixedG.sub(1), Constant(0), Corner(xmin, ymax), "pointwise")
bcs = [bc1]

lstsq_u = l2projection(p, W_2, 2)

# Loop and output
step = 0
t = 0.

# Store at step 0
xdmf_rho.write(rho0, t)
xdmf_u.write(Uh.sub(0), t)
xdmf_p.write(Uh.sub(1), t)

p.dump2file(mesh, fname_list, property_list, 'wb')
Esempio n. 14
0
def les_setup(u_, mesh, assemble_matrix, CG1Function, nut_krylov_solver, bcs,
              **NS_namespace):
    """
    Set up for solving the Germano Dynamic LES model applying
    Lagrangian Averaging.
    """

    # Create function spaces
    CG1 = FunctionSpace(mesh, "CG", 1)
    p, q = TrialFunction(CG1), TestFunction(CG1)
    dim = mesh.geometry().dim()

    # Define delta and project delta**2 to CG1
    delta = pow(CellVolume(mesh), 1. / dim)
    delta_CG1_sq = project(delta, CG1)
    delta_CG1_sq.vector().set_local(delta_CG1_sq.vector().array()**2)
    delta_CG1_sq.vector().apply("insert")

    # Define nut_
    Sij = sym(grad(u_))
    magS = sqrt(2 * inner(Sij, Sij))
    Cs = Function(CG1)
    nut_form = Cs**2 * delta**2 * magS
    # Create nut_ BCs
    ff = FacetFunction("size_t", mesh, 0)
    bcs_nut = []
    for i, bc in enumerate(bcs['u0']):
        bc.apply(u_[0].vector())  # Need to initialize bc
        m = bc.markers()  # Get facet indices of boundary
        ff.array()[m] = i + 1
        bcs_nut.append(DirichletBC(CG1, Constant(0), ff, i + 1))
    nut_ = CG1Function(nut_form,
                       mesh,
                       method=nut_krylov_solver,
                       bcs=bcs_nut,
                       bounded=True,
                       name="nut")

    # Create functions for holding the different velocities
    u_CG1 = as_vector([Function(CG1) for i in range(dim)])
    u_filtered = as_vector([Function(CG1) for i in range(dim)])
    dummy = Function(CG1)
    ll = LagrangeInterpolator()

    # Assemble required filter matrices and functions
    G_under = Function(CG1, assemble(TestFunction(CG1) * dx))
    G_under.vector().set_local(1. / G_under.vector().array())
    G_under.vector().apply("insert")
    G_matr = assemble(inner(p, q) * dx)

    # Set up functions for Lij and Mij
    Lij = [Function(CG1) for i in range(dim * dim)]
    Mij = [Function(CG1) for i in range(dim * dim)]
    # Check if case is 2D or 3D and set up uiuj product pairs and
    # Sij forms, assemble required matrices
    Sijcomps = [Function(CG1) for i in range(dim * dim)]
    Sijfcomps = [Function(CG1) for i in range(dim * dim)]
    # Assemble some required matrices for solving for rate of strain terms
    Sijmats = [assemble_matrix(p.dx(i) * q * dx) for i in range(dim)]
    if dim == 3:
        tensdim = 6
        uiuj_pairs = ((0, 0), (0, 1), (0, 2), (1, 1), (1, 2), (2, 2))
    else:
        tensdim = 3
        uiuj_pairs = ((0, 0), (0, 1), (1, 1))

    # Set up Lagrange functions
    JLM = Function(CG1)
    JLM.vector()[:] += 1E-32
    JMM = Function(CG1)
    JMM.vector()[:] += 1

    return dict(Sij=Sij,
                nut_form=nut_form,
                nut_=nut_,
                delta=delta,
                bcs_nut=bcs_nut,
                delta_CG1_sq=delta_CG1_sq,
                CG1=CG1,
                Cs=Cs,
                u_CG1=u_CG1,
                u_filtered=u_filtered,
                ll=ll,
                Lij=Lij,
                Mij=Mij,
                Sijcomps=Sijcomps,
                Sijfcomps=Sijfcomps,
                Sijmats=Sijmats,
                JLM=JLM,
                JMM=JMM,
                dim=dim,
                tensdim=tensdim,
                G_matr=G_matr,
                G_under=G_under,
                dummy=dummy,
                uiuj_pairs=uiuj_pairs)
Esempio n. 15
0
# Create function space
V = VectorFunctionSpace(mesh, ("Lagrange", 1))

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
a = inner(sigma(u), grad(v)) * dx
L = inner(f, v) * dx

u0 = Function(V)
with u0.vector.localForm() as bc_local:
    bc_local.set(0.0)

# Set up boundary condition on inner surface
bc = DirichletBC(V, u0, boundary)

# Assemble system, applying boundary conditions and preserving symmetry)
A = assemble_matrix(a, [bc])
A.assemble()

b = assemble_vector(L)
apply_lifting(b, [a], [[bc]])
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, [bc])

# Create solution function
u = Function(V)

# Create near null space basis (required for smoothed aggregation AMG).
null_space = build_nullspace(V)
Esempio n. 16
0
def truth_solve(mu_unkown):
    print("Performing truth solve at mu =", mu_unkown)
    (mesh, subdomains, boundaries, restrictions) = read_mesh()
    # (mesh, subdomains, boundaries, restrictions) = create_mesh()
    dx = Measure('dx', subdomain_data=subdomains)
    ds = Measure('ds', subdomain_data=boundaries)
    W = generate_block_function_space(mesh, restrictions)

    # Test and trial functions
    block_v = BlockTestFunction(W)
    v, q = block_split(block_v)
    block_du = BlockTrialFunction(W)
    du, dp = block_split(block_du)
    block_u = BlockFunction(W)
    u, p = block_split(block_u)

    # gap
    # V2 = FunctionSpace(mesh, "CG", 1)
    # gap = Function(V2, name="Gap")

    # obstacle
    R = 0.25
    d = 0.15
    x_0 = mu_unkown[0]
    y_0 = mu_unkown[1]
    obstacle = Expression("-d+(pow(x[0]-x_0,2)+pow(x[1]-y_0, 2))/2/R", d=d, R=R , x_0 = x_0, y_0 = y_0, degree=0)

    # Constitutive parameters
    E = Constant(10.0)
    nu = Constant(0.3)
    mu, lmbda = Constant(E/(2*(1 + nu))), Constant(E*nu/((1 + nu)*(1 - 2*nu)))

    B  = Constant((0.0, 0.0, 0.0))      # Body force per unit volume
    T  = Constant((0.0, 0.0, 0.0))      # Traction force on the boundary

    # Kinematics
    # -----------------------------------------------------------------------------
    mesh_dim = mesh.topology().dim()                    # Spatial dimension
    I = Identity(mesh_dim)                 # Identity tensor
    F = I + grad(u)                 # Deformation gradient
    C = F.T*F                       # Right Cauchy-Green tensor
    J = det(F)                      # 3rd invariant of the deformation tensor

    # Strain function
    def P(u):                       # P = dW/dF:
        return mu*(F - inv(F.T)) + lmbda*ln(J)*inv(F.T)
    def eps(v):
        return sym(grad(v))
    def sigma(v):
        return lmbda*tr(eps(v))*Identity(3) + 2.0*mu*eps(v)
    # Definition of The Mackauley bracket <x>+
    def ppos(x):
        return (x+abs(x))/2.
    # Define the augmented lagrangian
    def aug_l(x):
        return x + pen*(obstacle-u[2])

    pen = Constant(1e4)

    # Boundary conditions
    # bottom_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 2)
    # left_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 3)
    # right_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 4)
    # front_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 5)
    # back_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 6)
    # # sym_x_bc = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 2)
    # # sym_y_bc = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3)
    # # bc = BlockDirichletBC([bottom_bc, sym_x_bc, sym_y_bc])
    # bc = BlockDirichletBC([bottom_bc, left_bc, right_bc, front_bc, back_bc])

    bottom_bc = DirichletBC(W.sub(0), Constant((0., 0., 0.)), boundaries, 2)
    left_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 3)
    left_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3)
    right_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 4)
    right_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 4)
    front_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 5)
    front_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 5)
    back_bc_x = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 6)
    back_bc_y = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 6)
    # sym_x_bc = DirichletBC(W.sub(0).sub(0), Constant(0.), boundaries, 2)
    # sym_y_bc = DirichletBC(W.sub(0).sub(1), Constant(0.), boundaries, 3)
    # bc = BlockDirichletBC([bottom_bc, sym_x_bc, sym_y_bc])
    bc = BlockDirichletBC([bottom_bc, left_bc_x, left_bc_y, \
                           right_bc_x, right_bc_y, front_bc_x, front_bc_y, \
                           back_bc_x, back_bc_y])

    # Variational forms
    # F = inner(sigma(u), eps(v))*dx + pen*dot(v[2], ppos(u[2]-obstacle))*ds(1)

    # F = [inner(sigma(u), eps(v))*dx - aug_l(l)*v[2]*ds(1) + ppos(aug_l(l))*v[2]*ds(1),
    #     (obstacle-u[2])*v*ds(1) - (1/pen)*ppos(aug_l(l))*v*ds(1)]

    # F_a = inner(sigma(u), eps(v))*dx
    # F_b = - aug_l(p)*v[2]*ds(1) + ppos(aug_l(p))*v[2]*ds(1)
    # F_c = (obstacle-u[2])*q*ds(1)
    # F_d = - (1/pen)*ppos(aug_l(p))*q*ds(1)
    #
    # block_F = [[F_a, F_b],
    #            [F_c, F_d]]

    F_a = inner(P(u), grad(v))*dx - dot(B, v)*dx - dot(T, v)*ds \
        - aug_l(p)*v[2]*ds(1) + ppos(aug_l(p))*v[2]*ds(1)

    F_b = (obstacle-u[2])*q*ds(1) - (1/pen)*ppos(aug_l(p))*q*ds(1)

    block_F = [F_a,
               F_b]
    J = block_derivative(block_F, block_u, block_du)

    # Setup solver
    problem = BlockNonlinearProblem(block_F, block_u, bc, J)
    solver = BlockPETScSNESSolver(problem)
    solver.parameters.update({
        "linear_solver": "mumps",
        "absolute_tolerance": 1E-4,
        "relative_tolerance": 1E-4,
        "maximum_iterations": 50,
        "report": True,
        "error_on_nonconvergence": True
    })

    # solver.parameters.update({
    #     "linear_solver": "cg",
    #     "absolute_tolerance": 1E-4,
    #     "relative_tolerance": 1E-4,
    #     "maximum_iterations": 50,
    #     "report": True,
    #     "error_on_nonconvergence": True
    # })

    # Perform a fake loop over time. Note how up will store the solution at the last time.
    # Q. for?
    # A. You can remove it, since your problem is stationary. The template was targeting
    #    a final application which was transient, but in which the ROM should have only
    #    described the final solution (when reaching the steady state).
    # for _ in range(2):
    #     solver.solve()
    a1 = solver.solve()
    print(a1)
        # save all the solution here as a function of time

    # Return the solution at the last time
    # Q. block_u or block
    # A. I think block_u, it will split split among the components elsewhere
    return block_u
        # Define the variational (projection problem)
        W_e = FiniteElement("DG", mesh.ufl_cell(), k)
        T_e = FiniteElement("DG", mesh.ufl_cell(), 0)
        Wbar_e = FiniteElement("DGT", mesh.ufl_cell(), k)

        W = FunctionSpace(mesh, W_e)
        T = FunctionSpace(mesh, T_e)
        Wbar = FunctionSpace(mesh, Wbar_e)

        psi_h, psi0_h = Function(W), Function(W)
        lambda_h = Function(T)
        psibar_h = Function(Wbar)

        # Boundary conditions
        bc = DirichletBC(Wbar, Constant(0.), "on_boundary")

        # Initialize forms
        FuncSpace_adv = {
            'FuncSpace_local': W,
            'FuncSpace_lambda': T,
            'FuncSpace_bar': Wbar
        }
        forms_pde = FormsPDEMap(mesh, FuncSpace_adv).forms_theta_linear(
            psi0_h, uh, dt, Constant(1.0))
        pde_projection = PDEStaticCondensation(
            mesh, p, forms_pde['N_a'], forms_pde['G_a'], forms_pde['L_a'],
            forms_pde['H_a'], forms_pde['B_a'], forms_pde['Q_a'],
            forms_pde['R_a'], forms_pde['S_a'], [bc], property_idx)

        # Set initial condition at mesh and particles
Esempio n. 18
0
 def bc(t):
     exact_solution_expression.t = t
     return [DirichletBC(V, exact_solution_expression, boundary)]
Esempio n. 19
0
 def dbc(self, subspace, subdomains, mark):
     return DirichletBC(subspace.sub(self.dim),
                        self.value, subdomains, mark)
Esempio n. 20
0
    def solve(self):
        """ Find eigenvalues for transformed mesh. """
        self.progress("Building mesh.")
        # build transformed mesh
        mesh = self.refineMesh()
        # dim = mesh.topology().dim()
        if self.bcLast:
            mesh = transform_mesh(mesh, self.transformList)
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
        else:
            Robin, Steklov, shift, bcs = get_bc_parts(mesh, self.bcList)
            mesh = transform_mesh(mesh, self.transformList)
            # boundary conditions computed on non-transformed mesh
            # copy the values to transformed mesh
            fun = FacetFunction("size_t", mesh, shift)
            fun.array()[:] = bcs.array()[:]
            bcs = fun
        ds = Measure('ds', domain=mesh, subdomain_data=bcs)
        V = FunctionSpace(mesh, self.method, self.deg)
        u = TrialFunction(V)
        v = TestFunction(V)
        self.progress("Assembling matrices.")
        wTop = Expression(self.wTop)
        wBottom = Expression(self.wBottom)

        #
        # build stiffness matrix form
        #
        s = dot(grad(u), grad(v)) * wTop * dx
        # add Robin parts
        for bc in Robin:
            s += Constant(bc.parValue) * u * v * wTop * ds(bc.value + shift)

        #
        # build mass matrix form
        #
        if len(Steklov) > 0:
            m = 0
            for bc in Steklov:
                m += Constant(
                    bc.parValue) * u * v * wBottom * ds(bc.value + shift)
        else:
            m = u * v * wBottom * dx

        # assemble
        # if USE_EIGEN:
        #     S, M = EigenMatrix(), EigenMatrix()
        # tempv = EigenVector()
        # else:
        S, M = PETScMatrix(), PETScMatrix()
        # tempv = PETScVector()

        if not np.any(bcs.array() == shift + 1):
            # no Dirichlet parts
            assemble(s, tensor=S)
            assemble(m, tensor=M)
        else:
            #
            # with EIGEN we could
            #   apply Dirichlet condition symmetrically
            #   completely remove rows and columns
            #
            # Dirichlet parts are marked with shift+1
            #
            # temp = Constant(0)*v*dx
            bc = DirichletBC(V, Constant(0.0), bcs, shift + 1)
            # assemble_system(s, temp, bc, A_tensor=S, b_tensor=tempv)
            # assemble_system(m, temp, bc, A_tensor=M, b_tensor=tempv)
            assemble(s, tensor=S)
            bc.apply(S)
            assemble(m, tensor=M)
            # bc.zero(M)

        # if USE_EIGEN:
        #    M = M.sparray()
        #    M.eliminate_zeros()
        #    print M.shape
        #    indices = M.indptr[:-1] - M.indptr[1:] < 0
        #    M = M[indices, :].tocsc()[:, indices]
        #    S = S.sparray()[indices, :].tocsc()[:, indices]
        #    print M.shape
        #
        # solve the eigenvalue problem
        #
        self.progress("Solving eigenvalue problem.")
        eigensolver = SLEPcEigenSolver(S, M)
        eigensolver.parameters["problem_type"] = "gen_hermitian"
        eigensolver.parameters["solver"] = "krylov-schur"
        if self.target is not None:
            eigensolver.parameters["spectrum"] = "target real"
            eigensolver.parameters["spectral_shift"] = self.target
        else:
            eigensolver.parameters["spectrum"] = "smallest magnitude"
            eigensolver.parameters["spectral_shift"] = -0.01
        eigensolver.parameters["spectral_transform"] = "shift-and-invert"
        eigensolver.solve(self.number)
        self.progress("Generating eigenfunctions.")
        if eigensolver.get_number_converged() == 0:
            return None
        eigf = []
        eigv = []
        if self.deg > 1:
            mesh = refine(mesh)
        W = FunctionSpace(mesh, 'CG', 1)
        for i in range(eigensolver.get_number_converged()):
            pair = eigensolver.get_eigenpair(i)[::2]
            eigv.append(pair[0])
            u = Function(V)
            u.vector()[:] = pair[1]
            eigf.append(interpolate(u, W))
        return eigv, eigf
Esempio n. 21
0
def _test_nonlinear_solver_sparse(callback_type):
    # Create mesh and define function space
    mesh = IntervalMesh(132, 0, 2*pi)
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Define Dirichlet boundary (x = 0 or x = 2*pi)
    def boundary(x):
        return x[0] < 0 + DOLFIN_EPS or x[0] > 2*pi - 10*DOLFIN_EPS
        
    # Define exact solution
    exact_solution_expression = Expression("x[0] + sin(2*x[0])", element=V.ufl_element())
    exact_solution = project(exact_solution_expression, V)

    # Define variational problem
    du = TrialFunction(V)
    v = TestFunction(V)
    u = Function(V)
    g = Expression("4*sin(2*x[0])*(pow(x[0]+sin(2*x[0]), 2)+1)-2*(x[0]+sin(2*x[0]))*pow(2*cos(2*x[0])+1, 2)", element=V.ufl_element())
    r = inner((1+u**2)*grad(u), grad(v))*dx - g*v*dx
    j = derivative(r, u, du)
    x = inner(du, v)*dx

    # Assemble inner product matrix
    X = assemble(x)
    
    # Define initial guess
    def sparse_initial_guess():
        initial_guess_expression = Expression("0.1 + 0.9*x[0]", element=V.ufl_element())
        return project(initial_guess_expression, V)

    # Define boundary condition
    bc = [DirichletBC(V, exact_solution_expression, boundary)]
    
    # Define callback function depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        def callback(arg):
            return arg
    elif callback_type == "tensor callbacks":
        def callback(arg):
            return assemble(arg)
    
    # Define problem wrapper
    class SparseFormProblemWrapper(NonlinearProblemWrapper):
        # Residual function
        def residual_eval(self, solution):
            return callback(r)
            
        # Jacobian function
        def jacobian_eval(self, solution):
            return callback(j)
            
        # Define boundary condition
        def bc_eval(self):
            return bc
        
    # Solve the nonlinear problem
    sparse_problem_wrapper = SparseFormProblemWrapper()
    sparse_solution = u
    assign(sparse_solution, sparse_initial_guess())
    sparse_solver = SparseNonlinearSolver(sparse_problem_wrapper, sparse_solution)
    sparse_solver.set_parameters({
        "linear_solver": "mumps",
        "maximum_iterations": 20,
        "report": True
    })
    sparse_solver.solve()

    # Compute the error
    sparse_error = Function(V)
    sparse_error.vector().add_local(+ sparse_solution.vector().get_local())
    sparse_error.vector().add_local(- exact_solution.vector().get_local())
    sparse_error.vector().apply("")
    sparse_error_norm = sparse_error.vector().inner(X*sparse_error.vector())
    print("SparseNonlinearSolver error (" + callback_type + "):", sparse_error_norm)
    assert isclose(sparse_error_norm, 0., atol=1.e-5)
    return (sparse_error_norm, V, u, r, j, X, sparse_initial_guess, exact_solution)
Esempio n. 22
0
# Define boundary condition
u_D = Expression(
    '1 + x[0]*x[0] + alpha*x[1]*x[1] + theta*x[2]*x[2] + beta*t',
    # '1 + beta*t',
    degree=2,
    alpha=alpha,
    theta=theta,
    beta=beta,
    t=0)


def boundary(x, on_boundary):
    return on_boundary


bc = DirichletBC(V, u_D, boundary)

# Define initial value
u_n = interpolate(u_D, V)
# u_n = project(u_D, V)

# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
f = Constant(beta - 2 - 2 * alpha)

F = u * v * dx + dt * dot(grad(u), grad(v)) * dx - (u_n + dt * f) * v * dx
a, L = lhs(F), rhs(F)

# Time-stepping
u = Function(V)
Esempio n. 23
0
    def __init__(self):
        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, _, cell_data, _ = meshes.ball_in_tube_cyl.generate()
        # 2018.1
        # self.mesh = Mesh(
        #     dolfin.mpi_comm_world(), dolfin.cpp.mesh.CellType.Type_triangle,
        #     points[:, :2], cells['triangle']
        #     )
        with TemporaryDirectory() as temp_dir:
            tmp_filename = os.path.join(temp_dir, "test.xml")
            meshio.write_points_cells(
                tmp_filename,
                points,
                cells,
                cell_data=cell_data,
                file_format="dolfin-xml",
            )
            self.mesh = Mesh(tmp_filename)

        V0_element = FiniteElement("CG", self.mesh.ufl_cell(), 2)
        V1_element = FiniteElement("B", self.mesh.ufl_cell(), 3)
        self.W = FunctionSpace(self.mesh, V0_element * V1_element)

        self.P = FunctionSpace(self.mesh, "CG", 1)

        # Define mesh and boundaries.
        class LeftBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] < GMSH_EPS

        left_boundary = LeftBoundary()

        class RightBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[0] > 1.0 - GMSH_EPS

        right_boundary = RightBoundary()

        class LowerBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                return on_boundary and x[1] < GMSH_EPS

        lower_boundary = LowerBoundary()

        # class UpperBoundary(SubDomain):
        #     # pylint: disable=no-self-use
        #     def inside(self, x, on_boundary):
        #         return on_boundary and x[1] > 5.0-GMSH_EPS

        class CoilBoundary(SubDomain):
            # pylint: disable=no-self-use
            def inside(self, x, on_boundary):
                # One has to pay a little bit of attention when defining the
                # coil boundary; it's easy to miss the edges closest to x[0]=0.
                return (on_boundary and x[1] > 1.0 - GMSH_EPS
                        and x[1] < 2.0 + GMSH_EPS and x[0] < 1.0 - GMSH_EPS)

        coil_boundary = CoilBoundary()

        self.u_bcs = [
            DirichletBC(self.W, (0.0, 0.0), right_boundary),
            DirichletBC(self.W.sub(0), 0.0, left_boundary),
            DirichletBC(self.W, (0.0, 0.0), lower_boundary),
            DirichletBC(self.W, (0.0, 0.0), coil_boundary),
        ]
        self.p_bcs = []
        # self.p_bcs = [DirichletBC(Q, 0.0, upper_boundary)]
        return
Esempio n. 24
0
            def __call__(self, degree=3, y=0., standard_deviation=1.):
                V = FunctionSpace(self._mesh, "CG", degree)
                v = TestFunction(V)
                potential_trial = TrialFunction(V)
                potential = Function(V)
                dx = Measure("dx")(subdomain_data=self._subdomains)
                # ds = Measure("ds")(subdomain_data=self._boundaries)
                csd = Expression(f'''
                                  x[1] >= {self.H} ?
                                  0 :
                                  a * exp({-0.5 / standard_deviation ** 2}
                                          * ((x[0])*(x[0])
                                             + (x[1] - {y})*(x[1] - {y})
                                             + (x[2])*(x[2])
                                             ))
                                  ''',
                                 degree=degree,
                                 a=1.0)

                self.a = csd.a = 1.0 / assemble(
                    csd * Measure("dx", self._mesh))
                # print(assemble(csd * Measure("dx", self._mesh)))
                L = csd * v * dx

                known_terms = assemble(L)
                # a = (inner(grad(potential_trial), grad(v))
                #      * (Constant(self.SALINE_CONDUCTIVITY) * dx(self.SALINE_VOL)
                #         + Constant(self.SLICE_CONDUCTIVITY) * (dx(self.SLICE_VOL)
                #                                                + dx(self.ROI_VOL))))
                a = sum(
                    Constant(conductivity) *
                    inner(grad(potential_trial), grad(v)) * dx(domain)
                    for domain, conductivity in [
                        (self.SALINE_VOL, self.SALINE_CONDUCTIVITY),
                        (self.SLICE_VOL, self.SLICE_CONDUCTIVITY),
                        (self.ROI_VOL, self.SLICE_CONDUCTIVITY),
                    ])
                terms_with_unknown = assemble(a)
                dirchlet_bc = DirichletBC(
                    V,
                    Constant(2.0 * 0.25 /
                             (self.RADIUS * np.pi * self.SALINE_CONDUCTIVITY)),
                    # 2.0 becaue of dielectric base duplicating
                    # the current source
                    # slice conductivity and thickness considered
                    # negligible
                    self._boundaries,
                    self.MODEL_DOME)
                dirchlet_bc.apply(terms_with_unknown, known_terms)
                solver = KrylovSolver("cg", "ilu")
                solver.parameters["maximum_iterations"] = MAX_ITER
                solver.parameters["absolute_tolerance"] = 1E-8
                # solver.parameters["monitor_convergence"] = True
                start = datetime.datetime.now()
                try:
                    self.iterations = solver.solve(terms_with_unknown,
                                                   potential.vector(),
                                                   known_terms)
                    return potential

                except RuntimeError as e:
                    self.iterations = MAX_ITER
                    logger.warning("Solver failed: {}".format(repr(e)))
                    return None

                finally:
                    self.time = datetime.datetime.now() - start
Esempio n. 25
0
def test_krylov_reuse_pc():
    "Test preconditioner re-use with PETScKrylovSolver"

    # Define problem
    mesh = UnitSquareMesh(MPI.comm_world, 8, 8)
    V = FunctionSpace(mesh, ('Lagrange', 1))
    bc = DirichletBC(V, Constant(0.0), lambda x, on_boundary: on_boundary)
    u = TrialFunction(V)
    v = TestFunction(V)

    # Forms
    a, L = inner(grad(u), grad(v)) * dx, dot(Constant(1.0), v) * dx

    A, P = PETScMatrix(), PETScMatrix()
    b = PETScVector()

    # Assemble linear algebra objects
    assemble(a, tensor=A)  # noqa
    assemble(a, tensor=P)  # noqa
    assemble(L, tensor=b)  # noqa

    # Apply boundary conditions
    bc.apply(A)
    bc.apply(P)
    bc.apply(b)

    # Create Krysolv solver and set operators
    solver = PETScKrylovSolver("gmres", "bjacobi")
    solver.set_operators(A, P)

    # Solve
    x = PETScVector()
    num_iter_ref = solver.solve(x, b)

    # Change preconditioner matrix (bad matrix) and solve (PC will be
    # updated)
    a_p = u * v * dx
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter_mod = solver.solve(x, b)
    assert num_iter_mod > num_iter_ref

    # Change preconditioner matrix (good matrix) and solve (PC will be
    # updated)
    a_p = a
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_ref

    # Change preconditioner matrix (bad matrix) and solve (PC will not
    # be updated)
    solver.set_reuse_preconditioner(True)
    a_p = u * v * dx
    assemble(a_p, tensor=P)  # noqa
    bc.apply(P)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_ref

    # Update preconditioner (bad PC, will increase iteration count)
    solver.set_reuse_preconditioner(False)
    x = PETScVector()
    num_iter = solver.solve(x, b)
    assert num_iter == num_iter_mod
Esempio n. 26
0
    degree=1)
rhs = -D * inner(grad(u), grad(v)) * dx + domainSource * v * dx


# Define left and right boundary
def boundaryLeft(x, on_boundary):
    return x[0] < DOLFIN_EPS


def boundaryRight(x, on_boundary):
    return 1.0 - x[0] < DOLFIN_EPS


# Left boundary has an explicit time dependency
boundarySource = Expression("t", t=0, degree=1)
bcLeft = DirichletBC(V, boundarySource, boundaryLeft)
bcRight = DirichletBC(V, 0.0, boundaryRight)

# Define the time domain
T = [0, 1.0]

# Define initial condition
W_exact = Function(V)
W_exact.interpolate(Constant(0.0))

exactSolver = ESDIRK(T,
                     W_exact,
                     rhs,
                     bcs=[bcLeft, bcRight],
                     tdfBC=[boundarySource],
                     tdf=[domainSource])
Esempio n. 27
0
    def __init__(self):
        n = 40
        self.mesh = UnitSquareMesh(n, n, "crossed")

        # Define mesh and boundaries.
        class LeftBoundary(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[0] < DOLFIN_EPS

        class RightBoundary(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[0] > 1.0 - DOLFIN_EPS

        class LowerBoundary(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[1] < DOLFIN_EPS

        class UpperBoundary(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[1] > 1.0 - DOLFIN_EPS

        class RestrictedUpperBoundary(SubDomain):
            def inside(self, x, on_boundary):
                return (on_boundary and x[1] > 1.0 - DOLFIN_EPS
                        and DOLFIN_EPS < x[0] and x[0] < 0.5 - DOLFIN_EPS)

        left = LeftBoundary()
        right = RightBoundary()
        lower = LowerBoundary()
        upper = UpperBoundary()
        # restricted_upper = RestrictedUpperBoundary()

        # Be particularly careful with the boundary conditions.
        # The main problem here is that the PPE system is consistent if and
        # only if
        #
        #     \int_\Omega div(u) = \int_\Gamma n.u = 0.
        #
        # This is exactly and even pointwise fulfilled for the continuous
        # problem.  In the discrete case, we can have to make sure that n.u is
        # 0 all along the boundary.
        # In the lid-driven cavity problem, of particular interest are the
        # corner points at the lid. One has to assert that the z-component of u
        # is 0 all across the lid, and the x-component of u is 0 everywhere but
        # the lid.  Since u is L2-"continuous", the lid condition on u_x must
        # not be enforced in the corner points. The u_y component must be
        # enforced all over the lid, including the end points.
        V_element = FiniteElement("CG", self.mesh.ufl_cell(), 2)
        self.W = FunctionSpace(self.mesh, V_element * V_element)

        self.u_bcs = [
            DirichletBC(self.W, (0.0, 0.0), left),
            DirichletBC(self.W, (0.0, 0.0), right),
            # DirichletBC(self.W.sub(0), Expression('x[0]'), restricted_upper),
            DirichletBC(self.W, (0.0, 0.0), lower),
            DirichletBC(self.W.sub(0), Constant("1.0"), upper),
            DirichletBC(self.W.sub(1), 0.0, upper),
            # DirichletBC(self.W.sub(0), Constant('-1.0'), lower),
            # DirichletBC(self.W.sub(1), 0.0, lower),
            # DirichletBC(self.W.sub(1), Constant('1.0'), left),
            # DirichletBC(self.W.sub(0), 0.0, left),
            # DirichletBC(self.W.sub(1), Constant('-1.0'), right),
            # DirichletBC(self.W.sub(0), 0.0, right),
        ]
        self.P = FunctionSpace(self.mesh, "CG", 1)
        self.p_bcs = []
        return
Esempio n. 28
0
# The mixed finite element space is known as Taylor–Hood.
# It is a stable, standard element pair for the Stokes
# equations. Now we can define boundary conditions::


# Extract subdomain facet arrays
mf = sub_domains.values
mf0 = np.where(mf == 0)
mf1 = np.where(mf == 1)

# No-slip boundary condition for velocity
# x1 = 0, x1 = 1 and around the dolphin
noslip = Function(W.sub(0).collapse())
noslip.interpolate(lambda x: np.zeros((x.shape[0], 2)))

bc0 = DirichletBC(W.sub(0), noslip, mf0[0])

# Inflow boundary condition for velocity
# x0 = 1


def inflow_eval(x):
    values = np.zeros((x.shape[0], 2))
    values[:, 0] = - np.sin(x[:, 1] * np.pi)
    return values


inflow = Function(W.sub(0).collapse())
inflow.interpolate(inflow_eval)
bc1 = DirichletBC(W.sub(0), inflow, mf1[0])
Esempio n. 29
0
def solve(mesh, Eps, degree):
    V = FunctionSpace(mesh, "CG", degree)
    u = TrialFunction(V)
    v = TestFunction(V)

    n = FacetNormal(mesh)

    gdim = mesh.geometry().dim()

    A = [
        _assemble_eigen(
            Constant(Eps[i, j]) *
            (u.dx(i) * v.dx(j) * dx - u.dx(i) * n[j] * v * ds)).sparray()
        for j in range(gdim) for i in range(gdim)
    ]

    assert_equality = False
    if assert_equality:
        # The sum of the `A`s is exactly that:
        n = FacetNormal(V.mesh())
        AA = _assemble_eigen(+dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx -
                             dot(dot(as_tensor(Eps), grad(u)), n) * v *
                             ds).sparray()
        diff = AA - sum(A)
        assert numpy.all(abs(diff.data) < 1.0e-14)
        #
        # ATAsum = sum(a.T.dot(a) for a in A)
        # diff = AA.T.dot(AA) - ATAsum
        # # import betterspy
        # # betterspy.show(ATAsum)
        # # betterspy.show(AA.T.dot(AA))
        # # betterspy.show(ATAsum - AA.T.dot(AA))
        # print(diff.data)
        # assert numpy.all(abs(diff.data) < 1.0e-14)

    tol = 1.0e-10

    def lower(x, on_boundary):
        return on_boundary and x[1] < -1.0 + tol

    def upper(x, on_boundary):
        return on_boundary and x[1] > 1.0 - tol

    def left(x, on_boundary):
        return on_boundary and abs(x[0] + 1.0) < tol

    def right(x, on_boundary):
        return on_boundary and abs(x[0] - 1.0) < tol

    def upper_left(x, on_boundary):
        return on_boundary and x[1] > +1.0 - tol and x[0] < -0.8

    def lower_right(x, on_boundary):
        return on_boundary and x[1] < -1.0 + tol and x[0] > 0.8

    bcs = [
        # DirichletBC(V, Constant(0.0), lower_right),
        # DirichletBC(V, Constant(0.0), upper_left),
        DirichletBC(V, Constant(0.0), lower),
        DirichletBC(V, Constant(0.0), upper),
        # DirichletBC(V, Constant(0.0), upper_left, method='pointwise'),
        # DirichletBC(V, Constant(0.0), lower_left, method='pointwise'),
        # DirichletBC(V, Constant(0.0), lower_right, method='pointwise'),
    ]

    M = _assemble_eigen(u * v * dx).sparray()

    ATMinvAsum = sum(
        numpy.dot(a.toarray().T, numpy.linalg.solve(M.toarray(), a.toarray()))
        for a in A)

    AA2 = _assemble_eigen(
        +dot(dot(as_tensor(Eps), grad(u)), grad(v)) * dx -
        dot(dot(as_tensor(Eps), grad(u)), n) * v * ds,
        # bcs=[DirichletBC(V, Constant(0.0), 'on_boundary')]
        # bcs=bcs
        # bcs=[
        #     DirichletBC(V, Constant(0.0), lower),
        #     DirichletBC(V, Constant(0.0), right),
        #     ]
    ).sparray()

    ATA2 = numpy.dot(AA2.toarray().T,
                     numpy.linalg.solve(M.toarray(), AA2.toarray()))

    # Find combination of Dirichlet points:
    if False:
        # min_val = 1.0
        max_val = 0.0
        # min_combi = []
        max_combi = []
        is_updated = False
        it = 0
        # get boundary indices
        d = DirichletBC(V, Constant(0.0), "on_boundary")
        boundary_idx = numpy.sort(list(d.get_boundary_values().keys()))
        # boundary_idx = numpy.arange(V.dim())
        # print(boundary_idx)
        # pick some at random
        # idx = numpy.sort(numpy.random.choice(boundary_idx, size=3, replace=False))
        for idx in itertools.combinations(boundary_idx, 3):
            it += 1
            print()
            print(it)

            # Replace the rows corresponding to test functions living in one cell
            # (deliberately chosen as 0) by Dirichlet rows.
            AA3 = AA2.tolil()
            for k in idx:
                AA3[k] = 0
                AA3[k, k] = 1
            n = AA3.shape[0]
            AA3 = AA3.tocsr()

            ATA2 = numpy.dot(AA3.toarray().T,
                             numpy.linalg.solve(M.toarray(), AA3.toarray()))
            vals = numpy.sort(numpy.linalg.eigvalsh(ATA2))
            if vals[0] < 0.0:
                continue

            # op = sparse.linalg.LinearOperator(
            #     (n, n),
            #     matvec=lambda x: _spsolve(AA3, M.dot(_spsolve(AA3.T.tocsr(), x)))
            #     )
            # vals, _ = scipy.sparse.linalg.eigsh(op, k=3, which='LM')
            # vals = numpy.sort(1/vals[::-1])
            # print(vals)

            print(idx)

            # if min_val > vals[0]:
            #     min_val = vals[0]
            #     min_combi = idx
            #     is_updated = True

            if max_val < vals[0]:
                max_val = vals[0]
                max_combi = idx
                is_updated = True

            if is_updated:
                # vals, _ = scipy.sparse.linalg.eigsh(op, k=10, which='LM')
                # vals = numpy.sort(1/vals[::-1])
                # print(vals)
                is_updated = False
                # print(min_val, min_combi)
                print(max_val, max_combi)
                # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x')
                meshzoo.plot2d(mesh.coordinates(), mesh.cells())
                dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
                # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or')
                plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob")
                plt.gca().set_aspect("equal")
                plt.title("smallest eigenvalue: {}".format(max_val))
                plt.show()

            # # if True:
            # if abs(vals[0]) < 1.0e-8:
            #     gdim = mesh.geometry().dim()
            #     # plt.plot(dofs_x[:, 0], dofs_x[:, 1], 'x')
            #     X = mesh.coordinates()
            #     meshzoo.plot2d(mesh.coordinates(), mesh.cells())
            #     dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
            #     plt.plot(dofs_x[idx, 0], dofs_x[idx, 1], 'or')
            #     plt.gca().set_aspect('equal')
            #     plt.show()

        meshzoo.plot2d(mesh.coordinates(), mesh.cells())
        dofs_x = V.tabulate_dof_coordinates().reshape((-1, gdim))
        # plt.plot(dofs_x[min_combi, 0], dofs_x[min_combi, 1], 'or')
        plt.plot(dofs_x[max_combi, 0], dofs_x[max_combi, 1], "ob")
        plt.gca().set_aspect("equal")
        plt.title("final smallest eigenvalue: {}".format(max_val))
        plt.show()
        exit(1)

    # Eigenvalues of the operators
    if True:
        # import betterspy
        # betterspy.show(sum(A), colormap="viridis")

        AA = _assemble_eigen(+dot(grad(u), grad(v)) * dx -
                             dot(grad(u), n) * v * ds).sparray()

        eigvals, eigvecs = scipy.sparse.linalg.eigs(AA, k=5, which="SM")

        assert numpy.all(numpy.abs(eigvals.imag) < 1.0e-12)
        eigvals = eigvals.real
        assert numpy.all(numpy.abs(eigvecs.imag) < 1.0e-12)
        eigvecs = eigvecs.real

        i = numpy.argsort(eigvals)
        print(eigvals[i])

        import meshio

        for k in range(3):
            meshio.write_points_cells(
                f"eigval{k}.vtk",
                points,
                {"triangle": cells},
                point_data={"ev": eigvecs[:, i][:, k]},
            )
        exit(1)

        # import betterspy
        # betterspy.show(AA, colormap="viridis")
        # print(numpy.sort(numpy.linalg.eigvals(AA.todense())))
        exit(1)

        Asum = sum(A).todense()
        AsumT_Minv_Asum = numpy.dot(Asum.T,
                                    numpy.linalg.solve(M.toarray(), Asum))

        # print(numpy.sort(numpy.linalg.eigvalsh(Asum)))
        print(numpy.sort(numpy.linalg.eigvalsh(AsumT_Minv_Asum)))
        exit(1)

        # eigvals, eigvecs = numpy.linalg.eigh(Asum)
        # i = numpy.argsort(eigvals)
        # print(eigvals[i])
        # exit(1)
        # print(eigvals[:20])
        # eigvals[eigvals < 1.0e-15] = 1.0e-15
        #
        # eigvals = numpy.sort(numpy.linalg.eigvalsh(sum(A).todense()))
        # print(eigvals[:20])
        # plt.semilogy(eigvals, ".", label="Asum")
        # plt.legend()
        # plt.grid()
        # plt.show()
        # exit(1)

        ATMinvAsum_eigs = numpy.sort(numpy.linalg.eigvalsh(ATMinvAsum))
        print(ATMinvAsum_eigs[:20])
        ATMinvAsum_eigs[ATMinvAsum_eigs < 0.0] = 1.0e-12
        # ATA2_eigs = numpy.sort(numpy.linalg.eigvalsh(ATA2))
        # print(ATA2_eigs[:20])
        plt.semilogy(ATMinvAsum_eigs, ".", label="ATMinvAsum")
        # plt.semilogy(ATA2_eigs, ".", label="ATA2")
        plt.legend()
        plt.grid()
        plt.show()
        # # Preconditioned eigenvalues
        # # IATA_eigs = numpy.sort(scipy.linalg.eigvalsh(ATMinvAsum, ATA2))
        # # plt.semilogy(IATA_eigs, ".", label="precond eigenvalues")
        # # plt.legend()
        # # plt.show()
        exit(1)

    # # Test with A only
    # numpy.random.seed(123)
    # b = numpy.random.rand(sum(a.shape[0] for a in A))
    # MTM = M.T.dot(M)
    # MTb = M.T.dot(b)
    # sol = _gmres(
    #     MTM,
    #     # TODO linear operator
    #     # lambda x: M.T.dot(M.dot(x)),
    #     MTb,
    #     M=prec
    #     )
    # plt.semilogy(sol.resnorms)
    # plt.show()
    # exit(1)

    n = AA2.shape[0]

    # define the operator
    def matvec(x):
        # M^{-1} can be computed in O(n) with CG + diagonal preconditioning
        # or algebraic multigrid.
        # return sum([a.T.dot(a.dot(x)) for a in A])
        return numpy.sum([a.T.dot(_spsolve(M, a.dot(x))) for a in A], axis=0)

    op = sparse.linalg.LinearOperator((n, n), matvec=matvec)

    # pick a random solution and a consistent rhs
    x = numpy.random.rand(n)
    b = op.dot(x)

    linear_system = krypy.linsys.LinearSystem(op, b)
    print("unpreconditioned solve...")
    t = time.time()
    out = krypy.linsys.Gmres(linear_system,
                             tol=1.0e-12,
                             explicit_residual=True)
    out.xk = out.xk.reshape(b.shape)
    print("done.")
    print("  res: {}".format(out.resnorms[-1]))
    print("  unprec res: {}".format(
        numpy.linalg.norm(b - op.dot(out.xk)) / numpy.linalg.norm(b)))
    # The error isn't useful here; only with the nullspace removed
    # print('  error: {}'.format(numpy.linalg.norm(out.xk - x)))
    print("  its: {}".format(len(out.resnorms)))
    print("  duration: {}s".format(time.time() - t))

    # preconditioned solver
    ml = pyamg.smoothed_aggregation_solver(AA2)
    # res = []
    # b = numpy.random.rand(AA2.shape[0])
    # x0 = numpy.zeros(AA2.shape[1])
    # x = ml.solve(b, x0, residuals=res, tol=1.0e-12)
    # print(res)
    # plt.semilogy(res)
    # plt.show()

    mlT = pyamg.smoothed_aggregation_solver(AA2.T.tocsr())

    # res = []
    # b = numpy.random.rand(AA2.shape[0])
    # x0 = numpy.zeros(AA2.shape[1])
    # x = mlT.solve(b, x0, residuals=res, tol=1.0e-12)

    # print(res)
    def prec_matvec(b):
        x0 = numpy.zeros(n)
        b1 = mlT.solve(b, x0, tol=1.0e-12)
        b2 = M.dot(b1)
        x = ml.solve(b2, x0, tol=1.0e-12)
        return x

    prec = LinearOperator((n, n), matvec=prec_matvec)

    # TODO assert this in a test
    # x = prec_matvec(b)
    # print(b - AA2.T.dot(AA2.dot(x)))

    linear_system = krypy.linsys.LinearSystem(op, b, Ml=prec)
    print()
    print("preconditioned solve...")
    t = time.time()
    try:
        out_prec = krypy.linsys.Gmres(linear_system,
                                      tol=1.0e-14,
                                      maxiter=1000,
                                      explicit_residual=True)
    except krypy.utils.ConvergenceError:
        print("prec not converged!")
        pass
    out_prec.xk = out_prec.xk.reshape(b.shape)
    print("done.")
    print("  res: {}".format(out_prec.resnorms[-1]))
    print("  unprec res: {}".format(
        numpy.linalg.norm(b - op.dot(out_prec.xk)) / numpy.linalg.norm(b)))
    print("  its: {}".format(len(out_prec.resnorms)))
    print("  duration: {}s".format(time.time() - t))

    plt.semilogy(out.resnorms, label="original")
    plt.semilogy(out_prec.resnorms, label="preconditioned")
    plt.legend()
    plt.show()

    return out.xk
Esempio n. 30
0
    def update_mesh_from_boundary_nodes(self, perturbation):
        """
        Deform mesh with boundary perturbation (a numpy array)
        given as Neumann input in an linear elastic mesh deformation.
        """
        # Reset mesh
        self.mesh.coordinates()[:] = self.backup
        volume_function = Function(self.S)

        for i in self.design_map.keys():
            volume_function.vector()[self.design_map[i]] = perturbation[i]
        u, v = TrialFunction(self.S), TestFunction(self.S)

        def compute_mu(constant=True):
            """
            Compute mu as according to arxiv paper
            https://arxiv.org/pdf/1509.08601.pdf
            """
            mu_min=Constant(1)
            mu_max=Constant(500)
            if constant:
                return mu_max
            else:
                V = FunctionSpace(self.mesh, "CG",1)
                u, v = TrialFunction(V), TestFunction(V)
                a = inner(grad(u),grad(v))*dx
                l = Constant(0)*v*dx
                bcs = []
                for marker in self.move_dict["Fixed"]:
                    bcs.append(DirichletBC(V, mu_min, self.mf, marker))
                for marker in self.move_dict["Deform"]:
                    bcs.append(DirichletBC(V, mu_max, self.mf, marker))
                mu = Function(V)
                solve(a==l, mu, bcs=bcs)
                return mu
        mu = compute_mu(False)
        
        def epsilon(u):
            return sym(grad(u))
        def sigma(u,mu=500, lmb=0):
            return 2*mu*epsilon(u) + lmb*tr(epsilon(u))*Identity(2)
        a = inner(sigma(u,mu=mu), grad(v))*dx
        L = inner(Constant((0,0)), v)*dx

        
        bcs = []
        for marker in self.move_dict["Fixed"]:
            bcs.append(DirichletBC(self.S,
                                   Constant([0]*mesh.geometric_dimension()),
                                   self.mf, marker))
            
        dStress = Measure("ds", subdomain_data=self.mf)
        from femorph import VolumeNormal
        n = VolumeNormal(mesh)

        # Enforcing node movement through elastic stress computation
        # NOTE: This strategy does only work for the first part of the deformation
        for marker in self.move_dict["Deform"]:
            L += inner(volume_function, v)*dStress(marker)
        # Direct control of boundary nodes
        # for marker in self.move_dict["Deform"]:
        #     bcs.append(DirichletBC(self.S, volume_function, self.mf, marker))
        s = Function(self.S)
        solve(a==L, s, bcs=bcs)
        self.perturbation = s
        ALE.move(self.mesh, self.perturbation)