コード例 #1
0
ファイル: utils.py プロジェクト: pgh79/scikit-fem
def derivative(x: ndarray,
               basis1: GlobalBasis,
               basis0: GlobalBasis,
               i: Optional[int] = 0) -> ndarray:
    """Calculate the i'th partial derivative through projection.

    Parameters
    ----------
    x
        The solution vector.
    basis1
        The basis corresponding to the solution x (e.g. P_1).
    basis0
        The basis corresponding to the derivative field (e.g. P_0).
    i
        Return i'th partial derivative.

    Returns
    -------
    ndarray
        A new solution vector corresponding to the derivative.

    """
    @bilinear_form
    def deriv(u, du, v, dv, w):
        return du[i] * v

    @bilinear_form
    def mass(u, du, v, dv, w):
        return u * v

    A = asm(deriv, basis1, basis0)
    M = asm(mass, basis0)

    return solve(M, A @ x)
コード例 #2
0
ファイル: utils.py プロジェクト: HadrienNU/scikit-fem
def projection(fun,
               basis_to: Optional[Basis] = None,
               basis_from: Optional[Basis] = None,
               diff: Optional[int] = None,
               I: Optional[ndarray] = None,
               expand: bool = False) -> ndarray:
    """Perform projections onto a finite element basis.

    Parameters
    ----------
    fun
        A solution vector or a function handle.
    basis_to
        The finite element basis to project to.
    basis_from
        The finite element basis to project from.
    diff
        Differentiate with respect to the given dimension.
    I
        Index set for limiting the projection to a subset.
    expand
        Passed to :func:`skfem.utils.condense`.

    Returns
    -------
    ndarray
        The projected solution vector.

    """
    @BilinearForm
    def mass(u, v, w):
        p = u * v
        return sum(p) if isinstance(basis_to.elem, ElementVector) else p

    @LinearForm
    def funv(v, w):
        p = fun(w.x) * v
        return sum(p) if isinstance(basis_to.elem, ElementVector) else p

    @BilinearForm
    def deriv(u, v, w):
        from skfem.helpers import grad
        du = grad(u)
        return du[diff] * v

    M = asm(mass, basis_to)

    if not isinstance(fun, ndarray):
        f = asm(funv, basis_to)
    else:
        if diff is not None:
            f = asm(deriv, basis_from, basis_to) @ fun
        else:
            f = asm(mass, basis_from, basis_to) @ fun

    if I is not None:
        return solve_linear(*condense(M, f, I=I, expand=expand))

    return solve_linear(M, f)
コード例 #3
0
def project(fun,
            basis_from: Basis = None,
            basis_to: Basis = None,
            diff: int = None,
            I: ndarray = None) -> ndarray:
    """Projection from one basis to another.

    Parameters
    ----------
    fun
        A solution vector or a function handle.
    basis_from
        The finite element basis to project from.
    basis_to
        The finite element basis to project to.
    diff
        Differentiate with respect to the given dimension.
    I
        Index set for limiting the projection to a subset.

    Returns
    -------
    ndarray
        The projected solution vector.

    """

    @BilinearForm
    def mass(u, v, w):
        p = u * v
        return sum(p) if isinstance(basis_to.elem, ElementVectorH1) else p

    @LinearForm
    def funv(v, w):
        p = fun(*w.x) * v
        return sum(p) if isinstance(basis_to.elem, ElementVectorH1) else p

    @BilinearForm
    def deriv(u, v, w):
        from skfem.helpers import grad
        du = grad(u)
        return du[diff] * v

    M = asm(mass, basis_to)

    if not isinstance(fun, ndarray):
        f = asm(funv, basis_to)
    else:
        if diff is not None:
            f = asm(deriv, basis_from, basis_to) @ fun
        else:
            f = asm(mass, basis_from, basis_to) @ fun

    if I is not None:
        return solve(*condense(M, f, I=I, expand=False))

    return solve(M, f)
コード例 #4
0
def solve_problem1(m,
                   element_type='P1',
                   solver_type='pcg',
                   intorder=6,
                   tol=1e-8,
                   epsilon=1e-6,
                   basis_only=False):
    '''
    switching to mgcg solver for problem 1
    '''
    if element_type == 'P1':
        element = {'w': ElementTriP1(), 'u': ElementTriMorley()}
    elif element_type == 'P2':
        element = {'w': ElementTriP2(), 'u': ElementTriMorley()}
    else:
        raise Exception("Element not supported")

    basis = {
        variable: InteriorBasis(m, e, intorder=intorder)
        for variable, e in element.items()
    }  # intorder: integration order for quadrature

    if basis_only:
        return basis

    K1 = asm(laplace, basis['w'])
    f1 = asm(f_load, basis['w'])

    if solver_type == 'amg':
        wh = solve(*condense(K1, f1, D=basis['w'].find_dofs()),
                   solver=solver_iter_pyamg(tol=tol))
    elif solver_type == 'pcg':
        wh = solve(*condense(K1, f1, D=basis['w'].find_dofs()),
                   solver=solver_iter_krylov(Precondition=True, tol=tol))
    elif solver_type == 'mgcg':
        wh = solve(*condense(K1, f1, D=basis['w'].find_dofs()),
                   solver=solver_iter_mgcg(tol=tol))
    else:
        raise Exception("Solver not supported")

    K2 = epsilon**2 * asm(a_load, basis['u']) + asm(b_load, basis['u'])
    f2 = asm(wv_load, basis['w'], basis['u']) * wh

    if solver_type == 'amg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary(m, basis['u'])),
                    solver=solver_iter_pyamg(tol=tol))
    elif solver_type == 'pcg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary(m, basis['u'])),
                    solver=solver_iter_krylov(Precondition=True, tol=tol))
    elif solver_type == 'mgcg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary(m, basis['u'])),
                    solver=solver_iter_mgcg(tol=tol))
    else:
        raise Exception("Solver not supported")

    return uh0, basis
コード例 #5
0
ファイル: utils.py プロジェクト: zhucer2003/scikit-fem
def derivative(x, basis1, basis0, i=0):
    """Calculate the i'th partial derivative through projection."""
    from skfem.assembly import asm, bilinear_form

    @bilinear_form
    def deriv(u, du, v, dv, w):
        return du[i] * v

    @bilinear_form
    def mass(u, du, v, dv, w):
        return u * v

    A = asm(deriv, basis1, basis0)
    M = asm(mass, basis0)

    return solve(M, A @ x)
コード例 #6
0
ファイル: utils.py プロジェクト: YerbaPage/FEM_forth_perturb
def solve_problem2(m, element_type='P1', solver_type='pcg', intorder=6, tol=1e-8, epsilon=1e-6):
    '''
    adding mgcg solver for problem 2
    '''
    if element_type == 'P1':
        element = {'w': ElementTriP1(), 'u': ElementTriMorley()}
    elif element_type == 'P2':
        element = {'w': ElementTriP2(), 'u': ElementTriMorley()}
    else:
        raise Exception("The element not supported")

    basis = {
        variable: InteriorBasis(m, e, intorder=intorder)
        for variable, e in element.items()
    }

    K1 = asm(laplace, basis['w'])
    f1 = asm(f_load, basis['w'])

    if solver_type == 'amg':
        wh = solve(
            *condense(K1, f1, D=basis['w'].find_dofs()), solver=solver_iter_pyamg(tol=tol))
    elif solver_type == 'pcg':
        wh = solve(*condense(K1, f1, D=basis['w'].find_dofs()),
                   solver=solver_iter_krylov(Precondition=True, tol=tol))
    elif solver_type == 'mgcg':
        wh = solve(
            *condense(K1, f1, D=basis['w'].find_dofs()), solver=solver_iter_mgcg(tol=tol))
    else:
        raise Exception("Solver not supported")

    fbasis = FacetBasis(m, element['u'])

    p1 = asm(penalty_1, fbasis)
    p2 = asm(penalty_2, fbasis)
    p3 = asm(penalty_3, fbasis)
    P = p1 + p2 + p3

    K2 = epsilon**2 * asm(a_load, basis['u']) + \
        epsilon**2 * P + asm(b_load, basis['u'])
    f2 = asm(wv_load, basis['w'], basis['u']) * wh

    if solver_type == 'amg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary_penalty(m,
                                                              basis['u'])), solver=solver_iter_pyamg(tol=tol))
    elif solver_type == 'pcg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary_penalty(m,
                                                              basis['u'])), solver=solver_iter_krylov(Precondition=True, tol=tol))
    elif solver_type == 'mgcg':
        uh0 = solve(*condense(K2, f2, D=easy_boundary_penalty(m,
                                                              basis['u'])), solver=solver_iter_mgcg(tol=tol))
    else:
        raise Exception("Solver not supported")

    return uh0, basis, fbasis
コード例 #7
0
ファイル: utils.py プロジェクト: pgh79/scikit-fem
def L2_projection(fun,
                  basis: GlobalBasis,
                  ix: Optional[ndarray] = None) -> ndarray:
    """Initialize a solution vector with L2 projection.

    Parameters
    ----------
    fun
        The function to project.
    basis
        The finite element basis
    ix
        Do the projection only on a subset of DOF's.

    Returns
    -------
    ndarray
        The projected solution vector.

    """

    if ix is None:
        ix = np.arange(basis.N)

    @bilinear_form
    def mass(u, du, v, dv, w):
        p = u * v
        return sum(p) if isinstance(basis.elem, ElementVectorH1) else p

    @linear_form
    def funv(v, dv, w):
        p = fun(*w.x) * v
        return sum(p) if isinstance(basis.elem, ElementVectorH1) else p

    M = asm(mass, basis)
    f = asm(funv, basis)

    return solve(*condense(M, f, I=ix))
コード例 #8
0
ファイル: utils.py プロジェクト: xanderyin/scikit-fem
def project(fun,
            basis_from: Basis = None,
            basis_to: Basis = None,
            diff: int = None,
            I: ndarray = None,
            expand: bool = False) -> ndarray:
    """Projection from one basis to another.

    Parameters
    ----------
    fun
        A solution vector or a function handle.
    basis_from
        The finite element basis to project from.
    basis_to
        The finite element basis to project to.
    diff
        Differentiate with respect to the given dimension.
    I
        Index set for limiting the projection to a subset.
    expand
        Passed to :func:`skfem.utils.condense`.

    Returns
    -------
    ndarray
        The projected solution vector.

    """
    @BilinearForm
    def mass(u, v, w):
        p = u * v
        return sum(p) if isinstance(basis_to.elem, ElementVectorH1) else p

    @LinearForm
    def funv(v, w):
        if len(signature(fun).parameters) == 1:
            p = fun(w.x) * v
        else:
            warnings.warn(
                "The function provided to 'project' should "
                "take only one argument in the future.", DeprecationWarning)
            p = fun(*w.x) * v
        return sum(p) if isinstance(basis_to.elem, ElementVectorH1) else p

    @BilinearForm
    def deriv(u, v, w):
        from skfem.helpers import grad
        du = grad(u)
        return du[diff] * v

    M = asm(mass, basis_to)

    if not isinstance(fun, ndarray):
        f = asm(funv, basis_to)
    else:
        if diff is not None:
            f = asm(deriv, basis_from, basis_to) @ fun
        else:
            f = asm(mass, basis_from, basis_to) @ fun

    if I is not None:
        return solve(*condense(M, f, I=I, expand=expand))

    return solve(M, f)