From e545677d6776f2d8fd560ae64e40eebf51d8b259 Mon Sep 17 00:00:00 2001 From: Don Cross Date: Thu, 21 Apr 2022 16:04:53 -0400 Subject: [PATCH] Kotlin: observerGravity function. --- generate/template/astronomy.kt | 33 +++++++++++++++++++ source/kotlin/README.md | 1 + source/kotlin/doc/index.md | 1 + source/kotlin/doc/observer-gravity.md | 23 +++++++++++++ .../github/cosinekitty/astronomy/astronomy.kt | 33 +++++++++++++++++++ .../io/github/cosinekitty/astronomy/Tests.kt | 25 ++++++++++++++ 6 files changed, 116 insertions(+) create mode 100644 source/kotlin/doc/observer-gravity.md diff --git a/generate/template/astronomy.kt b/generate/template/astronomy.kt index f2b54982..6808c407 100644 --- a/generate/template/astronomy.kt +++ b/generate/template/astronomy.kt @@ -6523,6 +6523,39 @@ fun searchPeakMagnitude(body: Body, startTime: Time): IlluminationInfo { } +/** + * Calculates the gravitational acceleration experienced by an observer on the Earth. + * + * This function implements the WGS 84 Ellipsoidal Gravity Formula. + * The result is a combination of inward gravitational acceleration + * with outward centrifugal acceleration, as experienced by an observer + * in the Earth's rotating frame of reference. + * The resulting value increases toward the Earth's poles and decreases + * toward the equator, consistent with changes of the weight measured + * by a spring scale of a fixed mass moved to different latitudes and heights + * on the Earth. + * + * @param latitude + * The latitude of the observer in degrees north or south of the equator. + * By formula symmetry, positive latitudes give the same answer as negative + * latitudes, so the sign does not matter. + * + * @param height + * The height above the sea level geoid in meters. + * No range checking is done; however, accuracy is only valid in the + * range 0 to 100000 meters. + * + * @return + * The effective gravitational acceleration expressed in meters per second squared. + */ +fun observerGravity(latitude: Double, height: Double): Double { + val s = dsin(latitude) + val s2 = s*s + val g0 = 9.7803253359 * (1.0 + 0.00193185265241*s2) / sqrt(1.0 - 0.00669437999013*s2) + return g0 * (1.0 - (3.15704e-07 - 2.10269e-09*s2)*height + 7.37452e-14*height*height) +} + + /** * Calculates a rotation matrix from equatorial J2000 (EQJ) to ecliptic J2000 (ECL). * diff --git a/source/kotlin/README.md b/source/kotlin/README.md index 036b42fd..180c9c04 100644 --- a/source/kotlin/README.md +++ b/source/kotlin/README.md @@ -133,6 +133,7 @@ these are used in function and type names. | [nextLunarEclipse](doc/next-lunar-eclipse.md) | [jvm]
fun [nextLunarEclipse](doc/next-lunar-eclipse.md)(prevEclipseTime: [Time](doc/-time/index.md)): [LunarEclipseInfo](doc/-lunar-eclipse-info/index.md)
Searches for the next lunar eclipse in a series. | | [nextMoonQuarter](doc/next-moon-quarter.md) | [jvm]
fun [nextMoonQuarter](doc/next-moon-quarter.md)(mq: [MoonQuarterInfo](doc/-moon-quarter-info/index.md)): [MoonQuarterInfo](doc/-moon-quarter-info/index.md)
Continues searching for lunar quarters from a previous search. | | [nextTransit](doc/next-transit.md) | [jvm]
fun [nextTransit](doc/next-transit.md)(body: [Body](doc/-body/index.md), prevTransitTime: [Time](doc/-time/index.md)): [TransitInfo](doc/-transit-info/index.md)
Searches for another transit of Mercury or Venus. | +| [observerGravity](doc/observer-gravity.md) | [jvm]
fun [observerGravity](doc/observer-gravity.md)(latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), height: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Calculates the gravitational acceleration experienced by an observer on the Earth. | | [pairLongitude](doc/pair-longitude.md) | [jvm]
fun [pairLongitude](doc/pair-longitude.md)(body1: [Body](doc/-body/index.md), body2: [Body](doc/-body/index.md), time: [Time](doc/-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Returns one body's ecliptic longitude with respect to another, as seen from the Earth. | | [radiansToDegrees](doc/radians-to-degrees.md) | [jvm]
fun [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html).[radiansToDegrees](doc/radians-to-degrees.md)(): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Convert an angle expressed in radians to an angle expressed in degrees. | | [refractionAngle](doc/refraction-angle.md) | [jvm]
fun [refractionAngle](doc/refraction-angle.md)(refraction: [Refraction](doc/-refraction/index.md), altitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. | diff --git a/source/kotlin/doc/index.md b/source/kotlin/doc/index.md index 83091fb1..9fd43e70 100644 --- a/source/kotlin/doc/index.md +++ b/source/kotlin/doc/index.md @@ -78,6 +78,7 @@ | [nextLunarEclipse](next-lunar-eclipse.md) | [jvm]
fun [nextLunarEclipse](next-lunar-eclipse.md)(prevEclipseTime: [Time](-time/index.md)): [LunarEclipseInfo](-lunar-eclipse-info/index.md)
Searches for the next lunar eclipse in a series. | | [nextMoonQuarter](next-moon-quarter.md) | [jvm]
fun [nextMoonQuarter](next-moon-quarter.md)(mq: [MoonQuarterInfo](-moon-quarter-info/index.md)): [MoonQuarterInfo](-moon-quarter-info/index.md)
Continues searching for lunar quarters from a previous search. | | [nextTransit](next-transit.md) | [jvm]
fun [nextTransit](next-transit.md)(body: [Body](-body/index.md), prevTransitTime: [Time](-time/index.md)): [TransitInfo](-transit-info/index.md)
Searches for another transit of Mercury or Venus. | +| [observerGravity](observer-gravity.md) | [jvm]
fun [observerGravity](observer-gravity.md)(latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), height: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Calculates the gravitational acceleration experienced by an observer on the Earth. | | [pairLongitude](pair-longitude.md) | [jvm]
fun [pairLongitude](pair-longitude.md)(body1: [Body](-body/index.md), body2: [Body](-body/index.md), time: [Time](-time/index.md)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Returns one body's ecliptic longitude with respect to another, as seen from the Earth. | | [radiansToDegrees](radians-to-degrees.md) | [jvm]
fun [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html).[radiansToDegrees](radians-to-degrees.md)(): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Convert an angle expressed in radians to an angle expressed in degrees. | | [refractionAngle](refraction-angle.md) | [jvm]
fun [refractionAngle](refraction-angle.md)(refraction: [Refraction](-refraction/index.md), altitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)
Calculates the amount of "lift" to an altitude angle caused by atmospheric refraction. | diff --git a/source/kotlin/doc/observer-gravity.md b/source/kotlin/doc/observer-gravity.md new file mode 100644 index 00000000..e30b6c03 --- /dev/null +++ b/source/kotlin/doc/observer-gravity.md @@ -0,0 +1,23 @@ +//[astronomy](../../index.md)/[io.github.cosinekitty.astronomy](index.md)/[observerGravity](observer-gravity.md) + +# observerGravity + +[jvm]\ +fun [observerGravity](observer-gravity.md)(latitude: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html), height: [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html)): [Double](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/index.html) + +Calculates the gravitational acceleration experienced by an observer on the Earth. + +This function implements the WGS 84 Ellipsoidal Gravity Formula. The result is a combination of inward gravitational acceleration with outward centrifugal acceleration, as experienced by an observer in the Earth's rotating frame of reference. The resulting value increases toward the Earth's poles and decreases toward the equator, consistent with changes of the weight measured by a spring scale of a fixed mass moved to different latitudes and heights on the Earth. + +#### Return + +The effective gravitational acceleration expressed in meters per second squared. + +## Parameters + +jvm + +| | | +|---|---| +| latitude | The latitude of the observer in degrees north or south of the equator. By formula symmetry, positive latitudes give the same answer as negative latitudes, so the sign does not matter. | +| height | The height above the sea level geoid in meters. No range checking is done; however, accuracy is only valid in the range 0 to 100000 meters. | diff --git a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt index 126898ac..d0da3e37 100644 --- a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt +++ b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt @@ -6523,6 +6523,39 @@ fun searchPeakMagnitude(body: Body, startTime: Time): IlluminationInfo { } +/** + * Calculates the gravitational acceleration experienced by an observer on the Earth. + * + * This function implements the WGS 84 Ellipsoidal Gravity Formula. + * The result is a combination of inward gravitational acceleration + * with outward centrifugal acceleration, as experienced by an observer + * in the Earth's rotating frame of reference. + * The resulting value increases toward the Earth's poles and decreases + * toward the equator, consistent with changes of the weight measured + * by a spring scale of a fixed mass moved to different latitudes and heights + * on the Earth. + * + * @param latitude + * The latitude of the observer in degrees north or south of the equator. + * By formula symmetry, positive latitudes give the same answer as negative + * latitudes, so the sign does not matter. + * + * @param height + * The height above the sea level geoid in meters. + * No range checking is done; however, accuracy is only valid in the + * range 0 to 100000 meters. + * + * @return + * The effective gravitational acceleration expressed in meters per second squared. + */ +fun observerGravity(latitude: Double, height: Double): Double { + val s = dsin(latitude) + val s2 = s*s + val g0 = 9.7803253359 * (1.0 + 0.00193185265241*s2) / sqrt(1.0 - 0.00669437999013*s2) + return g0 * (1.0 - (3.15704e-07 - 2.10269e-09*s2)*height + 7.37452e-14*height*height) +} + + /** * Calculates a rotation matrix from equatorial J2000 (EQJ) to ecliptic J2000 (ECL). * diff --git a/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt b/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt index 1ffa32d5..9931e9aa 100644 --- a/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt +++ b/source/kotlin/src/test/kotlin/io/github/cosinekitty/astronomy/Tests.kt @@ -2012,4 +2012,29 @@ class Tests { } //---------------------------------------------------------------------------------------- + + @Test + fun `Gravity measured on Earth`() { + // Spot-check against values calculated by the Python version of Astronomy Engine. + verifyObserverGravity( 0.0, 0.0, 9.7803253359 ) + verifyObserverGravity(+10.0, 0.0, 9.781882400630266) + verifyObserverGravity(-10.0, 0.0, 9.781882400630266) + verifyObserverGravity(+10.0, 1000.0, 9.778795562804849) + verifyObserverGravity(-10.0, 1000.0, 9.778795562804849) + verifyObserverGravity(+30.0, 100.0, 9.792938614507834) + verifyObserverGravity(-30.0, 100.0, 9.792938614507834) + verifyObserverGravity(+45.0, 0.0, 9.80619776937321 ) + verifyObserverGravity(-45.0, 0.0, 9.80619776937321 ) + verifyObserverGravity(+90.0, 0.0, 9.832184937858958) + verifyObserverGravity(-90.0, 0.0, 9.832184937858958) + } + + private fun verifyObserverGravity(latitude: Double, height: Double, correct: Double) { + val tolerance = 1.0e-16 + val calc = observerGravity(latitude, height) + val diff = abs(calc - correct) + assertTrue(diff < tolerance, "excessive gravity error: calc=$calc, correct=$correct") + } + + //---------------------------------------------------------------------------------------- }