Imports System
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Threading
Imports System.Windows.Forms
Imports System.Math

Public Class PlanetForm
    Inherits System.Windows.Forms.Form

    Private hh, dhh, dd, ddd As Integer

    Public x(idim), y(idim), z(idim)
    Public vx(idim), vy(idim), vz(idim)
    Public ax(idim), ay(idim), az(idim)
    Public Rev(idim) As Integer              ' revolution counter
    Public pl_itercnt(idim) As Integer       ' cycle counter per planet
    Public m(idim)
    Public itercnt(5), seccnt(5)
    Public npreq, np, nplanets, nplanetsl, holdreq, holdrev, cancelreq, errorc As Integer
    Public state(5) As Integer
    Const StartSt As Integer = 1, ActiveSt As Integer = 2, StopSt As Integer = 0, CancelSt As Integer = 3, Endst = 0
    Const StartSt1 As Integer = 4, Holdst As Integer = 5
    Const idim As Integer = 100
    Public dt, dtl As Single              ' delta t
    Const Trace As Integer = 0
    Const npmax As Integer = 5


    Public Sub New()

        InitializeComponent()
        InitializeForm()

    End Sub 'New

    Private Sub StartAsyncButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartAsyncButton.Click

        cancelreq = 0

        ResultLabelpp1.Text = " "
        ResultLabelpp2.Text = " "
        ResultLabelpp3.Text = " "
        ResultLabelpp4.Text = " "
        ResultLabelpp5.Text = " "

        StartAsyncButton.Enabled = False
        CancelAsyncButton.Enabled = True
        CancelAsyncButton.Text = "Stop"

        holdrev = HoldT.Value
        tdeltaT.Enabled = False
        nplT.Enabled = False
        HoldT.Enabled = False

        np = 0
        npreq = nProcT.Value

        Assign(npreq)


    End Sub

    Private Sub CancelAsyncButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CancelAsyncButton.Click


        If CancelAsyncButton.Text = "Stop" Then
            holdreq = 2

            ' See Display

            Exit Sub
        Else
            Test()
            If errorc > 0 Then
                StateTpp1.Text = pl_itercnt(0)
                StateTpp2.Text = pl_itercnt(1)
                StateTpp3.Text = pl_itercnt(2)
                StateTpp4.Text = pl_itercnt(3)
                StateTpp5.Text = pl_itercnt(4)
            End If

            CancelAsyncButton.Text = "Stop"
            EndAsyncButton.Enabled = True
            holdreq = 0
            holdrev = HoldT.Value
            If holdrev = Rev(1) Then holdrev = -1
            HoldT.Enabled = False
            For i = 0 To npmax
                itercnt(i) = 0 : seccnt(i) = -2
            Next
        End If


    End Sub


    Private Sub EndSyncButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles EndAsyncButton.Click

        If np <> 0 Then
            StartAsyncButton.Enabled = True
            CancelAsyncButton.Enabled = False
            tdeltaT.Enabled = True
            nplT.Enabled = True
            HoldT.Enabled = True
            cancelreq = 1   'Display
            holdreq = 0
        Else
            Debug.Print("Click End - no Error")
            End
        End If

    End Sub

    Private Sub MonitorButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MonitorButton.Click

        StateTpp1.Text = state(1)
        StateTpp2.Text = state(2)
        StateTpp3.Text = state(3)
        StateTpp4.Text = state(4)
        StateTpp5.Text = state(5)

    End Sub

    Private Sub nProcT_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles nProcT.Click

        Dim npreqt As Integer

        If npreq > 0 Then

            npreqt = nProcT.Value
            If npreqt > np Then Assign(npreqt)
            If npreq < np Then
                For i = 1 To npmax
                    If npreq < i And np >= i Then
                        Select Case i
                            Case Is = 1
                            Case Is = 2
                                ProcTpp2.Text = " "
                            Case Is = 3
                                ProcTpp3.Text = " "
                            Case Is = 4
                                ProcTpp4.Text = " "
                            Case Is = 5
                                ProcTpp5.Text = " "
                        End Select
                    End If

                Next i
            End If

            npreq = npreqt
        End If

    End Sub 'Main



    ' This event handler 1 is where the time-consuming work is done.
    Private Sub backgroundWorker1_DoWork(ByVal sender As System.Object, _
    ByVal e As DoWorkEventArgs) Handles BackgroundWorkerpp1.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i, j, pstr As Integer
        Dim sec1, sec2 As Integer
        Dim dx, dy, dz, r2, r, a, ynew As Double
        Dim b As String
        Const pp As Integer = 1
        sec1 = Second(Now)
        pstr = pp - 1                           ' Processor start = 1-1
        holdrev = HoldT.Value
        holdreq = 0
        b = tdeltaT.Text : dt = Val(b)          ' Delta t
        If dt = 0 Then dt = 0.02 : dtl = 0
        b = nplT.Value : nplanets = Val(b)
        If nplanets < 1 Then nplanets = 1
        If nplanets > idim Then nplanets = idim

        If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Load  dt = " + Str(dt) + " nplanets" + Str(nplanets) + " " + tdeltaT.Text)

        Init()

        Do
            ' If pl_itercnt(0) Mod 10000 = 0 Then Debug.Print(Str(pl_itercnt(0)) + " x" + Str(x(1)) + Str(y(1)) + " v" + Str(vx(1)) + Str(vy(1)) + " a" + Str(ax(1)) + Str(ay(1)) + Str(az(1)))
            If cancelreq = 1 Then npreq = 0
            If npreq <> np Then
                If Trace = 1 Then Debug.Print("npreq" + Str(npreq) + "  np" + Str(np))
                If npreq < np Then CancelS(npreq)
                For i = 0 To npmax
                    itercnt(i) = 0
                    seccnt(i) = -1
                Next
                np = npreq
            End If

            If Rev(1) = holdrev Or holdreq = 2 Then
                holdrev = -1
                holdreq = 1
                For i = 1 To npmax
                    state(i) = Holdst
                Next i
                worker.ReportProgress(-1)
            End If
            If state(1) = Holdst Then
                If holdreq = 0 Then
                    For i = 1 To npmax
                        state(i) = Endst
                    Next
                Else
                    System.Threading.Thread.Sleep(1)
                End If
            Else
                If state(1) = CancelSt Then
                    e.Cancel = True
                    state(1) = Endst
                    If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Cancelst ")
                    Exit Sub
                Else
                    itercnt(1) = itercnt(1) + 1

                    GoTo skip1
                    ' Do not remove this statement !!!
                    End
skip1:
                    If np > 1 Then state(2) = StartSt ' Start P1
                    If np > 2 Then state(3) = StartSt ' start p2
                    If np > 3 Then state(4) = StartSt ' Start P3
                    If np > 4 Then state(5) = StartSt ' Start P3
                    If np > 0 Then
                        For i = pstr To nplanets Step np
                            ax(i) = 0 : ay(i) = 0 : az(i) = 0
                            For j = 0 To nplanets
                                If i <> j Then
                                    dx = x(i) - x(j) : dy = y(i) - y(j) : dz = z(i) - z(j)
                                    r2 = (dx * dx + dy * dy + dz * dz) : r = Sqrt(r2)
                                    a = m(j) / (r2 * r)
                                    ax(i) = ax(i) + a * dx
                                    ay(i) = ay(i) + a * dy
                                    az(i) = az(i) + a * dz
                                End If
                            Next
                            vx(i) = vx(i) - ax(i) * dt
                            vy(i) = vy(i) - ay(i) * dt
                            vz(i) = vz(i) - az(i) * dt
                        Next
                    End If

                    If np > 1 Then
                        Do
                        Loop Until state(2) = StopSt And state(3) = StopSt And state(4) = StopSt And state(5) = StopSt
                    End If

                    If np > 1 Then state(2) = StartSt1 ' Start P1
                    If np > 2 Then state(3) = StartSt1 ' start p2
                    If np > 3 Then state(4) = StartSt1 ' Start P3
                    If np > 4 Then state(5) = StartSt1 ' Start P3
                    If np > 0 Then
                        For i = pstr To nplanets Step np
                            x(i) = x(i) + vx(i) * dt
                            ynew = y(i) + vy(i) * dt
                            If y(i) < 0 And ynew > 0 Then Rev(i) = Rev(i) + 1
                            y(i) = ynew
                            z(i) = z(i) + vz(i) * dt
                            pl_itercnt(i) = pl_itercnt(i) + 1
                        Next
                    End If

                    If np > 1 Then
                        Do
                        Loop Until state(2) = StopSt And state(3) = StopSt And state(4) = StopSt And state(5) = StopSt
                    End If

                    ' Perform a time consuming operation and report progress.
                    sec2 = Second(Now)
                    If sec2 <> sec1 Then
                        sec1 = Second(Now)
                        seccnt(1) = seccnt(1) + 1
                        If seccnt(1) <= 0 Then
                            itercnt(1) = 0
                            worker.ReportProgress(0)
                        Else
                            worker.ReportProgress(itercnt(1) / seccnt(1))
                        End If
                    End If
                End If
            End If
        Loop

    End Sub

    ' This event handler 1 updates the progress.
    Private Sub backgroundWorkerpp1_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles BackgroundWorkerpp1.ProgressChanged
        Dim pl As Integer
        Dim r As Double
        If holdreq = 0 Then
            ResultLabelpp1.Text = (e.ProgressPercentage.ToString())
        Else
            ' endAsyncButton.Enabled = False
            CancelAsyncButton.Enabled = True
            CancelAsyncButton.Text = "Restart"
            HoldT.Enabled = True
            Test()
            If errorc > 0 Then
                StateTpp1.Text = pl_itercnt(0)
                StateTpp2.Text = pl_itercnt(1)
                StateTpp3.Text = pl_itercnt(2)
                StateTpp4.Text = pl_itercnt(3)
                StateTpp5.Text = pl_itercnt(4)
            End If
        End If
        seccntT.Text = Str(seccnt(1))

        pl = Val(pl1T.Text)
        If pl < 0 Then pl = 0
        x1T.Text = Str(Int(x(pl)))
        y1T.Text = Str(Int(y(pl)))
        r = Sqrt(x(pl) * x(pl) + y(pl) * y(pl))
        r1T.Text = r
        rev1T.Text = Str(Rev(pl))

        pl = Val(pl2T.Text)
        If pl < 0 Then pl = 0
        x2T.Text = Str(Int(x(pl)))
        y2T.Text = Str(Int(y(pl)))
        r = Sqrt(x(pl) * x(pl) + y(pl) * y(pl))
        r2T.Text = r
        rev2T.Text = Str(Rev(pl))

        pl = Val(pl3T.Text)
        If pl < 0 Then pl = 0
        x3T.Text = Str(Int(x(pl)))
        y3T.Text = Str(Int(y(pl)))
        r = Sqrt(x(pl) * x(pl) + y(pl) * y(pl))
        r3T.Text = r
        rev3T.Text = Str(Rev(pl))

        pl = Val(pl4T.Text)
        If pl < 0 Then pl = 0
        x4T.Text = Str(Int(x(pl)))
        y4T.Text = Str(Int(y(pl)))
        r = Sqrt(x(pl) * x(pl) + y(pl) * y(pl))
        r4T.Text = r
        rev4T.Text = Str(Rev(pl))

    End Sub


    ' This event handler 1  deals with the results of the background operation.
    Private Sub backgroundWorkerpp1_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorkerpp1.RunWorkerCompleted
        If e.Cancelled = True Then
            If cancelreq = 0 Then ResultLabelpp1.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            ResultLabelpp1.Text = "Error: " & e.Error.Message
        Else
            ResultLabelpp1.Text = "Done!"
        End If
    End Sub

    ' This event handler 2 is where the time-consuming work is done.
    Private Sub backgroundWorkerpp2_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorkerpp2.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i, j, pstr As Integer
        Dim sec1, sec2 As Integer
        Dim dx, dy, dz, r2, r, a, ynew As Double
        Const pp As Integer = 2
        sec1 = Second(Now)
        pstr = pp - 1
        If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Load")
        Do
            itercnt(pp) = itercnt(pp) + 1
            Select Case state(pp)
                Case Is = Holdst
                    System.Threading.Thread.Sleep(1)

                Case Is = CancelSt
                    e.Cancel = True
                    If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Cancelst " + Str(state(pp)))
                    state(pp) = Endst
                    Exit Sub

                Case Is = StartSt
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        ax(i) = 0 : ay(i) = 0 : az(i) = 0
                        For j = 0 To nplanets
                            If i <> j Then
                                dx = x(i) - x(j) : dy = y(i) - y(j) : dz = z(i) - z(j)
                                r2 = (dx * dx + dy * dy + dz * dz) : r = Sqrt(r2)
                                a = m(j) / (r2 * r)
                                ax(i) = ax(i) - a * dx
                                ay(i) = ay(i) - a * dy
                                az(i) = az(i) - a * dz
                            End If
                        Next
                        vx(i) = vx(i) + ax(i) * dt
                        vy(i) = vy(i) + ay(i) * dt
                        vz(i) = vz(i) + az(i) * dt
                    Next
                    state(pp) = StopSt


                Case Is = StartSt1
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        x(i) = x(i) + vx(i) * dt
                        ynew = y(i) + vy(i) * dt
                        If y(i) < 0 And ynew > 0 Then Rev(i) = Rev(i) + 1
                        y(i) = ynew
                        z(i) = z(i) + vz(i) * dt
                        pl_itercnt(i) = pl_itercnt(i) + 1
                    Next
                    state(pp) = StopSt


                    sec2 = Second(Now)
                    If sec2 <> sec1 Then
                        sec1 = Second(Now)
                        seccnt(pp) = seccnt(pp) + 1
                        If seccnt(pp) <= 0 Then
                            itercnt(pp) = 0
                            worker.ReportProgress(0)
                        Else
                            worker.ReportProgress(itercnt(pp) / seccnt(pp))
                        End If
                    End If
                Case Else
            End Select
        Loop

    End Sub

    ' This event handler 2 updates the progress.
    Private Sub backgroundWorkerpp2_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles BackgroundWorkerpp2.ProgressChanged
        ResultLabelpp2.Text = (e.ProgressPercentage.ToString())
    End Sub

    ' This event handler 2 deals with the results of the background operation.
    Private Sub backgroundWorkerpp2_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorkerpp2.RunWorkerCompleted
        If e.Cancelled = True Then
            If cancelreq = 0 Then ResultLabelpp2.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            ResultLabelpp2.Text = "Error: " & e.Error.Message
        Else
            ResultLabelpp2.Text = "Done!"
        End If
    End Sub

    ' This event handler 3 is where the time-consuming work is done.
    Private Sub backgroundWorkerpp3_DoWork(ByVal sender As System.Object, _
    ByVal e As DoWorkEventArgs) Handles BackgroundWorkerpp3.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i, j, pstr As Integer
        Dim sec1, sec2 As Integer
        Dim dx, dy, dz, r2, r, a, ynew As Double
        Const pp As Integer = 3
        sec1 = Second(Now)
        pstr = pp - 1
        If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Load")
        Do
            itercnt(pp) = itercnt(pp) + 1
            Select Case state(pp)
                Case Is = Holdst
                    System.Threading.Thread.Sleep(1)

                Case Is = CancelSt
                    e.Cancel = True
                    If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Cancelst " + Str(state(pp)))
                    state(pp) = Endst
                    Exit Sub

                Case Is = StartSt
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        ax(i) = 0 : ay(i) = 0 : az(i) = 0
                        For j = 0 To nplanets
                            If i <> j Then
                                dx = x(i) - x(j) : dy = y(i) - y(j) : dz = z(i) - z(j)
                                r2 = (dx * dx + dy * dy + dz * dz) : r = Sqrt(r2)
                                a = m(j) / (r2 * r)
                                ax(i) = ax(i) - a * dx
                                ay(i) = ay(i) - a * dy
                                az(i) = az(i) - a * dz
                            End If
                        Next
                        vx(i) = vx(i) + ax(i) * dt
                        vy(i) = vy(i) + ay(i) * dt
                        vz(i) = vz(i) + az(i) * dt
                    Next
                    state(pp) = StopSt


                Case Is = StartSt1
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        x(i) = x(i) + vx(i) * dt
                        ynew = y(i) + vy(i) * dt
                        If y(i) < 0 And ynew > 0 Then Rev(i) = Rev(i) + 1
                        y(i) = ynew
                        z(i) = z(i) + vz(i) * dt
                        pl_itercnt(i) = pl_itercnt(i) + 1
                    Next
                    state(pp) = StopSt


                    sec2 = Second(Now)
                    If sec2 <> sec1 Then
                        sec1 = Second(Now)
                        seccnt(pp) = seccnt(pp) + 1
                        If seccnt(pp) <= 0 Then
                            itercnt(pp) = 0
                            worker.ReportProgress(0)
                        Else
                            worker.ReportProgress(itercnt(pp) / seccnt(pp))
                        End If
                    End If
            End Select
        Loop

    End Sub

    ' This event handler 3 updates the progress.
    Private Sub backgroundWorkerpp3_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles BackgroundWorkerpp3.ProgressChanged
        ResultLabelpp3.Text = (e.ProgressPercentage.ToString())
    End Sub

    ' This event handler 3 deals with the results of the background operation.
    Private Sub backgroundWorkerpp3_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorkerpp3.RunWorkerCompleted
        If e.Cancelled = True Then
            If cancelreq = 0 Then ResultLabelpp3.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            ResultLabelpp3.Text = "Error: " & e.Error.Message
        Else
            ResultLabelpp3.Text = "Done!"
        End If
    End Sub


    ' This event handler 4 is where the time-consuming work is done.
    Private Sub backgroundWorkerpp4_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorkerpp4.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i, j, pstr As Integer
        Dim sec1, sec2 As Integer
        Dim dx, dy, dz, r2, r, a, ynew As Double
        Const pp As Integer = 4
        sec1 = Second(Now)
        pstr = pp - 1
        If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Load")
        Do
            itercnt(pp) = itercnt(pp) + 1
            Select Case state(pp)
                Case Is = Holdst
                    System.Threading.Thread.Sleep(1)

                Case Is = CancelSt
                    e.Cancel = True
                    state(pp) = Endst
                    If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Cancelst ")
                    Exit Sub

                Case Is = StartSt
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        ax(i) = 0 : ay(i) = 0 : az(i) = 0
                        For j = 0 To nplanets
                            If i <> j Then
                                dx = x(i) - x(j) : dy = y(i) - y(j) : dz = z(i) - z(j)
                                r2 = (dx * dx + dy * dy + dz * dz) : r = Sqrt(r2)
                                a = m(j) / (r2 * r)
                                ax(i) = ax(i) - a * dx
                                ay(i) = ay(i) - a * dy
                                az(i) = az(i) - a * dz
                            End If
                        Next
                        vx(i) = vx(i) + ax(i) * dt
                        vy(i) = vy(i) + ay(i) * dt
                        vz(i) = vz(i) + az(i) * dt
                    Next
                    state(pp) = StopSt


                Case Is = StartSt1
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        x(i) = x(i) + vx(i) * dt
                        ynew = y(i) + vy(i) * dt
                        If y(i) < 0 And ynew > 0 Then Rev(i) = Rev(i) + 1
                        y(i) = ynew
                        z(i) = z(i) + vz(i) * dt
                        pl_itercnt(i) = pl_itercnt(i) + 1
                    Next
                    state(pp) = StopSt


                    sec2 = Second(Now)
                    If sec2 <> sec1 Then
                        sec1 = Second(Now)
                        seccnt(pp) = seccnt(pp) + 1
                        If seccnt(pp) <= 0 Then
                            itercnt(pp) = 0
                            worker.ReportProgress(0)
                        Else
                            worker.ReportProgress(itercnt(pp) / seccnt(pp))
                        End If
                    End If
            End Select
        Loop

    End Sub

    ' This event handler 4 updates the progress.
    Private Sub backgroundWorkerpp4_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles BackgroundWorkerpp4.ProgressChanged
        ResultLabelpp4.Text = (e.ProgressPercentage.ToString())
    End Sub

    ' This event handler 4 deals with the results of the background operation.
    Private Sub backgroundWorkerpp4_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorkerpp4.RunWorkerCompleted
        If e.Cancelled = True Then
            If cancelreq = 0 Then ResultLabelpp4.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            ResultLabelpp4.Text = "Error: " & e.Error.Message
        Else
            ResultLabelpp4.Text = "Done!"
        End If
    End Sub

    ' This event handler 5 is where the time-consuming work is done.
    Private Sub backgroundWorkerpp5_DoWork(ByVal sender As System.Object, ByVal e As DoWorkEventArgs) Handles BackgroundWorkerpp5.DoWork
        Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
        Dim i, j, pstr As Integer
        Dim sec1, sec2 As Integer
        Dim dx, dy, dz, r2, r, a, ynew As Double
        Const pp As Integer = 5
        sec1 = Second(Now)
        If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Load")
        pstr = pp - 1
        Do
            itercnt(pp) = itercnt(pp) + 1
            Select Case state(pp)
                Case Is = Holdst
                    System.Threading.Thread.Sleep(1)

                Case Is = CancelSt
                    e.Cancel = True
                    state(pp) = Endst
                    If Trace = 1 Then Debug.Print("PP " + Str(pp) + " Cancelst ")
                    Exit Sub

                Case Is = StartSt
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        ax(i) = 0 : ay(i) = 0 : az(i) = 0
                        For j = 0 To nplanets
                            If i <> j Then
                                dx = x(i) - x(j) : dy = y(i) - y(j) : dz = z(i) - z(j)
                                r2 = (dx * dx + dy * dy + dz * dz) : r = Sqrt(r2)
                                a = m(j) / (r2 * r)
                                ax(i) = ax(i) - a * dx
                                ay(i) = ay(i) - a * dy
                                az(i) = az(i) - a * dz
                            End If
                        Next
                        vx(i) = vx(i) + ax(i) * dt
                        vy(i) = vy(i) + ay(i) * dt
                        vz(i) = vz(i) + az(i) * dt
                    Next
                    state(pp) = StopSt


                Case Is = StartSt1
                    state(pp) = ActiveSt
                    For i = pstr To nplanets Step np
                        x(i) = x(i) + vx(i) * dt
                        ynew = y(i) + vy(i) * dt
                        If y(i) < 0 And ynew > 0 Then Rev(i) = Rev(i) + 1
                        y(i) = ynew
                        z(i) = z(i) + vz(i) * dt
                        pl_itercnt(i) = pl_itercnt(i) + 1
                    Next
                    state(pp) = StopSt


                    sec2 = Second(Now)
                    If sec2 <> sec1 Then
                        sec1 = Second(Now)
                        seccnt(pp) = seccnt(pp) + 1
                        If seccnt(pp) <= 0 Then
                            itercnt(pp) = 0
                            worker.ReportProgress(0)
                        Else
                            worker.ReportProgress(itercnt(pp) / seccnt(pp))
                        End If
                    End If
            End Select
        Loop
    End Sub

    ' This event handler 5 updates the progress.
    Private Sub backgroundWorkerpp5_ProgressChanged(ByVal sender As System.Object, _
    ByVal e As ProgressChangedEventArgs) Handles BackgroundWorkerpp5.ProgressChanged
        ResultLabelpp5.Text = (e.ProgressPercentage.ToString())
    End Sub

    ' This event handler 5 deals with the results of the background operation.
    Private Sub backgroundWorkerpp5_RunWorkerCompleted(ByVal sender As System.Object, _
    ByVal e As RunWorkerCompletedEventArgs) Handles BackgroundWorkerpp5.RunWorkerCompleted
        If e.Cancelled = True Then
            If cancelreq = 0 Then ResultLabelpp5.Text = "Canceled!"
        ElseIf e.Error IsNot Nothing Then
            ResultLabelpp5.Text = "Error: " & e.Error.Message
        Else
            ResultLabelpp5.Text = "Done!"
        End If
    End Sub

    Private Sub Init()

        Dim i As Integer

        For i = 0 To idim
            x(i) = 0 : y(i) = 0 : z(i) = 0
            vx(i) = 0 : vy(i) = 0 : vz(i) = 0
            ax(i) = 0 : ay(i) = 0 : az(i) = 0
            pl_itercnt(i) = 0
            Rev(i) = 0     ' Revolution counter
        Next

        m(0) = 1000

        For i = 1 To nplanets
            m(i) = 0
            x(i) = 1000 + (i - 1) * 100
            If x(i) <> 0 Then vy(i) = Sqrt(m(0) / x(i))
        Next

        Printa(x, Str(pl_itercnt(0)) + " x")
        Printa(vy, Str(pl_itercnt(0)) + " vy")

    End Sub

    Private Sub Test()
        Dim a As String
        Dim i, j As Integer
        For i = 0 To nplanets - 1
            If pl_itercnt(i) <> pl_itercnt(i + 1) Then
                errorc = 1
            End If
        Next i
        If errorc = 1 Then
            a = "Test error "
            For j = 0 To nplanets
                a = a + Str(j) + " " + Str(pl_itercnt(j)) + " "
            Next j
            Debug.Print(a)
        End If


    End Sub

    Private Sub Printa(ByVal xp(), ByVal str1)
        Dim b As String
        Dim j As Integer
        b = str1
        For j = 0 To nplanets
            b = b + Str(j) + " " + Str(xp(j)) + " "
        Next j
        Debug.Print(b)

    End Sub


    Private Sub Assign(ByVal npreq)
        ' npreq = request        np = actual 
        For i = 1 To npmax
            If npreq >= i And np < i Then
                Select Case i
                    Case Is = 1
                        BackgroundWorkerpp1.RunWorkerAsync(i)
                        If Trace = 1 Then Debug.Print("Assign " + Str(i))
                        ProcTpp1.Text = 1
                    Case Is = 2
                        BackgroundWorkerpp2.RunWorkerAsync(i)
                        If Trace = 1 Then Debug.Print("Assign " + Str(i))
                        ProcTpp2.Text = 2
                    Case Is = 3
                        BackgroundWorkerpp3.RunWorkerAsync(i)
                        If Trace = 1 Then Debug.Print("Assign " + Str(i))
                        ProcTpp3.Text = 3
                    Case Is = 4
                        BackgroundWorkerpp4.RunWorkerAsync(i)
                        If Trace = 1 Then Debug.Print("Assign " + Str(i))
                        ProcTpp4.Text = 4
                    Case Is = 5
                        BackgroundWorkerpp5.RunWorkerAsync(i)
                        If Trace = 1 Then Debug.Print("Assign " + Str(i))
                        ProcTpp5.Text = 5
                End Select
            End If
        Next i
    End Sub
    Private Sub CancelS(ByVal npreq)
        ' npreq = request        np = actual 
        For i = 1 To npmax

            If npreq < i And np >= i Then
                Select Case i
                    Case Is = 1
                        state(i) = CancelSt
                        If Trace = 1 Then Debug.Print("Cancel " + Str(i))
                    Case Is = 2
                        state(i) = CancelSt
                        If Trace = 1 Then Debug.Print("Cancel " + Str(i))
                    Case Is = 3
                        state(i) = CancelSt
                        If Trace = 1 Then Debug.Print("Cancel " + Str(i))
                    Case Is = 4
                        state(i) = CancelSt
                        If Trace = 1 Then Debug.Print("Cancel " + Str(i))
                    Case Is = 5
                        state(i) = CancelSt
                        If Trace = 1 Then Debug.Print("Cancel " + Str(i))
                End Select
            End If
        Next
        ' np = npreq
    End Sub




    Private Sub InitializeForm()
        Dim hh, dhh, dd, ddd As Single
        '
        'Row  1
        '
        hh = 12 : dhh = 34
        Me.stateL.Location = New System.Drawing.Point(3, hh)
        Me.stateL.Size = New System.Drawing.Size(32, 13)

        dd = 60 : ddd = 70
        Me.StateTpp1.Location = New System.Drawing.Point(dd, hh)
        Me.StateTpp1.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.StateTpp2.Location = New System.Drawing.Point(dd, hh)
        Me.StateTpp2.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.StateTpp3.Location = New System.Drawing.Point(dd, hh)
        Me.StateTpp3.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.StateTpp4.Location = New System.Drawing.Point(dd, hh)
        Me.StateTpp4.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.StateTpp5.Location = New System.Drawing.Point(dd, hh)
        Me.StateTpp5.Size = New System.Drawing.Size(64, 20)
        '
        'Row  2
        '
        hh = hh + dhh
        Me.ProcL.Location = New System.Drawing.Point(3, hh)
        Me.ProcL.Size = New System.Drawing.Size(39, 13)

        dd = 60
        Me.ProcTpp1.Location = New System.Drawing.Point(dd, hh)
        Me.ProcTpp1.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.ProcTpp2.Location = New System.Drawing.Point(dd, hh)
        Me.ProcTpp2.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.ProcTpp3.Location = New System.Drawing.Point(dd, hh)
        Me.ProcTpp3.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.ProcTpp4.Location = New System.Drawing.Point(dd, hh)
        Me.ProcTpp4.Size = New System.Drawing.Size(64, 20)

        dd = dd + ddd
        Me.ProcTpp5.Location = New System.Drawing.Point(dd, hh)
        Me.ProcTpp5.Size = New System.Drawing.Size(64, 20)
        '
        'Row 3
        '
        hh = hh + dhh
        Me.Label2.Location = New System.Drawing.Point(3, hh)
        Me.Label2.Size = New System.Drawing.Size(67, 13)

        dd = 85
        Me.ResultLabelpp1.Location = New System.Drawing.Point(dd, hh)
        Me.ResultLabelpp1.Size = New System.Drawing.Size(70, 13)

        dd = dd + ddd
        Me.ResultLabelpp2.Location = New System.Drawing.Point(dd, hh)
        Me.ResultLabelpp2.Size = New System.Drawing.Size(60, 13)

        dd = dd + ddd
        Me.ResultLabelpp3.Location = New System.Drawing.Point(dd, hh)
        Me.ResultLabelpp3.Size = New System.Drawing.Size(70, 13)

        dd = dd + ddd
        Me.ResultLabelpp4.Location = New System.Drawing.Point(dd, hh)
        Me.ResultLabelpp4.Size = New System.Drawing.Size(60, 13)

        dd = dd + ddd
        Me.ResultLabelpp5.Location = New System.Drawing.Point(dd, hh)
        Me.ResultLabelpp5.Size = New System.Drawing.Size(70, 13)

        '
        'Row  4
        '
        dd = 20 : ddd = 95
        hh = hh + dhh
        Me.nProcL.Location = New System.Drawing.Point(dd, hh)
        'Me.nProcL.Size = New System.Drawing.Size(55, 13)

        dd = dd + nProcL.Width
        Me.nProcT.Location = New System.Drawing.Point(dd, hh)
        Me.nProcT.Size = New System.Drawing.Size(40, 20)

        dd = dd + nProcT.Width
        Me.tdeltaL.Location = New System.Drawing.Point(dd, hh)
        'Me.tdeltaL.Size = New System.Drawing.Size(55, 13)

        dd = dd + tdeltaL.Width
        Me.tdeltaT.Location = New System.Drawing.Point(dd, hh)
        Me.tdeltaT.Size = New System.Drawing.Size(40, 20)

        dd = dd + tdeltaT.Width
        Me.seccntL.Location = New System.Drawing.Point(dd, hh)
        'Me.seccntL.Size = New System.Drawing.Size(40, 13)

        dd = dd + seccntL.Width
        Me.seccntT.Location = New System.Drawing.Point(dd, hh)
        Me.seccntT.Size = New System.Drawing.Size(40, 20)

        dd = dd + seccntT.Width
        Me.nplL.Location = New System.Drawing.Point(dd, hh)
        'Me.nplL.Size = New System.Drawing.Size(55, 13)

        dd = dd + nplL.Width
        Me.nplT.Location = New System.Drawing.Point(dd, hh)
        Me.nplT.Size = New System.Drawing.Size(40, 20)

        dd = dd + nplT.Width
        Me.HoldL.Location = New System.Drawing.Point(dd, hh)
        Me.HoldL.Size = New System.Drawing.Size(29, 13)

        dd = dd + HoldL.Width
        Me.HoldT.Location = New System.Drawing.Point(dd, hh)
        Me.HoldT.Size = New System.Drawing.Size(40, 20)
        '
        ' row 5 startAsyncButton   cancelAsyncButton  endAsyncButton   MonitorButton
        '
        dd = 60
        hh = hh + dhh
        Me.StartAsyncButton.Location = New System.Drawing.Point(dd, hh)
        Me.StartAsyncButton.Size = New System.Drawing.Size(63, 25)

        dd = dd + ddd
        Me.CancelAsyncButton.Enabled = False
        Me.CancelAsyncButton.Location = New System.Drawing.Point(dd, hh)
        Me.CancelAsyncButton.Size = New System.Drawing.Size(63, 25)

        dd = dd + ddd
        Me.EndAsyncButton.Location = New System.Drawing.Point(dd, hh)
        Me.EndAsyncButton.Size = New System.Drawing.Size(63, 25)

        dd = dd + ddd
        Me.MonitorButton.Location = New System.Drawing.Point(dd, hh)
        Me.MonitorButton.Size = New System.Drawing.Size(63, 25)
        '
        'Row  6    Planet  x  y  r  rev
        '
        dd = 80
        hh = hh + dhh
        Me.Label1.Location = New System.Drawing.Point(6, hh)
        Me.Label1.Size = New System.Drawing.Size(40, 13)

        Me.Label3.Location = New System.Drawing.Point(dd, hh)
        Me.Label3.Size = New System.Drawing.Size(12, 13)

        dd = dd + ddd
        Me.Label4.Location = New System.Drawing.Point(dd, hh)
        Me.Label4.Size = New System.Drawing.Size(15, 13)

        dd = dd + ddd
        Me.Label5.Location = New System.Drawing.Point(dd, hh)
        Me.Label5.Size = New System.Drawing.Size(12, 13)

        dd = dd + ddd
        Me.Label6.Location = New System.Drawing.Point(dd, hh)
        Me.Label6.Size = New System.Drawing.Size(22, 13)
        '
        'Row  7    Planet 1
        '
        dhh = 25
        hh = hh + dhh    'hh=200
        Me.pl1T.Location = New System.Drawing.Point(13, hh)
        Me.pl1T.Size = New System.Drawing.Size(21, 20)
        dd = 60
        Me.x1T.Location = New System.Drawing.Point(dd, hh)
        Me.x1T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.y1T.Location = New System.Drawing.Point(dd, hh)
        Me.y1T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.r1T.Location = New System.Drawing.Point(dd, hh)
        Me.r1T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.rev1T.Location = New System.Drawing.Point(dd, hh)
        Me.rev1T.Size = New System.Drawing.Size(61, 20)
        '
        'Row  8    Planet 2
        '
        hh = hh + dhh
        Me.pl2T.Location = New System.Drawing.Point(13, hh)
        Me.pl2T.Size = New System.Drawing.Size(21, 20)
        dd = 60
        Me.x2T.Location = New System.Drawing.Point(dd, hh)
        Me.x2T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.y2T.Location = New System.Drawing.Point(dd, hh)
        Me.y2T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.r2T.Location = New System.Drawing.Point(dd, hh)
        Me.r2T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.rev2T.Location = New System.Drawing.Point(dd, hh)
        Me.rev2T.Size = New System.Drawing.Size(61, 20)
        '
        'Row  9    Planet 3
        '
        hh = hh + dhh
        Me.pl3T.Location = New System.Drawing.Point(13, hh)
        Me.pl3T.Size = New System.Drawing.Size(21, 20)
        dd = 60
        Me.x3T.Location = New System.Drawing.Point(dd, hh)
        Me.x3T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.y3T.Location = New System.Drawing.Point(dd, hh)
        Me.y3T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.r3T.Location = New System.Drawing.Point(dd, hh)
        Me.r3T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.rev3T.Location = New System.Drawing.Point(dd, hh)
        Me.rev3T.Size = New System.Drawing.Size(61, 20)
        '
        'Row  10    Planet 4
        '
        hh = hh + dhh
        Me.pl4T.Location = New System.Drawing.Point(13, hh)
        Me.pl4T.Size = New System.Drawing.Size(21, 20)
        dd = 60
        Me.x4T.Location = New System.Drawing.Point(dd, hh)
        Me.x4T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.y4T.Location = New System.Drawing.Point(dd, hh)
        Me.y4T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.r4T.Location = New System.Drawing.Point(dd, hh)
        Me.r4T.Size = New System.Drawing.Size(61, 20)
        dd = dd + ddd
        Me.rev4T.Location = New System.Drawing.Point(dd, hh)
        Me.rev4T.Size = New System.Drawing.Size(61, 20)
        '
        'backgroundWorkerpp1
        '
        Me.BackgroundWorkerpp1.WorkerReportsProgress = True
        Me.BackgroundWorkerpp1.WorkerSupportsCancellation = True
        Me.BackgroundWorkerpp2.WorkerReportsProgress = True
        Me.BackgroundWorkerpp2.WorkerSupportsCancellation = True
        Me.BackgroundWorkerpp3.WorkerReportsProgress = True
        Me.BackgroundWorkerpp3.WorkerSupportsCancellation = True
        Me.BackgroundWorkerpp4.WorkerReportsProgress = True
        Me.BackgroundWorkerpp4.WorkerSupportsCancellation = True
        Me.BackgroundWorkerpp5.WorkerReportsProgress = True
        Me.BackgroundWorkerpp5.WorkerSupportsCancellation = True

        '
        'PlanetForm
        '
        Me.ClientSize = New System.Drawing.Size(dd + ddd - 25, hh + dhh + 10)


    End Sub 'InitializeComponent

     _
    Shared Sub Main()
        Application.Run(New PlanetForm)
    End Sub  'Main


End Class 'PlanetForm