Example #1
0
def SchemeUniform(u, SB, f, bc):
    # Compute the finite differences along the superbase directions
    d2u = bc.Diff2(u, SB)
    d2u[..., bc.not_interior] = 0.  # Placeholder value to silent NaN warnings

    # Generate the parameters for the low dimensional optimization problem
    Q = 0.5 * np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]])
    l = -d2u
    m = lp.dot_VV(SB, SB)

    # Evaluate the numerical scheme
    m = bc.as_field(m)
    from agd.FiniteDifferences import as_field
    Q = as_field(Q, m.shape[1:])

    dim = 2
    alpha = dim * f**(1 / dim)
    mask = (alpha == 0)

    Q = Q * np.where(mask, 1., alpha**2)
    residue = ConstrainedMaximize(Q, l, m).max(axis=0)
    residue[mask] = np.max(l / m, axis=0).max(axis=0)[mask]

    # Boundary conditions
    return ad.where(bc.interior, residue, u - bc.grid_values)
def SchemeCentered(u,cst,mult,omega,diff,bc,ret_hmax=False):
    """Discretization of a linear non-divergence form second order PDE
        cst + mult u + <omega,grad u>- tr(diff hess(u)) = 0
        Second order accurate, centered yet monotone finite differences are used for <omega,grad u>
        - bc : boundary conditions. 
        - ret_hmax : return the largest grid scale for which monotony holds
    """
    # Decompose the tensor field
    coefs2,offsets = Selling.Decomposition(diff)
    
    # Decompose the vector field
    scals = lp.dot_VA(lp.solve_AV(diff,omega), offsets.astype(float))
    coefs1 = coefs2*scals
    if ret_hmax: return 2./norm(scals,ord=np.inf)
    
    # Compute the first and second order finite differences    
    du  = bc.DiffCentered(u,offsets)
    d2u = bc.Diff2(u,offsets)
    
    # In interior : cst + mult u + <omega,grad u>- tr(diff hess(u)) = 0
    coefs1,coefs2 = (bc.as_field(e) for e in (coefs1,coefs2))    
    residue = cst + mult*u +lp.dot_VV(coefs1,du) - lp.dot_VV(coefs2,d2u)
    
    # On boundary : u-bc = 0
    return ad.where(bc.interior,residue,u-bc.grid_values)
Example #3
0
def SchemeSampling_Opt(u, diffs, beta, bc):
    # Evaluate the operator using the envelope theorem
    result, _ = ad.apply(SchemeSampling_OptInner,
                         u,
                         bc.as_field(diffs),
                         bc,
                         envelope=True)

    # Boundary conditions
    return ad.where(bc.interior, beta - result, u - bc.grid_values)
Example #4
0
def SchemeSampling(u, diffs, beta, bc):
    # Tensor decomposition
    coefs, offsets = Selling.Decomposition(diffs)

    # Numerical scheme
    coefs = bc.as_field(coefs)
    residue = beta - (coefs * bc.Diff2(u, offsets)).sum(0).min(0)

    # Boundary conditions
    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #5
0
def SchemeMALBR_Opt(u, SB, f, bc):

    # Evaluate using the envelope theorem
    result, _ = ad.apply(SchemeMALBR_OptInner,
                         u,
                         bc.as_field(SB),
                         bc,
                         envelope=True)

    # Boundary conditions
    return ad.where(bc.interior, f - result, u - bc.grid_values)
Example #6
0
def SchemeMALBR(u, SB, f, bc):
    # Compute the finite differences along the superbase directions
    d2u = bc.Diff2(u, SB)
    d2u[..., bc.
        not_interior] = 0.  # Replace NaNs with arbitrary values to silence warnings

    # Numerical scheme
    residue = f - MALBR_H(d2u).min(axis=0)

    # Boundary conditions
    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #7
0
def SchemeUniform_Opt(u, SB, f, bc):

    # Evaluate the maximum over the superbases using the envelope theorem
    residue, _ = ad.apply(SchemeUniform_OptInner,
                          u,
                          bc.as_field(SB),
                          f,
                          bc,
                          envelope=True)

    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #8
0
def SchemeNonMonotone(u, f, bc):
    # Compute the hessian matrix of u
    uxx = bc.Diff2(u, (1, 0))
    uyy = bc.Diff2(u, (0, 1))
    uxy = 0.25 * (bc.Diff2(u, (1, 1)) - bc.Diff2(u, (1, -1)))

    # Numerical scheme
    det = uxx * uyy - uxy**2
    residue = f - det

    # Boundary conditions
    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #9
0
def MALBR_H(d2u):
    a, b, c = ad.sort(np.maximum(0., d2u), axis=0)

    # General formula, handling infinite values separately
    A, B, C = (ad.where(e == np.inf, 0., e) for e in (a, b, c))
    result = 0.5 * (A * B + B * C + C * A) - 0.25 * (A**2 + B**2 + C**2)

    pos_inf = np.logical_or.reduce(d2u == np.inf)
    result[pos_inf] = np.inf

    pos_ineq = a + b < c
    result[pos_ineq] = (A * B)[pos_ineq]

    return result
Example #10
0
def SchemeLaxFriedrichs(u, A, F, bc):
    """
    Discretization of - Tr(A(x) hess u(x)) + F(grad u(x)) - 1 = 0,
    with Dirichlet boundary conditions. The scheme is second order,
    and degenerate elliptic under suitable assumptions.
    """
    # Compute the tensor decomposition
    coefs, offsets = Selling.Decomposition(A)
    A, coefs, offsets = (bc.as_field(e) for e in (A, coefs, offsets))

    # Obtain the first and second order finite differences
    grad = Gradient(u, A, bc, decomp=(coefs, offsets))
    d2u = bc.Diff2(u, offsets)

    # Numerical scheme in interior
    residue = -lp.dot_VV(coefs, d2u) + F(grad) - 1.

    # Placeholders outside domain
    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #11
0
def SchemeNonMonotone(u, alpha, beta, bc, sqrt_relax=1e-6):
    # Compute the hessian matrix of u
    uxx = bc.Diff2(u, (1, 0))
    uyy = bc.Diff2(u, (0, 1))
    uxy = 0.25 * (bc.Diff2(u, (1, 1)) - bc.Diff2(u, (1, -1)))

    # Compute the eigenvalues
    # The relaxation is here to tame the non-differentiability of the square root.
    htr = (uxx + uyy) / 2.
    sdelta = np.sqrt(np.maximum(((uxx - uyy) / 2.)**2 + uxy**2, sqrt_relax))

    lambda_max = htr + sdelta
    lambda_min = htr - sdelta

    # Numerical scheme
    residue = beta - alpha * lambda_max - lambda_min

    # Boundary conditions
    return ad.where(bc.interior, residue, u - bc.grid_values)
def SchemeUpwind(u,cst,mult,omega,diff,bc):
    """Discretization of a linear non-divergence form second order PDE
        cst + mult u + <omega,grad u>- tr(diff hess(u)) = 0
        First order accurate, upwind finite differences are used for <omega,grad u>
        - bc : boundary conditions. 
    """
    # Decompose the tensor field
    coefs2,offsets2 = Selling.Decomposition(diff)
    omega,coefs2 = (bc.as_field(e) for e in (omega,coefs2))    

    # Decompose the vector field
    coefs1 = -np.abs(omega)
    basis = bc.as_field(np.eye(len(omega)))
    offsets1 = -np.sign(omega)*basis
    
    # Compute the first and second order finite differences    
    du  = bc.DiffUpwind(u,offsets1.astype(int))
    d2u = bc.Diff2(u,offsets2)
    
    # In interior : cst + mult u + <omega,grad u>- tr(diff hess(u)) = 0
    residue = cst + mult*u +lp.dot_VV(coefs1,du) - lp.dot_VV(coefs2,d2u)
    
    # On boundary : u-bc = 0
    return ad.where(bc.interior,residue,u-bc.grid_values)
Example #13
0
def SchemeConsistent_Opt(u, alpha, beta, bc):
    value, _ = ad.apply(MinimizeTrace_Opt, u, alpha, bc, envelope=True)
    residue = beta - value
    return ad.where(bc.interior, residue, u - bc.grid_values)
Example #14
0
def SchemeConsistent(u, alpha, beta, bc):
    value, _ = MinimizeTrace(u, alpha, bc)
    residue = beta - value
    return ad.where(bc.interior, residue, u - bc.grid_values)