package XCrySDen; use Exporter; @ISA = qw(Exporter); #公開したいサブルーチン @EXPORT = qw(); use strict; use Sci::Science; use JFile; use ProgVars; #use Crystal::MyUtility; use Crystal::Crystal; use Crystal::AtomType; use Crystal::AtomSite; use Crystal::CIF; my $WebRootDir = ProgVars::WebRootDir(); my $ProgramDir = ProgVars::ProgramDir(); my $KListDBDir = ProgVars::KListDBDir(); #=============================================== # 変数取得関数 #=============================================== sub KListDBDir { my $this = shift; return $this->{'KListDBDir'} if($this->{'KListDBDir'}); return $this->{'KListDBDir'} = $KListDBDir; } sub SetKListDBDir { my($this, $d) = @_; $this->{'KListDBDir'} = $d; return $d; } #=============================================== # コンストラクタ、デストラクタ #=============================================== BEGIN { } sub new { my ($module) = @_; my $this = {}; bless $this; return $this; } sub DESTROY { my $this = shift; } #=============================================== # 一般関数 #=============================================== sub AddXSFAnimationFileStepFromCIF { my ($this, $outfile, $iStep, $CIF) = @_; my $Crystal = $CIF->GetCCrystal(); $this->AddXSFAnimationFileStepFromCrystal($outfile, $iStep, $Crystal); } sub WriteXSFFileHeader { my ($this, $outfile) = @_; return $this->WriteXSFAnimationFileHeader($outfile, ''); } sub WriteXSFAnimationFileHeader { my ($this, $outfile, $nStep) = @_; unless(open(OUT,">$outfile")) { return 0; } binmode(OUT); if($nStep ne '') { print OUT "ANIMSTEPS $nStep\n"; } print OUT "CRYSTAL\n"; # print OUT "\n"; close(OUT); return 1; } sub WriteXSFAnimationFileHeaderFromCIF { my ($this, $outfile, $nStep, $CIF) = @_; return $this->WriteXSFAnimationFileHeader($outfile, $nStep); } sub AddXSFAnimationFileStepFromCrystal { my ($this, $outfile, $iStep, $Crystal) = @_; return 0 unless(open(OUT,">>$outfile")); binmode(OUT); my ($a11,$a12,$a13,$a21,$a22,$a23,$a31,$a32,$a33) = $Crystal->LatticeVectors(); print OUT "PRIMVEC $iStep\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; print OUT "CONVVEC $iStep\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; my @AtomList = $Crystal->GetCExpandedAtomSiteList(); my $nAtom = @AtomList; print OUT "PRIMCOORD $iStep\n"; printf OUT " %d 1\n", $nAtom; for(my $i = 0 ; $i < $nAtom ; $i++) { my $atom = $AtomList[$i]; my $name = $atom->AtomNameOnly(); my ($x,$y,$z) = $atom->Position(1); #print "X: $i: ($x,$y,$z)
\n"; my ($vx,$vy,$vz) = $atom->Velocity(); #print "V: $i: ($vx,$vy,$vz)
\n"; my $AtomicNumber = AtomType::GetAtomicNumber($name); my ($xc,$yc,$zc) = $Crystal->FractionalToCartesian($x,$y,$z); printf OUT "%3d %12.7f %12.7f %12.7f %12.7f %12.7f %12.7f\n", $AtomicNumber, $xc, $yc, $zc, $vx, $vy, $vz; } close(OUT); return $iStep; } sub WriteXSFFileFromCrystal { my ($this, $outfile, $iCycle, $Crystal, $Crystal2) = @_; return 0 unless(open(OUT,">>$outfile")); binmode(OUT); # my $Title = $Crystal->CrystalName(); # $Title = 'undefined' if($Title eq ''); # print OUT "# this is a specification\n"; # print OUT "# of $Title crystal structure\n"; # print OUT "\n"; # print OUT "CRYSTAL\n"; # print OUT "\n"; my ($a11,$a12,$a13,$a21,$a22,$a23,$a31,$a32,$a33) = $Crystal->LatticeVectors(); print OUT "PRIMVEC $iCycle\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; # print OUT "\n"; print OUT "CONVVEC $iCycle\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; # print OUT "\n"; my @AtomList = $Crystal->GetCExpandedAtomSiteList(); my @AtomList2; @AtomList2 = $Crystal2->GetCExpandedAtomSiteList() if($Crystal2 ne ''); my $nAtom = @AtomList; #$Crystal->nTotalExpandedAtomSite(); my $nAtom2 = @AtomList2; $nAtom = $nAtom2 if($nAtom2 > 0 and $nAtom > $nAtom2); #print "nAtom: $nAtom, $nAtom2
\n"; print OUT "PRIMCOORD $iCycle\n"; printf OUT " %d 1\n", $nAtom; #$Crystal2 != ''の時、重心の変化を調べる my ($centx1, $centy1, $centz1) = (0.0, 0.0, 0.0); my ($centx2, $centy2, $centz2) = (0.0, 0.0, 0.0); if(defined $Crystal2) { for(my $i = 0 ; $i < $nAtom ; $i++) { my $atom = $AtomList[$i]; my $atom2 = $AtomList2[$i]; my ($x,$y,$z) = $atom->Position(1); my ($x2,$y2,$z2) = $atom2->Position(1); $x2 = $Crystal->FindNearestEquivalentFractionCoordinate($x2, $x); $y2 = $Crystal->FindNearestEquivalentFractionCoordinate($y2, $y); $z2 = $Crystal->FindNearestEquivalentFractionCoordinate($z2, $z); $centx1 += $x; $centy1 += $y; $centz1 += $z; $centx2 += $x2; $centy2 += $y2; $centz2 += $z2; } $centx1 = ($centx2 - $centx1) / $nAtom; $centy1 = ($centy2 - $centy1) / $nAtom; $centz1 = ($centz2 - $centz1) / $nAtom; printf "Center change: (%12.6f, %12.6f, %12.6f)
\n", $centx1, $centy1, $centz1; } for(my $i = 0 ; $i < $nAtom ; $i++) { my $atom = $AtomList[$i]; my $name = $atom->AtomNameOnly(); my ($x,$y,$z) = $atom->Position(1); my ($fx,$fy,$fz) = $atom->Force(); #print "$i: force=($fx,$fy,$fz)\n"; ($fx,$fy,$fz) = $atom->Velocity() if(!defined $fx); #print "$i: Velocity=($fx,$fy,$fz)\n"; my $AtomicNumber = AtomType::GetAtomicNumber($name); my ($xc,$yc,$zc) = $Crystal->FractionalToCartesian($x,$y,$z); #print "$i($nAtom): ($xc,$yc,$zc)
"; if(!defined $Crystal2) { if(!defined $fz) { $fx = $fy = $fz = 0.0; } printf OUT "%3d %12.7f %12.7f %12.7f %12.7f %12.7f %12.7f\n", $AtomicNumber, $xc, $yc, $zc, $fx, $fy, $fz; } else { my $atom2 = $AtomList2[$i]; my ($x2,$y2,$z2) = $atom2->Position(1); #print "$i: x-x2: (", $y2-$y, ")
\n"; $x2 = $Crystal->FindNearestEquivalentFractionCoordinate($x2, $x) - $centx1; $y2 = $Crystal->FindNearestEquivalentFractionCoordinate($y2, $y) - $centy1; $z2 = $Crystal->FindNearestEquivalentFractionCoordinate($z2, $z) - $centz1; #print "$i: x-x2: (", $y2-$y, ")
\n"; my ($xc2,$yc2,$zc2) = $Crystal2->FractionalToCartesian($x2,$y2,$z2); printf OUT "%3d %12.7f %12.7f %12.7f %12.7f %12.7f %12.7f\n", $AtomicNumber, $xc, $yc, $zc, $xc2-$xc, $yc2-$yc, $zc2-$zc; } } close(OUT); return 1; } sub WriteXSFFileFromCIF { my ($this, $outfile, $CIF, $CIF2) = @_; my $Crystal = $CIF->GetCCrystal(); my $Crystal2; $Crystal2 = $CIF2->GetCCrystal() if($CIF2 ne ''); return $this->WriteXSFFileFromCrystal($outfile, '', $Crystal, $Crystal2) = @_; unless(open(OUT,">>$outfile")) { return 0; } binmode(OUT); my $Title = $Crystal->CrystalName(); $Title = 'undefined' if($Title eq ''); print OUT "# this is a specification\n"; print OUT "# of $Title crystal structure\n"; print OUT "\n"; print OUT "CRYSTAL\n"; print OUT "\n"; my ($a11,$a12,$a13,$a21,$a22,$a23,$a31,$a32,$a33) = $Crystal->LatticeVectors(); print OUT "PRIMVEC\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; print OUT "\n"; print OUT "CONVVEC\n"; printf OUT " %16.10f %16.10f %16.10f\n", $a11,$a12,$a13; printf OUT " %16.10f %16.10f %16.10f\n", $a21,$a22,$a23; printf OUT " %16.10f %16.10f %16.10f\n", $a31,$a32,$a33; print OUT "\n"; print OUT "PRIMCOORD\n"; my @AtomList = $Crystal->GetCExpandedAtomSiteList(); my @AtomList2; @AtomList2 = $Crystal2->GetCExpandedAtomSiteList() if($CIF2 ne ''); my $nAtom = @AtomList; #$Crystal->nTotalExpandedAtomSite(); my $nAtom2 = @AtomList2; $nAtom = $nAtom2 if($nAtom2 > 0 and $nAtom > $nAtom2); #print "nAtom: $nAtom, $nAtom2
\n"; printf OUT " %d 1\n", $nAtom; #$CIF2!=''の時、重心の変化を調べる my ($centx1, $centy1, $centz1) = (0.0, 0.0, 0.0); my ($centx2, $centy2, $centz2) = (0.0, 0.0, 0.0); if($CIF2 ne '') { for(my $i = 0 ; $i < $nAtom ; $i++) { my $atom = $AtomList[$i]; my $atom2 = $AtomList2[$i]; my ($x,$y,$z) = $atom->Position(1); my ($x2,$y2,$z2) = $atom2->Position(1); $x2 = $Crystal->FindNearestEquivalentFractionCoordinate($x2, $x); $y2 = $Crystal->FindNearestEquivalentFractionCoordinate($y2, $y); $z2 = $Crystal->FindNearestEquivalentFractionCoordinate($z2, $z); $centx1 += $x; $centy1 += $y; $centz1 += $z; $centx2 += $x2; $centy2 += $y2; $centz2 += $z2; } $centx1 = ($centx2 - $centx1) / $nAtom; $centy1 = ($centy2 - $centy1) / $nAtom; $centz1 = ($centz2 - $centz1) / $nAtom; print "Center change: ($centx1,$centy1,$centz1)
\n"; } for(my $i = 0 ; $i < $nAtom ; $i++) { my $atom = $AtomList[$i]; my $name = $atom->AtomNameOnly(); my ($x,$y,$z) = $atom->Position(1); my $AtomicNumber = AtomType::GetAtomicNumber($name); my ($xc,$yc,$zc) = $Crystal->FractionalToCartesian($x,$y,$z); #print "$i($nAtom): ($xc,$yc,$zc)
"; if($CIF2 eq '') { printf OUT "%3d %12.7f %12.7f %12.7f %12.7f %12.7f %12.7f\n", $AtomicNumber, $xc, $yc, $zc, 0.0, 0.0, 0.0; } else { my $atom2 = $AtomList2[$i]; my ($x2,$y2,$z2) = $atom2->Position(1); #print "$i: x-x2: (", $y2-$y, ")
\n"; $x2 = $Crystal->FindNearestEquivalentFractionCoordinate($x2, $x) - $centx1; $y2 = $Crystal->FindNearestEquivalentFractionCoordinate($y2, $y) - $centy1; $z2 = $Crystal->FindNearestEquivalentFractionCoordinate($z2, $z) - $centz1; #print "$i: x-x2: (", $y2-$y, ")
\n"; my ($xc2,$yc2,$zc2) = $Crystal2->FractionalToCartesian($x2,$y2,$z2); printf OUT "%3d %12.7f %12.7f %12.7f %12.7f %12.7f %12.7f\n", $AtomicNumber, $xc, $yc, $zc, $xc2-$xc, $yc2-$yc, $zc2-$zc; } } close(OUT); return 1; } sub WriteBXSFFile { my ($this, $OutFile, $PrimCrystal, $Title, $nBand, $nx, $ny, $nz, $EF, $BandIndex, $BandEnergy, $ProgName, $OneByOne, $IsPrint) = @_; $IsPrint = 1 if(!defined $IsPrint); print("Save to [$OutFile]\n") if($IsPrint); open(OUT, ">$OutFile") or return 0; my ($nx1, $ny1, $nz1) = ($nx+1, $ny+1, $nz+1); print OUT <{Ra11}, $PrimCrystal->{Ra12}, $PrimCrystal->{Ra13}); printf(OUT " %12.4g %12.4g %12.4g\n", $PrimCrystal->{Ra21}, $PrimCrystal->{Ra22}, $PrimCrystal->{Ra23}); printf(OUT " %12.4g %12.4g %12.4g\n", $PrimCrystal->{Ra31}, $PrimCrystal->{Ra32}, $PrimCrystal->{Ra33}); for(my $ib = 0 ; $ib < $nBand ; $ib++) { printf(OUT " BAND: %3d\n", $BandIndex->[$ib]); my $ie = 0; for(my $ix = 0 ; $ix <= $nx ; $ix++) { for(my $iy = 0 ; $iy <= $ny ; $iy++) { for(my $iz = 0 ; $iz <= $nz ; $iz++) { printf(OUT " %8.5f", $BandEnergy->[$ib][$ix][$iy][$iz]); print(OUT "\n") if($OneByOne); $ie++; if($ie % 10 == 0) { # if($ie % 10 == 0 and $iz != $nz) { print(OUT "\n") if(!$OneByOne); } } print(OUT "\n"); } if($OneByOne) { } else { print(OUT "\n\n"); } $ie = 0; } } print OUT <KListDBDir(); my $fmask = Deps::MakePath($KListDBDir, "${iSPG}_*.klist", 0); #print "KList DB fmask: $fmask
\n"; my ($path) = glob($fmask); if(!defined $path) { # if($SPGName =~ /^\s*F/i) { if($CellType =~ /^\s*F-Prim/i) { $path = Deps::MakePath($KListDBDir, "FCC-PrimitiveCell.klist", 0); } # elsif($SPGName =~ /^\s*I/i) { elsif($SPGName =~ /^\s*I-Prim/i) { $path = Deps::MakePath($KListDBDir, "BCC-PrimitiveCell.klist", 0); } elsif($SPGName =~ /^\s*[HR]/i) { $path = Deps::MakePath($KListDBDir, "HCP.klist", 0); } } if(!defined $path) { $path = Deps::MakePath($KListDBDir, "SimpleCubic.klist", 0); } #print "KList DB file: $path
\n"; my $in = new JFile($path, "r"); return ($path) unless($in); my @KList; my $nPoint = 0; while(!$in->eof()) { my $line = $in->ReadLine(); my $label = substr($line, 0, 10); my $rest = substr($line, 10); Utils::DelSpace($label); $nPoint++; next if($label eq ''); last if($label eq 'END'); #print "line: $line
\n"; #print "rest: $rest
\n"; my ($kx, $ky, $kz, $div) = Utils::Split("\\s+", $rest); #print "div=$div: $kx $ky $kz
\n"; $kx /= $div; $ky /= $div; $kz /= $div; #print "$label: $kx $ky $kz ($nPoint)
\n"; my %k; $k{'Label'} = $label; $k{'kx'} = $kx; $k{'ky'} = $ky; $k{'kz'} = $kz; $k{'nPoint'} = $nPoint; push(@KList, \%k); $nPoint = 0; } $in->Close(); return ($path, @KList); } 1;