package CRYSTAL06;
use Exporter;
@ISA = qw(Exporter);
#公開したいサブルーチン
@EXPORT = qw();
use strict;
use File::Basename;
use ProgVars;
use Utils;
use GraphData;
use Sci::Science;
use Crystal::Crystal;
use Crystal::AtomType;
use Crystal::AtomSite;
use Crystal::XCrySDen;
use Crystal::CIF;
#===============================================
# スクリプト大域変数
#===============================================
my $LF = "
\n";
my $DirectorySeparator = Deps::DirectorySeparator();
#===============================================
# パス(読み込みDB)
# Web関係変数
# CGI の仮想パス
# プログラム名
#===============================================
my $Program = ProgVars::Program();
my $ProgramDir = ProgVars::ProgramDir();
my $CRYSTAL06Dir = ProgVars::CRYSTAL06Dir();
my $BasisSetDir = Deps::MakePath($CRYSTAL06Dir, "Basis_Sets", 0);
my $WebRootDir = ProgVars::WebRootDir();
#my $DVXaDir = ProgVars::DVXaDir();
#my $PeriodicTable1DBPath = Deps::MakePath($DVXaDir, "PeriodicTable1.html", 0);
#============================================================
# 変数等取得、再定義関数
#============================================================
sub ClearAll { my $this=shift; undef $this->{'FileType'}; undef $this->{'DataArray'}; }
sub FileType { return shift->{'FileType'}; }
sub FileName { return shift->{'FileName'}; }
sub SetFileName { my ($this,$f)=@_; return $this->{'FileName'} = $f; }
#sub DataArray { return shift->{'DataArray'}; }
#sub SetDataArray { my ($this, $da) = @_; return $this->{'DataArray'} = $da; }
sub SetSampleName { my ($this,$n)=@_; return $this->{'SampleName'} = $n; }
sub SampleName { return shift->{'SampleName'}; }
sub GetFileName {
my($this, $path, $fname) = @_;
my ($drive, $dir, $filename, $ext, $lastdir, $filebody)
= Deps::SplitFilePath($path);
my $s = Deps::MakePath($drive, $dir);
return Deps::MakePath($s, $fname);
}
sub GetD12FileName { my($this,$f)=@_; return Deps::ReplaceExtension($f, ".d12"); }
sub GetD3FileName { my($this,$f)=@_; return Deps::ReplaceExtension($f, ".d12"); }
sub FindD12FileName
{
my ($path) = @_;
my @files = <*.d12>;
print " *** d12 file: $files[0]\n";
return $files[0];
}
sub ReadSampleNameFromD12File
{
my ($path) = @_;
my $in = new JFile($path, "rb");
if(!$in) {
print("Error: Can not read [$path].\n");
return undef;
}
my $line = $in->ReadLine();
$in->Close();
Utils::DelSpace($line);
return $line;
}
#============================================================
# 継承クラスで定義しなおす関数
#============================================================
sub CheckFileType
{
my ($path) = @_;
my ($drive, $dir, $filename, $ext, $lastdir, $filebody)
= Deps::SplitFilePath($path);
#print "f: $filename\n";
if($filename =~ /\.out$/i) {
return "CRYSTAL06 OUTPUT file";
}
elsif($filename =~ /\.outp$/i) {
return "CRYSTAL06 PROPERTY OUTPUT file";
}
elsif($filename =~ /^DOSS\.DAT$/i) {
return "CRYSTAL06 DOS file";
}
elsif($filename =~ /^BAND\.DAT$/i) {
return "CRYSTAL06 BAND file";
}
return undef;
}
sub ReadStructureFromD12
{
my ($this, $path) = @_;
my $Crystal = new Crystal;
my $SPG = $Crystal->GetCSpaceGroup();
my $in = new JFile($path, "rb");
if(!$in) {
print("Error in CRYSTAL06::ReadStructureFromD12: Can not read [$path].\n");
return undef;
}
my $Sample = $in->ReadLine();
Utils::DelSpace($Sample);
my $line = $in->ReadLine();
if($line =~ /CRYSTAL/i) {
$in->ReadLine();
my $iSPG = $in->ReadLine() + 0;
print " iSPG: $iSPG\n";
$SPG->ReadRietanSpaceGroupDB($iSPG);
#print "SPG:ls: ", $SPG->LatticeSystem(), "\n";
$Crystal->SetLatticeSystem($SPG->LatticeSystem());
$line = $in->ReadLine();
my (@a) = Utils::Split("\\s+", $line);
#print "l: $a[0]\n";
$Crystal->SetMinimalLatticeParameters(@a);
my $nSites = $in->ReadLine() + 0;
print " nSites: $nSites\n";
my %AtomCount;
for(my $is = 0 ; $is < $nSites ; $is++) {
$line = $in->ReadLine();
my ($AtomicNumber, $x, $y, $z) = Utils::Split("\\s+", $line);
my $atomtype = $AtomicNumber;
$AtomCount{$atomtype}++;
my $Label = $atomtype . "-" . $AtomCount{$atomtype};
$Crystal->AddAtomSite($Label, $atomtype, $x, $y, $z, 1.0);
print " $Label: $atomtype: ($x, $y, $z)\n";
}
}
$in->Close();
$Crystal->ExpandCoordinates();
return $Crystal;
}
sub ReadOUTPUT
{
my ($this, $path, $target) = @_;
my $HartreeToeV = Sci::HartreeToeV();
print "CRYSTAL06::ReadOUTPUT: Read [$path].\n";
my $in = new JFile($path, "rb");
return undef unless($in);
$this->SetDataArray(new GraphDataArray);
my $Data = new GraphData;
my ($SampleName) = $in->ReadLine();
Utils::DelSpace($SampleName);
#print "Sample: $SampleName\n";
$Data->SetTitle($SampleName);
if($target =~ /ForceConvergence/i) {
}
else { #'EnergyConvergence'
my @Iteration;
my @Energy;
my $iter = 0;
$in->rewind();
while(!$in->eof()) {
my $line = $in->SkipTo("^ CYC ");
# my $line = $in->SkipTo("^\\s*CYC \\d+");
#print "line: $line\n";
last if($in->eof());
my ($DETot) = ($line =~ /DETOT\s+([\d\.+\-Ee]+)/i);
$Energy[$iter] = $DETot * $HartreeToeV;
$Iteration[$iter] = $iter+1;
print "i=$iter: dE(total)=$Energy[$iter]\n";
$iter++;
}
$Data->{'x0'} = \@Iteration;
$Data->{'x0_Name'} = "Iteration";
$Data->{'y0'} = \@Energy;
$Data->{'y0_Name'} = "Energy / eV";
}
$in->Close();
$Data->CalMinMax();
$this->{'DataArray'}->AddGraphData($Data);
$this->{'DataArray'}->{'TargetData'} = $target;
print "CRYSTAL06::ReadOUTPUT: finished.\n";
return $path;
}
sub ReadOUTPUTP
{
my ($this, $filename, $TargetData) = @_;
return undef;
}
sub ReadDOSS
{
my ($this, $filename) = @_;
my $HartreeToeV = Sci::HartreeToeV();
print "CRYSTAL06::ReadDOSS: Read [$filename].\n";
my $d12File = FindD12FileName($filename);
my $SampleName = ReadSampleNameFromD12File($d12File);
my $EF = 0.0;
print "EF: $EF eV\n";
my $in = new JFile($filename, "rb");
if(!$in) {
print("Error: Can not read [$filename].\n");
return undef;
}
$this->SetDataArray(new GraphDataArray);
## NEPTS 102 NPROJ 3 NSPIN 1
my $line = $in->ReadLine();
#print "line: $line\n";
my ($nData) = ($line =~ /NEPTS\s+(\d+)\s/i);
my ($nDOS) = ($line =~ /NPROJ\s+(\d+)\s/i);
my ($nSpin) = ($line =~ /NSPIN\s+(\d+)\s/i);
print(" nData: $nData\n");
print(" nDOS : $nDOS\n");
print(" nSpin: $nSpin\n");
my $Data0 = new GraphData;
$Data0->SetTitle($SampleName);
my $Data1;
if($nDOS > 1) {
$Data1 = new GraphData;
$Data1->SetTitle($SampleName);
}
##
#@ XAXIS LABEL "ENERGY (HARTREE)"
#@ YAXIS LABEL "DENSITY OF STATES (STATES/HARTREE/CELL)"
$in->ReadLine();
$in->ReadLine();
$in->ReadLine();
my @Energy;
my @pDOS;
my @Ne;
for(my $j = 0 ; $j < $nDOS ; $j++) {
my @DOS;
$pDOS[$j] = \@DOS;
}
for(my $i = 0 ; $i < $nData ; $i++) {
$line = $in->ReadLine();
last if(not defined $line);
my @a = Utils::Split("\\s+", $line);
last if(not defined $a[1]);
$Energy[$i] = $HartreeToeV*($a[0] - $EF);
print " $i: $Energy[$i] ";
for(my $j = 0 ; $j < $nDOS ; $j++) {
$pDOS[$j]->[$i] = $a[$j+1];
print $pDOS[$j]->[$i], " ";
}
print "\n";
$Ne[$i] = 2;
last if($in->eof());
}
for(my $j = 0 ; $j < $nDOS ; $j++) {
$Data0->{"x$j"} = \@Energy;
$Data0->{"x${j}_Name"} = "Energy / eV";
$Data0->{"y$j"} = $pDOS[$j];
$Data0->{"y${j}_Name"} = "DOS";
}
$Data0->CalMinMax();
$this->{'DataArray'}->AddGraphData($Data0);
print "CRYSTAL06::ReadDOSS: finished.\n";
return $filename;
}
sub ReadBAND
{
my ($this, $path) = @_;
my $HartreeToeV = Sci::HartreeToeV();
print "CRYSTAL06::ReadBAND: Read [$path].\n";
my $d12File = FindD12FileName($path);
my $SampleName = ReadSampleNameFromD12File($d12File);
my $Crystal = $this->ReadStructureFromD12($d12File);
my $EF = 0.0;
print "EF: $EF eV\n";
my $in = new JFile($path, "rb");
return undef unless($in);
## NKPT 20 NBND 8 NSPIN 1
my $line = $in->ReadLine();
#print "line: $line\n";
my ($nKPoint) = ($line =~ /NKPT\s+(\d+)\s/i);
my ($nBand) = ($line =~ /NBND\s+(\d+)\s/i);
my ($nSpin) = ($line =~ /NSPIN\s+(\d+)\s/i);
print(" nKPoint: $nKPoint\n");
print(" nBand : $nBand\n");
print(" nSpin : $nSpin\n");
## NPANEL 3
$line = $in->ReadLine();
my ($nPanel) = ($line =~ /NPANEL\s+(\d+)\s/i);
print(" nPanel : $nPanel\n");
my (@kbx, @kby, @kbz, @nKPoints);
for(my $ip = 0 ; $ip < $nPanel+1 ; $ip++) {
## 1 (1,0,0)/2
$line = $in->ReadLine();
#print "line: [$line]";
my ($n, $x, $y, $z, $m) = ($line =~ /(\d+)\D+(\d+)\D+(\d+)\D+(\d+)\D+(\d+)/);
#print "$ip=$n,$x,$y,$z,$m\n";
$kbx[$ip] = $x / $m;
$kby[$ip] = $y / $m;
$kbz[$ip] = $z / $m;
$nKPoints[$ip] = $n;
print "Boundary $ip [$nKPoints[$ip]]: ($kbx[$ip],$kby[$ip],$kbz[$ip])\n";
}
$in->SkipTo("\@ VIEW ");
my $EnergyBandArray = new EnergyBandArray;
$EnergyBandArray->SetTitle($SampleName);
$EnergyBandArray->SetCrystal($Crystal);
my $Distance = 0.0;
for(my $iK = 0 ; $iK < $nKPoint ; $iK++) {
$line = $in->ReadLine();
my ($k, @e) = Utils::Split("\\s+", $line);
for(my $iL = 0 ; $iL < @e ; $iL++) {
if($iK == 0) {
$EnergyBandArray->AddEnergyBand();
}
$EnergyBandArray->AddByKE($iL, $iK, 0, 0,
$HartreeToeV*($e[$iL]-$EF));
}
#print "k[$iK]: $kx $ky $kz\n";
# for(my $iL = 0 ; $iL < $nLevels ; $iL++) {
# $line = $in->ReadLine();
# my ($ib,$e) = Utils::Split("\\s+", $line);
# $EnergyBandArray->AddByKE($iL, $kx, $ky, $kz, $e-$EF);
# }
}
$EnergyBandArray->CalMinMax();
$EnergyBandArray->GetBandBoundary();
my $DataArray = new GraphDataArray;
$this->SetDataArray($DataArray);
$EnergyBandArray->SetGraphDataArray($DataArray);
print "CRYSTAL06::ReadBAND: finished.\n";
return $path;
}
sub ReadFiles
{
my ($this, $filename, $TargetData) = @_;
$TargetData = '' unless($TargetData);
$this->ClearAll();
my $FileType = $this->{'FileType'} = CheckFileType($filename);
$this->SetFileName($filename);
if($FileType eq "CRYSTAL06 OUTPUT file") {
return $this->ReadOUTPUT($filename, $TargetData);
}
elsif($FileType eq "CRYSTAL06 PROPERTY OUTPUT file") {
return $this->ReadOUTPUTP($filename, $TargetData);
}
elsif($FileType eq "CRYSTAL06 DOS file") {
return $this->ReadDOSS($filename);
}
elsif($FileType eq "CRYSTAL06 BAND file") {
return $this->ReadBAND($filename);
}
return undef;
}
#============================================================
# コンストラクタ、デストラクタ
#============================================================
sub new
{
my ($module) = @_;
my $this = {};
bless $this;
return $this;
}
sub DESTROY { my $this = shift; }
#============================================================
# ファイル読み込み関数
#============================================================
#============================================================
# 一般関数
#============================================================
sub MakeD12File
{
my ($this, $Crystal, $Function, $SpinPolarized, $fname) = @_;
#print "
(.*?)\<\/pre\>/si); #print "bcontent: $basis
\n"; my @lines = Utils::Split("\\n", $basis); my $Go = 0; my $Format = 0; for(my $i = 0 ; $i < @lines ; $i++) { #print("a:$lines[$i] (Go=$Go)
\n"); # if($lines[$i] =~ /^\s*\d+\s+\d+\s*$"/) { my @a = Utils::Split("\\s+", $lines[$i]); if($Go == 0 and (@a == 2 or @a == 5) and $lines[$i] =~ /^[\s\.\d]*$/) { if(@a == 5) { $Format = 1; $out->print("$AtomicNumber N\n"); } $Go = 1; } next if($Go == 0); $lines[$i] =~ s/\s*(\r\n)$//; last if($lines[$i] =~ /^\s*$/); if($Go == 1) { if($Format == 0) { $out->print("$AtomicNumber $a[1]\n"); } else { $out->print("$lines[$i]\n"); } #print("$lines[$i]
\n"); } elsif($Go == 2) { # if($lines[$i] =~ /^\s*\d/) { # $out->print("$lines[$i]\n"); # } $out->print("$lines[$i]\n"); } else { last if($lines[$i] =~ /^\s*[a-zA-Z]/); $out->print("$lines[$i]\n"); } $Go++; } } $out->print("99 0\n"); $out->print("END\n"); if($SpinPolarized eq 'Yes') { $out->print("UHF\n"); } $out->print("SHRINK\n"); $out->print("8 6 8\n"); $out->print("END\n"); $out->print("FMIXING\n"); $out->print("30\n"); $out->print("END\n"); $out->Close(); return 1; } sub MakeD3File { my ($this, $Crystal, $Function, $D3) = @_; my $Sample = $this->SampleName(); unless(open(OUTCRYSTAL06, ">$D3")) { print "Error!: Can not write to [$D3]
\n"; return -1; } print OUTCRYSTAL06 <\n"; my $SampleName = $this->SampleName(); my $D12 = Deps::MakePath($Dir, "$SampleName.d12", 0); if(unlink($D12)) { print "$D12 was deleted.$LF"; } my $D3 = Deps::MakePath($Dir, "$SampleName.d3", 0); if(unlink($D3)) { print "$D3 was deleted.$LF"; } my $ret = $this->MakeD12File($Crystal, $Function, $SpinPolarized, $D12); return () if($ret <= 0); $ret = $this->MakeD3File($Crystal, $Function, $D3); return ($D12) if($ret <= 0); return ($D12, $D3); } 1;