Fix ball on springs demo

This commit is contained in:
Alexander Nozik 2024-06-03 18:34:08 +03:00
parent 9f21a14f96
commit 1799a9a909
3 changed files with 18 additions and 6 deletions

View File

@ -26,17 +26,23 @@ public class MaterialPoint(
private var currentForce = force.value private var currentForce = force.value
private val movement = onTimer( private val movement = onTimer(
DefaultTimer.REALTIME,
reads = setOf(velocity, position), reads = setOf(velocity, position),
writes = setOf(velocity, position) writes = setOf(velocity, position)
) { prev, next -> ) { prev, next ->
val dtSeconds = (next - prev).toDouble(DurationUnit.SECONDS) val dtSeconds = (next - prev).toDouble(DurationUnit.SECONDS)
// compute new value based on velocity and acceleration from the previous step // compute new value based on velocity and acceleration from the previous step
position.value += (velocity.value * dtSeconds).cast(Meters) + val deltaR = (velocity.value * dtSeconds).cast(Meters) +
(currentForce / mass.value * dtSeconds.pow(2) / 2).cast(Meters) (currentForce / mass.value * dtSeconds.pow(2) / 2).cast(Meters)
position.value += deltaR
// compute new velocity based on acceleration on the previous step // compute new velocity based on acceleration on the previous step
velocity.value += (currentForce / mass.value * dtSeconds).cast(MetersPerSecond) val deltaV = (currentForce / mass.value * dtSeconds).cast(MetersPerSecond)
//TODO apply energy correction
//val work = deltaR.length.value * currentForce.length.value
velocity.value += deltaV
currentForce = force.value currentForce = force.value
} }
} }

View File

@ -1,5 +1,8 @@
package space.kscience.controls.constructor.units package space.kscience.controls.constructor.units
import kotlin.math.pow
import kotlin.math.sqrt
public data class XY<U : UnitsOfMeasurement>(val x: NumericalValue<U>, val y: NumericalValue<U>) public data class XY<U : UnitsOfMeasurement>(val x: NumericalValue<U>, val y: NumericalValue<U>)
public fun <U : UnitsOfMeasurement> XY(x: Number, y: Number): XY<U> = XY(NumericalValue(x), NumericalValue((y))) public fun <U : UnitsOfMeasurement> XY(x: Number, y: Number): XY<U> = XY(NumericalValue(x), NumericalValue((y)))
@ -18,6 +21,11 @@ public data class XYZ<U : UnitsOfMeasurement>(
val z: NumericalValue<U>, val z: NumericalValue<U>,
) )
public val <U : UnitsOfMeasurement> XYZ<U>.length: NumericalValue<U>
get() = NumericalValue(
sqrt(x.value.pow(2) + y.value.pow(2) + z.value.pow(2))
)
public fun <U : UnitsOfMeasurement> XYZ(x: Number, y: Number, z: Number): XYZ<U> = public fun <U : UnitsOfMeasurement> XYZ(x: Number, y: Number, z: Number): XYZ<U> =
XYZ(NumericalValue(x), NumericalValue((y)), NumericalValue(z)) XYZ(NumericalValue(x), NumericalValue((y)), NumericalValue(z))

View File

@ -16,8 +16,6 @@ import space.kscience.controls.constructor.models.MaterialPoint
import space.kscience.controls.constructor.units.* import space.kscience.controls.constructor.units.*
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import java.awt.Dimension import java.awt.Dimension
import kotlin.math.pow
import kotlin.math.sqrt
private class Spring( private class Spring(
@ -33,7 +31,7 @@ private class Spring(
*/ */
val tension: DeviceState<XYZ<Newtons>> = combineState(begin, end) { begin: XYZ<Meters>, end: XYZ<Meters> -> val tension: DeviceState<XYZ<Newtons>> = combineState(begin, end) { begin: XYZ<Meters>, end: XYZ<Meters> ->
val delta = end - begin val delta = end - begin
val l = sqrt(delta.x.value.pow(2) + delta.y.value.pow(2) + delta.z.value.pow(2)) val l = delta.length.value
((delta / l) * k * (l - l0.value)).cast(Newtons) ((delta / l) * k * (l - l0.value)).cast(Newtons)
} }
} }
@ -87,7 +85,7 @@ private class BodyOnSprings(
} }
fun main() = application { fun main() = application {
val initialState = XYZ<Meters>(0.01, 0.1, 0) val initialState = XYZ<Meters>(0, 0.4, 0)
Window(title = "Ball on springs", onCloseRequest = ::exitApplication) { Window(title = "Ball on springs", onCloseRequest = ::exitApplication) {
window.minimumSize = Dimension(400, 400) window.minimumSize = Dimension(400, 400)