package MXD; use Exporter; @ISA = qw(Exporter); #公開したいサブルーチン @EXPORT = qw(); use strict; use File::Basename; use Cwd; use IPC::Open2; use Sci::Science; use ProgVars; #use Crystal::MyUtility; use Crystal::Crystal; use Crystal::SpaceGroupObject; use Crystal::AtomType; use Crystal::AtomSite; use Crystal::CIF; #=============================================== # スクリプト大域変数 #=============================================== my $LF = "
\n"; my $DirectorySeparator = "\\"; #F0...Born-Mayer Potential CONSTANT (J/A) # R(r) = F0 * (bi+bj) * exp( (ai+aj - rij) / (bi+bj) ) my $F0 = 6.947700141e-21; #K0...Coulomb Potential Coefficient (J.A) e^2/4/PI/E0*1.0E+10 my $K0=2.307100407e-18; #=============================================== # パス(読み込みDB) # Web関係変数 # CGI の仮想パス # プログラム名 #=============================================== my $Program = basename($0); my $ProgramDir = "d:\\Programs"; my $MXDDir = ProgVars::MXDDir(); my $MXDOrtoDir = ProgVars::MXDOrtoDir(); my $MXDExecDir = ProgVars::MXDExecDir(); my $SX1DBPath = ProgVars::SX1DBPath(); my $MXDInputPath = ProgVars::MXDInputPath(); BEGIN { } sub new { my ($module) = @_; my $this = {}; bless $this; return $this; } sub DESTROY { my $this = shift; } sub SetSampleName { my ($this, $name) = @_; return $this->{'SampleName'} = $name; } sub SampleName { my ($this) = @_; return $this->{'SampleName'}; } sub GetBusingParameter { my ($this,$atomname) = @_; unless(open(IN, "<$SX1DBPath")) { print "Error in MXD.pm::GetBusingParameter: " ."Can not read DB [$SX1DBPath].
\n"; return (''); } ; while() { my ($name, $mass, $charge, $ai, $bi, $ci, $rad) = split(/\s+/, $_); if(uc $name eq uc $atomname) { return ($mass, $charge, $ai, $bi, $ci, $rad); } } close(IN); return (''); } sub SetnExpandCells { my ($this, $nExpandLatticeA, $nExpandLatticeB, $nExpandLatticeC) = @_; $this->{'nExpandLatticeA'} = $nExpandLatticeA; $this->{'nExpandLatticeB'} = $nExpandLatticeB; $this->{'nExpandLatticeC'} = $nExpandLatticeC; return ($this->{'nExpandLatticeA'}, $this->{'nExpandLatticeB'}, $this->{'nExpandLatticeC'}); } sub nExpandCells { my ($this) = @_; return ($this->{'nExpandLatticeA'}, $this->{'nExpandLatticeB'}, $this->{'nExpandLatticeC'}); } sub MakeMXDFiles { my ($this, $Crystal, $MXDFunction, $fname05, $fname07, $fname10, $Version, $IsChooseRandomly) = @_; if(!defined $IsChooseRandomly) { $IsChooseRandomly = $Version; $Version = 1.0; } $Version = 2.0 if(!defined $Version); my $LF = "
\n"; my $ret = $this->MakeFILE05($Crystal, $MXDFunction, $fname05, $IsChooseRandomly); return $ret if($ret <= 0); $ret = $this->MakeFILE07($Crystal, $MXDFunction, $fname07, $Version, $IsChooseRandomly); return $ret if($ret <= 0); if($MXDFunction =~ /^XD/i) { $ret = $this->MakeFILE10($Crystal, $MXDFunction, $fname10, $IsChooseRandomly); return $ret if($ret <= 0); } return 1; } sub MakeFILE05 { my ($this, $Crystal, $MXDFunction, $fname05, $IsChooseRandomly) = @_; my $LF = "
\n"; unless(open(OUT,">$fname05")) { print "Can not write to $fname05.$LF$LF"; return -1; } my $SampleName = $this->SampleName(); my $mode = "XD"; $mode = "MD" if($MXDFunction =~ /^MD/i); printf OUT "%2s.......I....:....I....:....I....:....I....:....I....:....I....:....I:\n", $mode; print OUT "START $SampleName\n"; print OUT "NORMAL 01000. 0100. 50. 5. 5. :\n"; print OUT "NOACCUM 2.0 1.0 0.0 :\n"; print OUT "T SCALING 300.00 1.0 10. :\n"; print OUT "P SCALING 0.0001 0.0001 0.0001 :\n"; print OUT "V :\n"; print OUT "BUSING 3. 0.0 :\n"; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteListByOutputMode(); my $nExpandedAtomSite = @ExpandedAtomSiteList; my @atomlist = $Crystal->GetCAtomTypeList(); my %AtomCount; for(my $i = 0 ; $i < $nExpandedAtomSite ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); $AtomCount{$atomname}++; } my $count =0; for(my $i = 0 ; $i < @atomlist ; $i++) { my $atom = $atomlist[$i]; my $atomname = $atom->AtomNameOnly(); # my $charge = $atom->Charge(); $count++; my ($Mass, $charge, $ai, $bi, $ci, $rad) = $this->GetBusingParameter($atomname); $Mass = AtomType::GetAtomInformationByKey($atomname, "原子量") if($Mass eq ''); printf OUT "%1d %-2s%5d. %6.3f %7.2f %9.4f %9.4f %9.4f :\n", $count, $atomname, $AtomCount{$atomname}, $charge, $Mass, $ai, $bi, $ci; } print OUT " :\n"; print OUT " :\n"; printf OUT "%2s.......I....:....I....:....I....:....I....:....I....:....I....:....I:\n", $mode; print OUT "STOP :\n"; print OUT "\n"; close(OUT); return 1; } sub MakeFILE07 { my ($this, $Crystal, $MXDFunction, $fname07, $Version, $IsChooseRandomly) = @_; if(!defined $IsChooseRandomly) { $IsChooseRandomly = $Version; $Version = 1.0; } $Version = 2.0 if(!defined $Version); my $LF = "
\n"; my $SampleName = $this->SampleName(); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParametersByOutputMode(0); my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteListByOutputMode(); my $nExpandedAtomSite = @ExpandedAtomSiteList; unless(open(OUT,">$fname07")) { print "Can not write to $fname07.$LF$LF"; return -1; } printf OUT "%-60s%5d%5d\n", $SampleName, 0, 0; printf OUT " %6d%3d 0 0 0 0 0 1 0 0 0\n", $nExpandedAtomSite, $nAtomType; for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); printf OUT " %-4s", $atomname; } print OUT "\n"; my %AtomCount; for(my $i = 0 ; $i < $nExpandedAtomSite ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); $AtomCount{$atomname}++; } for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); printf OUT "%6d", $AtomCount{$atomname}; } print OUT "\n"; my $CurPos = 1; for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); printf OUT "%6d", $CurPos; $CurPos += $AtomCount{$atomname}; } print OUT "\n"; my $EndPos = 0; my %iAtom; for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); $iAtom{$atomname} = $i+1; $EndPos += $AtomCount{$atomname}; printf OUT "%6d", $EndPos; } print OUT "\n"; printf OUT " 300.00 1.0000 300.00 0.00010 0.00010 0.00010\n"; printf OUT " 0.200E-14 %10.6f%10.6f%10.6f 0.000000 0.000000 0.000000\n", $a, $b, $c; printf OUT "%10.6f 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000\n", $Crystal->Density(); for(my $it = 0 ; $it < $nAtomType ; $it++) { my $atomtype = $AtomTypeList[$it]; my $atomtypename = $atomtype->AtomNameOnly(); for(my $i = 0 ; $i < @ExpandedAtomSiteList ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); next if(uc $atomname ne uc $atomtypename); my ($x,$y,$z) = $atom->Position(1); if($Version >= 2.0) { printf OUT "%10.8f%10.8f%10.8f %9.7f%9.7f%9.7f %8.6f %8.6f %8.6f%3d\n", $x, $y, $z, 0, 0, 0, $x, $y, $z, $iAtom{$atomname}; } else { printf OUT "%9.7f%9.7f%9.7f %8.6f%8.6f%8.6f %9.6f%9.6f%9.6f\n", $x, $y, $z, 0, 0, 0, $x, $y, $z; } } } print OUT " 800 300 0 940608\n"; close(OUT); return 1; } sub MakeFILE10 { my ($this, $Crystal, $MXDFunction, $fname10, $IsChooseRandomly) = @_; my $LF = "
\n"; #print "

Error: MD is not supported.

\n"; #return -1; my ($nx, $ny, $nz ) = $this->nExpandCells(); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParametersByOutputMode(0); my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteListByOutputMode(); my $nExpandedAtomSite = @ExpandedAtomSiteList; my $SPG = $Crystal->GetCSpaceGroup(); my $nSymmetry = 1; #$SPG->nSymmetryOperation(); unless(open(OUT,">$fname10")) { print "Can not write to $fname10.$LF$LF"; return -1; } printf OUT "%10.7f%10.7f%10.7f%10.8f%10.8f%10.8f\n", $a, $b, $c, $alpha, $beta, $gamma; printf OUT "%5d%5d%5d%5d%5d%5d%4s %6d\n", $nx, $ny, $nz, $nExpandedAtomSite, $nExpandedAtomSite, $nSymmetry, ' ', $nAtomType; my %AtomCount; for(my $i = 0 ; $i < $nExpandedAtomSite ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); $AtomCount{$atomname}++; } for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); printf OUT "%-4s", $atomname; print OUT "\n" if(($i+1) % 18 == 0); } print OUT "\n" if($nAtomType % 18 != 0); for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $atomname = $atom->AtomNameOnly(); printf OUT "%4d", $AtomCount{$atomname}; print OUT "\n" if(($i+1) % 18 == 0); } print OUT "\n" if($nAtomType % 18 != 0); for(my $it = 0 ; $it < $nAtomType ; $it++) { my $atomtype = $AtomTypeList[$it]; my $atomtypename = $atomtype->AtomNameOnly(); for(my $i = 0 ; $i < @ExpandedAtomSiteList ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); next if(uc $atomname ne uc $atomtypename); my ($x,$y,$z) = $atom->Position(1); printf OUT "%5d%10.7f%10.7f%10.7f\n", 1, $x, $y, $z, 0, 0, 0, $x, $y, $z; # $it+1, $x, $y, $z, 0, 0, 0, $x, $y, $z; } } print OUT " 1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0\n"; for(my $i = 0 ; $i < @ExpandedAtomSiteList ; $i++) { printf OUT "%6d", $i*200 + 1; print OUT "\n" if(($i+1) % 12 == 0); } print OUT "\n" if($nExpandedAtomSite % 12 != 0); print OUT " \n"; close(OUT); return 1; } sub MakeXTALDATA { my ($this, $Crystal, $Function, $WorkingDirectory, $FilePrefix) = @_; my $LF = "
\n"; my $SampleName = $this->SampleName(); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParameters(); my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AsymmetricAtomSiteList = $Crystal->GetCExpandedAtomSiteListByOutputMode(); my $nAsymmetricAtomSite = @AsymmetricAtomSiteList; # my $SPG = "P 1"; #$Crystal->GetCSpaceGroup(); # my $nSymmetry = 1; #$SPG->nSymmetryOperation(); my $FileXTALDATA = Deps::MakePath($WorkingDirectory, "XTALDATA.DAT", 0); my $MXDInputFile = Deps::MakePath($WorkingDirectory, "MXDInput.in", 0); my $MXDInputOutFile = Deps::MakePath($WorkingDirectory, "MXDInput.out", 0); my $MXDFile05File = Deps::MakePath($WorkingDirectory, "FILE05.dat", 0); my $MXDFile06File = Deps::MakePath($WorkingDirectory, "FILE06.dat", 0); my $MXDFile07File = Deps::MakePath($WorkingDirectory, "FILE07.dat", 0); my $MXDFile10File = Deps::MakePath($WorkingDirectory, "FILE10.dat", 0); my $MXDf05File = Deps::MakePath($WorkingDirectory, "$FilePrefix.f05", 0); my $MXDf07File = Deps::MakePath($WorkingDirectory, "$FilePrefix.f07", 0); my $MXDf10File = Deps::MakePath($WorkingDirectory, "$FilePrefix.f10", 0); print "[$FileXTALDATA] was deleted.$LF" if(unlink($FileXTALDATA)); print "[$MXDInputFile] was deleted.$LF" if(unlink($MXDInputFile)); print "[$MXDInputOutFile] was deleted.$LF" if(unlink($MXDInputOutFile)); print "[$MXDFile05File] was deleted.$LF" if(unlink($MXDFile05File)); print "[$MXDFile06File] was deleted.$LF" if(unlink($MXDFile06File)); print "[$MXDFile07File] was deleted.$LF" if(unlink($MXDFile07File)); print "[$MXDFile10File] was deleted.$LF" if(unlink($MXDFile10File)); print "[$MXDf05File] was deleted.$LF" if(unlink($MXDf05File)); print "[$MXDf07File] was deleted.$LF" if(unlink($MXDf07File)); print "[$MXDf10File] was deleted.$LF" if(unlink($MXDf10File)); print "$LF"; print "Create XTALDATA.DATA [$FileXTALDATA]$LF"; unless(open(OUT,">$FileXTALDATA")) { print "Can not write to $FileXTALDATA.$LF$LF"; return (-1); } print OUT ':"""""""""""""""""""""""""""""""""""""""""""""""""""""""""":', "\n"; print OUT ": CRYSTAL DATA BASE CREATED BY MXD.pm (C) T. Kamiya :\n"; print OUT ":..........................................................:\n"; print OUT ": :\n"; print OUT "----:----I----:----I----:----I----:----I----:----I----:----I\n"; print OUT "...................I \n"; my $ShortSampleName = $SampleName; $ShortSampleName =~ s/^\s+//; $ShortSampleName =~ s/\s.*$//; $ShortSampleName = substr($ShortSampleName, 0, 18); printf OUT "%-19sI----:----I----:----I----:----I----:----I\n", $ShortSampleName; print OUT "$SampleName\n"; printf OUT "%8.3f %8.3f %8.3f %8.3f %8.3f %8.3f\n", $a, $b, $c, $alpha, $beta, $gamma; my $nCation = 0; my $nAnion = 0; for(my $i = 0 ; $i < $nAsymmetricAtomSite ; $i++) { my $atom = $AsymmetricAtomSiteList[$i]; my $charge = $atom->Charge(); if($charge =~ /-/) { $nAnion++; } else { $nCation++; } } # my $SPGName = $SPG->SPGName(); # $SPGName =~ s/\s//g; # my @SymmetryOperation = ('x,y,z'); #$SPG->ExpandSymmetryOperation(); # my $nSymmetryOperation = 1; #@SymmetryOperation; # printf OUT "%-10s %4d %d %4d %4d\n", $SPGName, $nSymmetry, 0, $nCation, $nAnion; printf OUT "%-10s %4d %d %4d %4d\n", "P1", 1, 0, $nCation, $nAnion; printf OUT "%02d%02d%02d%2d%2d%2d%2d%2d%2d%2d%2d%2d\n", 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1; my %AtomCount; for(my $i = 0 ; $i < $nAsymmetricAtomSite ; $i++) { my $atom = $AsymmetricAtomSiteList[$i]; my $name = uc $atom->AtomNameOnly(); # $name = sprintf "%2s", $name; my $charge = $atom->Charge(); $charge = - ($charge + 0) if($charge =~ /-/); my ($x,$y,$z) = $atom->Position(); my $iAtomType = $Crystal->FindiAtomType($name); $AtomCount{$name}++; # 1020 FORMAT (A4,1X, I5, F10.5,3F10.5, 3I5) printf OUT "%-4s %5d%10.5f%10.5f%10.5f%10.5f\n", "$name" . $AtomCount{$name}, $iAtomType, abs($charge), $x, $y, $z; } for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $name = uc $atom->AtomNameOnly(); $name = sprintf "%2s", $name; printf OUT "%-5s", $name; } print OUT "\n"; print OUT "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n"; close(OUT); print "Change working directory to [$WorkingDirectory]$LF"; unless(chdir($WorkingDirectory)) { print "Error in MXD.pm::MakeXTALDATA: " ."Could not change to [$WorkingDirectory]$LF"; my $dir = cwd(); print "+++ Current working directory is [$dir].$LF"; return (-1); } print "Create MXDInput.in [$MXDInputFile]$LF"; unless(open(OUTI,">$MXDInputFile")) { print "Can not write to $MXDInputFile.$LF$LF"; return (-1); } print "Execute MXDInput [$MXDInputPath]$LF"; print "
\n";
no strict;
	my $pid = open2(IN, OUT, $MXDInputPath);
use strict;
	unless(open(OUT2,">$MXDInputOutFile")) {
		print "Can not write to $MXDInputOutFile.$LF$LF";
		close(IN);
		close(OUT);
		return (-1);
	}

#	print "lat: ", $Crystal->LatticeSystem(), "
"; # print "lat: $a $b $c $alpha $beta $gamma
"; print OUTI "$ShortSampleName\n"; print OUT "$ShortSampleName\n"; if($Crystal->LatticeSystem() eq 'hexagonal' or ($Crystal->LatticeSystem() eq 'rhombohedral' and abs($alpha-90.0) < 0.1 and abs($beta-90.0) < 0.1 and abs($gamma-120.0) <0.1) ) { print "This crystal has a hexagonal cell.\n"; print "The hexagonal cell was converted to the orthorhombic cell.\n"; print OUTI "y\n"; print OUT "y\n"; } for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $name = uc $atom->AtomNameOnly(); $name = sprintf "%2s", $name; printf OUT "%-5s", $name; printf OUTI "%-5s", $name; #CA O TI #123451234512345 } print OUT "\n"; print OUTI "\n"; my ($nx,$ny,$nz) = $this->nExpandCells(); printf OUT "%5d%5d%5d\n", $nx, $ny, $nz; printf OUTI "%5d%5d%5d\n", $nx, $ny, $nz; print OUT "\n"; print OUTI "\n"; printf OUT " %7.2f\n", 300.0; printf OUTI " %7.2f\n", 300.0; print OUT "y\n"; print OUTI "y\n"; print OUT "\n\n"; print OUTI "\n\n"; close(OUTI); close(OUT); while() { # print "$_$LF"; print OUT2 "$_\n"; } close(IN); close(OUT2); #Convert FILE05 to .f05 unless(open(IN2,"<$MXDFile05File")) { print "Can not read [$MXDFile05File].$LF$LF"; return (-1); } unless(open(OUT2,">$MXDf05File")) { print "Can not write to [$MXDf05File].$LF$LF"; return (-1); } #XD.......I....:....I....:....I....:....I....:....I....:....I....:....I: my $line = ; $line =~ s/^XD/MD/ if($Function =~ /^MD/i); print OUT2 $line; #START IGZOm1 (1 x 1 x 1) : $line = ; print OUT2 $line; #ECONOMY 00500. 0500. 50. 5. 5. : $line = ; $line =~ s/^ECONOMY/NORMAL /; $line =~ s/00500/05000/; print OUT2 $line; #NOACCUM 2.00 1.0 0.0 : $line = ; print OUT2 $line; #T SCALING 300.00 -0.1 1. : $line = ; print OUT2 $line; #P NO-CNTL 0.0001 0.0001 0.0001 : $line = ; $line =~ s/^P NO-CNTL/P SCALING/; print OUT2 $line; #V CONST. : $line = ; $line =~ s/^V CONST. /V /; print OUT2 $line; #BUSING 3. 0.0 : $line = ; print OUT2 $line; for(my $i = 0 ; $i < $nAtomType ; $i++) { #1 GA 12. 3.000 69.72 0.000 0.000 0.000 : $line = ; my ($sn, $name, $count) = ($line =~ /^\s*(\d+)\s+(\S+)\s+(\S+)/); #print "line: $line
"; #print "sn: $sn, $name, $count
"; my $iAtom = $Crystal->FindiAtomType($name); my $atom = $AtomTypeList[$iAtom-1]; my ($Mass, $charge, $ai, $bi, $ci, $rad) = $this->GetBusingParameter($name); $charge = $atom->Charge() if($charge eq ''); $Mass = AtomType::GetAtomInformationByKey($name, "原子量") if($Mass eq ''); printf OUT2 "%1d %-2s%5d. %6.3f %7.2f %9.4f %9.4f %9.4f :\n", $sn, $name, $count, $charge, $Mass, $ai, $bi, $ci; } # : $line = ; print OUT2 $line; $line = ; print OUT2 $line; #XD.......I....:....I....:....I....:....I....:....I....:....I....:....I: $line = ; $line =~ s/^XD/MD/ if($Function =~ /^MD/i); print OUT2 $line; #STOP : $line = ; print OUT2 $line; close(IN2); close(OUT2); use strict; print "
\n"; $MXDFile07File = $MXDf07File if(rename($MXDFile07File, $MXDf07File)); $MXDFile10File = $MXDf10File if(rename($MXDFile10File, $MXDf10File)); return ($FileXTALDATA, $MXDInputFile, $MXDInputOutFile, $MXDf05File, $MXDFile06File, $MXDFile07File, $MXDFile10File); } sub UijWithParams { my ($this, $r, $Zi, $ai, $bi, $ci, $Zj, $aj, $bj, $cj) = @_; my $KZ = $K0 * $Zi * $Zj; my $Aij = $ai + $aj; my $Bij = $bi + $bj; my $KA = $F0 * $Bij * exp($Aij / $Bij); my $Uij = $KZ / $r + $KA * exp(-$r / $Bij); return $Uij; } sub dUijdrWithParams { my ($this, $r, $Zi, $ai, $bi, $ci, $Zj, $aj, $bj, $cj) = @_; my $KZ = $K0 * $Zi * $Zj; my $Aij = $ai + $aj; my $Bij = $bi + $bj; my $KA = $F0 * $Bij * exp($Aij / $Bij); my $dUijdr = -$KZ / ($r*$r) - $KA / $Bij * exp(-$r / $Bij); return $dUijdr; } 1;