1

私は現在、自分のコードで機能していないものに非常にこだわっており、何時間も見つめています。有限要素法を使用してラプラス方程式の解を適応的に近似し、二重加重残差を使用してその誤差を推定する関数をいくつか作成しました。エラー関数は、エラーのベクトル (要素ごとに 1 つのエラー) を提供する必要があります。次に、最大のエラーを選択し、それらの周りにさらに要素を追加し、再度解決してエラーを再チェックします。しかし、エラーの見積もりが変わらない理由がわかりません!

私の最初の 4 つの関数は正しいですが、誰かがコードを試してみたい場合に備えてそれらを含めます。

def Poisson_Stiffness(x0):
    """Finds the Poisson equation stiffness matrix with any non uniform mesh x0"""

    x0 = np.array(x0)
    N = len(x0) - 1 # The amount of elements; x0, x1, ..., xN

    h = x0[1:] - x0[:-1]

    a = np.zeros(N+1)
    a[0] = 1 #BOUNDARY CONDITIONS
    a[1:-1] = 1/h[1:] + 1/h[:-1]
    a[-1] = 1/h[-1]
    a[N] = 1 #BOUNDARY CONDITIONS

    b = -1/h
    b[0] = 0 #BOUNDARY CONDITIONS

    c = -1/h
    c[N-1] = 0 #BOUNDARY CONDITIONS: DIRICHLET

    data = [a.tolist(), b.tolist(), c.tolist()]
    Positions = [0, 1, -1]
    Stiffness_Matrix = diags(data, Positions, (N+1,N+1))

    return Stiffness_Matrix

def NodalQuadrature(x0):
    """Finds the Nodal Quadrature Approximation of sin(pi x)"""

    x0 = np.array(x0)
    h = x0[1:] - x0[:-1]
    N = len(x0) - 1

    approx = np.zeros(len(x0))
    approx[0] = 0 #BOUNDARY CONDITIONS

    for i in range(1,N):
        approx[i] = math.sin(math.pi*x0[i])
        approx[i] = (approx[i]*h[i-1] + approx[i]*h[i])/2

    approx[N] = 0 #BOUNDARY CONDITIONS

    return approx

def Solver(x0):

    Stiff_Matrix = Poisson_Stiffness(x0)

    NodalApproximation = NodalQuadrature(x0)
    NodalApproximation[0] = 0

    U = scipy.sparse.linalg.spsolve(Stiff_Matrix, NodalApproximation)

    return U

def Dualsolution(rich_mesh,qoi_rich_node): #BOUNDARY CONDITIONS?
    """Find Z from stiffness matrix Z = K^-1 Q over richer mesh"""

    K = Poisson_Stiffness(rich_mesh)
    Q = np.zeros(len(rich_mesh))
    Q[qoi_rich_node] = 1.0

    Z = scipy.sparse.linalg.spsolve(K,Q)
    return Z

私のエラー インジケーター関数は、解決されたメッシュを使用して近似値を取得し、eta = (f - Bu)z を見つけます。

def Error_Indicators(Uh,U_mesh,Z,Z_mesh,f):
    """Take in U, Interpolate to same mesh as Z then solve for eta vector"""

    u_inter = interp1d(U_mesh,Uh) #Interpolation of old mesh
    U2 = u_inter(Z_mesh) #New function u for the new mesh to use in 

    Bz = Poisson_Stiffness(Z_mesh)
    Bz = Bz.tocsr()

    eta = np.empty(len(Z_mesh))
    for i in range(len(Z_mesh)):
        for j in range(len(Z_mesh)):
            eta[i] += (f[i] - Bz[i,j]*U2[j])

    for i in range(len(Z)):
        eta[i] = eta[i]*Z[i]

    return eta

私の次の関数は、メッシュを指定されたエラー インジケーターに非常にうまく適合させているようです! なぜインジケーターが変わらないように見えるのか、まったくわかりませんか?

def Mesh_Refinement(base_mesh,tolerance,refinement,z_mesh,QOI_z_mesh):
    """Solve for U on a normal mesh, Take in Z, Find error indicators, adapt. OUTPUT NEW MESH"""
    New_mesh = base_mesh
    Z = Dualsolution(z_mesh,QOI_z_mesh) #Solve dual solution only once

    f = np.empty(len(z_mesh))
    for i in range(len(z_mesh)):
        f[i] = math.sin(math.pi*z_mesh[i])

    U = Solver(New_mesh)
    eta = Error_Indicators(U,base_mesh,Z,z_mesh,f) 

    while max(abs(k) for k in eta) > tolerance:

        orderedeta = np.sort(eta) #Sort error indicators LENGTH 40
        biggest = np.flipud(orderedeta[int((1-refinement)*len(eta)):len(eta)]) 
        position = np.empty(len(biggest))
        ratio = float(len(New_mesh))/float(len(z_mesh))

        for i in range(len(biggest)):
            position[i] = eta.tolist().index(biggest[i])*ratio #GIVES WHAT NUMBER NODE TO REFINE

        refine = np.zeros(len(position))
        for i in range(len(position)):
            refine[i] = math.floor(position[i])+0.5 #AT WHAT NODE TO PUT NEW ELEMENT 5.5 ETC
        refine = np.flipud(sorted(set(refine)))

        for i in range(len(refine)):
            New_mesh = np.insert(New_mesh,refine[i]+0.5,(New_mesh[refine[i]+0.5]+New_mesh[refine[i]-0.5])/2)

        U = Solver(New_mesh)
        eta = Error_Indicators(U,New_mesh,Z,z_mesh,f)
        print eta

これに対する入力例は次のようになります: Mesh_Refinement(np.linspace(0,1,3),0.1,0.2,np.linspace(0,1,60),20)

ここにはたくさんのコードがあることは理解していますが、途方に暮れています。どこに向かうべきかわかりません!

4

1 に答える 1

1

からのこのコードを検討してくださいdef Error_Indicators:

eta = np.empty(len(Z_mesh))
for i in range(len(Z_mesh)):
    for j in range(len(Z_mesh)):
        eta[i] = (f[i] - Bz[i,j]*U2[j])

eta[i]ここでは、各反復をオーバーライドするjため、内側のサイクルは役に立たないことがわかり、最後の可能な に直接進むことができますj。級数の和を求めるつもりだったの(f[i] - Bz[i,j]*U2[j])ですか?

eta = np.empty(len(Z_mesh))
for i in range(len(Z_mesh)):
    for j in range(len(Z_mesh)):
        eta[i] += (f[i] - Bz[i,j]*U2[j])
于 2015-09-04T04:21:53.317 に答える