Chemistry-Harmonia
view release on metacpan or search on metacpan
lib/Chemistry/Harmonia.pm view on Meta::CPAN
}
}
if( $balance_A ){
return if $no_ion;
}else{
return $prop;
}
delete $prop->{$_}{'OS'} for keys %$prop;
}
}
# Read Pauling electronegativity and OSE
# only for given elements of substance
# input:
# %atoms -- elements
# return:
# %atom_el_neg
# %atom_OS
# $intermet
sub _read_atoms{
my $atoms = shift;
my %atom_el_neg; # atom electronegativity
my %atom_OS; # oxidation state
my $intermet = 1; # for intermetallic compound
my $adb = &_atoms_db;
for( my $i = 0; $i < @$adb; $i+=5 ){
$_ = $adb->[$i];
next if !exists $atoms->{ $_ };
$atom_el_neg{ $_ } = $adb->[$i+2];
$intermet = 0 unless $adb->[$i+3]; # Not intermetallic compound
$atom_OS{ $_ } = $adb->[$i+4];
}
\%atom_el_neg, \%atom_OS, $intermet;
}
# Read necessary ion-group
# input:
# $Chemistry_substance
# return:
# $ions
sub _read_ions {
my $chem_sub = shift;
my %ions;
my $idb = &_ions_db;
# Construct pattern
for( my $j = 0; $j < @$idb; $j+=2 ){
my $frm = $idb->[$j];
my $os = $idb->[$j+1];
my %a = split /_|=/,$os; # Parse to element end OSE
if($os =~ /~/){ # Macro-substitutions
my %ek;
my $max_n_ek = 0; # max number of element-pattern in macro-substitutions
while( my($e, $v) = each %a ){
if($e =~ /(\w+~)(.*)/){
$ek{$1}[0] = [ split ',',$2 ]; # elements
$ek{$1}[1] = $v; # OSE for group
my $n_ek = $#{ $ek{$1}[0] }; # number of element-substitutions
$max_n_ek = $n_ek if $n_ek > $max_n_ek; # max list
}
}
my $iter = variations_with_repetition( [ (0..$max_n_ek) ], scalar( keys %ek ) );
ELEMENT_MACRO_1:
while (my $p = $iter->next) {
my $m = $frm; # macro-formula (mask)
my $i = 0;
for my $em (sort keys %ek){
my $e = $ek{ $em }[0][ $p->[$i++] ]; # element
next ELEMENT_MACRO_1 unless defined $e; # pattern have ended
$m =~ s/$em/$e/g; # Construct ion mask
}
next unless $chem_sub =~ /($m)/; # Ions in substance aren't present
my $l = length($1); # Length of ion mask
$i = 0;
for my $em (sort keys %ek){
my $e = $ek{ $em }[0][ $p->[$i++] ]; # element
for my $z ( split /!/, $ek{ $em }[1] ){
# list OSE
push @{ $ions{ $e }{ $l }{ $m } }, [ split /;/,$z ];
}
}
while(my ($e, $v) = each %a ){
next if $e =~ /~/;
# list OSE
for my $z ( split /!/, $v ){
push @{ $ions{ $e }{ $l }{ $m } }, [ split /;/,$z ];
}
}
}
}else{
next unless $chem_sub =~ /($frm)/; # no ions in substance
my $l = length($1); # Length of the found group
while(my ($e, $v) = each %a ){
# list OSE
for my $z ( split /!/, $v ){
push @{ $ions{ $e }{ $l }{ $frm } }, [ split /;/,$z ];
( run in 1.068 second using v1.01-cache-2.11-cpan-364913b4093 )