戴森球计划中的恒星戴森球轨道半径如何计算?相信大部分玩家都还不清楚,下面一起来看看恒星戴森球轨道半径计算简析吧。
简介
在游戏里造戴森球的时候, 我们往往需要寻找一个合适的星系建造戴森球. 一般来讲, 一个适合建造戴森球的星系需要:
高的光度, 以达到更大的生产功率
最大戴森球轨道半径大于第一行星公转轨道半径的 1.35 倍, 以实现全行星全天候都可以接收到产生的电力.[1]
虽然, 我们能够使用 Y 键查看戴森球的最大半径, 但这个操作必须在伊卡洛斯在该恒星的星系内部才能进行, 而飞行过程则需要能量, 抛曲器, 和最重要的时间. 为了节约这些资源, 我们需要在不飞往目标恒星的情况下, 对恒星做出筛选. 因此, 获知恒星参数和戴森球轨道半径的关系就十分重要了. 根据数据反推公式十分消耗时间, 所以这里利用了反编译工具对游戏代码进行解析, 以直接获取恒星戴森球轨道半径的计算公式.
工具介绍
主要使用了 dotPeek 工具对戴森球计划的程序 dll 文件进行了反编译. dotPeek 是 JetBrains 开发的一款反编译 .Net 程序的软件. 可以在其官网上免费下载. 建议使用网络安装器, 离线安装器里面大部分的内容与本文所用的功能无关.
解析过程
首先, 找到游戏文件夹中的 DSPGAME_DataManagedAssembly-CSharp.dll, 用 dotPeek 打开. 在 中找到 DysonSphere. 双击其中的 Init 函数打开, 可以看到如下代码:
DysonSphere 类中的初始化代码, 包含了戴森球半径的范围信息
可以看到, minOrbitRadius, 也就是半径最小值, 是恒星半径的 1.5 倍, 但不会小于 40000 m, 但如果恒星的类型是巨星, 则在此基础上再乘以 0.6; 得到结果后, 向上取整到整百. 而半径的最大值 maxOrbitRadius, 则是和恒星的 dysonRadius 属性有关: 是 dysonRadius (根据 defOrbitRadius 的计算方式, 推断单位为 au) 的 2 倍, 然后四舍五入到整百. 因此, 我们需要到恒星数据 StarData 类里面寻找相关信息.
进入 StarData 类, 搜索 dysonRadius 属性, 发现除了一个默认值为 10 au 以外, 没有改动这个属性的代码. 因此, 我们可能需要到恒星生成相关的代码里面去寻找答案.
在按字母序排序的类列表里, StarData 的正下方是 StarGen 类, 这里可能有我们需要的代码段. 进入 StarGen 类, 再次搜索 dysonRadius 字段. 发现答案就在这里.
StarGen 类的代码片段, 包含了生成恒星的 dysonRadius 属性值的代码 (已选中部分)
从下往上读, 发现:
dysonRadius ≥ 1.5 倍恒星半径, 过小取下限
dysonRadius = 0.28 * orbitScaler
当 orbitScaler < 1 时, orbitScaler 取 0.4 * orbitScaler + 0.6
orbitScaler = 1.35 ^ p2
p2 = num9 + 2
如果 num9 < 0, 则自乘 4, 然后限制 num9 在 -4 到 2 之间, 过大取最大值, 过小取最小值.
这里 T 是恒星表面温度.
分类讨论并归纳可得:
可得戴森球最大半径计算公式:
因此, 可以得到恒星温度与戴森球最大半径的关系图:
温度与戴森球最大半径的对应关系图. 图中颜色代表了光谱类型. 从上面读到的代码中可以找到恒星的光谱类型: 将 num9 + 4 之后四舍五入到整数. 0~7 分别对应: M, K, G, F, A, B, O, X. 图中忽略了 X 型光谱. 为阅读方便, 图中温度轴从黑实线处分为比例不同的两段.
特殊情况
对于主序星, 上面的讨论是合适的. 但对于部分特殊恒星, 上述讨论并不适用. 因为在计算完戴森球半径之后, 程序会调用 StarGen::setStarAge 函数, 对恒星的温度做出修正:
对于黑洞, 温度设为 0 K;
对于中子星, 温度设为原来的 倍;
对于白矮星, 温度设为原本的 150000 倍;
对于巨星, , 这里 age 的取值范围为 0.959999978542328 ~ 1.0, 猜测为恒星的生命周期. 后面将阐述如何从面板数据中获取 age 参数.
Age 参数的获得
可以看到, 在计算 num9 的代码上方, 是决定恒星温度的代码. 这里用到了 age 参数和恒星质量. 因此, 可以根据恒星的温度和质量反解出恒星的 age 参数. 这里不再细究.
用 age 和 mass 决定温度的代码
计算程序
上述算法可以写成 Python 程序以供使用:
from numpy import log, clip, round
def getMaxDysonSphereRadius(T, starRadius=0):
num9 = log((T-1300)/4500)/log(2.6)-0.5
num9 = num9 * 4 if num9 < 0 else num9
p2 = clip(num9, -4, 2) + 2
orbitScaler = 1.35 ** p2
if orbitScaler < 1:
orbitScaler = 0.4 * orbitScaler + 0.6
result = 0.56 * orbitScaler
if result < 3 * starRadius: