Exemplo n.º 1
0
def _neutron_transmission_depth(material, wavelength):
    """
    Calculate the penetration depth for a material with a given neutron
    wavelength

    Parameters
    ----------
    material : pt.Formula

    wavelength : float
        neutron wavelength in Angstrom
    """
    import periodictable as pt

    return 10.0 * pt.neutron_scattering(material, wavelength=wavelength)[-1]
Exemplo n.º 2
0
def test():
    H, He, D, O = elements.H, elements.He, elements.D, elements.O
    assert H.neutron.absorption == 0.3326
    assert H.neutron.total == 82.02
    assert H.neutron.incoherent == 80.26
    assert H.neutron.coherent == 1.7568
    assert elements.Ru[101].neutron.bp == None
    assert H[1].nuclear_spin == '1/2'
    assert H[2].nuclear_spin == '1'
    assert not H[6].neutron.has_sld()

    assert He[3].neutron.b_c_i == -1.48
    assert He[3].neutron.bm_i == -5.925

    Nb = elements.Nb
    assert Nb.neutron.absorption == Nb[93].neutron.absorption

    # Check that b_c values match abundance-weighted values
    # Note: Currently they do not for match within 5% for Ar,V,Sm or Gd
    for el in elements:
        if not hasattr(el, 'neutron'): continue
        b_c = 0
        complete = True
        for iso in el:
            if iso.neutron != None:
                if iso.neutron.b_c == None:
                    complete = False
                else:
                    b_c += iso.neutron.b_c * iso.neutron.abundance / 100.
        if complete and b_c != 0 and abs((b_c - el.neutron.b_c) / b_c) > 0.05:
            err = abs((b_c - el.neutron.b_c) / b_c)
            ## Printing suppressed for the release version
            #print("%2s %.3f % 7.3f % 7.3f"%(el.symbol,err,b_c,el.neutron.b_c))

    # Check neutron_sld and neutron_xs against NIST calculator
    # Note that we are using different tables, so a general comparison with
    # NIST numbers is not possible, but ^30Si and ^18O are the same in both.
    M = formula('Si[30]O[18]2', density=2.2)
    sld, xs, depth = neutron_scattering(M, wavelength=4.75)
    sld2 = neutron_sld(M, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    #_summarize(M)
    #_summarize(formula('O2',density=1.14))
    # Alan's numbers:
    assert abs(sld[0] - 3.27) < 0.01
    assert abs(sld[1] - 0) < 0.01
    #assert abs(xs[2] - 0.00292) < 0.00001   # TODO fix test
    assert abs(xs[1] - 0.00569) < 0.00001
    #assert abs(depth - 4.329) < 0.001       # TODO fix test

    # Cu/Mo K-alpha = 1.89e-5 + 2.45e-7i / 1.87e-5 + 5.16e-8i

    Ni, Si = elements.Ni, elements.Si

    # Make sure molecular calculation corresponds to direct calculation
    sld = neutron_sld('Si', density=Si.density, wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    sld, _, _ = Si.neutron.scattering(wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    sld, xs, depth = neutron_scattering('Si',
                                        density=Si.density,
                                        wavelength=4.75)
    sld2, xs2, depth2 = Si.neutron.scattering(wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-10 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # incoherent cross sections for Ni[62] used to be negative
    sld, xs, depth = neutron_scattering('Ni[62]',
                                        density=Ni[62].density,
                                        wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    sld, xs, depth = Ni[62].neutron.scattering(wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    assert Ni[62].neutron.sld()[2] == 0

    # Test call from periodictable
    sld, xs, depth = periodictable.neutron_scattering('H2O',
                                                      density=1,
                                                      wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('H2O', density=1, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-10 for v, w in zip(xs, xs2))
    assert depth == depth2
    sld = periodictable.neutron_sld('H2O', density=1, wavelength=4.75)
    assert all(abs(v - w) < 1e-10 for v, w in zip(sld, sld2))

    # Check empty formula
    sld, xs, depth = neutron_scattering('', density=0, wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert np.isinf(depth)

    # Check density == 0 works
    sld, xs, depth = neutron_scattering('Si', density=0, wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert np.isinf(depth)

    # Test natural density
    D2O_density = (2 * D.mass + O.mass) / (2 * H.mass + O.mass)
    sld, xs, depth = neutron_scattering('D2O',
                                        natural_density=1,
                                        wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('D2O',
                                           density=D2O_density,
                                           wavelength=4.75)
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # Test that sld depends on density not on the size of the unit cell
    D2O_density = (2 * D.mass + O.mass) / (2 * H.mass + O.mass)
    sld, xs, depth = neutron_scattering('D2O',
                                        natural_density=1,
                                        wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('2D2O',
                                           natural_density=1,
                                           wavelength=4.75)
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14

    # Test energy <=> velocity <=> wavelength
    assert abs(
        nsf.neutron_wavelength_from_velocity(2200) -
        1.7981972618436388) < 1e-14
    assert abs(nsf.neutron_wavelength(25) - 1.8) < 0.1
    assert abs(nsf.neutron_energy(nsf.neutron_wavelength(25)) - 25) < 1e-14

    # Confirm scattering functions accept energy and wavelength
    sld, xs, depth = neutron_scattering('H2O', density=1, wavelength=4.75)
    sld2, xs2, depth2 = neutron_scattering('H2O',
                                           density=1,
                                           energy=nsf.neutron_energy(4.75))
    assert all(abs(v - w) < 1e-14 for v, w in zip(sld, sld2))
    assert all(abs(v - w) < 1e-14 for v, w in zip(xs, xs2))
    assert abs(depth - depth2) < 1e-14
Exemplo n.º 3
0
def test():
    H,He,D,O = elements.H,elements.He,elements.D,elements.O
    assert H.neutron.absorption == 0.3326
    assert H.neutron.total == 82.02
    assert H.neutron.incoherent == 80.26
    assert H.neutron.coherent == 1.7568
    assert elements.Ru[101].neutron.bp == None
    assert H[1].nuclear_spin == '1/2'
    assert H[2].nuclear_spin == '1'
    assert not H[6].neutron.has_sld()

    assert He[3].neutron.b_c_i == -1.48
    assert He[3].neutron.bm_i == -5.925

    Nb = elements.Nb
    assert Nb.neutron.absorption == Nb[93].neutron.absorption

    # Check that b_c values match abundance-weighted values
    # Note: Currently they do not for match within 5% for Ar,V,Sm or Gd
    for el in elements:
        if not hasattr(el,'neutron'): continue
        b_c = 0
        complete = True
        for iso in el:
            if iso.neutron != None:
                if iso.neutron.b_c == None:
                    complete = False
                else:
                    b_c += iso.neutron.b_c*iso.neutron.abundance/100.
        if complete and b_c != 0 and abs((b_c-el.neutron.b_c)/b_c) > 0.05:
            err = abs((b_c-el.neutron.b_c)/b_c)
            ## Printing suppressed for the release version
            #print("%2s %.3f % 7.3f % 7.3f"%(el.symbol,err,b_c,el.neutron.b_c))

    # Check neutron_sld and neutron_xs against NIST calculator
    # Note that we are using different tables, so a general comparison with
    # NIST numbers is not possible, but ^30Si and ^18O are the same in both.
    M = formula('Si[30]O[18]2',density=2.2)
    sld,xs,depth = neutron_scattering(M,wavelength=4.75)
    sld2 = neutron_sld(M,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    #_summarize(M)
    #_summarize(formula('O2',density=1.14))
    # Alan's numbers:
    assert abs(sld[0] - 3.27) < 0.01
    assert abs(sld[1] - 0) < 0.01
    #assert abs(xs[2] - 0.00292) < 0.00001   # TODO fix test
    assert abs(xs[1] - 0.00569) < 0.00001
    #assert abs(depth - 4.329) < 0.001       # TODO fix test

    # Cu/Mo K-alpha = 1.89e-5 + 2.45e-7i / 1.87e-5 + 5.16e-8i

    Ni,Si = elements.Ni, elements.Si

    # Make sure molecular calculation corresponds to direct calculation
    sld = neutron_sld('Si',density=Si.density,wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    sld,_,_ = Si.neutron.scattering(wavelength=4.75)
    sld2 = Si.neutron.sld(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    sld,xs,depth = neutron_scattering('Si',density=Si.density,wavelength=4.75)
    sld2,xs2,depth2 = Si.neutron.scattering(wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-10 for v,w in zip(xs,xs2))
    assert abs(depth-depth2) < 1e-14

    # incoherent cross sections for Ni[62] used to be negative
    sld,xs,depth = neutron_scattering('Ni[62]',density=Ni[62].density,
                                      wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    sld,xs,depth = Ni[62].neutron.scattering(wavelength=4.75)
    assert sld[2] == 0 and xs[2] == 0
    assert Ni[62].neutron.sld()[2] == 0


    # Test call from periodictable
    sld,xs,depth = periodictable.neutron_scattering('H2O',density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('H2O',density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-10 for v,w in zip(xs,xs2))
    assert depth==depth2
    sld = periodictable.neutron_sld('H2O',density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-10 for v,w in zip(sld,sld2))

    # Check empty formula
    sld,xs,depth = neutron_scattering('',density=0,wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert numpy.isinf(depth)

    # Check density == 0 works
    sld,xs,depth = neutron_scattering('Si',density=0,wavelength=4.75)
    assert all(v == 0 for v in sld)
    assert all(v == 0 for v in xs)
    assert numpy.isinf(depth)

    # Test natural density
    D2O_density = (2*D.mass + O.mass)/(2*H.mass + O.mass)
    sld,xs,depth = neutron_scattering('D2O',natural_density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('D2O',density=D2O_density,wavelength=4.75)
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14

    # Test that sld depends on density not on the size of the unit cell
    D2O_density = (2*D.mass + O.mass)/(2*H.mass + O.mass)
    sld,xs,depth = neutron_scattering('D2O',natural_density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('2D2O',natural_density=1,wavelength=4.75)
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14

    # Test energy <=> velocity <=> wavelength
    assert abs(nsf.neutron_wavelength_from_velocity(2200) - 1.7981972618436388) < 1e-14
    assert abs(nsf.neutron_wavelength(25) - 1.8) < 0.1
    assert abs(nsf.neutron_energy(nsf.neutron_wavelength(25)) - 25) < 1e-14

    # Confirm scattering functions accept energy and wavelength
    sld,xs,depth = neutron_scattering('H2O',density=1,wavelength=4.75)
    sld2,xs2,depth2 = neutron_scattering('H2O',density=1,energy=nsf.neutron_energy(4.75))
    assert all(abs(v-w)<1e-14 for v,w in zip(sld,sld2))
    assert all(abs(v-w)<1e-14 for v,w in zip(xs,xs2))
    assert abs(depth-depth2)<1e-14
Exemplo n.º 4
0
def cgi_call():
    form = cgi.FieldStorage()
    #print >>sys.stderr, form
    #print >>sys.stderr, "sample",form.getfirst('sample')
    #print >>sys.stderr, "mass",form.getfirst('mass')
    
    # Parse inputs
    errors = {};
    calculate = form.getfirst('calculate','all')
    if calculate not in ('scattering','activation','all'):
        errors['calculate'] = "calculate should be one of 'scattering', 'activation' or 'all'"
    try: chem = formula(form.getfirst('sample'))
    except: errors['sample'] = error()
    try: fluence = float(form.getfirst('flux',100000))
    except: errors['flux'] = error()
    try: fast_ratio = float(form.getfirst('fast','0'))
    except: errors['fast'] = error()
    try: Cd_ratio = float(form.getfirst('Cd','0'))
    except: errors['Cd'] = error()
    try: exposure = parse_hours(form.getfirst('exposure','1'))
    except: errors['exposure'] = error()
    try: 
        mass_str = form.getfirst('mass','1')
        if mass_str.endswith('kg'):
           mass = 1000*float(mass_str[:-2])
        elif mass_str.endswith('mg'):
           mass = 0.001*float(mass_str[:-2])
        elif mass_str.endswith('ug'):
           mass = 1e-6*float(mass_str[:-2])
        elif mass_str.endswith('g'):
           mass = float(mass_str[:-1])
        else:
           mass = float(mass_str)
    except: errors['mass'] = error()
    try: density_type,density_value = parse_density(form.getfirst('density','0'))
    except: errors['density'] = error()
    try: 
        #print >>sys.stderr,form.getlist('rest[]')
        rest_times = [parse_rest(v) for v in form.getlist('rest[]')]
        if not rest_times: rest_times = [0,1,24,360]
    except: errors['rest'] = error()
    try: decay_level = float(form.getfirst('decay','0.001'))
    except: errors['decay'] = error()
    try: thickness = float(form.getfirst('thickness', '1'))
    except: errors['thickness'] = error()
    try:
        wavelength_str = form.getfirst('wavelength','1').strip()
        if wavelength_str.endswith('meV'):
             wavelength = nsf.neutron_wavelength(float(wavelength_str[:-3]))
        elif wavelength_str.endswith('m/s'):
             wavelength = nsf.neutron_wavelength_from_velocity(float(wavelength_str[:-3]))
        elif wavelength_str.endswith('Ang'):
             wavelength = float(wavelength_str[:-3])
        else:
             wavelength = float(wavelength_str)
        #print >>sys.stderr,wavelength_str
    except: errors['wavelength'] = error()
    try:
        xray_source = form.getfirst('xray','Cu Ka').strip()
        if xray_source.endswith('Ka'):
            xray_wavelength = elements.symbol(xray_source[:-2].strip()).K_alpha
        elif xray_source.endswith('keV'):
            xray_wavelength = xsf.xray_wavelength(float(xray_source[:-3]))
        elif xray_source.endswith('Ang'):
            xray_wavelength = float(xray_source[:-3])
        elif xray_source[0].isalpha():
            xray_wavelength = elements.symbol(xray_source).K_alpha
        else:
            xray_wavelength = float(xray_source)
        #print >>sys.stderr,"xray",xray_source,xray_wavelength
    except: errors['xray'] = error()
    try:
        abundance_source = form.getfirst('abundance','IAEA')
        if abundance_source == "NIST":
            abundance = activation.NIST2001_isotopic_abundance
        elif abundance_source == "IAEA":
            abundance = activation.IAEA1987_isotopic_abundance
        else:
            raise ValueError("abundance should be NIST or IAEA")
    except: errors['abundance'] = error()
        

    if errors: return {'success':False, 'error':'invalid request', 'detail':errors}

    # Fill in defaults
    #print >>sys.stderr,density_type,density_value,chem.density
    if density_type == 'default' or density_value == 0:
        # default to a density of 1
        if chem.density is None: chem.density = 1
    elif density_type == 'volume':
        chem.density = chem.molecular_mass/density_value
    elif density_type == 'natural':
        # if density is given, assume it is for natural abundance
        chem.natural_density = density_value
    elif density_type == 'isotope':
        chem.density = density_value
    else:
        raise ValueError("unknown density type %r"%density_type)

    result = {'success': True}
    result['sample'] = {
            'formula': str(chem),
            'mass': mass,
            'density': chem.density,
            'thickness': thickness,
            'natural_density': chem.natural_density,
        }
        
    # Run calculations
    if calculate in ('activation', 'all'):
      try:
        env = activation.ActivationEnvironment(fluence=fluence,fast_ratio=fast_ratio, Cd_ratio=Cd_ratio)
        sample = activation.Sample(chem, mass=mass)
        sample.calculate_activation(env,exposure=exposure,rest_times=rest_times,abundance=abundance)
        decay_time = sample.decay_time(decay_level)
        total = [0]*len(sample.rest_times)
        rows = []
        for el,activity_el in activation.sorted_activity(sample.activity.items()):
            total = [t+a for t,a in zip(total,activity_el)]
            rows.append({'isotope':el.isotope,'reaction':el.reaction,'product':el.daughter,
                         'halflife':el.Thalf_str,'comments':el.comments,'levels':activity_el})
        result['activation'] = {
            'flux': fluence,
            'fast': fast_ratio,
            'Cd': Cd_ratio,
            'exposure': exposure,
            'rest': rest_times,
            'activity': rows, 
            'total': total,
            'decay_level': decay_level,
            'decay_time': decay_time,
        }
        #print >>sys.stderr,result
      except:
        result['activation'] = {"error": error()}
        
    #nsf_sears.replace_neutron_data()
    if calculate in ('scattering', 'all'):
      try: 
        sld,xs,penetration = neutron_scattering(chem, wavelength=wavelength)
        result['scattering'] = {
            'neutron': {
                'wavelength': wavelength,
                'energy': nsf.neutron_energy(wavelength),
                'velocity': nsf.VELOCITY_FACTOR/wavelength,
            },
            'xs': {'coh': xs[0], 'abs': xs[1], 'incoh': xs[2]},
            'sld': {'real': sld[0], 'imag': sld[1], 'incoh': sld[2]},
            'penetration': penetration,
            'transmission': 100*exp(-thickness/penetration),
        }
        
      except:
        missing = [str(el) for el in chem.atoms if not el.neutron.has_sld()]
        if any(missing):
            msg = "missing neutron cross sections for "+", ".join(missing)
        else:
            msg = error()
        result['scattering'] = {'error': msg }


      try: 
        xsld = xray_sld(chem, wavelength=xray_wavelength) 
        result['xray_scattering'] = {
            'xray': {
                'wavelength': xray_wavelength,
                'energy': xsf.xray_energy(xray_wavelength),
            },
            'sld': {'real': xsld[0], 'imag': xsld[1]},
        }
      except: 
        result['xray_scattering'] = {'error': error()}

    return result