2006-09-28 03:51:49 +08:00
|
|
|
#!/usr/bin/perl
|
|
|
|
#
|
2016-10-06 06:13:46 +08:00
|
|
|
# program: charmm2lammps.pl
|
|
|
|
# author: Pieter J. in 't Veld,
|
|
|
|
# pjintve@sandia.gov, veld@verizon.net
|
|
|
|
# date: February 12-23, April 5, 2005.
|
|
|
|
# purpose: Translation of charmm input to lammps input
|
2006-09-28 03:51:49 +08:00
|
|
|
#
|
2016-10-06 06:13:46 +08:00
|
|
|
# Notes: Copyright by author for Sandia National Laboratories
|
|
|
|
# 20050212 Needed (in the same directory):
|
|
|
|
# - $project.crd ; Assumed to be correct and running
|
|
|
|
# - $project.psf ; CHARMM configs
|
|
|
|
# - top_$forcefield.rtf ;
|
|
|
|
# - par_$forcefield.prm ;
|
|
|
|
# Ouput:
|
|
|
|
# - $project.data ; LAMMPS data file
|
|
|
|
# - $project.in ; LAMMPS input file
|
|
|
|
# - $project_ctrl.pdb ; PDB control file
|
|
|
|
# - $project_ctrl.psf ; PSF control file
|
|
|
|
# 20050218 Optimized for memory usage
|
|
|
|
# 20050221 Rotation added
|
|
|
|
# 20050222 Water added
|
|
|
|
# 20050223 Ions added
|
|
|
|
# 20050405 Water bug fixed; addition of .pdb input
|
|
|
|
# 20050407 project_ctrl.psf bug fixed; addition of -border
|
|
|
|
# 20050519 Added interpretation of charmm xplor psfs
|
|
|
|
# 20050603 Fixed centering issues
|
|
|
|
# 20050630 Fixed symbol issues arising from salt addition
|
|
|
|
# 20060818 Changed reading of pdb format to read exact columns
|
|
|
|
# 20070109 Changed AddMass() to use $max_id correctly
|
2016-10-03 08:33:20 +08:00
|
|
|
# 20160114 Added compatibility for parameter files that use IMPROPERS instead of IMPROPER
|
|
|
|
# Print warning when not all parameters are detected. Set correct number of atom types.
|
|
|
|
# 20160613 Fix off-by-one issue in atom type validation check
|
|
|
|
# Replace -charmm command line flag with -nohints flag
|
|
|
|
# and enable type hints in data file by default.
|
|
|
|
# Add hints also to section headers
|
|
|
|
# Add a brief minimization to example input template.
|
2016-10-06 06:13:46 +08:00
|
|
|
# 20161001 Added 'CMAP crossterms' section at the end of the data file
|
|
|
|
# 20161001 Added instructions in CMAP section to fix problem if 'ter'
|
|
|
|
# is not designated in the .pdb file to identify last amino acid
|
|
|
|
# 20161005 Added tweak to embed command line in generated LAMMPS input
|
2016-10-03 08:33:20 +08:00
|
|
|
#
|
2016-10-06 06:13:46 +08:00
|
|
|
# General Many thanks to Paul S. Crozier for checking script validity
|
|
|
|
# against his projects.
|
|
|
|
# Also thanks to Xiaohu Hu (hux2@ornl.gov) and Robert A. Latour
|
|
|
|
# (latourr@clemson.edu), David Hyde-Volpe, and Tigran Abramyan,
|
|
|
|
# Clemson University and Chris Lorenz (chris.lorenz@kcl.ac.uk),
|
|
|
|
# King's College London for their efforts to add CMAP sections,
|
|
|
|
# which is implemented using the option flag "-cmap".
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
# Initialization
|
|
|
|
|
|
|
|
sub Test
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $name = shift(@_);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
printf("Error: file %s not found\n", $name) if (!scalar(stat($name)));
|
|
|
|
return !scalar(stat($name));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub Initialize # initialization
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = 0;
|
|
|
|
my @dir = ("x", "y", "z");
|
|
|
|
my @options = ("-help", "-nohints", "-water", "-ions", "-center",
|
|
|
|
"-quiet", "-pdb_ctrl", "-l", "-lx", "-ly", "-lz",
|
|
|
|
"-border", "-ax", "-ay", "-az", "-cmap");
|
|
|
|
my @remarks = ("display this message",
|
2016-10-03 08:33:20 +08:00
|
|
|
"do not print type and style hints in data file",
|
2016-10-06 06:13:46 +08:00
|
|
|
"add TIP3P water [default: 1 g/cc]",
|
|
|
|
"add (counter)ions using Na+ and Cl- [default: 0 mol/l]",
|
|
|
|
"recenter atoms",
|
|
|
|
"do not print info",
|
|
|
|
"output project_ctrl.pdb [default: on]",
|
|
|
|
"set x-, y-, and z-dimensions simultaneously",
|
|
|
|
"x-dimension of simulation box",
|
|
|
|
"y-dimension of simulation box",
|
|
|
|
"z-dimension of simulation box",
|
|
|
|
"add border to all sides of simulation box [default: 0 A]",
|
|
|
|
"rotation around x-axis",
|
|
|
|
"rotation around y-axis",
|
|
|
|
"rotation around z-axis",
|
|
|
|
"generate a CMAP section in data file"
|
|
|
|
);
|
2006-09-28 03:51:49 +08:00
|
|
|
my $notes;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
$program = "charmm2lammps";
|
|
|
|
$version = "1.9.1";
|
|
|
|
$year = "2016";
|
|
|
|
$add = 1;
|
|
|
|
$water_dens = 0;
|
|
|
|
$ions = 0;
|
|
|
|
$info = 1;
|
|
|
|
$center = 0;
|
|
|
|
$net_charge = 0;
|
|
|
|
$ion_molar = 0;
|
|
|
|
$pdb_ctrl = 1;
|
|
|
|
$border = 0;
|
|
|
|
$L = (0, 0, 0);
|
|
|
|
$cmap = 0;
|
|
|
|
@R = M_Unit();
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
$notes = " * The average of extremes is used as the origin\n";
|
|
|
|
$notes .= " * Residues are numbered sequentially\n";
|
|
|
|
$notes .= " * Water is added on an FCC lattice: allow 5 ps for";
|
|
|
|
$notes .= " equilibration\n";
|
|
|
|
$notes .= " * Ions are added randomly and only when water is present\n";
|
|
|
|
$notes .= " * CHARMM force field v2.7 parameters used for";
|
|
|
|
$notes .= " water and NaCl\n";
|
|
|
|
$notes .= " * Rotation angles are in degrees\n";
|
|
|
|
$notes .= " * Rotations are executed consecutively: -ax -ay != -ay -ax\n";
|
|
|
|
$notes .= " * CHARMM files needed in execution directory:\n";
|
|
|
|
$notes .= " - project.crd coordinates\n";
|
|
|
|
$notes .= " - project.pdb when project.crd is absent\n";
|
|
|
|
$notes .= " - project.psf connectivity\n";
|
|
|
|
$notes .= " - top_forcefield.rtf topology\n";
|
|
|
|
$notes .= " - par_forcefield.prm parameters\n";
|
|
|
|
$notes .= " * Output files written to execution directory:\n";
|
|
|
|
$notes .= " - project.data LAMMPS data file\n";
|
|
|
|
$notes .= " - project.in suggested LAMMPS input script\n";
|
|
|
|
$notes .= " - project_ctrl.pdb control file when requested\n";
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
# record full command line for later use
|
|
|
|
$cmdline = "$program.pl " . join(" ",@ARGV);
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@ARGV)
|
|
|
|
{
|
2016-10-03 08:33:20 +08:00
|
|
|
if (substr($_, 0, 1) eq "-")
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = 0;
|
|
|
|
my @tmp = split("=");
|
|
|
|
my $switch = ($arg[1] eq "")||($arg[1] eq "on")||($arg[1]!=0);
|
|
|
|
$tmp[0] = lc($tmp[0]);
|
|
|
|
foreach (@options)
|
|
|
|
{
|
|
|
|
last if ($tmp[0] eq substr($_, 0 , length($tmp[0])));
|
|
|
|
++$k;
|
|
|
|
}
|
|
|
|
$help = 1 if (!$k--); # -help
|
|
|
|
$add = 0 if (!$k--); # -nohints
|
|
|
|
$water_dens = ($tmp[1] ne "" ? $tmp[1] : 1) if (!$k--); # -water
|
|
|
|
$ion_molar = abs($tmp[1]) if (!$k); # -ions
|
|
|
|
$ions = 1 if (!$k--); # ...
|
|
|
|
$center = 1 if (!$k--); # -center
|
|
|
|
$info = 0 if (!$k--); # -quiet
|
|
|
|
$pdb_ctrl = $switch if (!$k--); # -pdb_ctrl
|
|
|
|
my $flag = $k--; # -l
|
|
|
|
$L[0] = abs($tmp[1]) if (!($flag && $k--)); # -lx
|
|
|
|
$L[1] = abs($tmp[1]) if (!($flag && $k--)); # -ly
|
|
|
|
$L[2] = abs($tmp[1]) if (!($flag && $k--)); # -lz
|
|
|
|
$border = abs($tmp[1]) if (!$k--); # -border
|
|
|
|
@R = M_Dot(M_Rotate(0, $tmp[1]), @R) if (!$k--);# -ax
|
|
|
|
@R = M_Dot(M_Rotate(1, $tmp[1]), @R) if (!$k--);# -ay
|
|
|
|
@R = M_Dot(M_Rotate(2, $tmp[1]), @R) if (!$k--);# -az
|
|
|
|
$cmap = ($tmp[1] ne "" ? $tmp[1] : 22) if (!$k--); # -cmap
|
2016-10-03 18:52:30 +08:00
|
|
|
print("Warning: ignoring unknown command line flag: $tmp[0]\n") unless $k;
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$forcefield = $_ if (!$k);
|
|
|
|
$project = $_ if ($k++ == 1);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$water_dens = 1 if ($ions && !$water_dens);
|
2006-09-28 03:51:49 +08:00
|
|
|
if (($k<2)||$help)
|
|
|
|
{
|
2016-10-03 18:52:30 +08:00
|
|
|
printf("\n%s v%s (c)2005-%s by Pieter J. in \'t Veld and others\n\n",
|
2006-09-28 03:51:49 +08:00
|
|
|
$program, $version, $year);
|
|
|
|
printf("Usage:\n %s.pl [-option[=#] ..] forcefield project\n\n",$program);
|
|
|
|
printf("Options:\n");
|
|
|
|
for (my $i=0; $i<scalar(@options); ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(" %-10.10s %s\n", $options[$i], $remarks[$i]);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
printf("\nNotes:\n%s\n", $notes);
|
|
|
|
exit(-1);
|
|
|
|
}
|
2016-10-03 18:52:30 +08:00
|
|
|
else { printf("\n%s v%s (c)2005-%s\n\n", $program, $version, $year) if ($info); }
|
2016-10-06 06:13:46 +08:00
|
|
|
my $flag = Test($Parameters = "par_$forcefield.prm");
|
|
|
|
$flag |= Test($Topology = "top_$forcefield.rtf");
|
|
|
|
$flag |= Test($Pdb = "$project.pdb")
|
|
|
|
if (!scalar(stat($Crd = "$project.crd")));
|
|
|
|
$flag |= Test($Psf = "$project.psf") if ($look eq "");
|
|
|
|
$pdb = ($Pdb ne "") ? 1 : 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
printf("Conversion aborted\n\n") if ($flag);
|
|
|
|
exit(-1) if ($flag);
|
|
|
|
printf("Info: using $Pdb instead of $Crd\n") if (!scalar(stat($Crd)));
|
|
|
|
for (my $i=0; $i<3; ++$i)
|
|
|
|
{
|
|
|
|
printf("Info: l%s not set: will use extremes\n",
|
2016-10-06 06:13:46 +08:00
|
|
|
("x", "y", "z")[$i]) if ($info&&!$L[$i]);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
open(PARAMETERS, "<par_$forcefield.prm");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Vector manipulation
|
|
|
|
|
|
|
|
sub V_String
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v = @_;
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return "{".$v[0].", ".$v[1].", ".$v[2]."}";
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub V_Add
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v1 = splice(@_, 0, 3);
|
|
|
|
my @v2 = splice(@_, 0, 3);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return ($v1[0]+$v2[0], $v1[1]+$v2[1], $v1[2]+$v2[2]);
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub V_Subtr
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v1 = splice(@_, 0, 3);
|
|
|
|
my @v2 = splice(@_, 0, 3);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return ($v1[0]-$v2[0], $v1[1]-$v2[1], $v1[2]-$v2[2]);
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub V_Dot
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v1 = splice(@_, 0, 3);
|
|
|
|
my @v2 = splice(@_, 0, 3);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return $v1[0]*$v2[0]+$v1[1]*$v2[1]+$v1[2]*$v2[2];
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub V_Mult
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v = splice(@_, 0, 3);
|
|
|
|
my $f = shift(@_);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return ($f*$v[0], $f*$v[1], $f*$v[2]);
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub M_String
|
|
|
|
{
|
|
|
|
my $string;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
for (my $i=0; $i<3; ++$i)
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$string .= ", " if ($i);
|
|
|
|
$string .= V_String(splice(@_, 0, 3));
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return "{".$string."}";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub M_Transpose
|
|
|
|
{
|
|
|
|
return
|
|
|
|
(@_[0], @_[3], @_[6],
|
|
|
|
@_[1], @_[4], @_[7],
|
|
|
|
@_[2], @_[5], @_[8]);
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub M_Dot
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v11 = splice(@_, 0, 3);
|
|
|
|
my @v12 = splice(@_, 0, 3);
|
|
|
|
my @v13 = splice(@_, 0, 3);
|
|
|
|
my @m = M_Transpose(splice(@_, 0, 9));
|
|
|
|
my @v21 = splice(@m, 0, 3);
|
|
|
|
my @v22 = splice(@m, 0, 3);
|
|
|
|
my @v23 = splice(@m, 0, 3);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return (
|
|
|
|
V_Dot(@v11, @v21), V_Dot(@v11, @v22), V_Dot(@v11, @v23),
|
|
|
|
V_Dot(@v12, @v21), V_Dot(@v12, @v22), V_Dot(@v12, @v23),
|
|
|
|
V_Dot(@v13, @v21), V_Dot(@v13, @v22), V_Dot(@v13, @v23));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub M_Unit { return (1,0,0, 0,1,0, 0,0,1); }
|
|
|
|
|
|
|
|
sub PI { return 4*atan2(1,1); }
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub M_Rotate
|
2016-10-06 06:13:46 +08:00
|
|
|
{ # vmd convention
|
|
|
|
my $n = shift(@_);
|
|
|
|
my $alpha = shift(@_)*PI()/180;
|
|
|
|
my $cos = cos($alpha);
|
|
|
|
my $sin = sin($alpha);
|
|
|
|
|
|
|
|
$cos = 0 if (abs($cos)<1e-16);
|
|
|
|
$sin = 0 if (abs($sin)<1e-16);
|
2006-09-28 03:51:49 +08:00
|
|
|
return (1,0,0, 0,$cos,-$sin, 0,$sin,$cos) if ($n==0); # around x-axis
|
|
|
|
return ($cos,0,$sin, 0,1,0, -$sin,0,$cos) if ($n==1); # around y-axis
|
|
|
|
return ($cos,-$sin,0, $sin,$cos,0, 0,0,1) if ($n==2); # around z-axis
|
|
|
|
return M_Unit();
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
sub MV_Dot
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @v11 = splice(@_, 0, 3);
|
|
|
|
my @v12 = splice(@_, 0, 3);
|
|
|
|
my @v13 = splice(@_, 0, 3);
|
|
|
|
my @v2 = splice(@_, 0, 3);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return (V_Dot(@v11, @v2), V_Dot(@v12, @v2), V_Dot(@v13, @v2));
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
# CHARMM input
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub PSFConnectivity
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = PSFGoto(bonds);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return if (scalar(@nconnect));
|
|
|
|
printf("Info: creating connectivity\n") if ($info);
|
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @bond = PSFGet(2);
|
2006-09-28 03:51:49 +08:00
|
|
|
$connect[$bond[0]][$nconnect[$bond[0]]++] = $bond[1];
|
|
|
|
$connect[$bond[1]][$nconnect[$bond[1]]++] = $bond[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 08:33:20 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub PSFDihedrals # hack to accomodate
|
|
|
|
{ # LAMMPS' way of calc
|
|
|
|
$idihedral = 0; # LJ 1-4 interactions
|
2006-09-28 03:51:49 +08:00
|
|
|
return $ndihedral if (($dihedral_flag = $ndihedral ? 1 : 0));
|
|
|
|
PSFConnectivity();
|
|
|
|
printf("Info: creating dihedrals\n") if ($info);
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = scalar(@nconnect);
|
|
|
|
my @bonded = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=1; $i<=$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$bonded[0] = $i;
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<scalar($nconnect[$bonded[0]]); ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$bonded[1] = $connect[$bonded[0]][$i];
|
|
|
|
for (my $i=0; $i<scalar($nconnect[$bonded[1]]); ++$i)
|
|
|
|
{
|
|
|
|
next if (($bonded[2] = $connect[$bonded[1]][$i])==$bonded[0]);
|
|
|
|
for (my $i=0; $i<scalar($nconnect[$bonded[2]]); ++$i)
|
|
|
|
{
|
|
|
|
next if (($bonded[3] = $connect[$bonded[2]][$i])==$bonded[1]);
|
|
|
|
next if ($bonded[3]<$bonded[0]);
|
|
|
|
$dihedral[$ndihedral++] = join(" ", @bonded);
|
|
|
|
}
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$dihedral_flag = 1;
|
2006-09-28 03:51:49 +08:00
|
|
|
return $ndihedral;
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub CreatePSFIndex # make an index of id
|
|
|
|
{ # locations
|
|
|
|
my @psf_ids = ("!NATOM","!NBOND:","!NTHETA:","!NPHI:","!NIMPHI:");
|
|
|
|
my @ids = (atoms, bonds, angles, dihedrals, impropers);
|
|
|
|
my $k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
my %hash;
|
|
|
|
|
|
|
|
printf("Info: creating PSF index\n") if ($info);
|
|
|
|
open(PSF, "<$project.psf") if (fileno(PSF) eq "");
|
|
|
|
foreach (@psf_ids) { $hash{$_} = shift(@ids); };
|
|
|
|
while (<PSF>)
|
|
|
|
{
|
|
|
|
chop();
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = split(" ");
|
|
|
|
my $n = $hash{$tmp[1]};
|
|
|
|
$PSFIndex{$n} = tell(PSF)." ".$tmp[0] if ($n ne "");
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub PSFGoto # goto $ident in <PSF>
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
|
|
|
CreatePSFIndex() if (!scalar(%PSFIndex));
|
2016-10-06 06:13:46 +08:00
|
|
|
my $id = shift(@_);
|
|
|
|
my @n = split(" ", $PSFIndex{$id});
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
@PSFBuffer = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
# return PSFDihedrals() if ($id eq "dihedrals");
|
|
|
|
if (!scalar(@n))
|
|
|
|
{
|
|
|
|
printf("Warning: PSF index for $id not found\n");
|
2016-10-03 08:33:20 +08:00
|
|
|
seek(PSF, 0, SEEK_END);
|
2006-09-28 03:51:49 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
seek(PSF, $n[0], SEEK_SET);
|
|
|
|
return $n[1];
|
|
|
|
}
|
|
|
|
|
2016-10-03 08:33:20 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub PSFGet
|
|
|
|
{
|
|
|
|
if ($dihedral_flag)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$dihedral_flag = $idihedral+1<$ndihedral ? 1 : 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
return split(" ", $dihedral[$idihedral++]);
|
|
|
|
}
|
|
|
|
if (!scalar(@PSFBuffer))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $line = <PSF>;
|
2006-09-28 03:51:49 +08:00
|
|
|
chop($line);
|
2016-10-06 06:13:46 +08:00
|
|
|
@PSFBuffer = split(" ", $line);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return splice(@PSFBuffer, 0, shift(@_));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-03 08:33:20 +08:00
|
|
|
sub PSFWrite
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $items = shift(@_);
|
|
|
|
my $n = $items;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($psf_ncols>7) { printf(PSF_CTRL "\n"); $psf_ncols = 0; }
|
2016-10-03 19:07:28 +08:00
|
|
|
foreach(@_)
|
|
|
|
{
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(PSF_CTRL " %7d", $_);
|
|
|
|
++$psf_ncols;
|
|
|
|
if ((!--$n) && ($psf_ncols>7))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(PSF_CTRL "\n");
|
|
|
|
$psf_ncols = 0;
|
|
|
|
$n = $items;
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub CRDGoto
|
|
|
|
{
|
|
|
|
my $n;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return if (shift(@_) ne "atoms");
|
|
|
|
open(CRD, "<".($pdb ? $Pdb : $Crd)) if (fileno(CRD) eq "");
|
|
|
|
seek(CRD, 0, SEEK_SET);
|
|
|
|
return PSFGoto(atoms) if ($pdb);
|
|
|
|
while (substr($n = <CRD>, 0, 1) eq "*") {}
|
|
|
|
chop($n);
|
|
|
|
return $n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub NextPDB2CRD
|
|
|
|
{
|
|
|
|
my @n = (6,5,1,4,1,3,1,1,4,1,3,8,8,8,6,6,6,4,2,2);
|
|
|
|
my @data = ();
|
|
|
|
my $c = 0;
|
|
|
|
my $line;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
while (substr($line = <CRD>, 0, 4) ne "ATOM") {};
|
|
|
|
chop($line);
|
|
|
|
foreach (@n) { push(@data, substr($line, ($c += $_)-$_, $_)); }
|
|
|
|
return @data[1, 8, 5, 3, 11, 12, 13, 17, 8, 15];
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub Delete
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $item = shift(@_);
|
|
|
|
my $k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
my @list;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@_)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
delete($tmp[$item]);
|
2016-10-06 06:13:46 +08:00
|
|
|
$list[$k++] = join(" ", @tmp);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return @list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub CreateID # create id from list
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = scalar(@_);
|
|
|
|
my @list = @_;
|
|
|
|
my $id = "";
|
|
|
|
my $flag = $list[0] gt $list[-1];
|
|
|
|
my $j = $n;
|
2006-09-28 03:51:49 +08:00
|
|
|
my $tmp;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return "" if (scalar(@list)<$n);
|
2016-10-06 06:13:46 +08:00
|
|
|
$flag = $list[1] gt $list[-2]
|
|
|
|
if ((scalar(@list)>3)&&($list[0] eq $list[-1]));
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$id .= ($i ? " " : "").($tmp = $list[$flag ? --$j : $i]);
|
|
|
|
$id .= substr(" ", 0, 4-length($tmp));
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return $id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub AtomTypes
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = PSFGoto(atoms);
|
2006-09-28 03:51:49 +08:00
|
|
|
my %list;
|
|
|
|
|
|
|
|
return () if ($n<1);
|
2016-10-06 06:13:46 +08:00
|
|
|
$atom_types[0] = -1;
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = split(" ", <PSF>);
|
|
|
|
$tmp[5] = $symbols{$tmp[5]}
|
2006-09-28 03:51:49 +08:00
|
|
|
if ((substr($tmp[5],0,1) lt '0')||(substr($tmp[5],0,1) gt '9'));
|
|
|
|
push(@atom_types, $tmp[5]);
|
|
|
|
++$list{$tmp[5]};
|
|
|
|
}
|
|
|
|
if ($water_dens)
|
|
|
|
{
|
|
|
|
push(@atom_types, $symbols{HT}); ++$list{$symbols{HT}};
|
|
|
|
push(@atom_types, $symbols{OT}); ++$list{$symbols{OT}};
|
|
|
|
}
|
|
|
|
if ($ions)
|
|
|
|
{
|
|
|
|
push(@atom_types, $symbols{CLA}); ++$list{$symbols{CLA}};
|
|
|
|
push(@atom_types, $symbols{SOD}); ++$list{$symbols{SOD}};
|
|
|
|
}
|
|
|
|
return sort({$a<=>$b} keys(%list));
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub Markers
|
|
|
|
{
|
2016-10-03 08:33:20 +08:00
|
|
|
my %markers = (
|
|
|
|
NONBONDED => '0',
|
|
|
|
BONDS => '1',
|
|
|
|
ANGLES => '2',
|
|
|
|
DIHEDRALS => '3',
|
|
|
|
IMPROPERS => '4',
|
|
|
|
IMPROPER => '4'
|
|
|
|
);
|
2006-09-28 03:51:49 +08:00
|
|
|
return %markers;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub NonBond
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @cols = @_;
|
|
|
|
my $f = (scalar(@cols)>3)&&(substr($cols[3],0,1) ne "!");
|
|
|
|
my @tmp = (-$cols[1], $cols[2],
|
|
|
|
$f ? -$cols[4]:-$cols[1], $f ? $cols[5]:$cols[2]);
|
|
|
|
$tmp[1] *= 2.0**(5/6); # adjust sigma
|
|
|
|
$tmp[3] *= 2.0**(5/6); # adjust sigma 1-4
|
2006-09-28 03:51:49 +08:00
|
|
|
return join(" ", @tmp);
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub AtomParameters # non-bonded parameters
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
|
|
|
my @types;
|
|
|
|
my @list;
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = 0;
|
|
|
|
my $read = 0;
|
|
|
|
my %markers = Markers();
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
foreach(@_) { $types{$ids{$_}} = $k++; }
|
|
|
|
seek(PARAMETERS, 0, 0);
|
|
|
|
while (<PARAMETERS>)
|
|
|
|
{
|
|
|
|
chop();
|
2016-10-06 06:13:46 +08:00
|
|
|
my @cols = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($read&&(scalar(@cols)>1)&&
|
2016-10-06 06:13:46 +08:00
|
|
|
(substr($cols[0],0,1) ne "!")&&($cols[1] lt "A"))
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = $types{shift(@cols)};
|
|
|
|
$list[$k] = NonBond(@cols) if ($k ne "");
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
if ($markers{$cols[0]} ne "") {
|
2016-10-06 06:13:46 +08:00
|
|
|
$read = ($markers{$cols[0]} eq "0") ? 1 : 0; }
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$list[$types{HT}] = NonBond(0, -0.046, 0.2245)
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($water_dens&&($list[$types{HT}] eq ""));
|
2016-10-06 06:13:46 +08:00
|
|
|
$list[$types{OT}] = NonBond(0, -0.152100, 1.768200)
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($water_dens&&($list[$types{OT}] eq ""));
|
2016-10-06 06:13:46 +08:00
|
|
|
$list[$types{CLA}] = NonBond(0, -0.150, 2.27)
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($ions&&($list[$types{CLA}] eq ""));
|
|
|
|
$list[$types{SOD}] = NonBond(0, -0.0469, 1.36375)
|
|
|
|
if ($ions&&($list[$types{SOD}] eq ""));
|
|
|
|
return @list;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub BondedTypes # create bonded types
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $mode = shift(@_); # operation mode
|
|
|
|
my $items = (2, 3, 4, 4)[$mode]; # items per entry
|
|
|
|
my $id = (bonds, angles, dihedrals, impropers)[$mode];
|
|
|
|
my $n = PSFGoto($id);
|
2006-09-28 03:51:49 +08:00
|
|
|
my %list;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (PSFGet($items)) { push(@tmp, $ids{$atom_types[$_]}); }
|
|
|
|
++$list{CreateID(@tmp)};
|
|
|
|
}
|
|
|
|
++$list{CreateID(HT, OT)} if ($water_dens&&($mode==0));
|
|
|
|
++$list{CreateID(HT, OT, HT)} if ($water_dens&&($mode==1));
|
2016-10-06 06:13:46 +08:00
|
|
|
@types = sort(keys(%list));
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub Parameters # parms from columns
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $items = shift(@_);
|
|
|
|
my @cols = @_;
|
|
|
|
my $parms = "";
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
for (my $i=$items; ($i<scalar(@cols))&&(substr($cols[$i],0,1)ne"!"); ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$parms = $parms.($i>$items ? " " : "").$cols[$i];
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return $parms;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub BondedParameters # distil parms from
|
|
|
|
{ # <PARAMETERS>
|
|
|
|
my $mode = shift(@_); # bonded mode
|
2006-09-28 03:51:49 +08:00
|
|
|
return if (($mode>3)||($mode<0));
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
my $items = (2, 3, 4, 4)[$mode]; # items per entry
|
|
|
|
my $name = ("bond", "angle", "dihedral", "improper")[$mode];
|
|
|
|
my $read = 0;
|
|
|
|
my $k = 0;
|
|
|
|
my %markers = Markers();
|
2006-09-28 03:51:49 +08:00
|
|
|
my @set;
|
|
|
|
my @tmp;
|
|
|
|
my $f;
|
|
|
|
my %list;
|
|
|
|
my %link;
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
@parms = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach(@types) { $link{$_} = $k++; }
|
|
|
|
seek(PARAMETERS, 0, 0);
|
|
|
|
while (<PARAMETERS>)
|
|
|
|
{
|
|
|
|
chomp();
|
2016-10-06 06:13:46 +08:00
|
|
|
my @cols = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($read&&(scalar(@cols)>$items)&&($cols[$items] lt "A"))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
if (($items==4)&&(($f = ($cols[1] eq "X")&&($cols[2] eq "X"))||
|
|
|
|
(($cols[0] eq "X")&&($cols[3] eq "X")))) # wildcards
|
|
|
|
{
|
|
|
|
my $id = CreateID(($cols[1-$f], $cols[2+$f]));
|
|
|
|
for ($k=0; $k<scalar(@types); ++$k)
|
|
|
|
{
|
|
|
|
if (!$set[$k])
|
|
|
|
{
|
|
|
|
my @tmp = split(" ", $types[$k]);
|
|
|
|
if (CreateID($tmp[1-$f], $tmp[2+$f]) eq $id)
|
|
|
|
{
|
|
|
|
if ($mode==2)
|
|
|
|
{
|
|
|
|
if ($parms[$k] eq "") {
|
|
|
|
$parms[$k] = Parameters($items,@cols)." 1"; }
|
|
|
|
else {
|
|
|
|
$parms[$k] .= ":".Parameters($items,@cols)." 0"; }
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$parms[$k] .= Parameters($items,@cols); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else # regular
|
|
|
|
{
|
|
|
|
for (my $i=0; $i<$items; ++$i) { $tmp[$i] = $cols[$i]; };
|
|
|
|
$k = $link{CreateID(@tmp)};
|
|
|
|
if ($k ne "")
|
|
|
|
{
|
|
|
|
$parms[$k] = "" if (!$set[$k]);
|
|
|
|
$parms[$k] .= ($set[$k]++ ? ":" : "").Parameters($items,@cols);
|
|
|
|
$parms[$k] .= ($set[$k]-1 ? " 0" : " 1") if ($mode==2);
|
|
|
|
}
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
if ($markers{$cols[0]}) {
|
2016-10-06 06:13:46 +08:00
|
|
|
$read = ($markers{$cols[0]} eq $mode+1) ? 1 : 0; }
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
if ($water_dens)
|
|
|
|
{
|
|
|
|
$parms[$link{CreateID(HT, OT)}] = "450 0.9572" if ($mode==0);
|
|
|
|
$parms[$link{CreateID(HT, OT, HT)}] = "55 104.52" if ($mode==1);
|
|
|
|
}
|
|
|
|
for (my $i=0; $i<scalar(@types); ++$i)
|
|
|
|
{
|
2016-10-03 19:07:28 +08:00
|
|
|
printf("Warning: %s parameter %4d for [%s] was not found\n",
|
2016-10-06 06:13:46 +08:00
|
|
|
$name, $i+1, $types[$i]) if ($parms[$i] eq "");
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub SetScreeningFactor # set screening factor
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $id = shift(@_);
|
|
|
|
my $value = shift(@_);
|
|
|
|
my $new = "";
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (split(":", $parms[$id]))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = split(" ");
|
|
|
|
$tmp[-1] = $value if ($tmp[-1]);
|
|
|
|
$new .= ":" if ($new ne "");
|
|
|
|
$new .= join(" ", @tmp);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$parms[$id] = $new;
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub CorrectDihedralParameters
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = PSFGoto(dihedrals);
|
2006-09-28 03:51:49 +08:00
|
|
|
my %hash;
|
|
|
|
my $hash_id;
|
|
|
|
my $id1;
|
|
|
|
my $id2;
|
|
|
|
my $first;
|
|
|
|
my $last;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-03 08:33:20 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @bonded = PSFGet(4);
|
|
|
|
my @tmp = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@bonded) { push(@tmp, $ids{$atom_types[$_]}); }
|
2016-10-06 06:13:46 +08:00
|
|
|
$id1 = $link{CreateID(@tmp)}-1;
|
|
|
|
$first = $bonded[0];
|
|
|
|
$last = $bonded[3];
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($first>$last) { my $tmp = $first; $first = $last; $last = $tmp; }
|
2016-10-03 19:07:28 +08:00
|
|
|
if (($id2 = $hash{$hash_id = $first." ".$last}) eq "")
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$hash{$hash_id} = $id1; # add id to hash
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
SetScreeningFactor($id1, 0.5); # 6-ring: shared 1-4
|
|
|
|
SetScreeningFactor($id2, 0.5);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$n = PSFGoto(angles);
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @bonded = PSFGet(3);
|
|
|
|
$first = $bonded[0];
|
|
|
|
$last = $bonded[2];
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($first>$last) { my $tmp = $first; $first = $last; $last = $tmp; }
|
|
|
|
if (($id1 = $hash{$first." ".$last}) ne "")
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
SetScreeningFactor($id1, 0); # 5-ring: no 1-4
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub AddMass
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $symbol = shift(@_);
|
|
|
|
my $mass = shift(@_);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return if ($symbols{$symbol} ne "");
|
2016-10-06 06:13:46 +08:00
|
|
|
$ids{++$max_id} = $symbol;
|
|
|
|
$masses{$max_id} = $mass;
|
|
|
|
$symbols{$symbol} = $max_id;
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub ReadTopology # read topology links
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $id = shift(@_);
|
|
|
|
my $item = shift(@_);
|
|
|
|
my $read = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
my @tmp;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
open(TOPOLOGY, "<top_$forcefield.rtf");
|
2016-10-06 06:13:46 +08:00
|
|
|
$max_id = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
while (<TOPOLOGY>)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
chop(); # delete CR at end
|
|
|
|
my @tmp = split(" ");
|
|
|
|
$read = 1 if ($tmp[0] eq "MASS");
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($read&&($tmp[0] eq "MASS"))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
$symbols{$tmp[2]} = $tmp[1];
|
|
|
|
$ids{$tmp[1]} = $tmp[2];
|
|
|
|
$masses{$tmp[1]} = $tmp[3];
|
|
|
|
$max_id = $tmp[1] if ($max_id<$tmp[1]);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
# $names{$tmp[1]} = $tmp[4] if ($read&&($tmp[0] eq "MASS"));
|
|
|
|
last if ($read&&!scalar(@tmp)); # quit reading
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
AddMass(HT, 1.00800);
|
|
|
|
AddMass(OT, 15.99940);
|
|
|
|
AddMass(CLA, 35.450000);
|
|
|
|
AddMass(SOD, 22.989770);
|
|
|
|
close(TOPOLOGY);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub CrossLink # symbolic cross-links
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @list = @_;
|
|
|
|
my $n = scalar(@list);
|
2006-09-28 03:51:49 +08:00
|
|
|
my %hash;
|
|
|
|
|
|
|
|
for (my $i=0; $i<$n; ++$i) { $hash{$list[$i]} = $i+1; }
|
|
|
|
return %hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub CharacterizeBox
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $flag = 1;
|
|
|
|
my @x = (-$L[0]/2, $L[0]/2);
|
|
|
|
my @y = (-$L[1]/2, $L[1]/2);
|
|
|
|
my @z = (-$L[2]/2, $L[2]/2);
|
|
|
|
my $n = CRDGoto(atoms);
|
|
|
|
my $extremes = !($L[0] && $L[1] && $L[2]);
|
|
|
|
|
|
|
|
@Center = (0, 0, 0);
|
2006-09-28 03:51:49 +08:00
|
|
|
return if (!$n);
|
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @tmp = $pdb ? NextPDB2CRD() : split(" ", <CRD>);
|
|
|
|
my @p = @tmp[-6, -5, -4];
|
|
|
|
@p = MV_Dot(@R, @p);
|
|
|
|
$x[0] = $p[0] if ($flag||($p[0]<$x[0]));
|
|
|
|
$x[1] = $p[0] if ($flag||($p[0]>$x[1]));
|
|
|
|
$y[0] = $p[1] if ($flag||($p[1]<$y[0]));
|
|
|
|
$y[1] = $p[1] if ($flag||($p[1]>$y[1]));
|
|
|
|
$z[0] = $p[2] if ($flag||($p[2]<$z[0]));
|
|
|
|
$z[1] = $p[2] if ($flag||($p[2]>$z[1]));
|
|
|
|
$flag = 0 if ($flag);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$L[0] = $x[1]-$x[0] if (!$L[0]);
|
|
|
|
$L[1] = $y[1]-$y[0] if (!$L[1]);
|
|
|
|
$L[2] = $z[1]-$z[0] if (!$L[2]);
|
|
|
|
$L[0] += $border;
|
|
|
|
$L[1] += $border;
|
|
|
|
$L[2] += $border;
|
|
|
|
@Center = (($x[1]+$x[0])/2, ($y[1]+$y[0])/2, ($z[1]+$z[0])/2);
|
2006-09-28 03:51:49 +08:00
|
|
|
printf("Info: recentering atoms\n") if ($info&&$center);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub SetupWater
|
|
|
|
{
|
|
|
|
return if (!$water_dens);
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
my $dens = 1000*$water_dens; # kg/m^3
|
|
|
|
my $m = 0.018; # kg/mol
|
|
|
|
my $loh = 0.9572; # l[O-H] in [A]
|
|
|
|
my $s_OT = 1.7682; # CHARMM sigma [A]
|
|
|
|
my $ahoh = (180-104.52)/360*PI();
|
|
|
|
my @p = ($loh*cos($ahoh), $loh*sin($ahoh), 0);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
printf("Info: creating fcc water\n") if ($info);
|
2016-10-06 06:13:46 +08:00
|
|
|
$n_water = 4; # molecules/cell
|
|
|
|
$nav = 6.022e23; # 1/mol
|
|
|
|
$v_water = $m/$nav/$dens*1e30; # water volume [A^3]
|
|
|
|
$r_water = $s_OT*2**(-1/6); # sigma_OT in [A]
|
|
|
|
@p_water = (0,0,0, @p, -$p[0],$p[1],0);
|
|
|
|
$v_fcc = $n_water*$v_water; # cell volume
|
|
|
|
$l_fcc = $v_fcc**(1/3); # cell length
|
|
|
|
@p_fcc = (0.00,0.00,0.00, 0.50,0.50,0.00,
|
|
|
|
0.50,0.00,0.50, 0.00,0.50,0.50);
|
|
|
|
@n_fcc = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<scalar(@L); ++$i)
|
2016-10-03 19:07:28 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = $L[$i]/$l_fcc; # calculate n_fcc
|
|
|
|
$n = int($n-int($n) ? $n+1 : $n); # ceil($n)
|
|
|
|
$L[$i] = $n*$l_fcc; # adjust box length
|
2006-09-28 03:51:49 +08:00
|
|
|
printf("Info: changed l%s to %g A\n", ("x","y","z")[$i], $L[$i])
|
2016-10-06 06:13:46 +08:00
|
|
|
if ($info);
|
2006-09-28 03:51:49 +08:00
|
|
|
push(@n_fcc, $n);
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
foreach (@p_fcc) { $_ = ($_+0.25)*$l_fcc; } # p_fcc in [A]
|
|
|
|
for (my $x=0; $x<$n_fcc[0]; ++$x) { # initialize flags
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $y=0; $y<$n_fcc[1]; ++$y) {
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $z=0; $z<$n_fcc[2]; ++$z) {
|
|
|
|
$flags_fcc[$x][$y][$z] = 15; } } } # turn on all fcc sites
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub floor
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $x = shift(@_);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return $x>0 ? int($x) : int($x)-1;
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub Periodic
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @p = splice(@_, 0, 3);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return (
|
|
|
|
$p[0]-floor($p[0]/$L[0]+0.5)*$L[0],
|
|
|
|
$p[1]-floor($p[1]/$L[1]+0.5)*$L[1],
|
|
|
|
$p[2]-floor($p[2]/$L[2]+0.5)*$L[2]);
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub EraseWater
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $r = shift(@_)/2;
|
|
|
|
my @p = splice(@_, 0, 3);
|
|
|
|
@p = V_Subtr(@p, @Center) if (!$center);
|
|
|
|
my @edges = (
|
2006-09-28 03:51:49 +08:00
|
|
|
$p[0]-$r,$p[1]-$r,$p[2]-$r, $p[0]-$r,$p[1]-$r,$p[2]+$r,
|
|
|
|
$p[0]-$r,$p[1]+$r,$p[2]-$r, $p[0]-$r,$p[1]+$r,$p[2]+$r,
|
|
|
|
$p[0]+$r,$p[1]-$r,$p[2]-$r, $p[0]+$r,$p[1]-$r,$p[2]+$r,
|
|
|
|
$p[0]+$r,$p[1]+$r,$p[2]-$r, $p[0]+$r,$p[1]+$r,$p[2]+$r);
|
|
|
|
my %list;
|
|
|
|
my @n;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
my $d2 = ($r_water+$r)**2;
|
|
|
|
my @l = ($L[0]/2, $L[1]/2, $L[2]/2);
|
|
|
|
for (my $i=0; $i<scalar(@edges); $i+=3) # determine candidates
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @q = Periodic(@edges[$i, $i+1, $i+2]);
|
|
|
|
my @n = (int(($q[0]+$l[0])/$l_fcc),int(($q[1]+$l[1])/$l_fcc),
|
|
|
|
int(($q[2]+$l[2])/$l_fcc));
|
2006-09-28 03:51:49 +08:00
|
|
|
++$list{join(" ", @n)};
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
foreach (sort(keys(%list))) # check overlap
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @n = split(" ");
|
|
|
|
my @corner = ($n[0]*$l_fcc-$l[0]+$p_water[0],
|
|
|
|
$n[1]*$l_fcc-$l[1]+$p_water[1],
|
|
|
|
$n[2]*$l_fcc-$l[2]+$p_water[2]);
|
|
|
|
my $bit = 1;
|
|
|
|
my $flags = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<scalar(@p_fcc); $i+=3)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @q = V_Add(@corner, @p_fcc[$i,$i+1,$i+2]);
|
|
|
|
my @dp = Periodic(V_Subtr(@q, @p));
|
|
|
|
$flags |= $bit if (V_Dot(@dp, @dp)>$d2); # turn on fcc
|
|
|
|
$bit *= 2;
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$flags_fcc[$n[0]][$n[1]][$n[2]] &= $flags; # set flags
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
2016-10-03 19:07:28 +08:00
|
|
|
|
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub CountFCC
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return $n_fccs = 0 if (!$water_dens);
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $x=0; $x<$n_fcc[0]; ++$x) { # count water
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $y=0; $y<$n_fcc[1]; ++$y) {
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $z=0; $z<$n_fcc[2]; ++$z) {
|
|
|
|
my $bit = 1;
|
|
|
|
my $flags = $flags_fcc[$x][$y][$z];
|
|
|
|
for (my $i=0; $i<$n_water; ++$i) {
|
|
|
|
++$n if ($flags & $bit);
|
|
|
|
$bit *= 2; } } } }
|
2006-09-28 03:51:49 +08:00
|
|
|
return ($n_fccs = $n);
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub AddIons
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = ($n_waters = CountFCC())-int(abs($net_charge));
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return if (!$ions);
|
|
|
|
printf("Warning: charge not neutralized: too little water\n") if ($n<0);
|
|
|
|
return if ($n<0);
|
|
|
|
printf(
|
|
|
|
"Warning: charge not neutralized: net charge (%g) is not an integer\n",
|
|
|
|
$net_charge) if ($net_charge!=int($net_charge));
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n_na = $net_charge<0 ? int(abs($net_charge)) : 0;
|
|
|
|
my $n_cl = $net_charge>0 ? int(abs($net_charge)) : 0;
|
|
|
|
my $n_mol = int($ion_molar*$n*$v_water*1e-27*$nav+0.5);
|
|
|
|
my $n_atoms = ($n_na += $n_mol)+($n_cl += $n_mol);
|
|
|
|
$n_waters -= $n_atoms;
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(
|
|
|
|
"Info: adding ions: [NaCl] = %g mol/l (%d Na+, %d Cl-)\n",
|
|
|
|
$n_mol/$n/$v_water/$nav/1e-27, $n_na, $n_cl) if ($info);
|
2016-10-06 06:13:46 +08:00
|
|
|
$n += int(abs($net_charge));
|
|
|
|
my $salt = 2**$n_water;
|
|
|
|
srand(time()); # seed random number
|
|
|
|
for (my $x=0; $x<$n_fcc[0]; ++$x) # replace water by ions
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
|
|
|
for (my $y=0; $y<$n_fcc[1]; ++$y)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $z=0; $z<$n_fcc[2]; ++$z)
|
|
|
|
{
|
|
|
|
my $bit = 1;
|
|
|
|
my $flags = $flags_fcc[$x][$y][$z];
|
|
|
|
for (my $i=0; $i<$n_water; ++$i)
|
|
|
|
{
|
|
|
|
if ($flags & $bit)
|
|
|
|
{
|
|
|
|
my $prob = $n_atoms/$n;
|
|
|
|
--$n;
|
|
|
|
if (rand()<$prob)
|
|
|
|
{
|
|
|
|
my $na = rand()<$n_na/$n_atoms ? 1 : 0;
|
|
|
|
--$n_atoms;
|
|
|
|
if ($na) { --$n_na; } else { --$n_cl; }
|
|
|
|
$flags |= $salt*(1+$salt*$na)*$bit; # set type of ion
|
|
|
|
}
|
|
|
|
};
|
|
|
|
$bit *= 2;
|
|
|
|
}
|
|
|
|
$flags_fcc[$x][$y][$z] = $flags;
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
# LAMMPS output
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteLAMMPSHeader # print lammps header
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-03 18:52:30 +08:00
|
|
|
printf(LAMMPS "LAMMPS data file. %sCreated by $program v$version on %s\n",
|
|
|
|
($add ? "CGCMM Style. atom_style full. " : ""),`date`);
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%12d atoms\n", $natoms);
|
|
|
|
printf(LAMMPS "%12d bonds\n", $nbonds);
|
|
|
|
printf(LAMMPS "%12d angles\n", $nangles);
|
|
|
|
printf(LAMMPS "%12d dihedrals\n", $ndihedrals);
|
|
|
|
printf(LAMMPS "%12d impropers\n\n", $nimpropers);
|
|
|
|
printf(LAMMPS "%12d atom types\n", $natom_types);
|
|
|
|
printf(LAMMPS "%12d bond types\n", $nbond_types);
|
|
|
|
printf(LAMMPS "%12d angle types\n", $nangle_types);
|
|
|
|
printf(LAMMPS "%12d dihedral types\n", $ndihedral_types);
|
|
|
|
printf(LAMMPS "%12d improper types\n\n", $nimproper_types);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub WriteControlHeader
|
|
|
|
{
|
|
|
|
printf(PDB_CTRL "REMARK \n");
|
|
|
|
printf(PDB_CTRL "REMARK CONTROL PDB %s_ctrl.pdb\n", $project);
|
|
|
|
printf(PDB_CTRL "REMARK CREATED BY %s v%s ON %s",
|
|
|
|
$program, $version, `date`);
|
|
|
|
printf(PDB_CTRL "REMARK \n");
|
|
|
|
|
|
|
|
printf(PSF_CTRL "PSF\n");
|
|
|
|
printf(PSF_CTRL "\n");
|
|
|
|
printf(PSF_CTRL "%8d !NTITLE\n", 2);
|
|
|
|
printf(PSF_CTRL " REMARKS CONTROL PSF %s_ctrl.psf\n", $project);
|
|
|
|
printf(PSF_CTRL " REMARKS CREATED BY %s v%s ON %s",
|
|
|
|
$program, $version, `date`);
|
|
|
|
printf(PSF_CTRL "\n");
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteBoxSize # print box limits
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @lo = V_Mult(@L[0,1,2], -1/2);
|
|
|
|
my @hi = V_Mult(@L[0,1,2], 1/2);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
@lo = V_Add(@lo, @Center) if (!$center);
|
|
|
|
@hi = V_Add(@hi, @Center) if (!$center);
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%12.8g %12.8g xlo xhi\n", $lo[0], $hi[0]);
|
|
|
|
printf(LAMMPS "%12.8g %12.8g ylo yhi\n", $lo[1], $hi[1]);
|
|
|
|
printf(LAMMPS "%12.8g %12.8g zlo zhi\n\n", $lo[2], $hi[2]);
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteMasses # print mass list
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = 0;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "Masses\n\n");
|
|
|
|
foreach (@types)
|
|
|
|
{
|
|
|
|
printf(LAMMPS "%8d %10.7g%s\n",
|
2016-10-06 06:13:46 +08:00
|
|
|
++$k, $masses{$_}, $add ? " # ".$ids{$_} : "");
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
printf(LAMMPS "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub WriteFCCAtoms
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $k = shift(@_);
|
|
|
|
my $res = shift(@_);
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
return $k if (!$water_dens);
|
2016-10-06 06:13:46 +08:00
|
|
|
$k_fcc = $k+1;
|
|
|
|
my @id = ($symbols{OT}, $symbols{HT}, $symbols{HT},
|
|
|
|
$symbols{SOD}, $symbols{CLA});
|
|
|
|
my @par = ();
|
|
|
|
my @charge = (-0.834, 0.417, 0.417, 1, -1);
|
|
|
|
my $salt = 2**$n_water;
|
|
|
|
my @l = ($L[0]/2, $L[1]/2, $L[2]/2);
|
|
|
|
my $iwater = 0;
|
|
|
|
my $isalt = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach(@id) { push(@par, $link{$_}); }
|
|
|
|
for (my $x=0; $x<$n_fcc[0]; ++$x)
|
|
|
|
{
|
|
|
|
for (my $y=0; $y<$n_fcc[1]; ++$y)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $z=0; $z<$n_fcc[2]; ++$z)
|
|
|
|
{
|
|
|
|
my @corner = ($x*$l_fcc-$l[0], $y*$l_fcc-$l[1], $z*$l_fcc-$l[2]);
|
|
|
|
my $flags = $flags_fcc[$x][$y][$z];
|
|
|
|
my $bit = 1;
|
|
|
|
for (my $i=0; $i<scalar(@p_fcc); $i+=3)
|
|
|
|
{
|
|
|
|
my $pair = $bit;
|
|
|
|
if ($flags & $pair)
|
|
|
|
{
|
|
|
|
my @p = V_Add(@corner, @p_fcc[$i,$i+1,$i+2]);
|
|
|
|
my $j = 0; # print water
|
|
|
|
my $n = scalar(@p_water);
|
|
|
|
++$res;
|
|
|
|
if ($flags & ($pair *= $salt)) # print salt ion
|
|
|
|
{ # sodium if highest
|
|
|
|
$j = $flags & ($pair*$salt) ? 3 : 4;
|
|
|
|
$n = 1;
|
|
|
|
$counter = ++$isalt;
|
|
|
|
}
|
|
|
|
else { $counter = ++$iwater; }
|
|
|
|
for (my $i=0; $i<$n; $i+=3)
|
|
|
|
{
|
|
|
|
my @xyz = V_Add(@p, @p_water[$i,$i+1,$i+2]);
|
|
|
|
@xyz = V_Add(@xyz, @Center) if (!$center);
|
|
|
|
printf(LAMMPS "%8d %7d %5d %9.6g %16.12g %16.12g %16.12g%s\n",
|
|
|
|
++$k, $res, $par[$j], $charge[$j], $xyz[0], $xyz[1],
|
|
|
|
$xyz[2], $add ? " # ".$types[$par[$j]-1] : "");
|
|
|
|
printf(PDB_CTRL "ATOM %6.6s %-4.4s %-3.3s %5.5s %3.3s ".
|
|
|
|
"%7.7s %7.7s %7.7s %5.5s %5.5s %4.4s %s\n", $k,
|
|
|
|
$types[$par[$j]-1], $n-1 ? "HOH" : "ION", $res, "",
|
|
|
|
$xyz[0], $xyz[1], $xyz[2], "1.00", "0.00", "",
|
|
|
|
$n-1 ? "WATR" : "SALT") if ($pdb_ctrl);
|
|
|
|
printf(PSF_CTRL "%8d %4.4s %-4.4s %-4.4s %-4.4s %4.4s ".
|
|
|
|
"%16.8e %7.7s %9.9s 0\n", $k, $n-1 ? "WATR" : "SALT",
|
|
|
|
$counter, $n-1 ? "HOH" : "ION", $types[$par[$j]-1], $id[$j],
|
|
|
|
$charge[$j], $masses{$id[$j]}, "") if ($pdb_ctrl);
|
|
|
|
++$j;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$bit *= 2;
|
|
|
|
}
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $k;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub WritePSFAtoms()
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = PSFGoto(atoms);
|
|
|
|
my @res = (0, 0);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(PSF_CTRL "%8d !NATOM\n", $n+2*$n_waters+$n_fccs);
|
2016-10-03 19:07:28 +08:00
|
|
|
while (<PSF>)
|
|
|
|
{
|
|
|
|
last if (!$n--);
|
2016-10-06 06:13:46 +08:00
|
|
|
my @psf = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($res[1]!=$psf[2]) { ++$res[0]; $res[1] = $psf[2]; }
|
|
|
|
printf(PSF_CTRL "%8d %4.4s %-4.4s %-4.4s %-4.4s %-4.4s ".
|
2016-10-06 06:13:46 +08:00
|
|
|
"%16.8e %7.7s %9.9s %s\n", $psf[0], $psf[1], $res[0],
|
|
|
|
$psf[3], $psf[4], $psf[5], $psf[6], $psf[7], "", $psf[8]);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteAtoms # print positions etc.
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = PSFGoto(atoms);
|
|
|
|
my $k = 0;
|
|
|
|
my @res = (0, 0);
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
CRDGoto(atoms);
|
2016-10-06 06:13:46 +08:00
|
|
|
$net_charge = 0;
|
2016-10-03 18:52:30 +08:00
|
|
|
printf(LAMMPS "Atoms%s\n\n",($add ? " # full" : "")) if ($n>0);
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @crd = $pdb ? NextPDB2CRD() : split(" ", <CRD>);
|
|
|
|
my @psf = split(" ", <PSF>);
|
|
|
|
my @xyz = MV_Dot(@R, @crd[-6, -5, -4]);
|
|
|
|
@xyz = V_Subtr(@xyz, @Center) if ($center);
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($crd[-2]!=$res[1]) { ++$res[0]; $res[1] = $crd[-2]; }
|
2016-09-24 06:59:43 +08:00
|
|
|
printf(LAMMPS "%8d %7d %5d %9.6g %16.12g %16.12g %16.12g%s\n", ++$k,
|
2016-10-06 06:13:46 +08:00
|
|
|
$res[0], $link{$atom_types[$k]}, $psf[6], $xyz[0], $xyz[1], $xyz[2],
|
|
|
|
$add ? " # ".$types[$link{$atom_types[$k]}-1] : "");
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(PDB_CTRL "ATOM %6.6s %-4.4s %-4.4s %4.4s %3.3s ".
|
2016-10-06 06:13:46 +08:00
|
|
|
"%7.7s %7.7s %7.7s %5.5s %5.5s %4.4s %s\n", $k,
|
|
|
|
$crd[-7], $crd[-8], $res[0], "", $xyz[0], $xyz[1], $xyz[2],
|
|
|
|
"1.00", $crd[-1], "", $crd[-3]) if ($pdb_ctrl);
|
|
|
|
next if (!$water_dens); # is water added?
|
|
|
|
$net_charge += $psf[6];
|
|
|
|
my @c = split(" ", $parms[$link{$atom_types[$k]}-1]);
|
2006-09-28 03:51:49 +08:00
|
|
|
EraseWater($c[1], @xyz);
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$net_charge = int($net_charge*1e5+($net_charge>0?0.5:-0.5))/1e5;
|
2006-09-28 03:51:49 +08:00
|
|
|
AddIons() if ($water_dens);
|
|
|
|
WritePSFAtoms() if ($pdb_ctrl);
|
2016-10-06 06:13:46 +08:00
|
|
|
$k = WriteFCCAtoms($k, $res[0]+$res[1]);
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(PDB_CTRL "END\n") if ($pdb_ctrl);
|
|
|
|
printf(LAMMPS "\n");
|
|
|
|
return $k;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteParameters # print parameters
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $mode = shift(@_)+1;
|
|
|
|
my $header = ("Pair","Bond","Angle","Dihedral","Improper")[$mode];
|
2016-10-03 18:52:30 +08:00
|
|
|
my $hint = ("# lj/charmm/coul/long", "# harmonic", "# charmm", "# charmm", "# harmonic")[$mode];
|
2016-10-06 06:13:46 +08:00
|
|
|
my $n = (4, 2, 4, 4, 2)[$mode];
|
|
|
|
my $k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
printf("Info: converting ".lc($mode ? $header : "Atom")."s\n") if ($info);
|
|
|
|
if ($mode--)
|
|
|
|
{
|
|
|
|
BondedTypes($mode);
|
|
|
|
BondedParameters($mode);
|
2016-10-06 06:13:46 +08:00
|
|
|
%link = CrossLink(@types);
|
2006-09-28 03:51:49 +08:00
|
|
|
CorrectDihedralParameters() if ($mode==2);
|
2016-10-06 06:13:46 +08:00
|
|
|
@parms = Delete(1, @parms) if ($mode==3);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
return 0 if (!scalar(@parms));
|
2016-10-03 18:52:30 +08:00
|
|
|
printf(LAMMPS "%s Coeffs %s\n\n", $header, ($add ? $hint : ""));
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<scalar(@parms); ++$i)
|
|
|
|
{
|
|
|
|
if ($parms[$i] ne "")
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
foreach (split(":", $parms[$i]))
|
|
|
|
{
|
|
|
|
my @tmp = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%8d", ++$k);
|
2016-10-03 19:07:28 +08:00
|
|
|
for (my $j=0; $j<$n; ++$j) {
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS " %16.12g", $j<scalar(@tmp) ? $tmp[$j] : 0); }
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%s\n", $add ? " # ".$types[$i] : "");
|
2016-10-06 06:13:46 +08:00
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
} else { ++$k; }
|
|
|
|
}
|
|
|
|
printf(LAMMPS "\n");
|
|
|
|
return $k;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub WriteFCCBonded
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $mode = shift(@_);
|
|
|
|
my $k = shift(@_);
|
|
|
|
my $atom = $k_fcc;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return $k if (($mode>1)||!$water_dens);
|
2016-10-06 06:13:46 +08:00
|
|
|
my $type = $mode ? CreateID(HT, OT, HT) : CreateID(HT, OT);
|
|
|
|
my $id = $link{$type};
|
|
|
|
my $salt = 2**$n_water;
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $x=0; $x<$n_fcc[0]; ++$x)
|
|
|
|
{
|
|
|
|
for (my $y=0; $y<$n_fcc[1]; ++$y)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
for (my $z=0; $z<$n_fcc[2]; ++$z)
|
|
|
|
{
|
|
|
|
my @corner = ($x*$l_fcc-$L[0]/2, $y*$l_fcc-$L[1]/2,
|
|
|
|
$z*$l_fcc-$L[2]/2);
|
|
|
|
my $flags = $flags_fcc[$x][$y][$z];
|
|
|
|
my $bit = 1;
|
|
|
|
for (my $i=0; $i<scalar(@p_fcc); $i+=3)
|
|
|
|
{
|
|
|
|
if ($flags&$bit)
|
|
|
|
{
|
|
|
|
if ($flags&($bit*$salt)) { ++$atom; }
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf(LAMMPS "%8d %7d %7d %7d%s\n", ++$k, $id, $atom,
|
|
|
|
$atom+1, $add ? " # ".$type : "") if (!$mode);
|
|
|
|
printf(LAMMPS "%8d %7d %7d %7d%s\n", ++$k, $id, $atom,
|
|
|
|
$atom+2, $add ? " # ".$type : "") if (!$mode);
|
|
|
|
printf(LAMMPS "%8d %7d %7d %7d %7d%s\n", ++$k, $id, $atom+1,
|
|
|
|
$atom, $atom+2, $add ? " # ".$type : "") if ($mode);
|
|
|
|
if ($pdb_ctrl)
|
|
|
|
{
|
|
|
|
PSFWrite(2, $atom, $atom+1, $atom, $atom+2) if (!$mode);
|
|
|
|
PSFWrite(3, $atom+1, $atom, $atom+2) if ($mode);
|
|
|
|
}
|
|
|
|
$atom += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$bit *= 2;
|
|
|
|
}
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return $k;
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
sub WriteBonded # print bonded list
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $mode = shift(@_);
|
|
|
|
my $psf_id = ("!NBOND:", "!NTHETA:", "!NPHI:", "!NIMPHI:")[$mode];
|
|
|
|
my $title = ("bonds", "angles", "dihedrals", "impropers")[$mode];
|
|
|
|
my $items = (2, 3, 4, 4)[$mode];
|
|
|
|
my $n = PSFGoto($title);
|
|
|
|
my $k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
my @delta;
|
|
|
|
my @tmp;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
return 0 if ($n<1);
|
|
|
|
printf(LAMMPS "%s\n\n", ucfirst($title));
|
|
|
|
printf(PSF_CTRL "\n%8d %s %s\n", $n+($mode ? ($mode==1 ? $n_waters : 0)
|
2016-10-06 06:13:46 +08:00
|
|
|
: 2*$n_waters), $psf_id, $title) if ($pdb_ctrl);
|
|
|
|
$psf_ncols = 0 if ($pdb_ctrl);
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@parms)
|
|
|
|
{
|
|
|
|
push(@delta, $k);
|
2016-10-06 06:13:46 +08:00
|
|
|
$k += scalar(split(":"))-1 if ($_ ne "");
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
for (my $i=0; $i<$n; ++$i)
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my @bonded = PSFGet($items);
|
|
|
|
my @tmp = ();
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@bonded) { push(@tmp, $ids{$atom_types[$_]}); }
|
2016-10-06 06:13:46 +08:00
|
|
|
my $id = $link{CreateID(@tmp)}-1;
|
|
|
|
my $m = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($parms[$id] ne "")
|
|
|
|
{
|
|
|
|
foreach (split(":", $parms[$id]))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
++$m;
|
|
|
|
my @const = split(" ");
|
|
|
|
next if (($const[0]==0)&&($mode==2 ? $const[-1]==0 : 1));
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%8d %7d", ++$k, $id+$delta[$id]+$m);
|
2016-10-06 06:13:46 +08:00
|
|
|
foreach (@bonded) { printf(LAMMPS " %7d", $_); }
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%s\n", $add ? " # ".CreateID(@tmp) : "");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf(LAMMPS "%8d %7d", ++$k, $id+$delta[$id]+$m);
|
2016-10-06 06:13:46 +08:00
|
|
|
foreach (@bonded) { printf(LAMMPS " %7d", $_); }
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "%s\n", $add ? " # ".CreateID(@tmp) : "");
|
|
|
|
}
|
|
|
|
PSFWrite($items, @bonded) if ($pdb_ctrl);
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$k = WriteFCCBonded($mode, $k);
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(PSF_CTRL "\n") if ($pdb_ctrl && $psf_ncols);
|
|
|
|
printf(LAMMPS "\n");
|
|
|
|
return $k;
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub CreateCorrectedPairCoefficients
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $read = 0;
|
|
|
|
my $k = 0;
|
2006-09-28 03:51:49 +08:00
|
|
|
my %id;
|
|
|
|
my %type;
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
$coefficients = "";
|
2006-09-28 03:51:49 +08:00
|
|
|
foreach (@types) { $id{$ids{$_}} = $_; $type{$_} = ++$k; }
|
|
|
|
seek(PARAMETERS, 0, 0);
|
|
|
|
while (<PARAMETERS>)
|
|
|
|
{
|
|
|
|
chop();
|
2016-10-06 06:13:46 +08:00
|
|
|
my @cols = split(" ");
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($read&&(scalar(@cols)>3)&&
|
2016-10-06 06:13:46 +08:00
|
|
|
(substr($cols[0],0,1) ne "!")&&($cols[2] lt 'A'))
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
my $id1 = $id{$cols[0]};
|
|
|
|
my $id2 = $id{$cols[1]};
|
|
|
|
if (($id1 ne "")&&($id2 ne ""))
|
|
|
|
{
|
|
|
|
my @c = (abs($cols[2]), $cols[3]*2.0**(-1/6));
|
|
|
|
if ($type{$id2}<$type{$id1})
|
|
|
|
{
|
|
|
|
my $tmp = $id1; $id1 = $id2; $id2 = $tmp;
|
|
|
|
}
|
|
|
|
$coefficients .= ":" if ($coefficients ne "");
|
|
|
|
$coefficients .= $type{$id1}." ".$type{$id2}." ";
|
|
|
|
$coefficients .= $c[0]." ".$c[1]." ".$c[0]." ".$c[1];
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$read = 1 if ($cols[0] eq "NBFIX");
|
2006-09-28 03:51:49 +08:00
|
|
|
last if ($read&&!scalar(@cols));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2006-09-28 03:51:49 +08:00
|
|
|
sub WriteData
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
open(LAMMPS, ">$project.in"); # use .in for temporary
|
2006-09-28 03:51:49 +08:00
|
|
|
open(PDB_CTRL, ">".$project."_ctrl.pdb") if ($pdb_ctrl);
|
|
|
|
open(PSF_CTRL, ">".$project."_ctrl.psf") if ($pdb_ctrl);
|
|
|
|
WriteControlHeader() if ($pdb_ctrl);
|
|
|
|
ReadTopology();
|
|
|
|
CharacterizeBox();
|
|
|
|
SetupWater() if ($water_dens);
|
2016-10-06 06:13:46 +08:00
|
|
|
WriteBoxSize(); # body storage
|
|
|
|
@types = AtomTypes(); # atoms
|
|
|
|
@parms = AtomParameters(@types);
|
2006-09-28 03:51:49 +08:00
|
|
|
WriteMasses();
|
2016-10-06 06:13:46 +08:00
|
|
|
%link = CrossLink(@types);
|
2006-09-28 03:51:49 +08:00
|
|
|
CreateCorrectedPairCoefficients();
|
|
|
|
for (my $i=0; $i<scalar(@types); ++$i) { $types[$i] = $ids{$types[$i]}; }
|
2016-10-06 06:13:46 +08:00
|
|
|
$natom_types = WriteParameters(-1); # pairs
|
2016-10-03 08:33:20 +08:00
|
|
|
if ($#types+1 > $natom_types) {
|
|
|
|
print "Warning: $#types atom types present, but only $natom_types pair coeffs found\n";
|
|
|
|
# reset to what is found while determining the number of atom types.
|
|
|
|
$natom_types = $#types+1;
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
$natoms = WriteAtoms();
|
|
|
|
$nbond_types = WriteParameters(0); # bonds
|
|
|
|
$nbonds = WriteBonded(0);
|
|
|
|
$nangle_types = WriteParameters(1); # angles
|
|
|
|
$nangles = WriteBonded(1);
|
|
|
|
$shake = $link{CreateID(("HT", "OT", "HT"))};
|
|
|
|
$ndihedral_types = WriteParameters(2); # dihedrals
|
|
|
|
$ndihedrals = WriteBonded(2);
|
|
|
|
$nimproper_types = WriteParameters(3); # impropers
|
|
|
|
$nimpropers = WriteBonded(3);
|
|
|
|
close(LAMMPS); # close temp file
|
|
|
|
open(LAMMPS, ">$project.data"); # open data file
|
|
|
|
WriteLAMMPSHeader(); # header
|
|
|
|
open(TMP, "<$project.in"); # open temp file
|
|
|
|
while (<TMP>) { printf(LAMMPS "%s", $_); } # spool body
|
|
|
|
close(TMP); # close temp file
|
2006-09-28 03:51:49 +08:00
|
|
|
if ($pdb_ctrl)
|
|
|
|
{
|
|
|
|
#while (<PSF>) { printf(PSF_CTRL "%s", $_); }
|
|
|
|
close(PSF_CTRL); close(PDB_CTRL);
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
close(LAMMPS); # close data file
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub WriteLAMMPSInput
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
open(LAMMPS, ">$project.in"); # input file
|
|
|
|
printf(LAMMPS "# Created by $program v$version on %s", `date`);
|
|
|
|
printf(LAMMPS "# Command: %s\n\n", $cmdline);
|
|
|
|
printf(LAMMPS "units real\n"); # general
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "neigh_modify delay 2 every 1\n\n");
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "atom_style full\n"); # styles
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "bond_style harmonic\n") if ($nbond_types);
|
|
|
|
printf(LAMMPS "angle_style charmm\n") if ($nangle_types);
|
|
|
|
printf(LAMMPS "dihedral_style charmm\n") if ($ndihedral_types);
|
|
|
|
printf(LAMMPS "improper_style harmonic\n\n") if ($nimproper_types);
|
2016-09-24 06:59:43 +08:00
|
|
|
printf(LAMMPS "pair_style lj/charmm/coul/long 8 12\n");
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "pair_modify mix arithmetic\n");
|
2016-10-03 18:52:30 +08:00
|
|
|
printf(LAMMPS "kspace_style pppm 1e-6\n\n");
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-09-24 06:59:43 +08:00
|
|
|
if ($cmap) {
|
2016-10-03 18:52:30 +08:00
|
|
|
printf(LAMMPS "# Modify following line to point to the desired CMAP file\n");
|
|
|
|
printf(LAMMPS "fix cmap all cmap charmm$cmap.cmap\n");
|
2016-09-24 06:59:43 +08:00
|
|
|
printf(LAMMPS "fix_modify cmap energy yes\n");
|
2016-10-03 08:33:20 +08:00
|
|
|
printf(LAMMPS "read_data $project.data fix cmap crossterm CMAP\n\n");
|
2016-09-24 06:59:43 +08:00
|
|
|
}else{
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "read_data $project.data\n\n"); # read data
|
2016-09-24 06:59:43 +08:00
|
|
|
}
|
|
|
|
|
2016-10-06 06:13:46 +08:00
|
|
|
if ($coefficients ne "") # corrected coeffs
|
2006-09-28 03:51:49 +08:00
|
|
|
{
|
|
|
|
foreach (split(":", $coefficients))
|
|
|
|
{
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "pair_coeff %s\n", $_);
|
2006-09-28 03:51:49 +08:00
|
|
|
}
|
|
|
|
printf(LAMMPS "\n");
|
|
|
|
}
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "special_bonds charmm\n"); # invoke charmm
|
|
|
|
printf(LAMMPS "thermo 10\n"); # set thermo style
|
2016-10-03 08:33:20 +08:00
|
|
|
printf(LAMMPS "thermo_style multi\n");
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "timestep 1.0\n\n"); # 1.0 ps time step
|
|
|
|
printf(LAMMPS "minimize 0.0 0.0 50 200\n\n"); # take of the edge
|
|
|
|
printf(LAMMPS "reset_timestep 0\n");
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "fix 1 all nve\n");
|
|
|
|
printf(LAMMPS "fix 2 all shake 1e-6 500 0 m 1.0\n")
|
2016-10-06 06:13:46 +08:00
|
|
|
if ($shake eq ""); # shake all H-bonds
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "fix 2 all shake 1e-6 500 0 m 1.0 a %s\n",$shake)
|
2016-10-06 06:13:46 +08:00
|
|
|
if ($shake ne ""); # add water if present
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "velocity all create 0.0 12345678 dist uniform\n\n");
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "restart 500 $project.restart1 $project.restart2\n");
|
|
|
|
printf(LAMMPS "dump 1 all atom 100 $project.dump\n");
|
2006-09-28 03:51:49 +08:00
|
|
|
printf(LAMMPS "dump_modify 1 image yes scale yes\n\n");
|
2016-10-06 06:13:46 +08:00
|
|
|
printf(LAMMPS "thermo 100\n"); # set thermo style
|
|
|
|
printf(LAMMPS "run 1000\n"); # run for 1000 time steps
|
2006-09-28 03:51:49 +08:00
|
|
|
close(LAMMPS);
|
|
|
|
}
|
|
|
|
|
2016-10-03 08:33:20 +08:00
|
|
|
# ----------------------- DESCRIPTION: sub CharmmCmap ------------------------ #
|
|
|
|
# This subroutine add a new section "CMAP" to the LAMMPS data file, which #
|
|
|
|
# a part of the implementation of "CHARMM CMAP" (see references) in LAMMPS. #
|
|
|
|
# The section "CMAP" contains a list of dihedral ID pairs from adjecent #
|
|
|
|
# peptide backtone dihedrals whose dihedral angles are corrresponding to PHI #
|
|
|
|
# and PSI. (PHI: C--N--C_aphla_C and PSI: N--C_alpha--C--N) #
|
|
|
|
# #
|
|
|
|
# Initiated by: Xiaohu Hu (hux2@ornl.gov) #
|
|
|
|
# May 2009 #
|
|
|
|
# #
|
|
|
|
# Finalized Oct 2016 by: Robert Latour (latourr@clemson.edu), #
|
|
|
|
# David Hyde-Volpe, and Tigran Abramyan, Clemson University, #
|
|
|
|
# and Chris Lorenz (chris.lorenz@kcl.ac.uk #
|
|
|
|
# #
|
|
|
|
# References: #
|
|
|
|
# - MacKerell, A.D., Jr., Feig, M., Brooks, C.L., III, Improved Treatment of #
|
|
|
|
# Protein Backbone Conformational in Empirical Force Fields, J. Am. Chem. #
|
|
|
|
# Soc. 126(2004): 698-699. #
|
|
|
|
# - MacKerell, A.D., Jr., Feig, M., Brooks, C.L., III, Extending the Treatment #
|
|
|
|
# of Backbone Energetics in Protein Force Fields: Limitations of Gas-Phase #
|
|
|
|
# Quantum Mechnacis in Reproducing Protein Conformational Distributions in #
|
|
|
|
# Molecular Dynamics Simulations, J. Comput. Chem. 25(2004): 1400-1415. #
|
|
|
|
# ---------------------------------------------------------------------------- #
|
|
|
|
|
2016-10-03 19:07:28 +08:00
|
|
|
sub CharmmCmap
|
2016-10-03 08:33:20 +08:00
|
|
|
{
|
2016-09-24 06:59:43 +08:00
|
|
|
print "\nINITIATING CHARMM CMAP SUBROUTINE...\n\n";
|
|
|
|
|
|
|
|
# Reread and analyse $project.data
|
|
|
|
my @raw_data;
|
|
|
|
open(LAMMPS, "< $project.data") or
|
|
|
|
die "\"sub CharmmCmap()\" cannot open \"$project.data!\n";
|
|
|
|
print "Analyzing \"$project.data\"...\n\n";
|
|
|
|
@raw_data = <LAMMPS>;
|
|
|
|
close(LAMMPS);
|
|
|
|
|
|
|
|
# Locate and extract the sections "Masses" and "Atoms"
|
|
|
|
my $line_number = 0;
|
|
|
|
# Header infos, 0 by default
|
|
|
|
my $natom_types = 0;
|
|
|
|
my $natom_number = 0;
|
|
|
|
my $ndihedral_number = 0;
|
|
|
|
my $temp_string;
|
|
|
|
# splice points, 0 by default
|
|
|
|
my $splice_onset_masses = 0;
|
|
|
|
my $splice_onset_atoms = 0;
|
|
|
|
my $splice_onset_dihedrals = 0;
|
|
|
|
|
|
|
|
foreach my $line (@raw_data) {
|
|
|
|
$line_number++;
|
|
|
|
chomp($line);
|
|
|
|
# Extract useful informations from the header
|
|
|
|
if ($line =~ m/atom types/) {
|
|
|
|
($natom_types,$temp_string) = split(" ",$line);
|
|
|
|
if ($natom_types == 0) {
|
|
|
|
die "\nError: Number of atom types is 0!\n";
|
|
|
|
}
|
|
|
|
print "Total atom types: $natom_types\n";
|
|
|
|
}
|
|
|
|
if ($line =~ m/atoms/) {
|
|
|
|
($natom_number,$temp_string) = split(" ",$line);
|
|
|
|
if ($natom_number == 0) {
|
|
|
|
die "\nError: Number of atoms is 0!\n";
|
|
|
|
}
|
|
|
|
print "Total atoms: $natom_number\n";
|
|
|
|
}
|
|
|
|
if ($line =~ m/dihedrals/) {
|
|
|
|
($ndihedral_number,$temp_string) = split(" ",$line);
|
|
|
|
if ($ndihedral_number == 0) {
|
|
|
|
die "\nError: Number of dihedrals is 0\n";
|
|
|
|
}
|
|
|
|
print "Total dihedrals: $ndihedral_number\n";
|
|
|
|
}
|
|
|
|
# Locate and data from sections "Masses", "Atoms" and "Dihedrals"
|
|
|
|
if ($line =~ m/Masses/) {
|
|
|
|
$splice_onset_masses = $line_number + 1;
|
|
|
|
if ($splice_onset_masses-1 == 0) {
|
|
|
|
die "\nError: Can not find the section \"Masses\"\n";
|
|
|
|
}
|
|
|
|
print "Section \"Masses\" found: line $splice_onset_masses\n";
|
|
|
|
}
|
|
|
|
if ($line =~ m/Atoms/) {
|
|
|
|
$splice_onset_atoms = $line_number +1;
|
|
|
|
if ($splice_onset_atoms-1 == 0) {
|
|
|
|
die "\nError: Can not find the section \"Atoms\"\n";
|
|
|
|
}
|
|
|
|
print "Section \"Atoms\" found: line $splice_onset_atoms\n";
|
|
|
|
}
|
|
|
|
if ($line =~ m/Dihedrals/) {
|
|
|
|
$splice_onset_dihedrals = $line_number + 1;
|
|
|
|
if ($splice_onset_dihedrals-1 == 0) {
|
|
|
|
die "\nError: Can not find the section \"Dihedrals\"\n";
|
|
|
|
}
|
|
|
|
print "Section \"Dihedrals\" found: line $splice_onset_dihedrals\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
print "\nGenerating PHI/PSI dihedral pair list...\n\n";
|
|
|
|
|
|
|
|
my @temp1 = @raw_data;
|
|
|
|
my @temp2 = @raw_data;
|
|
|
|
my @temp3 = @raw_data;
|
|
|
|
|
|
|
|
# Extract the section "Masses", "Atoms" and "Dihedrals"
|
|
|
|
my @temp_masses_data = splice(@temp1,$splice_onset_masses,$natom_types);
|
|
|
|
my @temp_atoms_data = splice(@temp2,$splice_onset_atoms,$natom_number);
|
|
|
|
my @temp_dihedrals_data = splice(@temp3,$splice_onset_dihedrals,$ndihedral_number);
|
|
|
|
|
|
|
|
# Store @temp_masses_dat into a matrix
|
|
|
|
my @masses_matrix;
|
|
|
|
my $atom_type;
|
|
|
|
my $mass;
|
|
|
|
for (@temp_masses_data) {
|
|
|
|
($atom_type, $mass) = split(" ");
|
|
|
|
push(@masses_matrix,[$atom_type,$mass]);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Store @temp_atoms_data into a matrix
|
|
|
|
my @atoms_matrix;
|
|
|
|
my $atom_ID;
|
|
|
|
my $molecule_ID;
|
|
|
|
my $atype;
|
|
|
|
my $charge;
|
|
|
|
my $atom_x_coor;
|
|
|
|
my $atom_y_coor;
|
|
|
|
my $atom_z_coor;
|
|
|
|
for (@temp_atoms_data) {
|
|
|
|
($atom_ID,$molecule_ID,$atype,$charge,$atom_x_coor,$atom_y_coor,$atom_z_coor) = split(" ");
|
|
|
|
push(@atoms_matrix,
|
|
|
|
[$atom_ID,$molecule_ID,$atype,$charge,$atom_x_coor,$atom_y_coor,$atom_z_coor]);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Store @temp_dihedrals_data into a matrix
|
|
|
|
my @dihedrals_matrix;
|
|
|
|
my $dihedral_ID;
|
|
|
|
my $dihedtal_type;
|
|
|
|
my $dihe_atom1;
|
|
|
|
my $dihe_atom2;
|
|
|
|
my $dihe_atom3;
|
|
|
|
my $dihe_atom4;
|
|
|
|
for (@temp_dihedrals_data) {
|
|
|
|
($dihedral_ID,$dihedral_type,$dihe_atom1,$dihe_atom2,$dihe_atom3,$dihe_atom4) = split(" ");
|
|
|
|
push(@dihedrals_matrix,
|
|
|
|
[$dihedral_ID,$dihedral_type,$dihe_atom1,$dihe_atom2,$dihe_atom3,$dihe_atom4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
# Find out and extract the peptide backbone dihedrals
|
|
|
|
#
|
|
|
|
# Definitions of peptide backbone dihedrals
|
|
|
|
#
|
|
|
|
# For dihedral angle PHI: C--N--CA--C
|
|
|
|
# For dihedral angle PSI: N--CA--C--N
|
|
|
|
#
|
|
|
|
# ---------------------------------------------------------
|
|
|
|
# atom | mass |partial charge| amino-acid
|
|
|
|
# ---------------------------------------------------------
|
|
|
|
# C | 12.011 | 0.51 | all except GLY and PRO
|
|
|
|
# N | 14.007 | -0.29 | PRO
|
|
|
|
# N | 14.007 | -0.47 | all except PRO
|
|
|
|
# CA | 12.011 | 0.07 | all except GLY and PRO
|
|
|
|
# CA | 12.011 | -0.02 | GLY
|
|
|
|
# CA | 12.011 | 0.02 | PRO
|
|
|
|
# ---------------------------------------------------------
|
|
|
|
#
|
|
|
|
# Peptide backbone
|
|
|
|
# ...
|
|
|
|
# /
|
|
|
|
# O=C
|
|
|
|
# \
|
|
|
|
# N-H
|
|
|
|
# / -----> PHI (C-N-CA-C)
|
|
|
|
# H-CA-R
|
|
|
|
# \ -----> PSI (N-CA-C-N)
|
|
|
|
# C=O
|
|
|
|
# /
|
|
|
|
# H-N
|
|
|
|
# \
|
|
|
|
# ...
|
|
|
|
#
|
|
|
|
# Criteria to be a PHI/PSI dihedral pair:
|
2016-10-03 19:07:28 +08:00
|
|
|
# 1. Atoms have to match with the mass/charge constellations as
|
2016-09-24 06:59:43 +08:00
|
|
|
# defined above.
|
|
|
|
# 2. The atoms N--CA--C needs to be covalently bonded with each
|
|
|
|
# other.
|
|
|
|
|
|
|
|
# Find which types do C, N and CA correspond to and store them
|
|
|
|
# in lists
|
|
|
|
my $mass_carbon = 12.011;
|
|
|
|
my $mass_nitrogen = 14.007;
|
|
|
|
|
|
|
|
my @carbon_list;
|
|
|
|
my @nitrogen_list;
|
|
|
|
my $carbon_counter = 0;
|
|
|
|
my $nitrogen_counter = 0;
|
|
|
|
|
|
|
|
for (my $i = 0; $i < $natom_types; $i++) {
|
|
|
|
if (${$masses_matrix[$i]}[1] == $mass_carbon) {
|
|
|
|
push(@carbon_list,${$masses_matrix[$i]}[0]);
|
|
|
|
$carbon_counter++;
|
|
|
|
}
|
|
|
|
if (${$masses_matrix[$i]}[1] == $mass_nitrogen) {
|
|
|
|
push(@nitrogen_list,${$masses_matrix[$i]}[0]);
|
|
|
|
$nitrogen_counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Quit if no carbons or nitrogens
|
|
|
|
if ($carbon_counter == 0 or $nitrogen_counter == 0) {
|
|
|
|
if ($carbon_counter == 0) {
|
|
|
|
print "No carbon atoms exist in the system\n";
|
|
|
|
}
|
|
|
|
if ($nitrogen_counter == 0) {
|
|
|
|
print "No nitrogen atoms exist in the system\n";
|
|
|
|
}
|
|
|
|
print "CMAP usage impossible\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
print "Carbon atom type/s: @carbon_list\n";
|
|
|
|
print "Nitrogen atom type/s: @nitrogen_list\n";
|
|
|
|
|
|
|
|
# Determine the atom types of C, CA and N
|
|
|
|
|
|
|
|
# Charges of the backbone atoms
|
|
|
|
my $charge_C = 0.51;
|
|
|
|
my $charge_CA = 0.07;
|
|
|
|
my $charge_N = -0.47;
|
|
|
|
|
|
|
|
# Special setting for PRO
|
|
|
|
my $charge_N_PRO = -0.29;
|
|
|
|
my $charge_CA_PRO = 0.02;
|
|
|
|
|
|
|
|
# Special setting for GLY
|
|
|
|
my $charge_CA_GLY = -0.02;
|
|
|
|
|
|
|
|
# Peptide backbone atom types
|
|
|
|
my $C_type;
|
|
|
|
my $CA_type;
|
|
|
|
my $CA_GLY_type;
|
|
|
|
my $CA_PRO_type;
|
|
|
|
my $N_type;
|
|
|
|
my $N_PRO_type;
|
|
|
|
|
|
|
|
my $C_counter = 0;
|
|
|
|
my $CA_counter = 0;
|
|
|
|
my $CA_GLY_counter = 0;
|
|
|
|
my $CA_PRO_counter = 0;
|
|
|
|
my $N_counter = 0;
|
|
|
|
my $N_PRO_counter = 0;
|
|
|
|
|
|
|
|
my $C_flag = 0;
|
2016-10-03 19:07:28 +08:00
|
|
|
|
2016-09-24 06:59:43 +08:00
|
|
|
for (my $i = 0; $i <= $natom_number; $i++) {
|
|
|
|
my $cur_type = ${$atoms_matrix[$i]}[2];
|
|
|
|
my $cur_charge = ${$atoms_matrix[$i]}[3];
|
|
|
|
for (my $j = 0; $j <= $#carbon_list; $j++) {
|
|
|
|
if ($cur_type == $carbon_list[$j]) {
|
|
|
|
$C_flag = 1;
|
|
|
|
if ($cur_charge == $charge_C) {
|
|
|
|
$C_type = $cur_type;
|
|
|
|
$C_counter++;
|
|
|
|
}
|
|
|
|
if ($cur_charge == $charge_CA) {
|
|
|
|
$CA_type = $cur_type;
|
|
|
|
$CA_counter++;
|
|
|
|
}
|
|
|
|
if ($cur_charge == $charge_CA_GLY) {
|
|
|
|
$CA_GLY_type = $cur_type;
|
|
|
|
$CA_GLY_counter++;
|
|
|
|
}
|
|
|
|
if ($cur_charge == $charge_CA_PRO) {
|
|
|
|
$CA_PRO_type = $cur_type;
|
|
|
|
$CA_PRO_counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($C_flag == 0) {
|
|
|
|
for (my $k = 0; $k <= $#nitrogen_list; $k++) {
|
|
|
|
if ($cur_type == $nitrogen_list[$k]) {
|
|
|
|
if ($cur_charge == $charge_N) {
|
|
|
|
$N_type = $cur_type;
|
|
|
|
$N_counter++;
|
|
|
|
}
|
|
|
|
if ($cur_charge == $charge_N_PRO) {
|
|
|
|
$N_PRO_type = $cur_type;
|
|
|
|
$N_PRO_counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$C_flag = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Quit if one of the atom types dosen't exist
|
2016-10-03 19:07:28 +08:00
|
|
|
if ( $C_counter == 0 or
|
|
|
|
($CA_counter == 0 and $CA_GLY_counter == 0 and $CA_PRO_counter == 0) or
|
2016-09-24 06:59:43 +08:00
|
|
|
($N_counter == 0 and $N_PRO_counter == 0) ) {
|
|
|
|
if ($C_counter == 0) {
|
|
|
|
print "\nCannot find the peptide backbone C atom type\n";
|
|
|
|
}
|
|
|
|
if ($CA_counter == 0 and $CA_GLY_counter == 0 and $CA_PRO_counter == 0) {
|
|
|
|
print "\nCannot find the peptide backbone C-alpha atom type\n";
|
|
|
|
}
|
|
|
|
if ($N_counter == 0 and $N_PRO_counter == 0) {
|
|
|
|
print "\nCannot find the peptide backbone N atom type\n";
|
|
|
|
}
|
|
|
|
print "CMAP usage impossible\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
print "Peptide backbone carbon type: $C_type\n";
|
|
|
|
print "Alpha-carbon type: $CA_type\n" if ($CA_counter > 0);
|
|
|
|
print "Alpha-carbon type (GLY): $CA_GLY_type\n" if ($CA_GLY_counter > 0);
|
|
|
|
print "Alpha-carbon type (PRO): $CA_PRO_type\n" if ($CA_PRO_counter > 0);
|
|
|
|
print "Peptide backbone nitrogen type: $N_type\n" if ($N_counter >0);
|
|
|
|
print "Peptide backbone nitrogen type (PRO): $N_PRO_type\n" if ($N_PRO_counter > 0);
|
|
|
|
|
|
|
|
# Loop through the dihedral list to find the PHI- and PSI-dihedrals
|
|
|
|
my @PHI_dihedrals;
|
|
|
|
my @PSI_dihedrals;
|
|
|
|
my $PHI_counter = 0;
|
|
|
|
my $PSI_counter = 0;
|
|
|
|
|
|
|
|
for (my $i = 0; $i < $ndihedral_number; $i++) {
|
|
|
|
my $cur_dihe_ID = ${dihedrals_matrix[$i]}[0];
|
|
|
|
my $cur_atom1_type = ${atoms_matrix[${dihedrals_matrix[$i]}[2]-1]}[2];
|
|
|
|
my $cur_atom2_type = ${atoms_matrix[${dihedrals_matrix[$i]}[3]-1]}[2];
|
|
|
|
my $cur_atom3_type = ${atoms_matrix[${dihedrals_matrix[$i]}[4]-1]}[2];
|
|
|
|
my $cur_atom4_type = ${atoms_matrix[${dihedrals_matrix[$i]}[5]-1]}[2];
|
|
|
|
|
|
|
|
next if (${dihedrals_matrix[$i]}[2] == ${dihedrals_matrix[$i-1]}[2] and
|
2016-10-03 19:07:28 +08:00
|
|
|
${dihedrals_matrix[$i]}[3] == ${dihedrals_matrix[$i-1]}[3] and
|
2016-09-24 06:59:43 +08:00
|
|
|
${dihedrals_matrix[$i]}[4] == ${dihedrals_matrix[$i-1]}[4] and
|
|
|
|
${dihedrals_matrix[$i]}[5] == ${dihedrals_matrix[$i-1]}[5]);
|
|
|
|
|
|
|
|
# Determine PHI-dihedrals; If C-CA-N-C or C-N-CA-C, then save it in a list
|
|
|
|
if ($cur_atom1_type == $C_type and $cur_atom4_type == $C_type) {
|
2016-10-03 19:07:28 +08:00
|
|
|
if ( ( ($cur_atom2_type == $CA_type or
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom2_type == $CA_GLY_type or
|
2016-10-03 19:07:28 +08:00
|
|
|
$cur_atom2_type == $CA_PRO_type) and
|
2016-09-24 06:59:43 +08:00
|
|
|
($cur_atom3_type == $N_type or
|
2016-10-03 19:07:28 +08:00
|
|
|
$cur_atom3_type == $N_PRO_type) ) or
|
|
|
|
( ($cur_atom3_type == $CA_type or
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom3_type == $CA_GLY_type or
|
2016-10-03 19:07:28 +08:00
|
|
|
$cur_atom3_type == $CA_PRO_type) and
|
|
|
|
($cur_atom2_type == $N_type or
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom2_type == $N_PRO_type) ) ) {
|
|
|
|
push (@PHI_dihedrals,$cur_dihe_ID);
|
|
|
|
$PHI_counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Determin PSI-dihedrals; If N-CA-C-N or N-C-CA-N (N can be both normal N or N proline),
|
|
|
|
# then save it in a list
|
2016-10-03 19:07:28 +08:00
|
|
|
if ( ($cur_atom1_type == $N_type and $cur_atom4_type == $N_type) or
|
2016-09-24 06:59:43 +08:00
|
|
|
($cur_atom4_type == $N_PRO_type and $cur_atom1_type == $N_PRO_type) or
|
|
|
|
($cur_atom1_type == $N_type and $cur_atom4_type == $N_PRO_type) or
|
|
|
|
($cur_atom4_type == $N_type and $cur_atom1_type == $N_PRO_type) ) {
|
2016-10-03 19:07:28 +08:00
|
|
|
if ( ( ($cur_atom2_type == $CA_type or
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom2_type == $CA_GLY_type or
|
2016-10-03 19:07:28 +08:00
|
|
|
$cur_atom2_type == $CA_PRO_type) and
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom3_type == $C_type) or
|
2016-10-03 19:07:28 +08:00
|
|
|
( ($cur_atom3_type == $CA_type or
|
|
|
|
$cur_atom3_type == $CA_GLY_type or
|
|
|
|
$cur_atom3_type == $CA_PRO_type) and
|
2016-09-24 06:59:43 +08:00
|
|
|
$cur_atom2_type == $C_type) ) {
|
|
|
|
push (@PSI_dihedrals,$cur_dihe_ID);
|
|
|
|
$PSI_counter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Quit if no PHI or PSI dihedrals
|
|
|
|
if ($PHI_counter == 0 or $PSI_counter ==0) {
|
|
|
|
if ($PHI_counter == 0) {
|
|
|
|
print "Can not find the PHI backbone dihedrals\n";
|
|
|
|
}
|
|
|
|
if ($PSI_counter ==0) {
|
|
|
|
print "Can not find the PSI backbone dihedrals\n";
|
|
|
|
}
|
|
|
|
print "CMAP usage impossible\n";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Construct the PHI/PSI diheral pair list
|
|
|
|
#
|
|
|
|
# The algorithm:
|
|
|
|
# _____
|
2016-10-03 19:07:28 +08:00
|
|
|
# | |
|
2016-09-24 06:59:43 +08:00
|
|
|
# 1--2--3--4 PHI-dihedral
|
|
|
|
# 4--3--2--1
|
|
|
|
# --C--N-CA--C--N-- Peptide backbone
|
|
|
|
# 1--2--3--4
|
|
|
|
# 4--3--2--1 PSI-dihedral
|
|
|
|
# |_____|
|
|
|
|
#
|
|
|
|
# For a certain PHI dihedral, following conditions have to be met:
|
|
|
|
#
|
|
|
|
# PHI PSI
|
|
|
|
# If (2--3--4) = (1--2--3)
|
|
|
|
# or
|
|
|
|
# if (2--3--4) = (4--3--2)
|
|
|
|
# or
|
|
|
|
# if (3--2--1) = (1--2--3)
|
2016-10-03 19:07:28 +08:00
|
|
|
# or
|
2016-09-24 06:59:43 +08:00
|
|
|
# if (3--2--1) = (4--3--2),
|
|
|
|
#
|
|
|
|
# then these 2 dihedrals are a PHI/PSI pair. If a pair is found, the
|
|
|
|
# dihedral IDs will be stored in "@PHI_PSI_matrix".
|
|
|
|
|
|
|
|
my @PHI_PSI_matrix;
|
|
|
|
my $crossterm_CA_charge;
|
|
|
|
my $crossterm_type;
|
|
|
|
my $crossterm_counter = 0;
|
|
|
|
my $crossterm_type1_flag = 0;
|
|
|
|
my $crossterm_type2_flag = 0;
|
|
|
|
my $crossterm_type3_flag = 0;
|
|
|
|
my $crossterm_type4_flag = 0;
|
|
|
|
my $crossterm_type5_flag = 0;
|
|
|
|
my $crossterm_type6_flag = 0;
|
|
|
|
|
|
|
|
for (my $i = 0; $i <= $#PHI_dihedrals; $i++) {
|
|
|
|
my $cur_PHI_dihe = ${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[0];
|
|
|
|
my $phi1 = ${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[2];
|
|
|
|
my $phi2 = ${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[3];
|
|
|
|
my $phi3 = ${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[4];
|
|
|
|
my $phi4 = ${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[5];
|
|
|
|
for (my $j = 0; $j <= $#PSI_dihedrals; $j++) {
|
|
|
|
my $cur_PSI_dihe = ${dihedrals_matrix[$PSI_dihedrals[$j]-1]}[0];
|
|
|
|
my $psi1 = ${dihedrals_matrix[$PSI_dihedrals[$j]-1]}[2];
|
|
|
|
my $psi2 = ${dihedrals_matrix[$PSI_dihedrals[$j]-1]}[3];
|
|
|
|
my $psi3 = ${dihedrals_matrix[$PSI_dihedrals[$j]-1]}[4];
|
|
|
|
my $psi4 = ${dihedrals_matrix[$PSI_dihedrals[$j]-1]}[5];
|
|
|
|
if ( ($phi2 == $psi1 and $phi3 == $psi2 and $phi4 == $psi3) or
|
|
|
|
($phi2 == $psi4 and $phi3 == $psi3 and $phi4 == $psi2) or
|
|
|
|
($phi3 == $psi1 and $phi2 == $psi2 and $phi1 == $psi3) or
|
|
|
|
($phi3 == $psi4 and $phi2 == $psi3 and $phi1 == $psi2) ) {
|
|
|
|
|
|
|
|
# Find out to which amino acid the cross-term belongs
|
|
|
|
|
|
|
|
if ($phi3 == $psi2 or $phi3 == $psi3) {
|
|
|
|
$crossterm_CA_charge = ${atoms_matrix[${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[4]-1]}[3];
|
|
|
|
}
|
|
|
|
if ($phi2 == $psi2 or $phi2 == $psi3) {
|
|
|
|
$crossterm_CA_charge = ${atoms_matrix[${dihedrals_matrix[$PHI_dihedrals[$i]-1]}[3]-1]}[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
# Def. the type of the crossterm per cmap.data file; If C_alpha of the crossterm is
|
|
|
|
# - ALA type, then $crossterm_type = 1;
|
|
|
|
# - ALA-PRO (ALA is the current AA), then $crossterm_type = 2;
|
|
|
|
# - PRO type, then $crossterm_type = 3;
|
|
|
|
# - PRO-PRO (First PRO is the current AA), then $crossterm_type = 4;
|
|
|
|
# - GLY type, then $crossterm_type = 5;
|
|
|
|
# - GLY-PRO (GLY is the current AA), then $crossterm_type = 6;
|
|
|
|
|
|
|
|
if ($crossterm_CA_charge == $charge_CA) { $crossterm_type = 1; $crossterm_type1_flag = 1; }
|
|
|
|
if ($crossterm_CA_charge == $charge_CA_GLY) { $crossterm_type = 5; $crossterm_type5_flag = 1; }
|
2016-10-03 19:07:28 +08:00
|
|
|
if ($crossterm_CA_charge == $charge_CA_PRO) {
|
2016-09-24 06:59:43 +08:00
|
|
|
$crossterm_type = 3; $crossterm_type3_flag = 1;
|
|
|
|
# Checking the last crossterm, re-assign the last crossterm type if needed
|
|
|
|
if ($crossterm_counter-1 >= 0 and $PHI_PSI_matrix[$crossterm_counter-1][0] == 1) {
|
|
|
|
$PHI_PSI_matrix[$crossterm_counter-1][0] = 2;
|
|
|
|
$crossterm_type2_flag = 1;
|
|
|
|
}
|
|
|
|
if ($crossterm_counter-1 >= 0 and $PHI_PSI_matrix[$crossterm_counter-1][0] == 3) {
|
|
|
|
$PHI_PSI_matrix[$crossterm_counter-1][0] = 4;
|
|
|
|
$crossterm_type4_flag = 1;
|
|
|
|
}
|
|
|
|
if ($crossterm_counter-1 >= 0 and $PHI_PSI_matrix[$crossterm_counter-1][0] == 5) {
|
|
|
|
$PHI_PSI_matrix[$crossterm_counter-1][0] = 6;
|
|
|
|
$crossterm_type6_flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
push(@PHI_PSI_matrix,[$crossterm_type,$phi1,$phi2,$phi3,$phi4,$psi4]);
|
|
|
|
$crossterm_counter++;
|
|
|
|
|
|
|
|
$crossterm_CA_charge = 0;
|
|
|
|
$crossterm_type = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# Check whether the amino acid at the C-terminus is a PRO or not. If yes, the type of the last crossterm
|
|
|
|
# should be set to its X-PRO form instead of X, where X is ALA, PRO, or GLY. X-PRO form = X type + 1.
|
|
|
|
|
|
|
|
my @pdb_data;
|
|
|
|
open(PDB,"< $project.pdb")
|
|
|
|
or die "WARNING: Cannot open file \"$project.pdb\"! (required if the -cmap option is used)\n";
|
|
|
|
@pdb_data = <PDB>;
|
|
|
|
close(PDB);
|
|
|
|
|
|
|
|
my @ter_line;
|
|
|
|
my $ter_AA_type = 0;
|
|
|
|
my $ter_flag = 0;
|
|
|
|
foreach $line (@pdb_data) {
|
|
|
|
if ($line =~ m/TER/) {
|
|
|
|
@ter_line = split(" ",$line);
|
|
|
|
$ter_AA_type = $ter_line[2];
|
|
|
|
print "Terminal amino acid type is: $ter_AA_type\n";
|
|
|
|
$ter_flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ($ter_flag == 0) {
|
|
|
|
print "\n*** ERROR IN THE PDB FILE: ***\n";
|
|
|
|
print "In order for the CMAP section to be generated, the pdb file must \n";
|
|
|
|
print "identify the C-terminus amino acid in the file with 'TER'. \n";
|
|
|
|
print "This line is missing from the pdb file that was used.\n";
|
|
|
|
print "To correct this problem, open the pdb file in an editor,\n";
|
|
|
|
print "find the last atom of the last amino acid residue in the peptide\n";
|
|
|
|
print "chain and insert the following line immediately after that atom:\n";
|
|
|
|
print " 'TER <#1> <RES> <#2>' \n";
|
|
|
|
print "where '<#1> is the next atom number, <RES> is the three letter amino\n";
|
|
|
|
print "acid abbreviation for that amino acid, and <#2> is the molecule number\n";
|
|
|
|
print "of the terminal amino acid residue.\n\n";
|
|
|
|
print "For example, if the last atom of the last amino acid in the peptide\n";
|
2016-10-03 19:07:28 +08:00
|
|
|
print "sequence is listed in the pdb file as:\n\n";
|
2016-09-24 06:59:43 +08:00
|
|
|
print " 'ATOM 853 O GLU P 56 12.089 -1.695 -6.543 1.00 1.03 PROA'\n\n";
|
|
|
|
print "you would insert the following line after it:\n\n";
|
|
|
|
print " 'TER 854 GLU 56'\n\n";
|
|
|
|
print "If any additional atoms are listed in the pdb file (e.g., water, ions)\n";
|
|
|
|
print "after this terminal amino acid residue, their atom numbers and\n";
|
|
|
|
print "molecule numbers must be incremented by 1 to account for the new line\n";
|
|
|
|
print "that was inserted.\n\n";
|
|
|
|
die "Error: No terminating atom designated in pdb file! See above note to correct problem.\n\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($ter_AA_type eq PRO) {
|
|
|
|
$PHI_PSI_matrix[$crossterm_counter-1][0] = $PHI_PSI_matrix[$crossterm_counter-1][0]+1;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Print out PHI/PSI diheral pair list
|
|
|
|
my $pair_counter = 0;
|
|
|
|
# Don't presently use $ncrosstermtypes but have this available if wish to print it out
|
2016-10-03 19:07:28 +08:00
|
|
|
my $ncrosstermtypes = $crossterm_type1_flag + $crossterm_type2_flag + $crossterm_type3_flag +
|
2016-09-24 06:59:43 +08:00
|
|
|
$crossterm_type4_flag + $crossterm_type5_flag + $crossterm_type6_flag;
|
|
|
|
print "\nWriting \"$project.data\" with section \"CMAP crossterms\" added at the end.\n";
|
|
|
|
|
|
|
|
# Writing the new lammps data file
|
|
|
|
open(REWRITE,"> $project.data")
|
|
|
|
or die "Cannot write file \"$project.data\"!\n";
|
|
|
|
foreach $line (@raw_data) {
|
|
|
|
printf(REWRITE "$line\n");
|
|
|
|
if ($line =~ m/impropers/) {
|
|
|
|
printf(REWRITE "%12d crossterms\n", $crossterm_counter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf(REWRITE "CMAP\n\n");
|
|
|
|
|
|
|
|
my $ref_line;
|
|
|
|
my $column;
|
|
|
|
foreach $ref_line (@PHI_PSI_matrix) {
|
|
|
|
$pair_counter++;
|
|
|
|
printf(REWRITE "%8d",$pair_counter);
|
|
|
|
foreach $column (@$ref_line) {
|
|
|
|
printf(REWRITE " %7d",$column);
|
|
|
|
}
|
|
|
|
printf(REWRITE "\n");
|
|
|
|
}
|
|
|
|
close(REWRITE);
|
|
|
|
print "\nDone!\n\n";
|
|
|
|
}
|
2006-09-28 03:51:49 +08:00
|
|
|
|
|
|
|
# main
|
|
|
|
|
|
|
|
Initialize();
|
|
|
|
WriteData();
|
|
|
|
WriteLAMMPSInput();
|
|
|
|
printf("Info: conversion complete\n\n") if ($info);
|
2016-09-24 06:59:43 +08:00
|
|
|
CharmmCmap() if ($cmap);
|