1
\$\begingroup\$

I'm new to both Scala and Functional programming. I've been doing the excellent course Functional Programming Principles in Scala on Coursera and I want to test out what I've learned.

I've written a very simple program that integrates the lorenz attractor.

Here is the code:

object LorenzAttractor {

  def main(Arguments:Array[String]): Unit ={

    def func(y:List[Double], t:Double):List[Double] =
      List(10.0*(y(1)-y(0)), -y(0)*y(2)+28.0*y(0)-y(1), y(0)*y(1)-(8.0/3.0)*y(2))

    val w = null
    println(numerical.odeint(func, List(1.0, 1.0, 1.0), 0.0, 1000.0, 0.0001, w))
  }

}


object numerical {

  def odeint(f: (List[Double], Double) => List[Double], y:List[Double], tstart:Double, tend:Double, dt:Double, w:BufferedWriter): List[Double] = {

    def eulerMethod(): List[Double] =
      (y, f(y, tstart).map(x => x * dt)).zipped.map(_ + _)

    def getWriter(fileName:String):BufferedWriter =
      new BufferedWriter(new FileWriter(new File(fileName)))

    def writeData():Unit = {
      w.write(f"$tstart%.3f, ${y(0)}%.3f, ${y(1)}%.3f, ${y(2)}%.3f%n")
      w.flush()
    }

    def closeBuffer():Unit =
    {
      w.flush()
      w.close()
    }

    println(tstart)
    if ((w == null) && (tstart < tend)) odeint(f, eulerMethod(), tstart+dt, tend, dt, getWriter("lorenz.csv"))

    else if (tstart < tend) { writeData(); odeint(f, eulerMethod(), tstart+dt, tend, dt, w)}

    else y
  }
}

At the moment I don't like the way that I handle the writing output, but I can't really think of a better way.

Also eventually I'd like to add some more methods to odeint and make a driver function that checks integration is within a certain tolerance.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.