package LAMMPS; use Exporter; use Crystal::MD; use Crystal::ForceField; @ISA = qw(Exporter ForceField MD); #公開したいサブルーチン @EXPORT = qw(); use strict; use File::Basename; use ProgVars; use Crystal::XCrySDen; use Sci qw($torad $e0 $a0 $e $pi log10 erfc); use Sci::Science; #=============================================== # 大域変数 #=============================================== my $HOME = $ENV{'HOME'}; my $ProgramDir = ProgVars::ProgramDir(); my $LAMMPSPerlDir = ProgVars::LAMMPSPerlDir(); my $TemplateDir = Deps::MakePath($LAMMPSPerlDir, 'Template', 0); my $LAMMPSDatabaseDir = Deps::MakePath($LAMMPSPerlDir, 'Potentials', 0); my $GULPDir = ProgVars::GULPDir(); my $GULPLibDir = ProgVars::GULPLibDir(); my @PotentialLibs = ForceField::PotentialLibs(); #=============================================== # コンストラクタ、デストラクタ #=============================================== sub new { my ($module) = @_; my $this = {}; bless $this; $this->{pLibraryLines} = []; return $this; } sub DESTROY { my $this = shift; } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub CheckFileType { my ($path) = @_; my ($drive, $dir, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($path); if($filename =~ /\.dens$/i) { return "GULP DENS file"; } if($filename =~ /\.disp$/i) { return "GULP DISP file"; } return undef; } sub ReadFiles { my ($this, $filename, $TargetData) = @_; $this->ClearAll(); my $FileType = $this->{'FileType'} = LAMMPS::CheckFileType($filename); $this->SetFileName($filename); if($FileType eq "GULP DENS file") { return $this->ReadDENS($filename, $TargetData); } if($FileType eq "GULP DISP file") { return $this->ReadDISP($filename); } return undef; } #=============================================== # 変数取得関数 #=============================================== sub SetSampleName { my ($this, $name) = @_; return $this->{'SampleName'} = $name; } sub SampleName { my ($this) = @_; return $this->{'SampleName'}; } #=============================================== # 一般関数 #=============================================== sub SetUseShellModelForCation { my ($this,$val) = @_; return $this->{'UseShellModelForCation'} = $val; } sub UseShellModelForCation { my ($this) = @_; return $this->{'UseShellModelForCation'}; } sub SetUseShellModelForAnion { my ($this,$val) = @_; return $this->{'UseShellModelForAnion'} = $val; } sub UseShellModelForAnion { my ($this) = @_; return $this->{'UseShellModelForAnion'}; } sub ReadSpecies { my ($this, $atom, $cstype) = @_; #print "cs=$atom, $cstype\n"; return (undef, undef, undef) if($cstype eq 'undefined'); my $GULPLibaryPath = $this->LibraryPath(); #print "lib: $GULPLibaryPath\n"; if(!open(IN, "<$GULPLibaryPath")) { print "Error in LAMMPS::ReadBuckinghamPotential: Can not read [$GULPLibaryPath]\n"; return (); } while() { last if($_ =~ /^\s*species/i); } #Read species (ionic charges) my ($CoreCharge, $ShellCharge); while() { my $line = $_; chomp($line); #print "l:$line\n"; if($line =~ /^$atom\s+core\s+(\S+)/i) { $CoreCharge = $1; $this->AddPotentialLines($line); } if($line =~ /^$atom\s+shel\s+(\S+)/i) { $ShellCharge = $1; $this->AddPotentialLines($line); } last if($line =~ /^\s*buck/i); } close(IN); #print "Z: $CoreCharge, $ShellCharge\n"; return ($CoreCharge+$ShellCharge, $CoreCharge, $ShellCharge); } sub ReadSpring { my ($this, $atom, $cstype) = @_; my $GULPLibaryPath = $this->LibraryPath(); return ('', '') if($cstype eq 'core' or $cstype eq 'undefined'); if(!open(IN, "<$GULPLibaryPath")) { print "Error in LAMMPS::ReadBuckinghamPotential: Can not read [$GULPLibaryPath]\n"; return (); } my $Spring; while() { last if($_ =~ /^\s*spring/i); } #Read spring parameters while() { my $line = $_; chomp($line); if($line =~ /^$atom\s/i) { $Spring = $line; $this->AddPotentialLines($line); } } close(IN); unless($Spring =~ /^(\S+)\s+(\S+)\s+(\S+)/) { $Spring = "$Spring 0" if($Spring ne ''); } return $Spring; } sub SX1toBMH { my ($this, $ai, $bi, $ci, $aj, $bj, $cj) = @_; # Born-Mayer Potential CONSTANT (J/A) my $f0 = 6.947700141e-21; # A(I,J)=F0*B(I,J)*DEXP((PA(I)+PA(J))/B(I,J)) return (0.0, 0.1, 0.0) if($bi == 0.0 or $bj == 0.0); my $bij = $bi + $bj; my $Cij = $ci + $cj; my $Aij = $f0 * $bij * exp(($ai + $aj) / $bij) / $e; #print "aa: $Aij = $f0 * $bij * exp(($ai + $aj) / $bij) / $e\n"; return ($Aij, $bij, $Cij); } sub ReadSX1 { my ($this, $atom, $cstype) = @_; my $GULPLibaryPath = $this->LibraryPath(); # return ('', '') if($cstype eq 'shell' or $cstype eq 'undefined'); my $in = JFile->new($GULPLibaryPath, 'r'); if(!$in) { print "Error in LAMMPS::ReadBuckinghamPotential: Can not read [$GULPLibaryPath]\n"; return {}; } my %hash; $in->SkipTo("SX-1"); while(1) { my $line = $in->ReadLine(); last if(!defined $line); #print "l:$line"; my @a = Utils::Split("\\s+", $line); $a[0] =~ s/[0-9+\-_].*$//; if($a[0] eq $atom) { %hash = ( AtomName => $a[0], Mass => $a[1], Charge => $a[2], ai => $a[3], bi => $a[4], ci => $a[5], ARAD => $a[6], line => $line, ); $this->AddPotentialLines($line); last; } } $in->Close(); return \%hash; } sub ReadBuckinghamPotential { my ($this, $atom1, $atom2, $cstype1, $cstype2) = @_; my $GULPLibaryPath = $this->LibraryPath(); #print "read [$GULPLibaryPath] for $atom1 - $atom2\n"; my $pSX1Hash1 = $this->ReadSX1($atom1, $cstype1); my $pSX1Hash2 = $this->ReadSX1($atom2, $cstype1); #print "$pSX1Hash1, $pSX1Hash2\n"; #print "$atom1: $pSX1Hash1->{Charge}, $pSX1Hash1->{ai}, $pSX1Hash1->{bi}\n"; #print "$atom2: $pSX1Hash2->{Charge}, $pSX1Hash2->{ai}, $pSX1Hash2->{bi}\n"; if(defined $pSX1Hash1->{ai} and defined $pSX1Hash2->{ai}) { my ($Aij, $bij, $Cij) = $this->SX1toBMH( $pSX1Hash1->{ai}, $pSX1Hash1->{bi}, $pSX1Hash1->{ci}, $pSX1Hash2->{ai}, $pSX1Hash2->{bi}, $pSX1Hash2->{ci} ); #print " return ($pSX1Hash1->{Charge}, $pSX1Hash2->{Charge}, $Aij, $bij, $Cij)\n"; return ($pSX1Hash1->{Charge}, $pSX1Hash2->{Charge}, $Aij, $bij, $Cij); } my ($Charge1, $CoreCharge1, $ShellCharge1) = $this->ReadSpecies($atom1, $cstype1); my ($Charge2, $CoreCharge2, $ShellCharge2) = $this->ReadSpecies($atom2, $cstype2); my $Spring1 = $this->ReadSpring($atom1, $cstype1); my $Spring2 = $this->ReadSpring($atom2, $cstype2); #print "A1: $atom1 = $Charge1, $CoreCharge1, $ShellCharge1\n"; #print "A2: $atom2 = $Charge2, $CoreCharge2, $ShellCharge2\n"; my $in = JFile->new($GULPLibaryPath, 'r'); if(!$in) { print "Error in LAMMPS::ReadBuckinghamPotential: Can not read [$GULPLibaryPath]\n"; return (); } $in->SkipTo("\\s*buck"); #Read buckingham two body parameters while(1) { my $line = $in->ReadLine(); last if(!defined $line); if($line =~ /^$atom1\s+core\s+$atom2\s+core\s/i) { my @a = Utils::Split("\\s+", $line); my ($Aij, $bij, $Cij) = ($a[4], $a[5], $a[6]); #print "1 $atom1 - $atom2: ($Charge1, $Charge2, $Aij, $bij, $Cij)\n"; $this->AddPotentialLines($line); return ($Charge1, $Charge2, $Aij, $bij, $Cij); } elsif($line =~ /^$atom2\s+core\s+$atom1\s+core\s/i) { my @a = Utils::Split("\\s+", $line); my ($Aij, $bij, $Cij) = ($a[4], $a[5], $a[6]); #print "2 $atom2 - $atom1: ($Charge2, $Charge1, $Aij, $bij, $Cij)\n"; $this->AddPotentialLines($line); return ($Charge1, $Charge2, $Aij, $bij, $Cij); } last if($line =~ /^\s*spring/i); } return (); } sub AddAllPotentialsToHash { my ($this, $in, $type, $natom, $pHash, $IsPrint) = @_; $IsPrint = 1 if(!defined $IsPrint); #print "type:$type\n"; my %array; while(1) { my $pos = $in->tell(); my $line = $in->ReadLine(); #print "l2:$line"; last if(!defined $line); next if($line =~ /^#/ or $line =~ /^\s/); Utils::DelSpace($line); next if($line eq ''); if($line !~ /^cova\s/ and $line !~ /^mass\s/i and $line !~ /^[A-Z][a-z0-9\-+]*\s/ and $line !~ /^\s*[A-Z][a-z0-9\-]*_+[A-Za-z0-9+\-_]*\s/) { $in->seek($pos, 0); last; } my @a = Utils::Split("\\s+", $line); if($a[scalar @a - 1] eq '&') { pop @a; @a = (@a, Utils::Split($in->ReadLine())); } if($a[0] eq 'mass') { my $n = @a; @a = @a[1..$n]; } #print " $a[0] - $a[2] - $a[4] - $a[6]\n"; if($type eq 'element') { my %hash = ( Type => $type, nAtom => 1, AtomName1 => $a[1], ); $array{"$a[1]:$type"} = \%hash; } elsif($type eq 'SX-1') { # Born-Mayer Potential CONSTANT (J/A) $F0 = 6.947700141e-21 # A(I,J)=F0*B(I,J)*DEXP((PA(I)+PA(J))/B(I,J)) #Zn 65.39 2 1.5145 0.1200 0 0 if($a[4] != 0.0) { my %hash = ( Type => $type, nAtom => 1, AtomName1 => $a[0], ); $array{"$a[0]:$type"} = \%hash; } } elsif($natom == 1) { my %hash = ( Type => $type, nAtom => 1, AtomName1 => $a[0], ); $array{"$a[0]:$type"} = \%hash; } elsif($natom == 2) { my %hash = ( Type => $type, nAtom => 2, AtomName1 => $a[0], AtomName2 => $a[2], ); @a = sort ($a[0], $a[2]); $array{"$a[0]-$a[1]:$type"} = \%hash; } elsif($natom == 3) { my %hash = ( Type => $type, nAtom => 3, AtomName1 => $a[0], AtomName1 => $a[2], AtomName1 => $a[4], ); @a = sort ($a[0], $a[2], $a[4]); $array{"$a[0]-$a[1]-$a[2]:$type"} = \%hash; } elsif($natom == 4) { my %hash = ( Type => $type, nAtom => 4, AtomName1 => $a[0], AtomName1 => $a[2], AtomName1 => $a[4], ); @a = sort ($a[0], $a[2], $a[4], $a[6]); $array{"$a[0]-$a[1]-$a[2]-$a[3]:$type"} = \%hash; } } foreach my $key (keys %array) { #print "key:$key\n"; $pHash->{$key} = $array{$key}; } #foreach my $key (keys %$pHash) { #print "key:$key\n"; #} return $pHash; } sub ReadPotentialToHash { my ($this, $db, $IsPrint) = @_; $IsPrint = 1 if(!defined $IsPrint); #$IsPrint=1; my %array; my $c = 0; my $in = JFile->new($db, 'r') or return undef; while(1) { my $line = $in->ReadLine(); last if(!defined $line); next if($line =~ /^#/ or $line =~ /^\s/); Utils::DelSpace($line); next if($line eq ''); #print "l0:$line\n"; my $type = $line; print " type=$type\n" if($IsPrint); Utils::DelSpace($type); if($type =~ /^end$/i) { next; # last; } elsif($type =~ /^keyword/i) { next; } elsif($type =~ /^keywords/i) { next; } elsif($type =~ /^cutp/i) { next; } elsif($type =~ /^rtol/i) { next; } elsif($type =~ /^shellmass/i) { $in->ReadLine(); next; } elsif($type =~ /^reaxFFvdwcutoff/) { } elsif($type =~ /^reaxFFqcutoff/) { } elsif($type =~ /^reaxFFtol/) { } elsif($type =~ /^reaxff0_bond/i) { } elsif($type =~ /^reaxff0_over/i) { } elsif($type =~ /^reaxff0_valence/i) { } elsif($type =~ /^reaxff0_penalty/i) { } elsif($type =~ /^reaxff0_torsion/i) { } elsif($type =~ /^reaxff0_vdw/i) { } elsif($type =~ /^reaxff0_lonepair/i) { } elsif($type =~ /^cuts\s/i) { } elsif($type =~ /^SX-1/i) { $type =~ s/\s.*$//; $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_radii/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_valence/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_over/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_under/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_lonepair/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_angle/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_lonepair/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff1_morse/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff_chi/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff_mu/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff_gamma/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_bo/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_bond/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_over/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_morse/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_over/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_penalty/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff2_pen/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff3_angle/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff3_penalty/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff3_conjugation/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff3_hbond/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^reaxff4_torsion/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^torsion/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^inversion/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^element/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^species/i) { #print "hit\n"; $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^spring/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^general/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^bcross/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^urey-bradley/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^many/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^meam_functional/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^meam_density/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^meam_screening/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^meam_screen/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^meam_rhotype/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^baskes/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^mei-davenport/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^eam_fun/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^eam_den/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^eam_alloy/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^cfm_harm/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^cfm_power/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^cfm_gauss/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^cfm_fermi/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^vbo_twobody/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^buckingham/i or $type =~ /^buck/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^morse/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^uff1/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^smelectronegativity/i) { $this->AddAllPotentialsToHash($in, $type, 1, \%array); } elsif($type =~ /^buck/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^rydberg/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^qerfc/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^fermi/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^sw2/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^sw3/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^srglue/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^hydrogen-bond/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^three bond/i or $type =~ /^three/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^outofplane/i) { $this->AddAllPotentialsToHash($in, $type, 4, \%array); } elsif($type =~ /^polynomial/i) { my $npoly = $in->ReadLine() + 0; $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^harm/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^epsilon/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^edip_coordination/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^edip_twobody/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^edip_threebody/i) { $this->AddAllPotentialsToHash($in, $type, 3, \%array); } elsif($type =~ /^botwobody/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^borepulsive/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^boattractive/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^bocoordination/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^tsuneyuki/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^edip_zmax/i) { } elsif($type =~ /^lennard/i) { while(1) { my $pos = $in->tell(); $line = $in->ReadLine(); last if(!defined $line); if($line !~ /^[0-9\.eEdD+\-]+\s/ and $line !~ /^[A-Z][a-z]*\s/) { $in->seek($pos, 0); last; } } } elsif($type =~ /^damped_dispersion/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^lenn\s/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^aolm/i) { $this->AddAllPotentialsToHash($in, $type, 2, \%array); } elsif($type =~ /^tortaper/i) { $this->AddAllPotentialsToHash($in, $type, 4, \%array); } else { print "Error: Invalid type [$type].\n"; exit; } } $in->Close(); my %atomshash; foreach my $key (keys %array) { #print "key:$key\n"; $key =~ s/:.*$//; my @a = Utils::Split("-", $key); for(my $i = 0 ; $i < @a ; $i++) { $a[$i] =~ s/[\d_].*$//; $atomshash{$a[$i]}++; } } my @atoms = keys %atomshash; #for(my $i = 0 ; $i < @atoms ; $i++) { #print " $atoms[$i]"; #} #print "\n"; return (\%array, \@atoms); } sub ReadNextCrystalFromCustomDump { my ($this, $idx, $in, $cry) = @_; my $k = 1.0; my @AtomTypeList= $cry->GetCAtomTypeList(); my $Crystal = new Crystal(); # $Crystal->SetCrystalName($Title); # $Crystal->SetSampleName($Title); for(my $i = 0 ; $i < @AtomTypeList ; $i++) { $Crystal->AddAtomType($AtomTypeList[$i]->AtomNameOnly()); } my ($TimeStep, $nAtoms); my $IsRead = 0; while(1) { my $line = $in->ReadLine(); if(!defined $line) { if(!defined $nAtoms or !$IsRead) { return (undef, 0); } } #print "l:$line"; if($line =~ /ITEM:\s*(\S.*)\s*$/) { my $key = $1; print "key:$key\n"; if($key eq 'TIMESTEP') { $TimeStep = $in->ReadLine() + 0.0; print " Time step: $TimeStep\n"; } elsif($key eq 'NUMBER OF ATOMS') { $nAtoms = $in->ReadLine() + 0; print " nAtoms: $nAtoms\n"; } elsif($key =~ /^BOX BOUNDS/) { my ($xlo, $xhi, $xy) = Utils::Split("\\s+", $in->ReadLine()); my ($ylo, $yhi, $xz) = Utils::Split("\\s+", $in->ReadLine()); my ($zlo, $zhi, $yz) = Utils::Split("\\s+", $in->ReadLine()); # Vectors ($xhi-$xlo, 0, 0) ($xy, $yhi-$ylo, 0) ($xz, $yz, $zhi-$zlo) $Crystal->SetLatticeVector($xhi-$xlo, 0.0, 0.0, $xy, $yhi-$ylo, 0.0, $xz, $yz, $zhi-$zlo); } elsif($key =~ /^ATOMS\s*(\S.*)\s*$/) { $IsRead = 1; my @list = Utils::Split("\\s+", $1); print " list: ", join(', ', @list), "\n"; my %idx; for(my $i = 0 ; $i < @list ; $i++) { $idx{$list[$i]} = $i; } my %AtomCount; for(my $i = 0 ; $i < $nAtoms ; $i++) { # my ($id, $iType, $x, $y, $z, $ix, $iy, $iz) = Utils::Split("\\s+", $in->ReadLine()); # my ($id, $iType, $xr, $yr, $zr, $ix, $iy, $iz) = Utils::Split("\\s+", $in->ReadLine()); my @a = Utils::Split("\\s+", $in->ReadLine()); my $id = $a[$idx{id}]; my $iType = $a[$idx{type}]; my $x = $a[$idx{xs}]; my $y = $a[$idx{ys}]; my $z = $a[$idx{zs}]; my $atomname = $AtomTypeList[$iType-1]->AtomNameOnly(); $AtomCount{$atomname}++; my $Label = $atomname . $AtomCount{$atomname}; # my ($x, $y, $z) = $Crystal->CalFractionalCoordinate($k * $xr, $k * $yr, $k * $zr); #printf " $i: $atomname: $Label (%8.3g, %8.3g, %8.3g) => (%8.3g, %8.3g, %8.3g)\n", $xr, $yr, $zr, $x, $y, $z; printf " $i: $atomname: $Label (%12.4g, %12.4g, %12.4g)\n", $x, $y, $z; $Crystal->AddAtomSite($Label, $atomname, $x, $y, $z, 1.0); } last; } else { print "\nError: Invalid key in ITEM {$key]\n"; } } else { ; } } $Crystal->{TimeStep} = $TimeStep; $Crystal->{nAtom} = $nAtoms; $Crystal->ExpandCoordinates(); my @AtomList = $Crystal->GetCExpandedAtomSiteList(); print " nAtoms = ", scalar @AtomList, "\n"; return ($Crystal, 1); } sub GetnStepInCustomDump { my ($this, $DumpFile) = @_; my $in = JFile->new($DumpFile, 'r') or die "Can not read [$DumpFile].\n"; my $n = 0; while(1) { my $line = $in->SkipTo("ITEM:\\s*ATOMS"); last if(!defined $line); $n++; } $in->Close(); return $n; } sub MakeXSFFromCustomDump { my ($this, $pStep, $pTime, $pTemp, $DumpFile, $XSFFile, $IniCrystal, $HistoryFile) = @_; print("\n\nMake XSF File from LAMMPS custom dump file:\n"); print(" Read from [$DumpFile].\n"); print(" Save to [$XSFFile].\n"); my $nStep = $this->GetnStepInCustomDump($DumpFile); print "nStep: $nStep\n"; my $in = JFile->new($DumpFile, 'r') or die "Can not read [$DumpFile].\n"; my $csv; if($HistoryFile) { $csv = JFile->new($HistoryFile, 'w') or die "Can not write to [$HistoryFile].\n"; $csv->print("iStep,TimeStep,Temp,a,b,c,alpha,beta,gamma,Volume,Density\n"); # $csv->print("iStep,TimeStep,Temp,a,b,c,alpha,beta,gamma,Volume,Density,msd\n"); } my $xc = new XCrySDen; $xc->WriteXSFAnimationFileHeader($XSFFile, $nStep); my (@pos0, @prevpos, @pos, @offset); my ($Crystal, $FinalCrystal); my $ret; my $iStep = 0; my $msd = 0.0; while(1) { #$site->SetVelocity($dx, $dy, $dz); #$site->SetForce(0, 0, $tot); ($Crystal, $ret) = $this->ReadNextCrystalFromCustomDump($iStep, $in, $IniCrystal); last if(!$ret or !$Crystal); $iStep++; print "iStep=$iStep\n"; $FinalCrystal = $Crystal->Duplicate(); if($csv) { my @atoms = $Crystal->GetCExpandedAtomSiteList(); if($iStep == 1) { for(my $i = 0 ; $i < @atoms ; $i++) { my ($x, $y, $z) = $atoms[$i]->Position(); ($prevpos[$i][0], $prevpos[$i][1], $prevpos[$i][2]) = ($pos0[$i][0], $pos0[$i][1], $pos0[$i][2]) = ($x, $y, $z); } } for(my $i = 0 ; $i < @atoms ; $i++) { my ($x, $y, $z) = $atoms[$i]->Position(); # wrapされた座標から、実際の変位量を計算する # ただし、一単位格子以上の変位があると、変位量は不明になる。msdの計算はあきらめる if($prevpos[$i][0] - $x > 0.5) { $offset[$i][0] += 1.0; } elsif($x - $prevpos[$i][0] > 0.5) { $offset[$i][0] -= 1.0; } if($prevpos[$i][1] - $y > 0.5) { $offset[$i][1] += 1.0; } elsif($y - $prevpos[$i][1] > 0.5) { $offset[$i][1] -= 1.0; } if($prevpos[$i][2] - $z > 0.5) { $offset[$i][2] += 1.0; } elsif($z - $prevpos[$i][2] > 0.5) { $offset[$i][2] -= 1.0; } my $r = $Crystal->GetInterAtomicDistance( $pos0[$i][0], $pos0[$i][1], $pos0[$i][2], $x+$offset[$i][0], $y+$offset[$i][1], $z+$offset[$i][2]); $msd += $r*$r; #print "$i: r = $r ($pos0[$i][0], $pos0[$i][1], $pos0[$i][2]) - ($x+$offset[$i][0], $y+$offset[$i][1], $z+$offset[$i][2])\n"; ($prevpos[$i][0], $prevpos[$i][1], $prevpos[$i][2]) = ($x, $y, $z); } #exit if($iStep >= 3); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParameters(); my $V = $Crystal->Volume(); my $d = $Crystal->Density(); my $temp = Algorism::Interpolate($pStep, $pTemp, $Crystal->{TimeStep}); $csv->printf("$iStep,$Crystal->{TimeStep},$temp,$a,$b,$c,$alpha,$beta,$gamma,$V,$d\n"); # $csv->printf("$iStep,$Crystal->{TimeStep},$temp,$a,$b,$c,$alpha,$beta,$gamma,$V,$d\n", # $msd / $Crystal->{nAtom} / $iStep); } $xc->WriteXSFFileFromCrystal($XSFFile, $iStep, $Crystal); } $csv->Close() if($csv); print("\nMake XSF File from VASP *CAR Files: Finished\n"); return $FinalCrystal; } sub SaveHistoryFromLog { my ($this, $LogFile, $LogHistoryFile) = @_; print "\n"; print "Save log hisotry to [$LogHistoryFile] from [$LogFile].\n"; my @array; my $in = JFile->new($LogFile, 'r') or return undef; my $out = JFile->new($LogHistoryFile, 'w') or return undef; my $iRun = 0; my $tc = 0; my $PrevLabelLine = ''; while(1) { my $line = $in->SkipTo("^Step "); if($line) { $array[$iRun] = {}; } else { last; } my @label = Utils::Split("\\s+", $line); last if($label[0] ne 'Step'); print "iRun: $iRun: Labels: ", join(', ', @label), "\n"; if($PrevLabelLine ne $line) { $out->print(join(',', @label), "\n"); $PrevLabelLine = $line; } $tc++; my $c = 0; while(1) { $line = $in->ReadLine(); last if(!$line); my @a = Utils::Split("\\s+", $line); last if($a[0] !~ /^[+\-\d\.eEdD]+$/); $array[$iRun]{iRun}[$c] = $iRun+1; for(my $i = 0 ; $i < @a ; $i++) { $array[$iRun]{$label[$i]}[$c] = $a[$i]; } $out->print(join(',', @a), "\n"); $c++; $tc++; } last if(!$line); $iRun++; } $in->Close(); $out->Close(); print "\n"; return \@array; } sub ReadLogFileToHashArray { my ($this, $LogFile) = @_; print "\n"; print "Read log file from [$LogFile].\n"; my @array; my $in = JFile->new($LogFile, 'r') or return undef; my $iRun = 0; while(1) { my $line = $in->SkipTo("^Step "); if($line) { $array[$iRun] = {}; } else { last; } my @label = Utils::Split("\\s+", $line); last if($label[0] ne 'Step'); print "iRun: $iRun: Labels: ", join(', ', @label), "\n"; my $c = 0; while(1) { $line = $in->ReadLine(); last if(!$line); my @a = Utils::Split("\\s+", $line); last if($a[0] !~ /^[+\-\d\.eEdD]+$/); $array[$iRun]{iRun}[$c] = $iRun+1; for(my $i = 0 ; $i < @a ; $i++) { $array[$iRun]{$label[$i]}[$c] = $a[$i]; } $c++; } last if(!$line); $iRun++; } $in->Close(); print "\n"; return \@array; } sub ReadPotentialFromOutput { my ($this, $OutFile) = @_; my %hash; my $in = JFile->new($OutFile, "r") or die "Can not read [$OutFile]\n"; my $line = $in->SkipTo("G vector "); ($hash{gewald}) = ($line =~ /=\s*(\S+)/); $in->Close(); return \%hash; } sub ReadPotentialFromInput { my ($this, $InFile) = @_; my %hash; my $in = JFile->new($InFile, "r") or die "Can not read [$InFile]\n"; my $line = $in->SkipTo("pair_style"); ($hash{pair_style}, $hash{global_cutoff}) = ($line =~ /pair_style\s+(\S+)\s+(\S+)/i); print "pair_style: $hash{pair_style} $hash{global_cutoff}\n"; $line = $in->ReadLine(); $line =~ s/^#//; my @atoms = Utils::Split("\\s+", $line); $hash{pAtoms} = \@atoms; print "atoms: ", join(', ', @atoms), "\n"; print "\n"; while(1) { $line = $in->ReadLine(); last if(!defined $line); next if($line =~ /^#/); last if($line !~ /pair_coeff/i); my ($keyword, $idx1, $idx2, @params) = Utils::Split("\\s+", $line); $hash{"PotentialParameters$idx1-$idx2"} = $hash{"PotentialParameters$idx2-$idx1"} = \@params; my ($idx1m, $idx2m) = ($idx1-1, $idx2-1); print "$atoms[$idx1m] - $atoms[$idx2m]: ", join(', ', @params), "\n"; } $in->rewind(); $line = $in->SkipTo("^\\s*kspace_style"); my ($keyword, $key, $val) = Utils::Split("\\s+", $line); print "l: $keyword, $key, $val\n"; if($key eq 'ewald') { $hash{ewald} = 1; $hash{ewaldEPS} = $val; $in->rewind(); $line = $in->SkipTo("^\\s*kspace_modify"); ($keyword, $key, $val) = Utils::Split("\\s+", $line); print "l2: $keyword, $key, $val\n"; $hash{gewald} = $val if($key eq 'gewald');; } $in->rewind(); while(1) { $line = $in->SkipTo("pair_write"); last if(!defined $line); next if($line =~ /^#/); my ($keyword, $idx1, $idx2, $nr, $meshtype, $rmin, $rmax, $filename, $key, $Z1, $Z2) = Utils::Split("\\s+", $line); $hash{"PotentialFile$idx1-$idx2"} = $hash{"PotentialFile$idx2-$idx1"} = $filename; $hash{"Z$idx1"} = $Z1; $hash{"Z$idx2"} = $Z2; my ($idx1m, $idx2m) = ($idx1-1, $idx2-1); print "$atoms[$idx1m] - $atoms[$idx2m]: PotentialFile$idx1-$idx2: $filename\n"; } $in->Close(); return \%hash; } sub ReadCrystalStructureFromInput { my ($this, $InFile, $DataFile) = @_; my $k = 1.0; # my $k = $a0*1.0e10; my $Crystal = new Crystal(); # $Crystal->SetCrystalName($Title); # $Crystal->SetSampleName($Title); my $in = new JFile($InFile, "r"); return 0 unless($in); my $line; while(1) { $line = $in->ReadLine(); last if(!defined $line); last if($line =~ /^\s*pair_style\s/); } $line = $in->ReadLine(); $line =~ s/^\s*#//; $line =~ s/[\\s_\-\d]+/ /g; #print "l: $line\n"; #exit; my @atoms = Utils::Split("\\s+", $line); print "atoms: ", join(', ', @atoms), "\n"; for(my $i = 0 ; $i < @atoms ; $i++) { $Crystal->AddAtomType($atoms[$i]); } $in->Close(); $in = new JFile($DataFile, "r"); return 0 unless($in); my ($xhi, $yhi, $zhi, $xy, $xz, $yz); while(1) { $line = $in->ReadLine(); last if(!defined $line); last if($line =~ /^\s*(Masses|Atoms)/i); my @a = Utils::Split("\\s+", $line); if($line =~ /xlo/) { $xhi = $k * ($a[1] - $a[0]); } elsif($line =~ /ylo/) { $yhi = $k * ($a[1] - $a[0]); } elsif($line =~ /zlo/) { $zhi = $k * ($a[1] - $a[0]); } elsif($line =~ /xy/) { $xy = $k * $a[0]; $xz = $k * $a[1]; $yz = $k * $a[1]; } } print "Lattice vector: ($xhi, 0.0, 0.0) ($xy, $yhi, 0.0) ($xz, $yz, $zhi)\n"; $Crystal->SetLatticeVector($xhi, 0.0, 0.0, $xy, $yhi, 0.0, $xz, $yz, $zhi); $in->rewind(); while(1) { $line = $in->ReadLine(); last if(!defined $line); last if($line =~ /^\s*Atoms/); } my $c = 0; my %AtomCount; while(1) { $line = $in->ReadLine(); last if(!defined $line); my ($iAtom, $iType, $Z, $xr, $yr, $zr) = Utils::Split("\\s+", $line); next if(!defined $zr); $c++; my $atomname = $atoms[$iType-1]; $AtomCount{$atomname}++; my $Label = $atoms[$iType-1] . $AtomCount{$atomname}; my ($x, $y, $z) = $Crystal->CalFractionalCoordinate($k * $xr, $k * $yr, $k * $zr); printf " $c: $atomname: $Label (%8.3g, %8.3g, %8.3g) => (%8.3g, %8.3g, %8.3g)\n", $xr, $yr, $zr, $x, $y, $z; $Crystal->AddAtomSite($Label, $atomname, $x, $y, $z, 1.0); } $Crystal->ExpandCoordinates(); my @AtomList = $Crystal->GetCExpandedAtomSiteList(); print " nAtoms = ", scalar @AtomList, "\n"; $in->Close(); $Crystal->ExpandCoordinates(); print "\n"; return $Crystal; } sub WriteAtomTypes { my ($this, $out, $pAtomTypeList) = @_; #原子種をコメントで出力 $out->print("#"); for(my $i = 0 ; $i < @$pAtomTypeList ; $i++) { my $name1 = $pAtomTypeList->[$i]->AtomNameOnly(); $out->print("$name1 "); } $out->print("\n"); } sub WritePairPotentialCommand { my ($this, $out, $pPot, $pAtomTypeList) = @_; my $nAtomType = @$pAtomTypeList; my ($rmin, $rmax, $N) = (0.01, 10.0, 1000); $out->print("\n"); for(my $i = 0 ; $i < @$pAtomTypeList ; $i++) { my $name1 = $pAtomTypeList->[$i]->AtomNameOnly(); my $Z1 = $pPot->{"$name1-core"}{charge}; for(my $j = $i ; $j < @$pAtomTypeList ; $j++) { my $name2 = $pAtomTypeList->[$j]->AtomNameOnly(); my $Z2 = $pPot->{"$name2-core"}{charge}; my $key = "$name1-core-$name2-core"; $rmin = $pPot->{$key}{Rmin} if(defined $pPot->{$key}{Rmin} and $pPot->{$key}{Rmin} > $rmin); $rmax = $pPot->{$key}{Rmax} if(defined $pPot->{$key}{Rmax} and $pPot->{$key}{Rmax} < $rmax); print "$name2: $Z2\n"; $out->printf("pair_write %2d %2d %6d r %f %f Potential-%s-%s.txt %s %f %f\n", $i+1, $j+1, $N, $rmin, $rmax, $name1, $name2, "$name1-$name2", $Z1, $Z2); } } } sub WritePotential { my ($this, $out, $pPot, $pAtomTypeList, $LibraryPath, $UseGEWALD, $alpha) = @_; my $nAtomType = @$pAtomTypeList; $out->print("#Original potentials taken from [$LibraryPath]\n"); if($pPot->{type} eq 'buckingham') { my @lines = $this->GetPotentialLines(); for(my $i = 0 ; $i < @lines ; $i++) { $out->print("# $lines[$i]\n"); } $out->print("pair_style born/coul/long 10.0\n"); # $out->print("pair_style buck/coul/long 10.0\n"); $this->WriteAtomTypes($out, $pAtomTypeList); for(my $i = 0 ; $i < $nAtomType ; $i++) { #print "i=$i:$AtomTypeList[$i]\n"; my $name1 = $pAtomTypeList->[$i]->AtomNameOnly(); for(my $j = $i ; $j < $nAtomType ; $j++) { my $name2 = $pAtomTypeList->[$j]->AtomNameOnly(); # O core O core 25.410 0.6937 32.32 0.0 12.0 0 0 0 #print "($i - $j) $name1 - $name2: ", $BParams{"$name1-$name2"}, "\n"; my $key = "$name1-core-$name2-core"; my $p = $pPot->{$key}; my $Aij = $p->{A}; my $bij = $p->{rho}; my $Cij = $p->{C}; $Aij = 0.0 if(!defined $Aij); $bij = 1.0 if(!defined $bij); $Cij = 0.0 if(!defined $Cij); print " $name1 - $name2: $Aij $bij $Cij\n"; # my $Rcut = ($pPot->{$key}{Rmax} > 10.0)? 10.0 : $pPot->{$key}{Rmax}; # $Rcut = 10.0 if($Rcut <= 0.0); my $Rcut = 0.0; # $out->printf("pair_coeff %3d %3d %12.6g %12.6f %12.6f %8.4f %8.4f\n", # $i+1, $j+1, $Aij, $bij, $Cij, $Rcut, $Rcut); # $out->printf("pair_coeff %3d %3d %12.6g %12.6f %12.6f %8.4f %8.4f %8.4f\n", # $i+1, $j+1, $Aij, $bij, 0.0, $Cij, 0.0, $Rcut); $out->printf("pair_coeff %3d %3d %12.6g %12.6f %12.6f %8.4f %8.4f\n", $i+1, $j+1, $Aij, $bij, 0.0, $Cij, 0.0); } } $out->print("kspace_style ewald 1.0e-4\n"); if($UseGEWALD) { $out->print("kspace_modify gewald $alpha\n"); } else { $out->print("#kspace_modify gewald $alpha\n"); } } elsif($pPot->{type} eq 'morse') { my @lines = $this->GetPotentialLines(); for(my $i = 0 ; $i < @lines ; $i++) { $out->print("# $lines[$i]\n"); } $out->print("pair_style morse 10.0\n"); $this->WriteAtomTypes($out, $pAtomTypeList); for(my $i = 0 ; $i < @$pAtomTypeList ; $i++) { #print "i=$i:$AtomTypeList[$i]\n"; my $name1 = $pAtomTypeList->[$i]->AtomNameOnly(); for(my $j = $i ; $j < $nAtomType ; $j++) { my $name2 = $pAtomTypeList->[$j]->AtomNameOnly(); # O core O core 25.410 0.6937 32.32 0.0 12.0 0 0 0 #print "($i - $j) $name1 - $name2: ", $BParams{"$name1-$name2"}, "\n"; my $key = "$name1-core-$name2-core"; my $p = $pPot->{$key}; my $De = $p->{De}; my $a0 = $p->{a0}; my $r0 = $p->{r0}; # my $fsCoulomb = $p->{fsCoulomb}; print " $name1 - $name2: $De $a0 $r0\n"; my $Rcut = ($pPot->{$key}{Rmax} > 10.0)? 10.0 : $pPot->{$key}{Rmax}; $Rcut = 10.0 if($Rcut <= 0.0); $out->printf("pair_coeff %3d %3d %12.6g %12.6g %12.6f %8.4f\n", $i+1, $j+1, $De, $a0, $r0, $Rcut); } } $out->print("#kspace_style ewald 1.0e-4\n"); if($UseGEWALD) { $out->print("#kspace_modify gewald $alpha\n"); } else { $out->print("#kspace_modify gewald $alpha\n"); } } elsif($pPot->{type} eq 'table') { my @lines = $this->GetPotentialLines(); for(my $i = 0 ; $i < @lines ; $i++) { $out->print("# $lines[$i]\n"); } if($pPot->{SplitEwaldSum} == 1) { $out->print("pair_style table linear 1000 ewald\n"); } else { $out->print("pair_style table linear 1000\n"); } $this->WriteAtomTypes($out, $pAtomTypeList); for(my $i = 0 ; $i < @$pAtomTypeList ; $i++) { #print "i=$i:$AtomTypeList[$i]\n"; my $name1 = $pAtomTypeList->[$i]->AtomNameOnly(); for(my $j = $i ; $j < $nAtomType ; $j++) { my $name2 = $pAtomTypeList->[$j]->AtomNameOnly(); my $key = "$name1-core-$name2-core"; print " $name1 - $name2: N = $pPot->{$key}{nR}, R = $pPot->{$key}{Rmin} - $pPot->{$key}{Rmax}\n"; my $Rcut = ($pPot->{$key}{Rmax} > 10.0)? 10.0 : $pPot->{$key}{Rmax}; $Rcut = 10.0 if($Rcut <= 0.0); $out->printf("pair_coeff %3d %3d %s %10s %g\n", $i+1, $j+1, $LibraryPath, "$name1-$name2", $Rcut); } } if($pPot->{SplitEwaldSum} == 1) { $out->print("kspace_style ewald 1.0e-4\n"); $out->print("kspace_modify gewald $alpha\n"); } else { $out->print("#kspace_style ewald 1.0e-4\n"); $out->print("#kspace_modify gewald $alpha\n"); } } $this->WritePairPotentialCommand($out, $pPot, $pAtomTypeList); # if($nShellAtoms > 0) { # print OUT "spring\n"; # for(my $i = 0 ; $i < @Spring ; $i++) { # print OUT "$Spring[$i]\n"; # } # } return 1; } sub SaveInputFiles { my ($this, $Crystal, $Function, $InFile, $DataFile, $CopyScript, $ScriptPath, $IsChooseRandomly, %args) = @_; $CopyScript = 0 if(!defined $CopyScript); my $UseGEWALD = ($args{gewald})? 1 : 0; #ファイル名を(ベース名, ディレクトリ名, 拡張子)に分解 my @filenames = fileparse($InFile, "\.[^\.]+"); # my $InFile = "$filenames[0].in"; # my $DataFile = "$filenames[0].data"; my $LibraryPath = $this->LibraryPath(); my $SampleName = $this->SampleName(); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParametersByOutputMode(0); my ($a11, $a12, $a13) = ($a, 0.0, 0.0); my ($a21, $a22, $a23) = ($b * cos($torad*$gamma), $b * sin($torad*$gamma), 0.0); my $a31 = $c * cos($torad * $beta); my $a32 = $c * (cos($torad * $alpha) - cos($torad * $beta) * cos($torad * $gamma)) / sin($torad * $gamma); my $a33 = sqrt($c*$c - $a31*$a31 - $a32*$32); $a31 = 0.0 if(abs($a31) < 1.0e-6); $a32 = 0.0 if(abs($a31) < 1.0e-6); #print "a: $a31, $a32, $a33\n"; my $V = $Crystal->Volume(); my $RV = 1.0 / $V; my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my $nAtomSite = @AtomSiteList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteListByOutputMode(); my $nExpandedAtomSiteList = @ExpandedAtomSiteList; my $UseShellModelForCation = $this->UseShellModelForCation(); my $UseShellModelForAnion = $this->UseShellModelForAnion(); print "\n"; print "Atom types:\n"; for(my $i = 0 ; $i < @AtomTypeList ; $i++) { print " $i: ", $AtomTypeList[$i]->AtomNameOnly(), "\n"; } print "\n"; print "Potentials:\n"; my %CoreShellType; my $nShellAtoms = 0; for(my $i = 0 ; $i < @AtomTypeList ; $i++) { my $type = $AtomTypeList[$i]; my $name = $type->AtomNameOnly(); my $charge = $type->Charge(); my ($core, $shell) = $this->ReadSpecies($name); #print "Core: $core
\n"; #print "Shell: $shell
\n"; if($charge == 0) { my ($CoreCharge) = ($core =~ /([\+-\.\d]+)\s*$/); my ($ShellCharge) = ($shell =~ /([\+-\.\d]+)\s*$/); $charge = $CoreCharge + $ShellCharge; #print "CoreCharge : $CoreCharge
\n"; #print "ShellCharge: $ShellCharge
\n"; #print "Charge: $charge
\n"; } if($core eq '') { $CoreShellType{$name} = 'undefined'; } elsif($shell eq '') { $CoreShellType{$name} = 'core'; } else { $CoreShellType{$name} = 'core-shell'; } #print "$name: $CoreShellType{$name}
\n"; #print "UseAnion: $UseShellModelForAnion
\n"; if(!$UseShellModelForCation and $charge > 0 and $CoreShellType{$name} eq 'core-shell') { $CoreShellType{$name} = 'core'; } if(!$UseShellModelForAnion and $charge < 0 and $CoreShellType{$name} eq 'core-shell') { $CoreShellType{$name} = 'core'; } $nShellAtoms++ if($CoreShellType{$name} eq 'core-shell'); } print "Core-Shell type:\n"; my @list = keys %CoreShellType; for(my $i = 0 ; $i < @list ; $i++) { my $key = $list[$i]; my $val = $CoreShellType{$key}; print " $key: $val\n"; } print "\n"; printf "Read potential parameters from [%s]\n", $LibraryPath; $this->ClearPotentialLines(); my $pPot = $this->ReadPotentialLibrary($LibraryPath); print " Potential type: $pPot->{type}\n"; foreach my $key (sort keys %$pPot) { my $p = $pPot->{$key}; if($p =~ /hash/i) { foreach my $key2 (sort keys %$p) { print " $key:$key2:$p->{$key2}\n"; } } else { print " $key: $p\n"; } } my $EWALDalpha; if(defined $pPot->{gewald}) { $UseGEWALD = 1; $EWALDalpha = $pPot->{gewald}; } elsif($args{gewald}) { $UseGEWALD = 1; $EWALDalpha = $args{gewald}; } else { $UseGEWALD = 0; $EWALDalpha = 0.4; } my ($rmin, $rstep, $nr) = (0.01, 0.01, 400); $this->SavePotentials('Potentials.csv', $rmin, $rstep, $nr, \@AtomTypeList, $pPot, alpha => $EWALDalpha, ); print "\n"; my $EPS = 1.0e-6; my $Aijmax = 10.0; my $bijmax = 1.0; my $Cijmax = 10.0; print "Estimate calculation range (not implemented)\n"; print " Aijmax = $Aijmax\n"; print " bijmax = $bijmax\n"; print " Cijmax = $Cijmax\n"; print " EWALD alpha is assumed to be $EWALDalpha\n"; my $N = int(-log10($EPS) + 1.0e-6); print " for EPS = $EPS = 10^$N \n"; my $RDmax = ($EWALDalpha > 0)? (2.26 + 0.26 * $N)/$EWALDalpha : 0.0; my $erfcRDmax = erfc($EWALDalpha*$RDmax); my $RRmax = 1.0 + $bijmax * $N * log(10.0); my $expRRmax = exp(-$RRmax / $bijmax); my $RPmax = $N * log(10.0); my $recRPmax6 = 1.0 / $RPmax**6; printf " Direct term : RDmax = %12.6g A erfc(alpha*RDmax) = %10.4g\n", $RDmax, $erfcRDmax; printf " Repulsive term : RRmax = %12.6g A exp(-RRmax/bijmax) = %10.4g\n", $RRmax, $expRRmax; printf " Dispersion term: RPmax = %12.6g A 1.0/RPmax^6 = %10.4g\n", $RPmax, $recRPmax6; my $Rmax = $RDmax; $Rmax = $RRmax if($Rmax < $RRmax); $Rmax = $RDmax if($Rmax < $RDmax); my @NRmax; $NRmax[0] = int( $Rmax / sqrt($Crystal->{g11} * sin($torad*$beta ) * sin($torad*$gamma)) ) + 1; $NRmax[1] = int( $Rmax / sqrt($Crystal->{g22} * sin($torad*$alpha) * sin($torad*$gamma)) ) + 1; $NRmax[2] = int( $Rmax / sqrt($Crystal->{g33} * sin($torad*$alpha) * sin($torad*$beta )) ) + 1; print " Cal range estimated by Rmax = $Rmax A: ($NRmax[0], $NRmax[1], $NRmax[2])\n"; my $pi2 = 2.0 * $pi; my $CalN = (int(2.0/3.0 * $pi2 * $Rmax**3.0 / $V) + 1.0) * $nExpandedAtomSiteList; print " Number of calculations in direct term: $CalN\n"; my $max = sqrt( $Crystal->{g11} * sin($torad*$beta ) * sin($torad*$gamma) ) * $NRmax[0]; my $max2 = sqrt( $Crystal->{g22} * sin($torad*$alpha) * sin($torad*$gamma) ) * $NRmax[1]; $max = $max2 if($max < $max2); $max2 = sqrt( $Crystal->{g33} * sin($torad*$alpha) * sin($torad*$beta ) ) * $NRmax[2]; $max = $max2 if($max < $max2); my $max3 = sqrt( $Crystal->{g11} * sin($torad*$beta ) * sin($torad*$gamma) ) * ($NRmax[1] - 1); $max2 = sqrt( $Crystal->{g22} * sin($torad*$alpha) * sin($torad*$gamma) ) * ($NRmax[2] - 1); $max3 = $max2 if($max3 < $max2); $max2 = sqrt( $Crystal->{g33} * sin($torad*$alpha) * sin($torad*$beta ) ) * ($NRmax[3] - 1); $max3 = $max2 if($max3 < $max2); print " Rmax(Calculation) = $max3 - $max\n"; my $g2max = 4.0 * $EWALDalpha**2 * $N * log(10.0) + 1.0; my $expg2max = ($EWALDalpha > 0)? exp(-$g2max / 4.0 / $EWALDalpha**2) : 0; my ($Ra, $Rb, $Rc, @Rang) = $Crystal->ReciprocalLatticeParameters(); my @lsin; for(my $i = 0 ; $i < 3 ; $i++) { $lsin[$i] = sin($torad * $Rang[$i]); } my @hgmax; $hgmax[0] = int( sqrt($g2max / ($Crystal->{Rg11} * $lsin[1] * $lsin[2]) ) / $pi2) + 1; $hgmax[1] = int( sqrt($g2max / ($Crystal->{Rg22} * $lsin[0] * $lsin[2]) ) / $pi2) + 1; $hgmax[2] = int( sqrt($g2max / ($Crystal->{Rg33} * $lsin[0] * $lsin[1]) ) / $pi2) + 1; print " Cal range estimated for reciprocal space: " ."G2max = $g2max exp(-G2max / 4.0 / alpha^2) = $expg2max: hmax = ($hgmax[0], $hgmax[1], $hgmax[2])\n"; my $CalN = int( 2.0/3.0 * $pi2 * $g2max**1.5 / $RV / $pi2**3.0) + 1; print " Number of calculations in reciprocal term: $CalN\n"; $max = sqrt( $Crystal->{Rg11} * $lsin[1] * $lsin[2] ) * $hgmax[0]; $max2 = sqrt( $Crystal->{Rg22} * $lsin[0] * $lsin[2] ) * $hgmax[1]; $max = $max2 if($max < $max2); $max2 = sqrt( $Crystal->{Rg33} * $lsin[0] * $lsin[1] ) * $hgmax[3]; $max = $max2 if($max < $max2); $max3 = sqrt ($Crystal->{Rg11} * $lsin[1] * $lsin[2] ) * ($hgmax[0] - 1); $max2 = sqrt ($Crystal->{Rg22} * $lsin[0] * $lsin[2] ) * ($hgmax[1] - 1); $max3 = $max2; $max2 = sqrt ($Crystal->{Rg33} * $lsin[0] * $lsin[1] ) * ($hgmax[2] - 1); $max3 = $max2 if($max3 < $max2); print " G^2max(Calculation) = ", ($max3*$pi2)**2.0, " - ", ($max*$pi2)**2.0, "\n"; #exit; print "\n"; print(" Delete old input files [$InFile] and [$DataFile].\n"); unlink($InFile); unlink($DataFile); #print "C=$CopyScript $ScriptPath\n"; if($CopyScript) { my $TargetScriptPath = 'GoLAMMPS.bat'; print(" Delete old script file [$TargetScriptPath].\n"); unlink($TargetScriptPath); if(!Utils::CopyFile($ScriptPath, $TargetScriptPath)) { print "Error: Can not copy [$ScriptPath] to [$TargetScriptPath].\n"; exit; } } print "\n"; print(" Save to [$DataFile].\n"); #print "f:$DataFile\n"; my $out2 = JFile->new($DataFile, 'w') or die "Can not write to [$DataFile].\n"; $out2->print("\n"); $out2->printf("%10d atoms\n", $nExpandedAtomSiteList); $out2->print("\n"); $out2->printf("%10d atom types\n", $nAtomType); $out2->print("\n"); # Vector: (xhi, 0, 0), (xy, yhi, 0), (xz, yz, zhi) $out2->printf(" %18.15g %18.15g xlo xhi\n", 0.0, $a11); $out2->printf(" %18.15g %18.15g ylo yhi\n", 0.0, $a22); $out2->printf(" %18.15g %18.15g zlo zhi\n", 0.0, $a33); $out2->printf(" %18.15g %18.15g %18.15g xy xz yz\n", $a21, $31, $a32); $out2->print("\n"); $out2->print("Masses\n"); $out2->print("\n"); print "Atom types:\n"; for(my $i = 0 ; $i < $nAtomType ; $i++) { my $p = $AtomTypeList[$i]; my $atomname = $p->AtomNameOnly(); my $mass = $p->AtomicMass(); $out2->printf(" %4d %25.15f # %s\n", $i+1, $mass, $atomname); printf(" %4d %25.15f # %s\n", $i+1, $mass, $atomname); } $out2->print("\n"); $out2->print("Atoms\n"); $out2->print("\n"); print "\n"; print "Atom sites:\n"; for(my $i = 0 ; $i < $nExpandedAtomSiteList ; $i++) { my $p = $ExpandedAtomSiteList[$i]; my $atomname = $p->AtomNameOnly(); my $occupancy = $p->Occupancy(); # my $mult = $p->Multiplicity(); # my $id = $p->Id(); if($occupancy < 0.9999) { print "\nError: Partial occupancy (occ < 0.9999) is not allowed for atom #$i $atomname\n\n"; exit; } my $charge = $pPot->{"$atomname-core"}{charge}; my $idAtom; my $pat; for(my $j = 0 ; $j < $nAtomType ; $j++) { if($atomname eq $AtomTypeList[$j]->AtomNameOnly()) { $idAtom = $j + 1; $pat = $AtomTypeList[$j]; last; } } my ($x, $y, $z) = $p->Position(); my $xr = $a11 * $x + $a21 * $y + $a31 * $z; my $yr = $a12 * $x + $a22 * $y + $a32 * $z; my $zr = $a13 * $x + $a23 * $y + $a33 * $z; # " 1 1 -2.000000000000000 6.579577218202047 # 0.005786653198768 3.512676454470000 $out2->printf(" %5d %5d %18.15f %18.15f %18.15f %18.15f # %s\n", $i+1, $idAtom, $charge, $xr, $yr, $zr, $atomname); print " $atomname: ($x, $y, $z) ($xr, $yr, $zr)\n"; } $out2->print("\n"); $out2->Close(); print "\n"; print(" Save to [$InFile].\n"); unlink($InFile); my $out1 = JFile->new($InFile, 'w') or die "Can not write to [$InFile].\n"; $out1->print("#dimension 3\n"); $out1->print("#newton on\n"); $out1->print("units metal\n"); #モデル構造 $out1->print("\n"); $out1->print("#atom_style atomic\n"); $out1->print("atom_style charge\n"); $out1->print("#boundary x y z: [x,y,z]= p(eriodic)\n"); $out1->print("boundary p p p\n"); $out1->print("box tilt large\n"); $out1->print("read_data lmp_tmp.data\n"); # $out1->print("read_data $DataFile\n"); #力場 $out1->print("\n"); $this->WritePotential($out1, $pPot, \@AtomTypeList, $LibraryPath, $UseGEWALD, $EWALDalpha); #テーブル作成条件 $out1->print("\n"); $out1->print("#neighbor 2.0 bin\n"); $out1->print("#neigh_modify delay 10 every 1\n"); $out1->print("#neigh_modify every 2 delay 10 check yes\n"); $out1->print("neigh_modify delay 0\n"); $out1->print("#neighbor 0.3 bin\n"); #構造書き出し $out1->print("\n"); $out1->print("#compute: com yes => subtract the drift of the center-of-mass\n"); $out1->print("# average yes => use the average as the reference position\n"); $out1->print("#compute MSD1 all msd\n"); $out1->print("#compute MSD1 all msd com no average no\n"); $out1->print("dump 1 all custom 1000 lmp_tmp.dump id type xs ys zs ix iy iz\n"); $out1->print("dump 2 all xtc 1000 lmp_tmp.xtc\n"); $out1->print("#dump d0 all image 100 dump.*.jpg type type\n"); $out1->print("#dump d1 mobile image 500 snap.*.png element element ssao yes 4539 0.6\n"); $out1->print("#dump d2 all image 200 img-*.ppm type type zoom 2.5 adiam 1.5 size 1280 720\n"); $out1->print("#dump m0 all movie 1000 movie.mpg type type size 640 480\n"); $out1->print("#dump m1 all movie 1000 movie.avi type type size 640 480\n"); $out1->print("#dump m2 all movie 100 movie.m4v type type zoom 1.8 adiam v_value s\n"); $out1->print("#fix user-defined-ID group-ID style args\n"); $out1->print("# see https://lammps.sandia.gov/doc/fix.html\n"); $out1->print("#fix 1 all nve\n"); $out1->print("#fix 3 all nvt temp 300.0 300.0 0.01\n"); $out1->print("#fix mine top setforce 0.0 NULL 0.0\n"); $out1->print("#unfix 1\n"); #構造最適化 my $pre; $pre = ($Function =~ /relax/i)? '' : '#'; $out1->print("\n"); $out1->print("${pre}timestep 0.001\n"); $out1->print("${pre}thermo_style custom step etotal temp press lx vol\n"); $out1->print("${pre}thermo 500\n"); $out1->print("${pre}fix Relax1 all box/relax iso 0.0 vmax 0.01\n"); $out1->print("#min_style: cg, sd, hftn, quickmin, fire\n"); $out1->print("${pre}min_style cg\n"); $out1->print("${pre}minimize 0.0 1.0e-20 1000 100000\n"); if($Function =~ /relax/i) { $out1->print("${pre}unfix Relax1\n"); } else { $out1->print("#unfix Relax1\n"); } #MD $pre = ($Function =~ /MD/i)? '' : '#'; my $ensemble = ($Function =~ /NVT/i)? 'nvt' : 'npt'; $out1->print("\n"); $out1->print("${pre}timestep 0.001\n"); $out1->print("${pre}compute MSD1 all msd com no average no\n"); $out1->print("${pre}thermo_style custom step time temp epair emol etotal press vol density"); for(my $i = 1 ; $i <= $nAtomType ; $i++) { $out1->print(" c_MSD1[$i]"); } $out1->print("\n"); $out1->print("${pre}thermo 10\n"); $out1->print("${pre}velocity all create 300.0 12345\n"); $out1->print("${pre}fix MD1 all $ensemble temp 300.0 3000.0 0.2 iso 0.0 0.0 2.0\n"); $out1->print("${pre}run 50000\n"); $out1->print("${pre}unfix MD1\n"); $out1->print("${pre}fix MD1 all $ensemble temp 3000.0 3000.0 0.2 iso 0.0 0.0 2.0\n"); $out1->print("${pre}timestep 0.001\n"); $out1->print("${pre}run 50000\n"); $out1->print("${pre}unfix MD1\n"); $out1->print("${pre}fix MD1 all $ensemble temp 3000.0 300.0 0.2 iso 0.0 0.0 2.0\n"); $out1->print("${pre}timestep 0.001\n"); $out1->print("${pre}run 50000\n"); $out1->print("\n"); $out1->print("write_restart lmp_tmp.restart\n"); # $out1->print("write_restart $filenames[0].restart\n"); # マニュアル表示 $out1->print("\n"); $out1->print("\n"); $out1->print("# For reference, see blow, or search 'LAMMPS and keyword' \n"); $out1->print("# URL : https://lammps.sandia.gov/\n"); $out1->print("# Manual: https://lammps.sandia.gov/doc/Manual.html\n"); $out1->print("\n"); $out1->print("#dump user-defined ID group-ID style nCycleStepForDump FileName args\n"); $out1->print("# see https://lammps.sandia.gov/doc/dump.html\n"); $out1->print("# style: atom atom/gz atom/mpiio cfg cfg/gz cfg/mpiio custom custom/gz custom/mpiio\n"); $out1->print("# dcd h5md image local molfile movie netcdf netcdf/mpiio vtk xtc xyz xyz/gz xyz/mpiio\n"); $out1->print("# style=movie: mpg, avi, m4v\n"); $out1->print("# style=custom: args=id(AtomId), (mol(MoleculeID), proc, procp1, type(AtomType), element, mass\n"); $out1->print("# x, y, z(unscaled atom coords), xs, ys, zs(scaled coords), xu, yu, zu(unwrapped coords)\n"); $out1->print("# xsu, ysu, zsu(scaled unwrapped), ix, iy, iz(box image)\n"); $out1->print("# vx, vy, vz(velocities), fx, fy, fz(forces on atom)\n"); $out1->print("# q(atom charge), mux, muy, muz, mu(orientation of dipoles)\n"); $out1->print("# radius, diameter, omegax, omegay, omegaz\n"); $out1->print("# angmomx, angmomy, angmomz, tqx, tqy, tqz\n"); $out1->print("# c_ID, c_ID[N], f_ID, f_ID[N], v_name\n"); $out1->print("\n"); $out1->print("#units : mass len time energy velocity force Temp press viscosity charge E-field dipole density\n"); $out1->print("# real : g/mol A fs kcal/mol A/fs kcal/mol.A K atm poise e V/A e.A g/cm3\n"); $out1->print("# metal : g/mol A ps eV A/ps eV/A K bars poise e V/A e.A g/cm3\n"); $out1->print("# si : kg m s J m/s N K Pa Pa.s C V/m C.m kg/m3\n"); $out1->print("# cgs : g cm s erg cm/s dynes K dyne/cm2 poise esu dyne/esu 10^18debye g/cm3\n"); $out1->print("# electron: me bohr fs Hr bohr/au Hr/bohr K Pa e V/cm debye\n"); $out1->print("\n"); $out1->print("#thermo_style style args (to write to log file)\n"); $out1->print("# see https://lammps.sandia.gov/doc/thermo_style.html\n"); $out1->print("# style: step, elapsed, elaplong, dt, time\n"); $out1->print("# cpu, tpcpu, spcpu, cpuremain, part, timeremain\n"); $out1->print("# atoms, temp, press, pe, ke, etotal, enthalpy\n"); $out1->print("# evdwl, ecoul, epair, ebond, eangle, edihed, eimp\n"); $out1->print("# emol, elong, etail\n"); $out1->print("# vol, density, lx, ly, lz, xlo, xhi, ylo, yhi, zlo, zhi\n"); $out1->print("# xy, xz, yz, xlat, ylat, zlat\n"); $out1->print("# bonds, angles, dihedrals, impropers\n"); $out1->print("# pxx, pyy, pzz, pxy, pxz, pyz\n"); $out1->print("# fmax, fnorm, nbuild, ndanger\n"); $out1->print("# cella, cellb, cellc, cellalpha, cellbeta, cellgamma\n"); $out1->print("# c_ID, c_ID[I], c_ID[I][J], f_ID, f_ID[I], f_ID[I][J]\n"); $out1->print("# v_name, v_name[I]\n"); $out1->print("\n"); } 1;