@jjlmoya/utils-science 1.32.0 → 1.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/category/index.ts +3 -1
- package/src/entries.ts +5 -1
- package/src/index.ts +2 -0
- package/src/tests/locale_completeness.test.ts +2 -2
- package/src/tests/tool_validation.test.ts +2 -2
- package/src/tool/natural-selection-drift/component.astro +37 -6
- package/src/tool/natural-selection-drift/natural-selection-drift.css +134 -0
- package/src/tool/planet-atmosphere-survival/bibliography.astro +14 -0
- package/src/tool/planet-atmosphere-survival/bibliography.ts +16 -0
- package/src/tool/planet-atmosphere-survival/component.astro +404 -0
- package/src/tool/planet-atmosphere-survival/entry.ts +26 -0
- package/src/tool/planet-atmosphere-survival/i18n/de.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/en.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/es.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/fr.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/id.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/it.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/ja.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/ko.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/nl.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/pl.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/pt.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/ru.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/sv.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/tr.ts +255 -0
- package/src/tool/planet-atmosphere-survival/i18n/zh.ts +255 -0
- package/src/tool/planet-atmosphere-survival/index.ts +11 -0
- package/src/tool/planet-atmosphere-survival/logic.ts +201 -0
- package/src/tool/planet-atmosphere-survival/planet-atmosphere-survival-calculator.css +494 -0
- package/src/tool/planet-atmosphere-survival/seo.astro +15 -0
- package/src/tool/three-body-problem/app.ts +274 -0
- package/src/tool/three-body-problem/bibliography.astro +14 -0
- package/src/tool/three-body-problem/bibliography.ts +16 -0
- package/src/tool/three-body-problem/component.astro +70 -0
- package/src/tool/three-body-problem/entry.ts +26 -0
- package/src/tool/three-body-problem/i18n/de.ts +162 -0
- package/src/tool/three-body-problem/i18n/en.ts +162 -0
- package/src/tool/three-body-problem/i18n/es.ts +162 -0
- package/src/tool/three-body-problem/i18n/fr.ts +162 -0
- package/src/tool/three-body-problem/i18n/id.ts +162 -0
- package/src/tool/three-body-problem/i18n/it.ts +162 -0
- package/src/tool/three-body-problem/i18n/ja.ts +162 -0
- package/src/tool/three-body-problem/i18n/ko.ts +162 -0
- package/src/tool/three-body-problem/i18n/nl.ts +162 -0
- package/src/tool/three-body-problem/i18n/pl.ts +162 -0
- package/src/tool/three-body-problem/i18n/pt.ts +162 -0
- package/src/tool/three-body-problem/i18n/ru.ts +162 -0
- package/src/tool/three-body-problem/i18n/sv.ts +162 -0
- package/src/tool/three-body-problem/i18n/tr.ts +162 -0
- package/src/tool/three-body-problem/i18n/zh.ts +162 -0
- package/src/tool/three-body-problem/index.ts +11 -0
- package/src/tool/three-body-problem/logic/ThreeBodyEngine.ts +179 -0
- package/src/tool/three-body-problem/seo.astro +15 -0
- package/src/tool/three-body-problem/three-body-problem-simulator.css +503 -0
- package/src/tools.ts +4 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
|
|
4
|
+
const slug = 'uc-cisim-problemi-simulatoru';
|
|
5
|
+
const title = 'Üç Cisim Problemi Simülatörü';
|
|
6
|
+
const description = 'Düzenlenebilir kütleler, hız vektörleri, izler ve kararlı veya kaotik ön ayarlarla iki boyutlu bir düzlemde üç kütleçekimsel cismi simüle edin.';
|
|
7
|
+
|
|
8
|
+
const howTo = [
|
|
9
|
+
{
|
|
10
|
+
name: 'Bir yörünge ön ayarı seçin',
|
|
11
|
+
text: 'Kararlı bir referans için sekiz figürü yörüngesiyle, dönen bir denge için Lagrange üçgeniyle veya görünür şekilde kaotik bir karşılaşma için sapan ön ayarıyla başlayın.',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'Kütleleri ve hız vektörlerini ayarlayın',
|
|
15
|
+
text: 'Her cisim için kaydırıcıları kullanarak kütleyi ve başlangıç hızı bileşenlerini değiştirin. Küçük değişiklikler bir deseni koruyabilir, deforme edebilir veya tamamen yok edebilir.',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'Tanıları okuyun',
|
|
19
|
+
text: 'Sayısal yörüngenin bağlı kalıp kalmadığını veya dağılıp dağılmadığını anlamak için toplam enerjiyi, en yakın ve en uzak ayrılmayı ve kütle merkezini izleyin.',
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const faq = [
|
|
24
|
+
{
|
|
25
|
+
question: 'Üç cisim problemi nedir?',
|
|
26
|
+
answer: 'Üç cisim problemi, her bir cismin diğer ikisini kütleçekimsel olarak çekmesi durumunda üç kütlenin nasıl hareket ettiğini sorgular. İki cisim probleminden farklı olarak, her olası konfigürasyonu çözen genel bir kapalı form denklemi yoktur, bu nedenle pratik vakaların çoğu sayısal entegrasyonla keşfedilir.',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
question: 'Üç cisim yörüngeleri neden kararsızdır?',
|
|
30
|
+
answer: 'Birçok üç cisim sistemi başlangıç koşullarına duyarlıdır. Hız, konum veya kütledeki küçük bir değişiklik yakın karşılaşmaların zamanlamasını değiştirir ve bu karşılaşmalar enerjiyi dramatik bir şekilde değiş tokuş edebilir. Sonuç, bir süre bağlı kalıp ardından aniden bir cismi fırlatabilen bir sistemdir.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
question: 'Sekiz figürü ön ayarı neyi gösterir?',
|
|
34
|
+
answer: 'Sekiz figürü ön ayarı, üç eşit kütle için ünlü bir periyodik çözümdür. Her cisim aynı yolu bir faz kaymasıyla takip eder ve üç cisim probleminin çok daha büyük bir kaotik manzara içinde zarif kararlı adalar içerebileceğini gösterir.',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: 'Bu fiziksel olarak tam doğru bir astronomi simülatörü müdür?',
|
|
38
|
+
answer: 'Bu araç, hareketin öğrenme için sadık ve kararlı hissettirmesi amacıyla yumuşatılmış bir Newton modeli ve semplektik hız Verlet adımı kullanır. Yüksek hassasiyetli gök günlüğü tahmininden ziyade etkileşimli keşif için tasarlanmıştır.',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
question: 'Toplam enerjiyi nasıl yorumlamalıyım?',
|
|
42
|
+
answer: 'Negatif toplam enerji genellikle bağlı bir sistemi gösterirken, sıfıra yakın enerji kaçışı kolaylaştırabilir. Sayısal bir simülasyonda, büyük enerji sapması ayrıca zaman adımının veya karşılaşma geometrisinin entegratörü zorladığı konusunda uyarır.',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const content: ToolLocaleContent = {
|
|
47
|
+
slug,
|
|
48
|
+
title,
|
|
49
|
+
description,
|
|
50
|
+
ui: {
|
|
51
|
+
title,
|
|
52
|
+
kicker: 'Kütleçekimsel kaos laboratuvarı',
|
|
53
|
+
canvasLabel: 'Etkileşimli iki boyutlu üç cisim yörünge tuvali',
|
|
54
|
+
presetsLabel: 'Yörünge ön ayarları',
|
|
55
|
+
figureEightPreset: 'Sekiz figürü',
|
|
56
|
+
lagrangePreset: 'Lagrange üçgeni',
|
|
57
|
+
slingshotPreset: 'Sapan',
|
|
58
|
+
pauseButton: 'Duraklat',
|
|
59
|
+
playButton: 'Oynat',
|
|
60
|
+
resetButton: 'Sıfırla',
|
|
61
|
+
speedLabel: 'Simülasyon hızı',
|
|
62
|
+
trailLabel: 'İz uzunluğu',
|
|
63
|
+
massLabel: 'Kütle',
|
|
64
|
+
velocityXLabel: 'Hız X',
|
|
65
|
+
velocityYLabel: 'Hız Y',
|
|
66
|
+
energyLabel: 'Toplam enerji',
|
|
67
|
+
separationLabel: 'Ayrılma aralığı',
|
|
68
|
+
centerMassLabel: 'Kütle merkezi',
|
|
69
|
+
},
|
|
70
|
+
seo: [
|
|
71
|
+
{
|
|
72
|
+
type: 'title',
|
|
73
|
+
text: 'Yörüngesel Kaos için Etkileşimli Üç Cisim Problemi Simülatörü',
|
|
74
|
+
level: 2,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'paragraph',
|
|
78
|
+
html: 'Üç cisim problemi, basit yasaların karmaşık hareket üretebileceğinin en açık göstergelerinden biridir. Newton kütleçekimi kompakt bir kuvvet kuralı verir, ancak üçüncü bir kütleli cisim sisteme katıldığı anda her yörünge sürekli olarak diğer ikisini yeniden şekillendirir. Bu simülatör, bu kararsızlıkla doğrudan deney yapmanızı sağlar: bilinen bir konfigürasyon seçin, kütleleri ve hız vektörlerini ayarlayın ve cisimlerin tekrarlayan bir yörünge, dönen bir üçgen veya kaotik bir saçılma olayı oluşturup oluşturmadığını izleyin.',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: 'title',
|
|
82
|
+
text: 'Ön Ayarların Gösterdikleri',
|
|
83
|
+
level: 3,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: 'table',
|
|
87
|
+
headers: ['Ön Ayar', 'Fiziksel fikir', 'Nelere dikkat edilmeli'],
|
|
88
|
+
rows: [
|
|
89
|
+
['<strong>Sekiz figürü</strong>', 'Her üç cismin aynı döngüyü paylaştığı eşit kütleli periyodik bir çözüm.', 'Yörünge yalnızca simetri ve hız dengesi dikkatlice korunduğunda organize kalır.'],
|
|
90
|
+
['<strong>Lagrange üçgeni</strong>', 'Üç cisim, kütle merkezi etrafında dönen bir eşkenar üçgen işgal eder.', 'Kütle dengesi ve teğetsel hız, üçgenin içe çökmesini engeller.'],
|
|
91
|
+
['<strong>Sapan</strong>', 'Yakın bir karşılaşma cisimler arasında enerji transfer eder.', 'Bir cisim hız kazanırken diğeri daha sıkı bağlı hale gelir ve kaotik fırlatmaların neden oluştuğunu ortaya çıkarır.'],
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
type: 'title',
|
|
96
|
+
text: 'Küçük Değişiklikler Neden Önemlidir',
|
|
97
|
+
level: 3,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'paragraph',
|
|
101
|
+
html: 'İki cisim yörüngesinde, kütle merkezi ve yörünge elipsi istikrarlı bir geometrik resim sağlar. Üç cisim sisteminde, yakın geçişler kütleçekimsel müzakereler gibi davranır: bir cisim yörüngesel enerji ödünç alabilir, keskin bir şekilde yön değiştirebilir veya düzenli bir döngüyü saçılma olayına dönüştürebilir. Bu hassasiyet, üçlü yıldızlar, gezegen-ay karşılaşmaları ve erken güneş sistemi gezegenimsileri gibi gerçek astrofiziksel sistemlerin tek bir basit formül yerine genellikle sayısal entegrasyon gerektirmesinin nedenidir.',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'title',
|
|
105
|
+
text: 'Tanılar Nasıl Kullanılır',
|
|
106
|
+
level: 3,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'list',
|
|
110
|
+
items: [
|
|
111
|
+
'<strong>Toplam enerji</strong>, sistemin bağlı olup olmadığını ve sayısal entegrasyonun kararlı kalıp kalmadığını değerlendirmenize yardımcı olur.',
|
|
112
|
+
'<strong>Ayrılma aralığı</strong>, en yakın ve en uzak çift mesafelerini göstererek neredeyse çarpışmaları ve fırlatmaları kolayca tespit etmenizi sağlar.',
|
|
113
|
+
'<strong>Kütle merkezi</strong>, başlangıç momentumu dengeli olduğunda nispeten sabit kalmalıdır; sapma, kasıtlı olarak asimetrik bir kurulum veya değiştirilmiş bir hız vektörü olduğunu gösterir.',
|
|
114
|
+
'<strong>İz uzunluğu</strong>, uzun vadeli yapıyı ortaya çıkarır: kısa izler mevcut etkileşimi vurgularken, uzun izler tekrarlayan döngüleri ve yavaş yörüngesel devinimi sergiler.',
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'title',
|
|
119
|
+
text: 'Araçta Kullanılan Sayısal Model',
|
|
120
|
+
level: 3,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'paragraph',
|
|
124
|
+
html: 'Simülatör, aşırı yakın geçişler sırasında görsel patlamaları önleyen küçük bir yumuşatma terimi ile Newton ters-kare çekimini kullanır. Hareket, basit bir Euler güncellemesinden daha iyi enerji davranışı sağladığı için yörünge gösterimlerinde yaygın bir seçim olan hız Verlet adımıyla ilerletilir. Sonuç, profesyonel gök mekaniği yazılımının yerini almaya çalışmadan üç cisim probleminin niteliksel davranışını görünür kılan duyarlı bir eğitim modelidir.',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
faq,
|
|
128
|
+
bibliography,
|
|
129
|
+
howTo,
|
|
130
|
+
schemas: [
|
|
131
|
+
{
|
|
132
|
+
'@context': 'https://schema.org',
|
|
133
|
+
'@type': 'SoftwareApplication',
|
|
134
|
+
name: title,
|
|
135
|
+
description,
|
|
136
|
+
applicationCategory: 'ScientificApplication',
|
|
137
|
+
operatingSystem: 'Any',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
'@context': 'https://schema.org',
|
|
141
|
+
'@type': 'FAQPage',
|
|
142
|
+
mainEntity: faq.map((item) => ({
|
|
143
|
+
'@type': 'Question',
|
|
144
|
+
name: item.question,
|
|
145
|
+
acceptedAnswer: {
|
|
146
|
+
'@type': 'Answer',
|
|
147
|
+
text: item.answer,
|
|
148
|
+
},
|
|
149
|
+
})),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
'@context': 'https://schema.org',
|
|
153
|
+
'@type': 'HowTo',
|
|
154
|
+
name: title,
|
|
155
|
+
step: howTo.map((step) => ({
|
|
156
|
+
'@type': 'HowToStep',
|
|
157
|
+
name: step.name,
|
|
158
|
+
text: step.text,
|
|
159
|
+
})),
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { bibliography } from '../bibliography';
|
|
2
|
+
import type { ToolLocaleContent } from '../../../types';
|
|
3
|
+
|
|
4
|
+
const slug = 'three-body-problem-simulator';
|
|
5
|
+
const title = '三体问题模拟器';
|
|
6
|
+
const description = '在二维平面上模拟三个引力体,可编辑质量、速度矢量、轨迹,并支持稳定或混沌预设。';
|
|
7
|
+
|
|
8
|
+
const howTo = [
|
|
9
|
+
{
|
|
10
|
+
name: '选择轨道预设',
|
|
11
|
+
text: '从八字形轨道开始作为稳定基准,选择拉格朗日三角作为旋转平衡,或者选择弹弓预设观察明显的混沌交会。',
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: '调整质量与速度矢量',
|
|
15
|
+
text: '使用每个天体的滑块改变质量和初始速度分量。微小的改变可以保留模式、使其变形,或彻底破坏它。',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: '读取诊断信息',
|
|
19
|
+
text: '关注总能量、最近和最远间距以及质心,以判断数值轨道是否保持有界还是正在漂散。',
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
const faq = [
|
|
24
|
+
{
|
|
25
|
+
question: '什么是三体问题?',
|
|
26
|
+
answer: '三体问题探究三个质量体在彼此引力作用下的运动方式。与二体问题不同,不存在一个通用的封闭方程来求解所有可能的构型,因此大多数实际案例都通过数值积分来探索。',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
question: '为什么三体轨道不稳定?',
|
|
30
|
+
answer: '许多三体系统对初始条件非常敏感。速度、位置或质量的微小变化都会改变近距离交会的时机,而这些交会可以戏剧性地交换能量。结果就是一个系统可能在一段时间内保持有界,然后突然抛射出其中一个天体。',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
question: '八字形预设展示了什么?',
|
|
34
|
+
answer: '八字形预设是三个等质量体的一个著名周期解。每个天体以相位偏移的方式沿着相同的路径运动,展示了三体问题在更大的混沌景观中可以包含优雅的稳定孤岛。',
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
question: '这是一个物理上精确的天文学模拟器吗?',
|
|
38
|
+
answer: '该工具使用软化牛顿模型和辛速度韦尔莱步进,使运动感觉逼真且稳定,适合学习。它专为交互式探索而设计,而非高精度的星历预测。',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
question: '如何解读总能量?',
|
|
42
|
+
answer: '负的总能量通常表示有界系统,而接近零的能量则可能使逃逸更容易。在数值模拟中,较大的能量漂移也警告时间步长或交会几何形状正在对积分器造成压力。',
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
export const content: ToolLocaleContent = {
|
|
47
|
+
slug,
|
|
48
|
+
title,
|
|
49
|
+
description,
|
|
50
|
+
ui: {
|
|
51
|
+
title,
|
|
52
|
+
kicker: '引力混沌实验室',
|
|
53
|
+
canvasLabel: '交互式二维三体轨道画布',
|
|
54
|
+
presetsLabel: '轨道预设',
|
|
55
|
+
figureEightPreset: '八字形',
|
|
56
|
+
lagrangePreset: '拉格朗日三角',
|
|
57
|
+
slingshotPreset: '弹弓',
|
|
58
|
+
pauseButton: '暂停',
|
|
59
|
+
playButton: '播放',
|
|
60
|
+
resetButton: '重置',
|
|
61
|
+
speedLabel: '模拟速度',
|
|
62
|
+
trailLabel: '轨迹长度',
|
|
63
|
+
massLabel: '质量',
|
|
64
|
+
velocityXLabel: '速度 X',
|
|
65
|
+
velocityYLabel: '速度 Y',
|
|
66
|
+
energyLabel: '总能量',
|
|
67
|
+
separationLabel: '间距范围',
|
|
68
|
+
centerMassLabel: '质心',
|
|
69
|
+
},
|
|
70
|
+
seo: [
|
|
71
|
+
{
|
|
72
|
+
type: 'title',
|
|
73
|
+
text: '交互式三体问题模拟器 - 探索轨道混沌',
|
|
74
|
+
level: 2,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'paragraph',
|
|
78
|
+
html: '三体问题是证明简单定律可以产生复杂运动的最清晰例证之一。牛顿引力给出了一个简洁的力法则,但一旦第三个质量体加入系统,每条轨道都会持续重塑另外两条。这款模拟器让您直接体验这种不稳定性:选择已知构型,调整质量和速度矢量,观察天体是形成重复轨道、旋转三角形还是混沌散射事件。',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: 'title',
|
|
82
|
+
text: '预设所展示的物理原理',
|
|
83
|
+
level: 3,
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: 'table',
|
|
87
|
+
headers: ['预设', '物理概念', '观察要点'],
|
|
88
|
+
rows: [
|
|
89
|
+
['<strong>八字形</strong>', '三个等质量天体共享同一条环路的周期解。', '只有当对称性和速度平衡被精心保持时,轨道才能保持有序。'],
|
|
90
|
+
['<strong>拉格朗日三角</strong>', '三个天体占据一个绕质心旋转的等边三角形。', '质量平衡和切向速度防止三角向内坍缩。'],
|
|
91
|
+
['<strong>弹弓</strong>', '近距离交会时天体间传递能量。', '一个天体获得速度,同时另一个天体被更紧密地束缚,揭示了混沌抛射发生的原因。'],
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
type: 'title',
|
|
96
|
+
text: '微小改变为何重要',
|
|
97
|
+
level: 3,
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
type: 'paragraph',
|
|
101
|
+
html: '在二体轨道中,质心和轨道椭圆提供了稳定的几何图像。而在三体系统中,近距离通过如同引力谈判:一个天体可以借用轨道能量、急剧改变方向,或将有序的环路转变为散射事件。这种敏感性正是真实天体物理系统(如三合星、行星-卫星交会和早期太阳系的星子)通常需要数值积分而非单一简单公式的原因。',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: 'title',
|
|
105
|
+
text: '如何使用诊断信息',
|
|
106
|
+
level: 3,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'list',
|
|
110
|
+
items: [
|
|
111
|
+
'<strong>总能量</strong>帮助您判断系统是否受约束以及数值积分是否保持稳定。',
|
|
112
|
+
'<strong>间距范围</strong>显示最近和最远的天体对距离,使近碰撞和抛射易于识别。',
|
|
113
|
+
'<strong>质心</strong>在初始动量平衡时应保持相对稳定;漂移则暗示非对称设置或速度矢量的改变。',
|
|
114
|
+
'<strong>轨迹长度</strong>揭示了长期结构:短轨迹强调当前相互作用,而长轨迹则暴露重复环路和缓慢的轨道进动。',
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'title',
|
|
119
|
+
text: '工具中使用的数值模型',
|
|
120
|
+
level: 3,
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
type: 'paragraph',
|
|
124
|
+
html: '该模拟器使用牛顿反平方引力,并带有一个小的软化项,以防止极端接近通过时出现视觉爆炸。运动通过速度韦尔莱步进推进,这是轨道演示的常见选择,因为它比简单的欧拉更新更好地处理能量行为。结果是一个响应迅速的教育模型,使三体问题的定性行为可见,同时不试图取代专业的天体力学软件。',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
faq,
|
|
128
|
+
bibliography,
|
|
129
|
+
howTo,
|
|
130
|
+
schemas: [
|
|
131
|
+
{
|
|
132
|
+
'@context': 'https://schema.org',
|
|
133
|
+
'@type': 'SoftwareApplication',
|
|
134
|
+
name: title,
|
|
135
|
+
description,
|
|
136
|
+
applicationCategory: 'ScientificApplication',
|
|
137
|
+
operatingSystem: 'Any',
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
'@context': 'https://schema.org',
|
|
141
|
+
'@type': 'FAQPage',
|
|
142
|
+
mainEntity: faq.map((item) => ({
|
|
143
|
+
'@type': 'Question',
|
|
144
|
+
name: item.question,
|
|
145
|
+
acceptedAnswer: {
|
|
146
|
+
'@type': 'Answer',
|
|
147
|
+
text: item.answer,
|
|
148
|
+
},
|
|
149
|
+
})),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
'@context': 'https://schema.org',
|
|
153
|
+
'@type': 'HowTo',
|
|
154
|
+
name: title,
|
|
155
|
+
step: howTo.map((step) => ({
|
|
156
|
+
'@type': 'HowToStep',
|
|
157
|
+
name: step.name,
|
|
158
|
+
text: step.text,
|
|
159
|
+
})),
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { threeBodyProblem } from './entry';
|
|
2
|
+
import type { ToolDefinition } from '../../types';
|
|
3
|
+
|
|
4
|
+
export * from './entry';
|
|
5
|
+
|
|
6
|
+
export const THREE_BODY_PROBLEM_TOOL: ToolDefinition = {
|
|
7
|
+
entry: threeBodyProblem,
|
|
8
|
+
Component: () => import('./component.astro'),
|
|
9
|
+
SEOComponent: () => import('./seo.astro'),
|
|
10
|
+
BibliographyComponent: () => import('./bibliography.astro'),
|
|
11
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
export interface BodyState {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
mass: number;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
vx: number;
|
|
8
|
+
vy: number;
|
|
9
|
+
color: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ThreeBodyMetrics {
|
|
13
|
+
kineticEnergy: number;
|
|
14
|
+
potentialEnergy: number;
|
|
15
|
+
totalEnergy: number;
|
|
16
|
+
centerOfMassX: number;
|
|
17
|
+
centerOfMassY: number;
|
|
18
|
+
maxSeparation: number;
|
|
19
|
+
minSeparation: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SimulationSnapshot {
|
|
23
|
+
bodies: BodyState[];
|
|
24
|
+
metrics: ThreeBodyMetrics;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ThreeBodyPreset {
|
|
28
|
+
id: string;
|
|
29
|
+
bodies: BodyState[];
|
|
30
|
+
timeStep: number;
|
|
31
|
+
trailLength: number;
|
|
32
|
+
zoom: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface SeparationMetrics {
|
|
36
|
+
potentialEnergy: number;
|
|
37
|
+
maxSeparation: number;
|
|
38
|
+
minSeparation: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const GRAVITATIONAL_CONSTANT = 1;
|
|
42
|
+
const SOFTENING = 0.035;
|
|
43
|
+
|
|
44
|
+
export const THREE_BODY_PRESETS: ThreeBodyPreset[] = [
|
|
45
|
+
{
|
|
46
|
+
id: 'figureEight',
|
|
47
|
+
timeStep: 0.012,
|
|
48
|
+
trailLength: 720,
|
|
49
|
+
zoom: 145,
|
|
50
|
+
bodies: [
|
|
51
|
+
{ id: 'body-a', label: 'A', mass: 1, x: -0.97000436, y: 0.24308753, vx: 0.46620369, vy: 0.43236573, color: '#b85b62' },
|
|
52
|
+
{ id: 'body-b', label: 'B', mass: 1, x: 0.97000436, y: -0.24308753, vx: 0.46620369, vy: 0.43236573, color: '#2f7f8d' },
|
|
53
|
+
{ id: 'body-c', label: 'C', mass: 1, x: 0, y: 0, vx: -0.93240737, vy: -0.86473146, color: '#a9853d' },
|
|
54
|
+
],
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'lagrange',
|
|
58
|
+
timeStep: 0.014,
|
|
59
|
+
trailLength: 620,
|
|
60
|
+
zoom: 155,
|
|
61
|
+
bodies: [
|
|
62
|
+
{ id: 'body-a', label: 'A', mass: 1.2, x: 0, y: 1, vx: -0.54, vy: 0, color: '#b85b62' },
|
|
63
|
+
{ id: 'body-b', label: 'B', mass: 1.2, x: -0.866, y: -0.5, vx: 0.27, vy: -0.468, color: '#2f7f8d' },
|
|
64
|
+
{ id: 'body-c', label: 'C', mass: 1.2, x: 0.866, y: -0.5, vx: 0.27, vy: 0.468, color: '#a9853d' },
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'slingshot',
|
|
69
|
+
timeStep: 0.01,
|
|
70
|
+
trailLength: 520,
|
|
71
|
+
zoom: 120,
|
|
72
|
+
bodies: [
|
|
73
|
+
{ id: 'body-a', label: 'A', mass: 2.5, x: -0.45, y: 0, vx: 0, vy: -0.24, color: '#b85b62' },
|
|
74
|
+
{ id: 'body-b', label: 'B', mass: 1, x: 0.72, y: 0.1, vx: -0.2, vy: 0.66, color: '#2f7f8d' },
|
|
75
|
+
{ id: 'body-c', label: 'C', mass: 0.35, x: 0.16, y: -1.22, vx: 1.18, vy: 0.25, color: '#a9853d' },
|
|
76
|
+
],
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
export class ThreeBodyEngine {
|
|
81
|
+
public cloneBodies(bodies: BodyState[]): BodyState[] {
|
|
82
|
+
return bodies.map((body) => ({ ...body }));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public step(bodies: BodyState[], dt: number): SimulationSnapshot {
|
|
86
|
+
const accelerations = this.calculateAccelerations(bodies);
|
|
87
|
+
const halfStepBodies = bodies.map((body, index) => ({
|
|
88
|
+
...body,
|
|
89
|
+
vx: body.vx + accelerations[index].ax * dt * 0.5,
|
|
90
|
+
vy: body.vy + accelerations[index].ay * dt * 0.5,
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
const movedBodies = halfStepBodies.map((body) => ({
|
|
94
|
+
...body,
|
|
95
|
+
x: body.x + body.vx * dt,
|
|
96
|
+
y: body.y + body.vy * dt,
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
const nextAccelerations = this.calculateAccelerations(movedBodies);
|
|
100
|
+
const nextBodies = movedBodies.map((body, index) => ({
|
|
101
|
+
...body,
|
|
102
|
+
vx: body.vx + nextAccelerations[index].ax * dt * 0.5,
|
|
103
|
+
vy: body.vy + nextAccelerations[index].ay * dt * 0.5,
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
return {
|
|
107
|
+
bodies: nextBodies,
|
|
108
|
+
metrics: this.calculateMetrics(nextBodies),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public calculateMetrics(bodies: BodyState[]): ThreeBodyMetrics {
|
|
113
|
+
let kineticEnergy = 0;
|
|
114
|
+
let totalMass = 0;
|
|
115
|
+
let weightedX = 0;
|
|
116
|
+
let weightedY = 0;
|
|
117
|
+
|
|
118
|
+
bodies.forEach((body) => {
|
|
119
|
+
kineticEnergy += 0.5 * body.mass * (body.vx * body.vx + body.vy * body.vy);
|
|
120
|
+
totalMass += body.mass;
|
|
121
|
+
weightedX += body.mass * body.x;
|
|
122
|
+
weightedY += body.mass * body.y;
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const separation = this.calculateSeparationMetrics(bodies);
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
kineticEnergy,
|
|
129
|
+
potentialEnergy: separation.potentialEnergy,
|
|
130
|
+
totalEnergy: kineticEnergy + separation.potentialEnergy,
|
|
131
|
+
centerOfMassX: weightedX / totalMass,
|
|
132
|
+
centerOfMassY: weightedY / totalMass,
|
|
133
|
+
maxSeparation: separation.maxSeparation,
|
|
134
|
+
minSeparation: separation.minSeparation,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private calculateSeparationMetrics(bodies: BodyState[]): SeparationMetrics {
|
|
139
|
+
let potentialEnergy = 0;
|
|
140
|
+
let maxSeparation = 0;
|
|
141
|
+
let minSeparation = Number.POSITIVE_INFINITY;
|
|
142
|
+
|
|
143
|
+
for (let i = 0; i < bodies.length; i += 1) {
|
|
144
|
+
for (let j = i + 1; j < bodies.length; j += 1) {
|
|
145
|
+
const dx = bodies[j].x - bodies[i].x;
|
|
146
|
+
const dy = bodies[j].y - bodies[i].y;
|
|
147
|
+
const distance = Math.sqrt(dx * dx + dy * dy + SOFTENING * SOFTENING);
|
|
148
|
+
potentialEnergy -= (GRAVITATIONAL_CONSTANT * bodies[i].mass * bodies[j].mass) / distance;
|
|
149
|
+
maxSeparation = Math.max(maxSeparation, distance);
|
|
150
|
+
minSeparation = Math.min(minSeparation, distance);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return {
|
|
155
|
+
potentialEnergy,
|
|
156
|
+
maxSeparation,
|
|
157
|
+
minSeparation,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private calculateAccelerations(bodies: BodyState[]) {
|
|
162
|
+
return bodies.map((body, index) => {
|
|
163
|
+
let ax = 0;
|
|
164
|
+
let ay = 0;
|
|
165
|
+
|
|
166
|
+
bodies.forEach((other, otherIndex) => {
|
|
167
|
+
if (index === otherIndex) return;
|
|
168
|
+
const dx = other.x - body.x;
|
|
169
|
+
const dy = other.y - body.y;
|
|
170
|
+
const softenedDistanceSquared = dx * dx + dy * dy + SOFTENING * SOFTENING;
|
|
171
|
+
const inverseDistanceCubed = 1 / Math.pow(softenedDistanceSquared, 1.5);
|
|
172
|
+
ax += GRAVITATIONAL_CONSTANT * other.mass * dx * inverseDistanceCubed;
|
|
173
|
+
ay += GRAVITATIONAL_CONSTANT * other.mass * dy * inverseDistanceCubed;
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
return { ax, ay };
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SEORenderer } from '@jjlmoya/utils-shared';
|
|
3
|
+
import { threeBodyProblem } from './index';
|
|
4
|
+
import type { KnownLocale } from '../../types';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
locale?: KnownLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { locale = 'en' } = Astro.props;
|
|
11
|
+
const content = await threeBodyProblem.i18n[locale]?.();
|
|
12
|
+
if (!content) return null;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
{content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
|