File: formula

package info (click to toggle)
horae 066-3
  • links: PTS
  • area: contrib
  • in suites: lenny
  • size: 17,272 kB
  • ctags: 1,656
  • sloc: perl: 64,718; lisp: 744; sh: 82; makefile: 67; ansic: 35
file content (110 lines) | stat: -rwxr-xr-x 3,412 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/perl -w
######################################################################
##  This program is copyright (c) 2001 Bruce Ravel
##  <ravel@phys.washington.edu>
##  http://feff.phys.washington.edu/~ravel/
##
## -------------------------------------------------------------------
##     All rights reserved. This program is free software; you can
##     redistribute it and/or modify it under the same terms as Perl
##     itself.
##
##     This program is distributed in the hope that it will be useful,
##     but WITHOUT ANY WARRANTY; without even the implied warranty of
##     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##     Artistic License for more details.
## -------------------------------------------------------------------
######################################################################

use Xray::Absorption;
Xray::Absorption -> load("elam");
use Chemistry::Formula qw(parse_formula formula_data);
use strict;

(@ARGV) or &usage;
($ARGV[0] =~ /-{1,2}h(elp)?/i) and &usage;

use Getopt::Std;
use vars qw(%opt);
$opt{o} = "";
getopts('ld:e:f:', \%opt);

my (%count, $string);
my $energy  = $opt{e} || 0;
my $density = $opt{d} || 0;
if ($opt{f}||$opt{l}) {
  my (%formula, %density);
  &formula_data(\%formula, \%density);
  if ($opt{l}) {
    print "Known formulas:\n\n";
    printf " %-15s %-30s %-s\n", 'name', 'formula', 'density';
    print '-' x 70, $/;
    foreach my $f (sort (keys %formula)) {
      printf " %-15s %-30s %-s\n", $f, $formula{$f}, $density{$f};
    };
    exit;
  };
  ($formula{$opt{f}}) or die "\"$opt{f}\" is not a known material\n";
  $string  = $formula{$opt{f}};
  $density = $density{$opt{f}};
} else {
  $string = $ARGV[0];
};
($energy > 0) or $density = 0;
my $ok = parse_formula($string, \%count);
my $dens = ($density =~ /^(\d+\.?\d*|\.\d+)$/) ? $density : 0;

($ok) or do {
  print "Input error:\n\t$count{error}";
  die "\n";
};

print <<EOH;

Input string: "$string"

  element     number
 ---------   --------
EOH
my ($weight, $xsec) = (0,0);
my ($barns_per_formula_unit, $amu_per_formula_unit) = (0,0);
foreach my $k (sort (keys(%count))) {
  $barns_per_formula_unit += Xray::Absorption -> cross_section($k, $energy) * $count{$k};
  $amu_per_formula_unit += Xray::Absorption -> get_atomic_weight($k) * $count{$k};
  if ($count{$k} > 0.001) {
    printf("    %-2s        %.3f\n", $k, $count{$k});
  } else {
    printf("    %-2s        %g\n", $k, $count{$k});
  };
};
## 1 amu = 1.6607143 x 10^-24 gm
$xsec = $barns_per_formula_unit / $amu_per_formula_unit / 1.6607143;
printf "\nThis weighs %.3f amu.\n", $amu_per_formula_unit;
if ($xsec == 0) {
  print "(Energy too low or not provided.  Absorption calculation skipped.)\n";
} else {
  $xsec *= $dens;
  if ($xsec > 0) {
    if (10000/$xsec > 500) {
      printf("Absorbtion length = %.3f cm at %.2f eV.\n", 1/$xsec, $energy);
    } else {
      printf("Absorbtion length = %.1f microns at %.2f eV.\n", 10000/$xsec, $energy);
    };
  } else {
    print "(The absorption length calculation requires a value for density.)";
  };
};

sub usage {
  print <<EOH;
 Enumerate chemical formulas and compute absorption length

 usage:
   formula -e # -d # <string> // formula, energy, and density supplied
   formula -e # -f <string>   // use a known formula
   formula -l                 // list of known materials
   formula -h                 // this message

EOH
  exit;
};