generate-before.py

back to table · edit · history · where entries came from · files · download

4106 bytes, as of the version from 2026-10-30 06:50 (current). Recorded here, not run.

"""Moment of inertia I/(MR^2) of polytropic stars -- numberdb.org/T616.

Run with SageMath (install numberdb once with sage -pip install numberdb):
    sage -python generate.py              # verify all stored entries
    sage -python generate.py --fill       # send entries to the existing draft
Download the attachments listed in `files` beside this script first.
Set NUMBERDB_API_KEY for authenticated draft reads/writes. Campaign scripts
may pass the token on stdin with NUMBERDB_KEY_FROM_STDIN=1. Entry writing
never offers, reviews or publishes the table.

The sole parameter n selects the same finite background models as T613-T615.
See argument-selection.md for the disjoint intrinsic, application and bounded
reference groups. The solver implements half-integer n in [0,5), not arbitrary
rational indices. The n=0 value is exactly 2/5; n=1 uses an Arb evaluation of
2/3-4/pi^2. Other rows integrate J=integral xi^4 theta^n dxi alongside xi and
q in t=sqrt(theta), then return 2J/(3q*xi^2). The accumulated integral
H=integral xi^2 theta dxi checks J=q*xi^2-6H at every selected surface.

The two numerical runs use 150/210 decimal working digits, Taylor orders
160/210, step divisors 12/18 and central matching radii 1/2 and 2/3. The
worst relative discrepancy over all ten models is below 3.25e-154, leaving
ample margin for the 100 stored significant digits. These are heuristic
agreement checks: truncation and global ODE errors have no certified bound.
The separate radial formulation and literature approximant are validation,
not the controller's independent critique. See numerical-evidence.json and
independent-evidence.json for actual measurements and controls.
"""
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from solver import inertia

INDICES=('0','1/2','1','3/2','2','5/2','3','7/2','4','9/2')
CONFIG={150:(160,12,'1/2'),210:(210,18,'2/3')}

@lru_cache(maxsize=32)
def compute(n,working):
    return str(inertia(n,working,*CONFIG[working]))

class PolytropicInertia(numberdb.Generator):
    table='T616'
    parameters=('n',)
    type='R'
    digits=100
    rigour='heuristic (agreement-checked)'
    files=('generate.py','solver.py','argument-selection.md','compute.py',
           'numerical-evidence.json','independent_checks.py','independent-evidence.json',
           'readback_checks.py','skill-evidence.json','source-manifest.json',
           'check.py','dry_run.py','validate.py')

    def enumerate(self):
        for n in INDICES:
            yield {'n':n}

    def value(self,params,digits):
        n=str(QQ(params['n']))
        if n not in INDICES:
            raise ValueError('Use one of the selected finite polytropic indices.')
        if digits>100:
            raise ValueError('The current precision policy was checked for 100 digits.')
        if n=='0':
            return {'number':QQ(2)/5,'comment':r'The incompressible model has constant interior density, so $I/(MR^2)=2/5$.'}
        if n=='1':
            B=RealBallField(numberdb.bits(digits,losing=80))
            return {'number':B(2)/3-4/B.pi()**2,'comment':r'The linear profile $\theta_1(\xi)=\sin(\xi)/\xi$ gives $I/(MR^2)=2/3-4/\pi^2$.'}
        return numberdb.agreeing(lambda working:compute(n,working),at=(150,210))

if __name__=='__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN')=='1':
        token=sys.stdin.read().strip()
        if '=' in token and token.split('=',1)[0].replace('_','').isalnum():
            token=token.split('=',1)[1].strip().strip('\"\'')
        os.environ['NUMBERDB_API_KEY']=token
    generator=PolytropicInertia()
    if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH')=='1':
        for params in generator.enumerate():
            generator.value(params,generator.digits)
        print(generator.publish(message='Add ten axial inertia constants with numerical checks and reproducible sources.'))
    else:
        report=generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)