Разве fsolve не должен быть в состоянии решить систему нелинейных уравнений со степенью 4?

#python #nonlinear-optimization

Вопрос:

Я не знаю, что я делаю не так. Я должен решить систему нелинейных уравнений, которые включают радиационную теплопередачу, но каждый раз, когда я пытаюсь ее реализовать, алгоритм не сходится, при ier = 5, что означает «Итерация не продвигается хорошо, как измеряется улучшением по сравнению с последними десятью итерациями». Я довольно новичок в Python, но я не знаю, будет ли все это иметь смысл без всего контекста. Смысл моего кода состоит в том, чтобы использовать своего рода метод конечных элементов для вычисления поля температуры в печи для остекловывания. Это 1D-модель с большим количеством гипотез, и меня не интересует решение поля скоростей, создаваемого естественной конвекцией. Печь состоит из трех элементов : перерабатываемых отходов, огнеупорного песка и металлической оболочки, поэтому я использовал классы для каждого элемента, чтобы каждый раз сохранять физические свойства каждого элемента. Каждый объект каждого слоя печи затем хранится в объекте печи. Код выглядит следующим образом :

«‘ деф Билан(self, dt):

     dim_x = self.Nbcomposants                                   
    dim_y = self.Ncouches
    SFour = self.width**2                                      
    dz = self.height/dim_y
    S_MR = self.width*dz                       
    Pc = self.puissance
    dim_T = dim_x*dim_y                                       
    A = np.zeros((dim_T, dim_T))                                #  Ax = B
    B = np.zeros(dim_T)
    T_old = np.zeros(dim_T)                                     

    for i in range(self.NombredeCouchesLiquides, dim_y):
        if self.Couches[i].composants[2].Temperature > Tfusion:
            self.Couches[i].composants[2].IsLiquid = True
            self.Couches[i].composants[2].IsSolid = False
            self.NombredeCouchesLiquides  = 1
            self.Couches[i].composants[2].proportionLiquide = 1
                        

    for x in range(0, dim_x):                             
        for y in range(0, dim_y):                               
            i = y   dim_y*x
            T_old[i] = self.Couches[y].composants[x].Temperature
            

    for x in range(0, dim_x):
        for y in range(0, dim_y):
            Layer_i = self.Couches[y]
            Main = Layer_i.composants[x]

            i = y   dim_y*x

            if x == 0:                                          # metal liner

                A[i, i] = (Main.rho*Main.Cp*Main.dl/dt   2/(Layer_i.composants[x 1].dl/Layer_i.composants[x 1].lambdath   Main.dl/Main.lambdath)   Main.hConvectionAir)*S_MR
                A[i, i dim_y] = -2*S_MR/(Layer_i.composants[x 1].dl/Layer_i.composants[x 1].lambdath   Main.dl/Main.lambdath)
                B[i] = (Main.rho*Main.Cp*Main.dl*T_old[i]/dt   Main.hConvectionAir*Tamb   sigma*(Tamb   273.15)**4)*S_MR

                if y != 0:
                    A[i, i]  = self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))
                    A[i, i-1] = -self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))

                if y != dim_y - 1:
                    A[i, i]  = self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))
                    A[i, i 1] = -self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))


            elif x == 1:                                          # refractory sand

                A[i, i] = (Main.rho*Main.Cp*Main.dl/dt   2/(Main.dl/Main.lambdath)   2/(Layer_i.composants[x-1].dl/Layer_i.composants[x-1].lambdath   Main.dl/Main.lambdath))*S_MR
                A[i, i-dim_y] = -2*S_MR/(Layer_i.composants[x-1].dl/Layer_i.composants[x-1].lambdath   Main.dl/Main.lambdath)
                A[i, i dim_y] = -2*S_MR/(Main.dl/Main.lambdath)
                B[i] = Main.rho*Main.Cp*S_MR*Main.dl*T_old[i]/dt

                if y != 0:
                    A[i, i]  = self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))
                    A[i, i-1] = -self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))

                if y != dim_y - 1:
                    A[i, i]  = self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))
                    A[i, i 1] = -self.width*Main.dl/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))

            elif x == 2:                                          # Melt

                A[i, i] = Main.rho*Main.Cp*SFour*dz/dt   2*S_MR/(Layer_i.composants[x-1].dl/Layer_i.composants[x-1].lambdath)
                A[i, i-dim_y] = -2*S_MR/(Layer_i.composants[x-1].dl/Layer_i.composants[x-1].lambdath)
                B[i] = Main.rho*Main.Cp*SFour*dz*T_old[i]/dt

                if y != 0:
                    A[i, i]  = SFour/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))
                    A[i, i-1] = -SFour/(dz*(1/Main.lambdath   1/self.Couches[y-1].composants[x].lambdath))
                else:
                    B[i]  = Pc

                if y != dim_y - 1:
                    A[i, i]  = SFour/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))
                    A[i, i 1] = -SFour/(dz*(1/Main.lambdath   1/self.Couches[y 1].composants[x].lambdath))
                else:
                    A[i, i]  = self.Couches[dim_y][1].hconvection*SFour
                    B[i]  = SFour*(self.Couches[dim_y][1].hconvection*self.Couches[dim_y][1].Temperature) #
                    #  sigma*(FMeltToHood*(self.Couches[dim_y 1].Temperature   273.15)**4   2*FMeltToSideWall*(self.Couches[dim_y][0].Temperature   273.15)**4))

            else:
                print('Le nombre de composants dans une couche ne correspond pas')


    def CalculT(T, arg1, arg2):                   # solve Ax = B, adding radiative elements
        X = np.ravel(T)
        f = np.dot(arg1,X)
        f -= np.ravel(arg2)
        F = np.ravel(f)
        for i in range(dim_y):
            F[i]  = sigma*S_MR * (X[i]   273.15)**4           # radiation only for metal liner (0 to 99)

        F[dim_T-1]  = SFour*sigma*(FMeltToHood*(X[dim_T-1]   273.15)**4   2*FMeltToSideWall*(X[dim_T-1]   273.15)**4)
        return F


    results = fsolve(CalculT, T_old, args = (A,B), full_output = True)
    T_new = results[0]
    exitflag = results[2]

    if exitflag != 1:
        print("L'algorithme ne converge pas")
 

»’

Я действительно не знаю, понятно ли это без полного набора гипотез и уравнений, но если кто-то каким-то образом поймет, почему это не работает, я с радостью приму любой совет. Код отлично работает, если я прокомментирую детали, связанные с радиационной передачей тепла.