B4J Question How to solve nonlinear equation in B4J?

MicroDrie

Well-Known Member
Licensed User
Longtime User
Perhaps it is useful to be a little more concrete about what the nonlinear equation problem exactly is, how the result should be presented and what you have or have not achieved yourself. Claus's xChart Class and b4xlib can display very slick graphical results.
 
Upvote 0

derez

Expert
Licensed User
Longtime User
run a loop where lamda is changed in small increments (not including lamda <= 0):
res = 1/sqrt(lamda) - 2*logarithm(sqrt(lamda)-0.8))
when res is close enough to zero - log lamda and exit.
 
Upvote 0

angel_

Well-Known Member
Licensed User
Longtime User
You can use the newton-raphson algorithm but you need to know the derivative and an initial approximation.

If the derived function is correct it would be something like this, you could also do it with a for and set a maximum number of iterations

B4X:
Sub GetLambda(Re As Double) As Double
    Dim y   As Double         'f(x) = 0
    Dim x0  As Double = 1    'initial approach
    Dim x1  As Double
    Dim dx  As Double         'derivative function
    Dim Precision As Double = 0.0001
    Dim Check As Boolean = False
    
    Do While Check = False
        y = 2 * x0 * Logarithm(Re * Sqrt(x0) - 0.8, cE) - 1
        
        dx = 2 * Logarithm(Re * Sqrt(x0) - 0.8, cE) + 2 * x0 * Re * 1 / 2 * Power(x0, - 1 / 2) / (Re * Sqrt(x0) - 0.8)
    
        x1 = x0 - y / dx
    
        If Abs(x1 - x0) < Precision Then
            Return x1
        Else
            x0 = x1
        End If
    Loop
End Sub
 
Upvote 0

derez

Expert
Licensed User
Longtime User
B4X:
Dim lamda As Double
Dim res As Double
Dim p As Double
For lamda = 3.6 To 10 Step 0.0001
    p = Sqrt(lamda)
    res = 1/p - 2*Logarithm(p-0.8,cE)
    Log("lamda = " & lamda & "    res =  " & res)
    If Abs(res) <= 0.00001 Then Exit
Next

...
lamda = 4.29630000000342 res = 8.778585356983282E-5
lamda = 4.29640000000342 res = 4.426572195592726E-5
lamda = 4.2965000000034195 res = 7.469458777054072E-7
 
Last edited:
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
B4X:
    Dim greek() As Int = Array As Int(0x03B1,0x03B2,0x03B3,0x03B4,0x03B5,0x03B6,0x03B7,0x03B8,0x03B9,0x03BA,0x03BB,0x03BC,0x03BD,0x03BE,0x03BF)
    Log(Chr(greek(10)) & " = " & NumberFormat2(lamda, 0, 4, 4, False))

λ = 4.2965
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Or

B4X:
    Dim greek As String =   "αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ"
    Dim english As String = "abgdezhziklmvxoprstufcywABGDEZHIKLMVXOPRSTUFCYW"
    Log(greek.charAt(english.IndexOf("l")) & " = " & NumberFormat2(lamda, 1, 4, 4, False))
 
Upvote 0

daiweisc

Member
Thanks for reply.
Another question, why the below code is wrong . The first line has a wave line :
B4X:
Private Sub    GetLambda(Reynolds As Double) As Double
    Private y   As Double               'f(x) = 0
    Private x0  As Double = 0.0473    'initial approach
    Private x1  As Double
    Private dx  As Double         'derivative function
    Private Precision As Double = 0.0001
    Private LowerBound As Double = 1E-8
    Private MaxIterations As Int = 100
    Private Check As Boolean = False

    Do While Check = False
        Private count = 1 As Int
        ' Let x0 , x1 = Sqrt(Lambda) , simplify iteration formula
        y = 2 * x0 * Logarithm(Reynolds * x0 - 0.8, 10) - 1
        dx = 2 * Logarithm(Reynolds * x0 - 0.8, 10) + 2 * x0 * Reynolds / ((Reynolds * x0 - 0.8) * Logarithm(10 , cE))
        x1 = x0 - y / dx
        If ( Abs(x1 - x0) < Precision Or y = LowerBound ) Then
            Verify = True         
            Return x1
        Else
            x0 = x1
        End If
        If ( dx = 0 Or count > MaxIterations) Then
            Verify = False
            Return x1
        End If
        count=count+1
    Loop
End Sub
 
Upvote 0

daiweisc

Member
Can the Sub function return two values?
Is the syntax of the 1 , 20 , 26 line codes correct ?

B4X:
La , Verify = GetLambda(Re)

Private Sub    GetLambda(Reynolds As Double) As Double
    Private y   As Double               'f(x) = 0
    Private x0  As Double = 0.0276    'initial approach
    Private x1  As Double
    Private dx  As Double         'derivative function
    Private Precision As Double = 0.0001
    Private LowerBound As Double = 1E-8
    Private MaxIterations As Int = 100
    Private Check As Boolean = False

    Do While Check = False
        Private count = 1 As Int
        y = 2 * x0 * Logarithm(Reynolds * Sqrt(x0) - 0.8, 10) - 1
        dx = 2 * Logarithm(Reynolds * Sqrt(x0) - 0.8, 10) + Sqrt(x0) * Reynolds / ((Reynolds * Sqrt(x0) - 0.8) * Logarithm(10 , cE))
        x1 = x0 - y / dx
        If ( Abs(x1 - x0) < Precision Or y = LowerBound ) Then
            Verify = True          
            Return x1 , Verify
        Else
            x0 = x1
        End If
        If ( dx = 0 Or count > MaxIterations) Then
            Verify = False
            Return x1 , Verify
        End If
        count=count+1
    Loop
End Sub
 
Upvote 0

Brian Dean

Well-Known Member
Licensed User
Longtime User
Return multiple values as an array.
Another alternative which I think is more flexible and better in some situations is to use an object ...

B4X:
  Type result (item1 as int, item2 as double)
 
  . . .
 
  Sub Calculate(arg1 as double) As result
    Dim r as result
    . . .
    r.item1 = firstValue
    . . .
   
    r.item2 = secondValue
    . . .
    return r
  End Sub
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…