See p. 210, table 32.\n""" if not isinstance(when, find): when = find(None, when) # pity about not knowing eccentricities ... return rock(name, sol.orbiter(Q(period, 2, None, yr)), Q(1, 2, 12, mass * ton), maxdiameter=Q(maxdiam, 0, None, ml), periterrion=Q(1, 2, 6, miss * ml), # closest approach to Terra discovery=when) Ceres = DwarfAster('Ceres', Orbit(Sun, Quantity.fromDecimal(413.9, 1, 6, km), None), Quantity.fromDecimal(.87, 2, 21, kg), surface = Spheroid(Quantity.fromDecimal(466, 0, None, km)), number = 1, discovery=Discovery("Piazzi", 1801, day="January 1st 1801", __doc__="""The discovery of Ceres. A team of astronomers set out, in 1800, to look for a planet between Mars and Jupiter, as anticipated by the Titius-Bode law (see Sun.Bode); starting on the first day of the new year, Piazzi noticed a moving star which was, in due course, recognised as what they were looking for, even though it was a bit smaller than they expected and a few more showed up soon enough.\n"""), __doc__="""The first asteroid discovered. See Ceres.discovery and Sun.Bode for further details. Piazzi actually named
Most of our uncertainty about this arises from our ignorance of our motion relative to the Local Group: we know our own velocity relative to the background radiation far more accurately. See also: http://antwrp.gsfc.nasa.gov/apod/ap030209.html """, l = Quantity.within(273, 3, arc.degree), b = Quantity.within(30, 3, arc.degree)), mass = Quantity.fromDecimal( 2, 0, 43, kg, """Estimated mass of the Local Group The mass inwards from radius R within each galaxy grows in proportion to R, which might suggest that galactic masses vary in proportion to radii; a simple uniform area density model in each galactic disk would predict masses proportional to squares of radii; and a simple spherical model at fixed density would use the cubes. When I summed R**P for radii R and power P, dividing the total by the Milky Way's contribution, the ratio has a minimum of about 4.16 at about P = 1.9, falling from just under 6 at P = 1 and rising to just over 5 at P = 3 (however, these results are quite sensitive to variations in the value used for the radius of the Milky Way, shifting significantly even between 90 and 100 M ly). It thus seems reasonable to estimate that the mass of the local group is between four and six times that of the Milky Way. """)) # NB: MilkyWay.mass figure used is *not* the temporary one given immediately # below; see later correction once Sun has been successfully added as a # satelite. MilkyWay = body.Galaxy('Milky Way', mass=1.79e41 * kg, # NB: actual mass is O(1e42) - but see below ! orbit = Orbit(LocalGroup,
if not isinstance(when, find): when = find(None, when) # pity about not knowing eccentricities ... return rock( name, sol.orbiter(Q(period, 2, None, yr)), Q(1, 2, 12, mass * ton), maxdiameter=Q(maxdiam, 0, None, ml), periterrion=Q(1, 2, 6, miss * ml), # closest approach to Terra discovery=when) Ceres = DwarfAster('Ceres', Orbit(Sun, Quantity.fromDecimal(413.9, 1, 6, km), None), Quantity.fromDecimal(.87, 2, 21, kg), surface=Spheroid(Quantity.fromDecimal(466, 0, None, km)), number=1, discovery=Discovery("Piazzi", 1801, day="January 1st 1801", __doc__="""The discovery of Ceres. A team of astronomers set out, in 1800, to look for a planet between Mars and Jupiter, as anticipated by the Titius-Bode law (see Sun.Bode); starting on the first day of the new year, Piazzi noticed a moving star which was, in due course, recognised as what they were looking for, even though it was a bit smaller than they expected and a few more showed up soon enough.\n"""), __doc__="""The first asteroid discovered.
def NASelement(name, symbol, Z, A, isos=None, abundance=None, melt=None, boil=None, **what): """Create an Element based on my Nuffield Advanced Data book's data. Required arguments: name -- string giving the full name of the element. symbol -- string giving the (one or two letter) symbol of the element. Z -- atomic number. Optional arguments: A -- molar mass * mol / g; a.k.a. atomic mass / AMU (default, None, means unknown). isos -- description of isotopes (see below); default is None. abundance -- relative terrestrial abundance, scaled to make Si score 100; default is None, indicating an artificial element. melt -- melting temperature / K boil -- boiling temperature / K plus any further keyword arguments, to taste. See Element's constructor for further details; it receives a suitably scaled abundance. I have, rather arbitrarily, supposed that the phase change temperatures given in the NAS data book generally have an error bar of +/- half a Kelvin, except where marked as 'uncertain' (five K) or 'highly uncertain' (fifty K if the cited value's last two digits are zeros, otherwise ten K). Roughly as arbitrarily, where several forms of the elment are listed, I've used the lowest melting point and highest boiling point, ignoring any phase changes between forms and listing any sublimation (typically relevant only to one form, not the one whose melting and boiling are used) separately as sublime. The description of isotopes, if given, should either be a list of atomic mass numbers for which an isotope is known (for artificial elements and those natural radioactives whose isotopic composition varies wildly) or a mapping from known atomic mass numbers to relative abundances (or to None for those radioactive isotopes which normally have negligible abundance). If the sum of these relative abundances isn't 1, they'll be (fudged to make it 100 - because the NAS book is a bit off on some elements - and then) scaled down to make it 1. Both the element's terrestrial abundance and the relative abundance of its isotopes will be given an error bar, if they don't already have one, to accord with the limited precision indicated in the NAS table. """ if abundance is None: what["abundance"] = None # artificial elements else: try: abundance.width except AttributeError: # need an error bar (guess: two decimal places of precision) abundance = Quantity.fromSigFigs(abundance, 2) # NAS data book gives abundances relative to Silicon = 100, but notes # that Silicon's true abundance is believed to be 27.72 % what["abundance"] = abundance * 0.2772 try: A.width except AttributeError: # give it an error bar try: isos[:] # radioactive/artificial elements except TypeError: A = Quantity.fromDecimal(A, 4) # real ones else: A = Quantity.within(A, 0.5 * max(1, max(isos) - min(isos))) temp = {} if melt is not None: try: melt.width except AttributeError: melt = Quantity.fromDecimal(melt, 1) temp["melt"] = melt * Kelvin if boil is not None: try: boil.width except AttributeError: boil = Quantity.fromDecimal(boil, 1) temp["boil"] = boil * Kelvin try: temp["sublime"] = what["sublime"] except KeyError: pass else: del what["sublime"] if temp: T = Temperatures(**temp) else: T = None ans = Element(name, symbol, Z, A, T, **what) try: isos[:] except TypeError: try: isos.update except AttributeError: pass # no information else: # dictionary: { isotope: relative abundance } weights = filter(None, isos.values()) total = sum(weights) if total == 1: fix, scale = None, 1 # weights given as fractions else: # Otherwise, assume given as percentages; but the NAS table # has several entries that don't sum accurately to 100. scale = 0.01 if total == 100: fix = None else: # bodge: blur the non-tiny weights to make it all sum right ... assert 80 < total < 120, "Perhaps these aren't percentages after all" fix = 1 + (100 - total) * Quantity.below(2) / sum(filter(lambda x: x > 1, weights)) # Perhaps we can improve on this ... for k, v in isos.items(): iso = Isotope(Z, k - Z) if v: unit = 1 if v < 1: while unit > v: unit = unit * 0.1 unit = unit * 0.1 if fix and v > 1: v = v * fix # bodge v = Quantity.within(v, unit * 0.01) iso.abundance = v * scale else: # sequence: known isotopes for k in isos: Isotope(Z, k - Z) return ans
Iron = NASelement( "Iron", "Fe", 26, Float(55.847, 3), {54: 5.84, 56: 91.68, 57: 2.17, 58: 0.31}, 22, 1812, 3160, arcanum="Ferrum" ) Cobalt = NASelement("Cobalt", "Co", 27, 58.9332, {59: 1}, 0.01, 1768, 3150) Nickel = NASelement("Nickel", "Ni", 28, 58.71, {58: 67.76, 60: 26.16, 61: 1.25, 62: 3.66, 64: 1.16}, 3.5e-2, 1728, 3110) Copper = NASelement( "Copper", "Cu", 29, Float(63.54, 3), {63: 69.1, 65: 30.9}, 3.1e-2, 1356, 2855, arcanum="Cuprum", resistivity=Quantity.fromDecimal(16.8, 1) * nano * Ohm * metre, ) # resistivity: http://www.irregularwebcomic.net/3295.html Zinc = NASelement("Zinc", "Zn", 30, 65.37, {64: 48.89, 66: 27.81, 67: 4.11, 68: 18.56, 70: 0.62}, 5.8e-2, 693, 1181) Gallium = NASelement("Gallium", "Ga", 31, 69.72, {69: 60.2, 71: 39.8}, 6.6e-3, 303, Float(2510, -1)) Germanium = NASelement( "Germanium", "Ge", 32, 72.59, {70: 20.55, 72: 27.37, 73: 7.67, 74: 36.74, 76: 7.67}, 3.1e-3, 1210, Float(3100, -2) ) Arsenic = NASelement("Arsenic", "As", 33, 74.9216, {75: 1}, 2.2e-3, sublime=Float(886, 1, None, Kelvin)) Selenium = NASelement( "Selenium", "Se", 34, 78.96, {74: 0.89, 76: 9.02, 77: 7.58, 78: 23.52, 80: 49.82, 82: 9.19}, 4e-5, 490, 958 ) Bromine = NASelement("Bromine", "Br", 35, About(79.909, 0.001), {79: 50.52, 81: 49.48}, 7.1e-4, 266, 331) Krypton = NASelement( "Krypton", "Kr", 36, 83.8, {78: 0.35, 80: 2.27, 82: 11.56, 83: 11.55, 84: 56.9, 86: 17.37}, 4.3e-8, 116, 120 )
Most of our uncertainty about this arises from our ignorance of our motion relative to the Local Group: we know our own velocity relative to the background radiation far more accurately. See also: http://antwrp.gsfc.nasa.gov/apod/ap030209.html """, l = Quantity.within(273, 3, arc.degree), b = Quantity.within(30, 3, arc.degree)), mass = Quantity.fromDecimal( 2, 0, 43, kg, """Estimated mass of the Local Group The mass inwards from radius R within each galaxy grows in proportion to R, which might suggest that galactic masses vary in proportion to radii; a simple uniform area density model in each galactic disk would predict masses proportional to squares of radii; and a simple spherical model at fixed density would use the cubes. When I summed R**P for radii R and power P, dividing the total by the Milky Way's contribution, the ratio has a minimum of about 4.16 at about P = 1.9, falling from just under 6 at P = 1 and rising to just over 5 at P = 3 (however, these results are quite sensitive to variations in the value used for the radius of the Milky Way, shifting significantly even between 90 and 100 M ly). It thus seems reasonable to estimate that the mass of the local group is between four and six times that of the Milky Way. """)) # NB: MilkyWay.mass figure used is *not* the temporary one given immediately # below; see later correction once Sun has been successfully added as a # satelite. MilkyWay = body.Galaxy('Milky Way', mass=1.79e41 * kg, # NB: actual mass is O(1e42) - but see below ! orbit = Orbit(LocalGroup,
Phosphorus = NASelement('Phosphorus', 'P', 15, 30.9738, {31: 1}, 5.2, 317, 554, sublime=704*Kelvin) Sulphur = NASelement('Sulphur', 'S', 16, About(32.064, 1.5e-3), {32: 95, 33: .76, 34: 4.22, 36: .01}, .23, Float(392, -1), 718, alias=('Sulfur',)) Chlorine = NASelement('Chlorine', 'Cl', 17, Float(35.453, 3), {35: 75.53, 37: 24.47}, .14, 172, 239) Argon = NASelement('Argon', 'Ar', 18, 39.9480, {36: .34, 38: .063, 40: 99.6}, 1.8e-5, 84, 87, alias=('A',)) Potassium = NASelement('Potassium', 'K', 19, 39.102, {39: 93.22, 40: .12, 41: 6.77}, # components sum to 100.11, not 100 11.4, 336, 1039, arcanum='Kalium') Calcium = NASelement('Calcium', 'Ca', 20, 40.08, {40: 96.97, 42: .64, 43: .15, 44: 2.06, 46: .003, 48: .19}, 16, 1123, 1765) Scandium = NASelement('Scandium', 'Sc', 21, 44.956, {45: 1}, 2.2e-3, About(1673, 10), About(2750, 10)) Titanium = NASelement('Titanium', 'Ti', 22, 47.9, {46: 7.99, 47: 7.32, 48: 73.99, 49: 5.46, 50: 5.25}, 1.4, 1950, 3550) Vanadium = NASelement('Vanadium', 'V', 23, 50.942, {50: .25, 51: 99.75}, 6.6e-2, 2190, 3650) Chromium = NASelement('Chromium', 'Cr', 24, Float(51.996, 3), {50: 4.31, 52: 83.76, 53: 9.55, 54: 2.38}, 4.4e-2, 2176, 2915) Manganese = NASelement('Manganese', 'Mn', 25, 54.938, {55: 1}, .44, 1517, 2314) Iron = NASelement('Iron', 'Fe', 26, Float(55.847, 3), {54: 5.84, 56: 91.68, 57: 2.17, 58: .31}, 22, 1812, 3160, arcanum='Ferrum') Cobalt = NASelement('Cobalt', 'Co', 27, 58.9332, {59: 1}, .01, 1768, 3150) Nickel = NASelement('Nickel', 'Ni', 28, 58.71, {58: 67.76, 60: 26.16, 61: 1.25, 62: 3.66, 64: 1.16}, 3.5e-2, 1728, 3110) Copper = NASelement('Copper', 'Cu', 29, Float(63.54, 3), {63: 69.1, 65: 30.9}, 3.1e-2, 1356, 2855, arcanum='Cuprum', resistivity=Quantity.fromDecimal(16.8, 1) * nano * Ohm * metre) # resistivity: http://www.irregularwebcomic.net/3295.html Zinc = NASelement('Zinc', 'Zn', 30, 65.37, {64: 48.89, 66: 27.81, 67: 4.11, 68: 18.56, 70: .62}, 5.8e-2, 693, 1181) Gallium = NASelement('Gallium', 'Ga', 31, 69.72, {69: 60.2, 71: 39.8}, 6.6e-3, 303, Float(2510, -1)) Germanium = NASelement('Germanium', 'Ge', 32, 72.59, {70: 20.55, 72: 27.37, 73: 7.67, 74: 36.74, 76: 7.67}, 3.1e-3, 1210, Float(3100, -2)) Arsenic = NASelement('Arsenic', 'As', 33, 74.9216, {75: 1}, 2.2e-3, sublime=Float(886, 1, None, Kelvin)) Selenium = NASelement('Selenium', 'Se', 34, 78.96, {74: .89, 76: 9.02, 77: 7.58, 78: 23.52, 80: 49.82, 82: 9.19}, 4e-5, 490, 958) Bromine = NASelement('Bromine', 'Br', 35, About(79.909, .001), {79: 50.52, 81: 49.48}, 7.1e-4, 266, 331) Krypton = NASelement('Krypton', 'Kr', 36, 83.8, {78: .35, 80: 2.27, 82: 11.56, 83: 11.55, 84: 56.9, 86: 17.37}, 4.3e-8, 116, 120) Rubidium = NASelement('Rubidium', 'Rb', 37, 85.47, {85: 72.15, 87: 27.85}, .14, 312, 974) Strontium = NASelement('Strontium', 'Sr', 38, 87.62, {84: .56, 86: 9.86, 87: 7.02, 88: 82.56}, .13, 1043, 1640) Yttrium = NASelement('Yttrium', 'Y', 39, 88.905, {89: 1}, 1.2e-2, About(1773, 10), Float(3500, -2)) Zirconium = NASelement('Zirconium', 'Zr', 40, 91.22, {90: 51.46, 91: 11.23, 92: 17.11, 94: 17.4, 96: 2.8}, 9.7e-2, 2125, 4650) Niobium = NASelement('Niobium', 'Nb', 41, 92.9060, {93: 1}, 1.1e-2, 2770, 5200, alias=('Columbium', 'Cb')) Molybdenum = NASelement('Molybdenum', 'Mo', 42, 95.94, {92: 15.86, 94: 9.12, 95: 15.7, 96: 16.5, 97: 9.45, 98: 23.75, 100: 9.62}, 6.6e-3, Float(2890, -1), Float(5100, -1)) Technetium = NASelement('Technetium', 'Tc', 43, 99, [99], None, Float(2400, -2), Float(4900, -2))