Новосибирский институт органической химии им. Н.Н. Ворожцова СО РАН Лаборатория изучения механизмов органических реакций |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
molgeom#!/usr/bin/perl $debug = 0; # Чтобы добавить опцию, нужно в $expr добавить кусок, # состоящий из четырех полей, разделенных знаком |: # опция | индексы атомов | комментарий | формула для вычисления | # В формуле для вычисления: # Координаты исходных атомов нужно обозначать двумя буквами: # первая из них - x,y,z; вторая - латинская буква, например, xi yA zn; # каждая из вторых букв должна присутствовать в поле "индексы атомов". # Временные переменные - как в перле ($Rij) # Последнее выражение должно давать конечный рез-т и не присваиваться # - b c - e - - - i j k l m n - - - - - - u v - x y z $expr = q( r | i-j | длина i-j | sqrt ((xi-xj)**2+(yi-yj)**2+(zi-zj)**2); | q |i-j-k| расстояние от точки i до прямой j-k| sqrt ((((xi-xj)*(yk-yj)-(yi-yj)*(xk-xj))**2+ ((yi-yj)*(zk-zj)-(zi-zj)*(yk-yj))**2+ ((zi-zj)*(xk-xj)-(xi-xj)*(zk-zj))**2)/ ((xk-xj)**2+(yk-yj)**2+(zk-zj)**2)); | t |i-j-k-l| расстояние между точкой i и плоскостью j-k-l| $A = (yk-yj)*(zl-zj)-(zk-zj)*(yl-yj); $B = (zk-zj)*(xl-xj)-(xk-xj)*(zl-zj); $C = (xk-xj)*(yl-yj)-(yk-yj)*(xl-xj); $D = xj*yk*zl+xk*yl*zj+xl*yj*zk-xl*yk*zj-xk*yj*zl-xj*yl*zk; (xi*$A+yi*$B+zi*$C-$D)/sqrt($A**2+$B**2+$C**2); | p |i-j-k| проекция O-k на i-j (O - середина i-j)| $Rij = (xi-xj)**2+(yi-yj)**2+(zi-zj)**2; $xo = (xi+xj)/2; $yo = (yi+yj)/2; $zo = (zi+zj)/2; $Rok = ($xo-xk)**2+($yo-yk)**2+($zo-zk)**2; $ttt = (xi-xj)*($xo-xk)+(yi-yj)*($yo-yk)+(zi-zj)*($zo-zk); $Rok*$ttt/sqrt($Rij*$Rok); | o |i-j-k-l| расстояние между серединами отрезков i-j и k-l| (sqrt((xi+xj-xk-xl)**2+(yi+yj-yk-yl)**2+(zi+zj-zk-zl)**2))/2; | s |i-j-k-l| кратчайшее расстояние между прямыми i-j и k-l| $ax=xj-xi; $ay=yj-yi; $az=zj-zi; $bx=xl-xk; $by=yl-yk; $bz=zl-zk; $A=sqrt($ax**2+$ay**2+$az**2); $B=sqrt($bx**2+$by**2+$bz**2); $sing1=sqrt(1-(($ax*$bx+$ay*$by+$az*$bz)/$A/$B)**2); if ($sing1==0) { sqrt(($ay*(zi-zk)-$az*(yi-yk))**2+ ($az*(xi-xk)-$ax*(zi-zk))**2+ ($ax*(yi-yk)-$ay*(xi-xk))**2)/$A; } else { ((xi-xk)*$ay*$bz+(yi-yk)*$az*$bx+(zi-zk)*$ax*$by- (xi-xk)*$az*$by-(yi-yk)*$ax*$bz-(zi-zk)*$ay*$bx)/$A/$B/$sing1; } | a |i-j-k| валентный угол i-j-k| rad2deg (acos (((xi-xj)*(xk-xj)+(yi-yj)*(yk-yj)+(zi-zj)*(zk-zj))/ sqrt(((xi-xj)**2+(yi-yj)**2+(zi-zj)**2)* ((xk-xj)**2+(yk-yj)**2+(zk-zj)**2)))); | f |i-j-k-l| угол между прямыми i-j и k-l (0..90)| rad2deg (acos (abs((xi-xj)*(xk-xl)+(yi-yj)*(yk-yl)+(zi-zj)*(zk-zl))/ sqrt(((xi-xj)**2+(yi-yj)**2+(zi-zj)**2)* ((xl-xk)**2+(yl-yk)**2+(zl-zk)**2)))); | g |i-j-k-l-m| угол между прямой i-j и плоскостью k-l-m (0..90)| $ax=xj-xi; $ay=yj-yi; $az=zj-zi; $A = (yl-yk)*(zm-zk)-(zl-zk)*(ym-yk); $B = (zl-zk)*(xm-xk)-(xl-xk)*(zm-zk); $C = (xl-xk)*(ym-yk)-(yl-yk)*(xm-xk); rad2deg (asin (abs($ax*$A+$ay*$B+$az*$C)/ sqrt(($ax**2+$ay**2+$az**2)* ($A**2+$B**2+$C**2)))); | d |i-j-k-l| диэдральный угол i-j-k-l (-180..180)| $A1 = (yj-yi)*(zk-zi)-(zj-zi)*(yk-yi); $B1 = (zj-zi)*(xk-xi)-(xj-xi)*(zk-zi); $C1 = (xj-xi)*(yk-yi)-(yj-yi)*(xk-xi); $A2 = (yk-yj)*(zl-zj)-(zk-zj)*(yl-yj); $B2 = (zk-zj)*(xl-xj)-(xk-xj)*(zl-zj); $C2 = (xk-xj)*(yl-yj)-(yk-yj)*(xl-xj); $Vec = ($B1*$C2-$C1*$B2)*(xk-xj)+ ($C1*$A2-$A1*$C2)*(yk-yj)+ ($A1*$B2-$B1*$A2)*(zk-zj); $sign = ($Vec>=0) ? 1 : -1; $sign*rad2deg(acos(($A1*$A2+$B1*$B2+$C1*$C2)/ sqrt(($A1**2+$B1**2+$C1**2)* ($A2**2+$B2**2+$C2**2)))); | w |i-j-k-l-m-n| угол между плоскостями i-j-k и l-m-n (0..90)| $A1 = (yj-yi)*(zk-zi)-(zj-zi)*(yk-yi); $B1 = (zj-zi)*(xk-xi)-(xj-xi)*(zk-zi); $C1 = (xj-xi)*(yk-yi)-(yj-yi)*(xk-xi); $A2 = (ym-yl)*(zn-zl)-(zm-zl)*(yn-yl); $B2 = (zm-zl)*(xn-xl)-(xm-xl)*(zn-zl); $C2 = (xm-xl)*(yn-yl)-(ym-yl)*(xn-xl); rad2deg (acos (abs($A1*$A2+$B1*$B2+$C1*$C2)/ sqrt(($A1**2+$B1**2+$C1**2)* ($A2**2+$B2**2+$C2**2)))); | b |i-j-k-l| угол между прямой l-k и нормалью к плоскости k-j-i (в Природе это bend-1 4,i,j,k,l)| $ax=xk-xl; $ay=yk-yl; $az=zk-zl; $A = (yj-yk)*(zi-zk)-(zj-zk)*(yi-yk); $B = (zj-zk)*(xi-xk)-(xj-xk)*(zi-zk); $C = (xj-xk)*(yi-yk)-(yj-yk)*(xi-xk); rad2deg (acos (($ax*$A+$ay*$B+$az*$C)/ sqrt(($ax**2+$ay**2+$az**2)* ($A**2+$B**2+$C**2)))); | ); @expr = split /\|/s, $expr; foreach (@expr) { s/^\s*(\S+)\s*$/$1/; } for ($i=0; $expr[$i]=~/(\w)/; $i++) { $string_opts .= ($i==0) ? ($1) : (":$1"); $Satoms{$1} = $expr[$i+1]; @_ = split /-/, $expr[$i+1]; $Natoms{$1} = scalar @_; $description{$1} = $expr[$i+2]; $calculation{$1} = $expr[$i+3]; $i = $i+3; } if ($debug>=1) { foreach $opt (keys %calculation) { print "Опция: $opt\n"; print "Число атомов: $Natoms{$opt}, $Satoms{$opt}\n"; print "Описание: $description{$opt}\n"; print "Вычисление: $calculation{$opt}\n"; } } $string_opts .= ':hRPG'; use Getopt::Std; getopts("$string_opts", \%opts); use Math::Trig; if ($opts{h}) { $0 =~ s/^.*[\/\\]//; print " Calculate some geometry parameters from cartesian coordinates given in molden format file(s) Usage: $0 geometric_parameters [options] [filename] [filenames] [> results] Зависимости: Perl, модуль Math::Trig, gnuplot для опции -P filename - файл с декартовыми координатами в формате molden'а (http://www.cmbi.kun.nl/~schaft/molden/molden_format.html) Опции: -h этот help -R углы не в градусах, а в радианах -P показывает графики геом.параметр-энергия с помощью gnuplot -G печатает таблицу геом.параметр-энергия Геометрические параметры (i,j,... - номера атомов):\n"; foreach (sort keys %Satoms) { printf "-%s %-12s%s\n", $_ , $Satoms{$_}, $description{$_}; } print " Если нужно несколько однотипных величин: -r 'i-j j-k' \n"; exit; } undef @output; $count = 0; unless ($opts{P} || $opts{G}) { $output[0] = sprintf "%-6s\t%-14s\t", 'Point', 'Energy'; } while (<>) { # 1-st string if (/^\s*(\d+)\s*$/) { $N = $1; $count++; } else { print "Not molden format of $inp_file"; } # 2-nd string $_ = <>; ($energy) = /(-?\d+\.\d+)/; print "Point $count N=$N Energy $energy\n" if ($debug>=2); for ($i=1;$i<=$N;$i++) { $_ = <>; ($atom[$i],$x[$i],$y[$i],$z[$i],undef) = split; print "$atom[$i] $x[$i] $y[$i] $z[$i]\n" if ($debug>=3); } $output[$count] = sprintf "%-6u\t%-14s\t", "$count", "$energy"; foreach $option (sort keys %opts) { $calculation{$option} =~ s/\b([xyz])(\w)\b/\$$1\[\$$2\]/g; $calculation{$option} =~ s/\brad2deg\b//g if ($opts{R}); foreach $cur_opt (split /\s+/, $opts{$option}) { @numbers = split /-/, $cur_opt; @letters = split /-/, $Satoms{$option}; next if (scalar @numbers != scalar @letters); foreach (@numbers) { $ttt = shift @letters; ${$ttt} = $_; } $atoms = "$atom[$numbers[0]]$numbers[0]"; shift @numbers; foreach (@numbers) { $atoms .= "-$atom[$_]$_" } unless ($opts{P} || $opts{G}) { $output[0] .= sprintf ("%-14s\t", "$option".'_'."$atoms") if ($count==1); $output[$count] .= sprintf "%-14f\t", eval $calculation{$option}; } else { $plot{$cur_opt}[0] = "$option $atoms\n" if ($count==1); $plot{$cur_opt}[$count] = sprintf "%-14f\t%-14s\n", eval $calculation{$option},$energy; } } } } unless (%plot) { for (1..$count) { $plot{'IRC'}[0] = "IRC\n" if ($_==1); $plot{'IRC'}[$_] = "$output[$_]\n"; } } unless ($opts{P} || $opts{G}) { foreach (@output) {print "$_\n"}; } if ($opts{P}) { # print "Type q in gnuplot window to quite\n"; foreach my $opt (sort keys %plot) { $file = $plot{$opt}[0]; $file =~ s/\s/_/g; chomp $file; open GPF, ">$file"; foreach (1..$#{$plot{$opt}}) { print GPF $plot{$opt}[$_]; } close GPF; open GP, "|-", 'gnuplot', '-persist' or die "Can't run gnuplot: $!\n"; # open GP, "| gnuplot -persist" or die "Can't run gnuplot: $!\n"; print GP "plot '$file' with linespoints\n"; close GP; #unlink $file if $file; } } if ($opts{G}) { foreach my $opt (sort keys %plot) { $file = $plot{$opt}[0]; chomp $file; foreach (1..$#{$plot{$opt}}) { print $plot{$opt}[$_]; } # print "\n"; } } |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||