package PWSCF; use Exporter; @ISA = qw(Exporter); #公開したいサブルーチン @EXPORT = qw(); use strict; use File::Basename; use ProgVars; use Sci qw($RyToeV $a0 $torad $todeg asin acos); #use Sci::Science; #use Crystal::MyUtility; use Crystal::Crystal; use Crystal::AtomType; use Crystal::AtomSite; use Crystal::CIF; use Crystal::VASP; use Crystal::BandStructure; #my $ATKPPDir = "D:\\Programs\\Perl\\VNL\\pseudopotentials\\atk2.0"; my $PWSCFDir = ProgVars::QEDir(); #Deps::MakePath($TkPerlDir, "QE", 0); my $PWSCFPPDir = ProgVars::QEPPDir(); my $PWSCFPPURL = "http://www.pwscf.org/pseudo/1.3/html/{Atom}.html"; my @PPPriority = ( 'pbe-sp-kjpaw', 'pbe-sp', 'pbe-kjpaw', 'pbe-(n-|nsp-)?kjpaw', 'pbe-.*kjpaw', 'pbe(-n)?-rrkjus', 'pbe-.*rrkjus', 'pbe-.*van_ak', 'pbe-.*van_bm', 'pbe-.*van', 'pbe-mt_fhi', 'pbe-nsp', 'pbe-', 'rel-pbesol(-n)?-kjpaw', 'rel-pbesol(-n)?-rrkjus', 'pw91', 'pz-(-n)?kjpaw', 'pz-(-n)?rrkjus', 'pz-mt', 'pz-rrkjus', 'pz-van', 'blyp-(sp-?)van', 'blyp-mt', 'tpss-mt', ); 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 GetiPWSCFBravaisLattice { my ($this, $strCrystalBravaisLattice) = @_; $strCrystalBravaisLattice = uc $strCrystalBravaisLattice; my %iBravaisLattice = ( "FREELATTICE" => 0, # Free Lattice "P(CUBIC)" => 1, # Cubic P (sc) "FC(CUBIC)" => 2, # Cubic F (fcc) "BC(CUBIC)" => 3, # Cubic I (bcc) "P(HEXAGONAL)" => 4, # Hexagonal and Trigonal P "P(TRIGONAL)" => 4, # Hexagonal and Trigonal P "R(RHOMBOHEDRAL)" => 5, # Trigonal R "R(TRIGONAL)" => 5, # Trigonal R "P(TETRAGONAL)" => 6, # Tetragonal P (st) "BC(TETRAGONAL)" => 7, # Tetragonal I (bct) "P(ORTHORHOMBIC)" => 8, # Orthorhombic P # "A(ORTHORHOMBIC)" => -9, # Orthorhombic base-centered(bco) "C(ORTHORHOMBIC)" => 9, # Orthorhombic base-centered(bco) "FC(ORTHORHOMBIC)" => 10, # Orthorhombic face-centered "BC(ORTHORHOMBIC)" => 11, # Orthorhombic body-centered "P(MONOCLINIC)" => 12, # Monoclinick P "C(MONOCLINIC)" => 13, # Monoclinick base-centered "P(TRICLINIC)" => 14, # Triclinick P ); #foreach my $key (keys %iBravaisLattice) { # print "[$key]: $iBravaisLattice{$key}
\n"; #} #print "[$strCrystalBravaisLattice] => $iBravaisLattice{$strCrystalBravaisLattice}
\n"; my $ibrav = abs($iBravaisLattice{$strCrystalBravaisLattice}); if($ibrav >= 12) { $ibrav = 14; } elsif($ibrav == 2 or $ibrav == 3) { $ibrav = 1; } elsif($ibrav == 5) { $ibrav = 4; } elsif($ibrav == 7) { $ibrav = 6; } elsif($ibrav >= 9 and $ibrav <= 11) { $ibrav = 8; } return $ibrav; } sub GetnEVal { my ($this, $Crystal, $pPPFiles) = @_; print "\nCalculate total number of valence electrons\n"; # my $pPPFiles = $this->FindPPFiles(\@AtomTypeList, $Functional, $PPType, $IsPrint); # my @AtomTypeList = $Crystal->GetCAtomTypeList(); # my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my @nMultiplicityExpandedAtomSiteList = $Crystal->GetCnMultiplicityExpandedAtomSiteList(); my %nVal; my $nTotEVal = 0; for(my $i = 0 ; $i < @AtomSiteList ; $i++) { my $atomname = $AtomSiteList[$i]->AtomNameOnly(); my $PPFile = $pPPFiles->{$atomname}; my $pHash = $this->ReadPPtoHash(Deps::MakePath($PWSCFPPDir, $PPFile, 0), 0); #print "pHash=$pHash\n"; print " $i: $atomname: $pHash->{z_valence} in [$PPFile]\n"; $nTotEVal += $nMultiplicityExpandedAtomSiteList[$i] * $pHash->{z_valence}; #$hash{wfc_cutoff} = $1; #$hash{rho_cutoff} = $1; } print " Total number of valence electrons: $nTotEVal\n"; return $nTotEVal; } sub GetMaxEcut { my ($this, $Crystal, $pPPFiles) = @_; print "\nCalculate Ecut for base functions (wfc_cutoff) and electron density (rho_cutoff)\n"; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my ($MaxEcut, $MaxRhoEcut) = (0.0, 0.0); for(my $i = 0 ; $i < @AtomSiteList ; $i++) { my $atomname = $AtomSiteList[$i]->AtomNameOnly(); my $PPFile = $pPPFiles->{$atomname}; my $pHash = $this->ReadPPtoHash(Deps::MakePath($PWSCFPPDir, $PPFile, 0), 0); print " $i: $atomname: wfc_Ecut = $pHash->{wfc_cutoff}, rho_Ecut = $pHash->{rho_cutoff} in [$PPFile]\n"; $MaxEcut = $pHash->{wfc_cutoff} if($MaxEcut < $pHash->{wfc_cutoff}); $MaxRhoEcut = $pHash->{rho_cutoff} if($MaxRhoEcut < $pHash->{rho_cutoff}); } return ($MaxEcut, $MaxRhoEcut); } sub ReadPPtoHash { my ($this, $fname, $DebugMode) = @_; $DebugMode = 0 if(!defined $DebugMode); my ($drive, $directory, $filename, $ext1, $lastdir, $filebody) = Deps::SplitFilePath($fname); print "Read PP from [$filename]\n" if($DebugMode); my %hash = (path => $fname, filename => $filename); my $in = JFile->new($fname, 'r'); if(!$in) { print "Can not read [$fname].\n" if($DebugMode); return 0; } my $line = $in->SkipTo("Generated "); ($hash{method}) = ($line =~ /using\s+(\S.*),/); ($hash{method}) = ($line =~ /by\s+(\S.*),/) if($hash{method} eq ''); ($hash{method}) = ($line =~ /using\s+(\S+)/) if($hash{method} eq ''); ($hash{method}) = ($line =~ /by\s+(\S+)/) if($hash{method} eq ''); ($hash{method}) = ($line =~ /UPF file from\s+(\S+)/) if($hash{method} eq ''); Utils::DelQuote($hash{method}); $line = $in->SkipTo("Pseudopotential type:"); ($hash{PPType}) = ($line =~ /type:\s*(\S.+)\s*$/); Utils::DelQuote($hash{PPType}); if($hash{PPType} eq '') { $hash{PPType} = 'PAW' if($hash{method} =~ /paw/i); } $hash{PPType} = 'USPP' if($hash{PPType} eq 'US'); $line = $in->SkipTo("Element:"); ($hash{Element}) = ($line =~ /Element:\s*(\S.*)\s*$/); if($hash{Element} eq '') { $in->rewind(); for(my $i = 0 ; $i < 20 ; $i++) { $line = $in->ReadLine(); if($line =~ /^\s*([A-Z][a-z]?)\s/) { $hash{Element} = $1; #print "e:$hash{Element}\n"; #exit; last; } } } Utils::DelQuote($hash{Element}); $hash{Element} = ucfirst(lc($hash{Element})); $line = $in->SkipTo("Functional:"); ($hash{Functional}) = ($line =~ /Functional:\s*(\S.+)\s*$/); if($hash{Functional} eq '') { $in->rewind(); for(my $i = 0 ; $i < 20 ; $i++) { $line = $in->ReadLine(); if($line =~ /^\s*GGA-([A-Za-z0-9]+)\s/) { $hash{Functional} = $1; #print "e:$hash{Element}\n"; #exit; last; } } } Utils::DelQuote($hash{Functional}); while(1) { $line = $in->ReadLine(); last if(!$line); last if($line =~ /\rewind(); for(my $j = 0 ; $j < 7 ; $j++) { $line = $in->ReadLine(); exit if($line =~ /^Valence/); print " $line"; } exit; } #exit if($files[$i] =~ /Ga\.pbe.*nsp/); } $in->Close(); return \%hash; } sub ReadAllPP { my ($this, $Debug) = @_; $Debug = 0 if(!defined $Debug); print "Read all pseudo potentials from [$PWSCFPPDir]\n"; my (@PPHashArray, %PPTypeHash, %FunctionalHash, %ElementHash, %PPHash); my @files = sort glob(Deps::MakePath($PWSCFPPDir, "*.UPF", 0)); for(my $i = 0 ; $i < @files ; $i++) { #last if($i >= 90); print " Read [$files[$i]]\n" if($Debug); $PPHashArray[$i] = $this->ReadPPtoHash($files[$i], $Debug); my $Element = $PPHashArray[$i]->{Element}; my @PPType = Utils::Split("\\s+", $PPHashArray[$i]->{PPType}); my @Functional = Utils::Split("\\s+", $PPHashArray[$i]->{Functional}); $ElementHash{$Element}++; for(my $i = 0 ; $i < @PPType ; $i++) { $PPTypeHash{$PPType[$i]}++; } for(my $i = 0 ; $i < @Functional ; $i++) { $FunctionalHash{$Functional[$i]}++; } } my @ElementArray = sort keys %ElementHash; my @PPTypeArray = sort keys %PPTypeHash; my @FunctionalArray = sort keys %FunctionalHash; if($Debug) { print "\n"; print "PPTypes: "; for(my $i = 0 ; $i < @PPTypeArray ; $i++) { print "$PPTypeArray[$i] "; } print "\n"; print "Functionals: "; for(my $i = 0 ; $i < @FunctionalArray ; $i++) { print "$FunctionalArray[$i] "; } print "\n"; } for(my $l = 0 ; $l < @PPHashArray ; $l++) { my $p = $PPHashArray[$l]; my $e = $p->{Element}; my @PPTypes = Utils::Split("\\s+", $p->{PPType}); my @Functionals = Utils::Split("\\s+", $p->{Functional}); my %ph; for(my $i = 0 ; $i < @PPTypes ; $i++) { my $pptype = $PPTypes[$i]; next if($ph{$pptype}); $ph{$pptype}++; my %fh; for(my $j = 0 ; $j <@Functionals ; $j++) { my $f = $Functionals[$j]; next if($fh{$f}); $fh{$f}++; $PPHash{$e}{$pptype}{$f} = [] if(!defined $PPHash{$e}{$pptype}{$f}); my $p = $PPHash{$e}{$pptype}{$f}; #print "Add $PPHashArray[$l] to [$e]$[pptype][$f]\n" if($e eq 'Ba'); push(@$p, $PPHashArray[$l]); } } } return (\@PPHashArray, \@PPTypeArray, \@FunctionalArray, \%PPHash); } sub FindPPFiles { my ($this, $pAtomTypeList, $TargetFunctional, $TargetPPType, $IsPrint) = @_; $TargetFunctional = 'PBE' if(!defined $TargetFunctional); $TargetPPType = 'PAW' if(!defined $TargetPPType); $IsPrint = 1 if(!defined $IsPrint); my @AtomTypeList = @$pAtomTypeList; my ($pPPHashArray, $pPPTypes, $pFunctionals, $pPPHash) = $this->ReadAllPP($IsPrint); print "\n"; for(my $i = 0 ; $i < @AtomTypeList ; $i++) { my $atomname = $AtomTypeList[$i]->AtomName(); my $p = $pPPHash->{$atomname}; if(!defined $p) { print "Error: No pseudo potential is available for [$atomname].\n"; last; } #print "$i [$atomname][$PPType][$Functional]: p=$p "; print "Available pseudo potentials for [$atomname]:\n"; foreach my $PPType (sort keys %$p) { my $p2 = $p->{$PPType}; print " PPType=$PPType Functionals="; # if(!defined $p2) { # print "Error: No pseudo potential type is available for [$atomname].\n"; # last; # } #print "pp2=$p2 "; #print "hash=", %$p2, "\n"; foreach my $Functional (sort keys %$p2) { print "$Functional "; my $p3 = $p2->{$Functional}; # if(!defined $p3) { # print "Error: No pseudo potential for functional [$Functional] is available.\n"; # last; # } #print "pp3=$p3 [$PPType][$Functional]"; } print "\n"; } } print "PPT:$TargetPPType:"; my @PPTypes = Utils::Split(",", $TargetPPType); print join(', ', @PPTypes), "\n"; for(my $i = 0 ; $i < @PPTypes ; $i++) { my $pptype = $PPTypes[$i]; #print "$i: $ppt\n"; print "\n"; print "Available pseudo potentials for [$pptype][$TargetFunctional]\n"; my ($pPPToBeUsed, $atomname, $ppt2) = $this->FindPPFilesByPPType($pPPHash, $pAtomTypeList, $TargetFunctional, $pptype, $IsPrint); if($pPPToBeUsed == 0) { print " Error: No pseudo potential is available for [$atomname][$ppt2][$TargetFunctional].\n"; next; } else { my $MatchedIndex = $atomname; print " ***All PPs [$pptype][$TargetFunctional] are available for " ."[PPPriority=$PPPriority[$MatchedIndex]]\n";# if($IsPrint); foreach my $atomname (sort keys %$pPPToBeUsed) { printf " %2s: $pPPToBeUsed->{$atomname}\n", $atomname; } return $pPPToBeUsed; } } } sub FindPPFilesByPPType { my ($this, $pPPHash, $pAtomTypeList, $TargetFunctional, $TargetPPType, $IsPrint) = @_; my @AtomTypeList = @$pAtomTypeList; #print "\n"; #print "Enter PWSCF::FindPPFilesByPPType\n"; #print "Available pseudo potentials for [$TargetPPType][$TargetFunctional]\n"; for(my $i = 0 ; $i < @AtomTypeList ; $i++) { my $atomname = $AtomTypeList[$i]->AtomName(); my $p = $pPPHash->{$atomname}; if(!defined $p) { return (0, $atomname); } my $p2 = $p->{$TargetPPType}; if(!defined $p2) { print " Error in PWSCF::FindPPFilesByPPType: " ."No pseudo potential is available for [$atomname][$TargetPPType].\n"; return (0, $atomname, $TargetPPType); } my $p3 = $p2->{$TargetFunctional}; if(!defined $p3) { print " Error in PWSCF::FindPPFilesByPPType: " ."No pseudo potential is available for [$atomname][$TargetPPType][$TargetFunctional].\n"; return (0, $atomname, $TargetPPType, $TargetFunctional); # exit; } #print " [$atomname]: ", join(', ', @$p3), "\n"; for(my $i = 0 ; $i < @$p3 ; $i++) { my $p4 = $p3->[$i]; print " $p4->{filename}\n"; $p->{PPCandidates} = [] if(!defined $p->{PPCandidates}); my $ppc = $p->{PPCandidates}; push(@$ppc, $p4->{filename}); $p->{PPCandidates} = $ppc; } } # print "\n"; # print "PP files priority:\n"; my %PPToBeUsed; my $MatchedIndex = -1; for(my $i = 0 ; $i < @PPPriority ; $i++) { print " $i: $PPPriority[$i]\n"; my $AllPassed = 1; %PPToBeUsed = (); for(my $j = 0 ; $j < @AtomTypeList ; $j++) { my $atomname = $AtomTypeList[$j]->AtomName(); my $p = $pPPHash->{$atomname}; my $ppc = $p->{PPCandidates}; my $AtomPassed = 0; for(my $k = 0 ; $k < @$ppc ; $k++) { my $fname = $ppc->[$k]; if($fname =~ /$PPPriority[$i]/i) { print " check $PPPriority[$i] vs $fname: Passed\n"; $PPToBeUsed{$atomname} = $fname; $AtomPassed = 1; last; } } $AllPassed = 0 if(!$AtomPassed); } if($AllPassed) { $MatchedIndex = $i; # print " ***All PPs are available for $PPPriority[$i]\n" if($IsPrint); last; } } # print "\n"; # print "PP files to be used:\n"; # foreach my $atomname (sort keys %PPToBeUsed) { # printf " %2s: $PPToBeUsed{$atomname}\n", $atomname; # } return (\%PPToBeUsed, $MatchedIndex); } sub MakeKPOINTSForBand { my ($this, $Crystal, $klistfile, $KPoints, $nk) = @_; #klistファイル読み込み print "PWSCF::MakeKPOINTSForBand: *Read k points from [$klistfile]\n"; my @klist; if($klistfile) { @klist = BandStructure->ReadKListFile($klistfile); } else { for(my $i = 0 ; $i < length($KPoints) ; $i++) { my $c0 = substr($KPoints, $i, 1); if($c0 =~ /G/i) { push(@klist, {name => 'GAMMA', kx => 0.0, ky => 0.0, kz => 0.0}); } elsif($c0 =~ /X/i) { push(@klist, {name => 'X', kx => 0.5, ky => 0.0, kz => 0.0}); } elsif($c0 =~ /Y/i) { push(@klist, {name => 'Y', kx => 0.0, ky => 0.5, kz => 0.0}); } elsif($c0 =~ /Z/i) { push(@klist, {name => 'Z', kx => 0.0, ky => 0.0, kz => 0.5}); } elsif($c0 =~ /R/i) { push(@klist, {name => 'R', kx => 0.5, ky => 0.5, kz => 0.5}); } elsif($c0 =~ /M/i) { push(@klist, {name => 'M', kx => 0.5, ky => 0.5, kz => 0.0}); } } } if(@klist == 0) { print "Can not read $klistfile.\n"; print "Use default klist.\n"; push(@klist, {name => 'R', kx => 0.5, ky => 0.5, kz => 0.5}); push(@klist, {name => 'GAMMA', kx => 0.0, ky => 0.0, kz => 0.0}); push(@klist, {name => 'X', kx => 0.5, ky => 0.0, kz => 0.0}); push(@klist, {name => 'M', kx => 0.5, ky => 0.5, kz => 0.0}); push(@klist, {name => 'Z', kx => 0.0, ky => 0.0, kz => 0.5}); push(@klist, {name => 'GAMMA', kx => 0.0, ky => 0.0, kz => 0.0}); } return \@klist; } sub SavePWSCFInpFile { my ($this, $Function, $PseudoPotential, $Crystal, $filename, $IsChooseRandomly, $PWSCFUseBravaisLattice, $PWSCFUseCELLDM, $PPType, $Functional, $PPCopyMode, $SavePPDir, $IsPrint, %args) = @_; $PPType = 'PAW' if($PPType eq ''); $Functional = 'PBE' if($Functional eq ''); $PPCopyMode = 'Selected' if($PPCopyMode eq ''); if($PPCopyMode eq 'No') { $SavePPDir = $PWSCFPPDir; } elsif($SavePPDir eq '') { $SavePPDir = './' } $args{BurstToP1} = 0 if(!defined $args{BurstToP1}); $PWSCFUseBravaisLattice = 0 if(!defined $PWSCFUseBravaisLattice); $PWSCFUseCELLDM = 1 if(!defined $PWSCFUseCELLDM); $args{PrintForFindPP} = 1 if(!defined $args{PrintForFindPP}); $args{aKProduct} = 1.5 if(!defined $args{aKProduct}); $args{ecutwfc} = 30.0 if(!defined $args{ecutwfc}); $args{ecutrho} = 140.0 if(!defined $args{ecutrho}); $args{SpinPolarized} = 1 if(!defined $args{SpinPolarized}); $args{KPoints} = 50 if(!defined $args{KPoints}); $args{press} = 0.001 if(!defined $args{press}); $args{etot_conv_thr} = 0.5e-4 if(!defined $args{etot_conv_thr}); $args{forc_conv_thr} = 0.5e-3 if(!defined $args{forc_conv_thr}); $args{conv_thr} = 0.5e-6 if(!defined $args{conv_thr}); $args{press_conv_thr} = 1.0 if(!defined $args{press_conv_thr}); $IsPrint = 0 if(!defined $IsPrint); my $LF = "
\n"; if($args{BurstToP1}) { $Crystal->BurstToP1(); } my $kListFile; if($Function =~ /bands/i) { print "\n"; my @klists = glob("*.KPOINTS"); $kListFile = (@klists > 0)? $klists[0] : ''; if($kListFile eq '') { @klists = glob("*.klist"); $kListFile = (@klists > 0)? $klists[0] : ''; } if($kListFile) { print("\nkList file: $kListFile\n"); } else { print("\nLlist file is not found. Use default.\n"); } } if($PPCopyMode ne 'No' and !-e $SavePPDir) { mkdir($SavePPDir); } my $vasp = new VASP; my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my $nAtomSite = @AtomSiteList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList(); my $nTotalExpandedAtomSite = @ExpandedAtomSiteList; #print "nTEA=$nTotalExpandedAtomSite/$nAtomType/$nAtomSite\n"; #exit; my $pPPFiles = $this->FindPPFiles(\@AtomTypeList, $Functional, $PPType, $args{PrintForFindPP}); my $nEVal = $this->GetnEVal($Crystal, $pPPFiles); if($args{nbnd} eq '') { $args{nbnd} = int($nEVal / 2 - 1.0e-6) + 1; } else { my @a = (Utils::Split("\s*,\s*", $args{nbnd})); for(my $i = 0 ; $i < @a ; $i++) { if($args{nbnd} =~ /^x(.*)$/) { my $v = $1 * (int($nEVal / 2 - 1.0e-6) + 1); $args{nbnd} = $v if($args{nbnd} < $v); } else { my $v = $1; $args{nbnd} = $v if($args{nbnd} < $v); } } } $args{nbnd} = (int($nEVal / 2 - 1.0e-6) + 1) if($args{nbnd} < (int($nEVal / 2 - 1.0e-6) + 1)); $args{nbnd} = int($args{nbnd} - 1e-6) + 1; print "# of valence electrons: $nEVal from PP files. nbnd = $args{nbnd} will be used.\n"; my ($MaxEcut, $MaxRhoEcut) = $this->GetMaxEcut($Crystal, $pPPFiles); if($args{ecutwfc} eq '') { $args{ecutwfc} = $MaxEcut; } else { my @a = (Utils::Split("\s*,\s*", $args{ecutwfc})); for(my $i = 0 ; $i < @a ; $i++) { if($a[$i] =~ /^x(.*)$/) { my $v = $1 * $MaxEcut; $args{ecutwfc} = $v if($args{ecutwfc} < $v); #print "$v = $1 * $MaxEcut, $a[$i]\n"; } else { $args{ecutwfc} = $a[$i] if($args{ecutwfc} < $a[$i]); } } } $args{ecutwfc} = $MaxRhoEcut if($args{ecutwfc} < $MaxRhoEcut); print "Ecut for basis functions: $MaxEcut Ry from PP files, $args{ecutwfc} Ry will be used.\n"; if($args{ecutrho} eq '') { $args{ecutrho} = $MaxRhoEcut; } else { my @a = (Utils::Split("\s*,\s*", $args{ecutrho})); for(my $i = 0 ; $i < @a ; $i++) { if($a[$i] =~ /^x(.*)$/) { my $v = $1 * $MaxRhoEcut; $args{ecutrho} = $v if($args{ecutrho} < $v); #print "$v = $1 * $MaxRhoEcut, $a[$i]\n"; } else { $args{ecutrho} = $a[$i] if($args{ecutrho} < $a[$i]); } } } $args{ecutrho} = $MaxRhoEcut if($args{ecutrho} < $MaxRhoEcut); print "Ecut for rho : $MaxRhoEcut Ry from PP files, $args{ecutrho} Ry will be used.\n"; #exit; print "\n"; my @Files; my @filenames = fileparse($filename, "\.[^\.]+"); my $OutputDir = $filenames[1]; #ファイル作製開始 unless(open(OUT,">$filename")) { print "Can not write to $filename.$LF$LF"; return; } binmode(OUT); my ($dt, $nstep) = (20, 100); if($Function =~ /md/i) { $dt = 20; $nstep = 100; } elsif($Function =~ /relax/i) { $dt = 10; $nstep = 50; } $nstep = $args{nstep} if(defined $args{nstep}); print OUT " &CONTROL\n"; my $SampleName = $this->SampleName(); print OUT " title = '$SampleName'\n"; print OUT " prefix = 'wm'\n"; # print OUT " prefix = '$SampleName'\n"; print OUT " outdir = '${SampleName}_qe_data',\n"; # print OUT " outdir = './',\n"; print OUT " pseudo_dir = '$SavePPDir',\n"; print OUT " verbosity = 'high',\n"; # scf nscf relax vc-relax md phonon if($Function =~ /^dos$/i) { print OUT " calculation = 'nscf',\n"; } else { print OUT " calculation = '$Function',\n"; } if($Function =~ /^scf$/i or $Function =~ /relax/i) { print OUT " restart_mode = 'from_scratch',\n"; } else { print OUT " restart_mode = 'restart',\n"; } print OUT " wf_collect = .True.,\n"; print OUT " tprnfor = .True.,\n"; print OUT " iprint = 1,\n"; print OUT " etot_conv_thr = $args{etot_conv_thr},\n"; print OUT " forc_conv_thr = $args{forc_conv_thr},\n"; print OUT " dt = $dt,\n"; print OUT " nstep = $nstep,\n"; print OUT " tstress = .True.,\n"; # print OUT " max_seconds = 6000,\n"; print OUT " disk_io = 'high',\n"; print OUT " /\n"; print OUT " &SYSTEM\n"; # my $SPGName = $Crystal->SPGNameByOutputMode(); # my $iSPG = $Crystal->iSPGByOutputMode(); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParameters(); # my ($ax,$ay,$az,$bx,$by,$bz,$cx,$cy,$cz) = $Crystal->LatticeVectors(); my $cosG = Sci::dcos($gamma); my $cosB = Sci::dcos($beta); my $cosA = Sci::dcos($alpha); my $ka = 20.0; my ($nkx, $nky, $nkz) = $vasp->AnalyzeaKProduct($Crystal, $args{aKProduct}); # my ($nkx, $nky, $nkz); # $nkx = int($ka / $a + 1.001); # $nky = int($ka / $b + 1.001); # $nkz = int($ka / $c + 1.001); my $BravaisLattice = 'P'; my $iPWSCFBravaisLattice = 14; if($PWSCFUseBravaisLattice) { # @ExpandedAtomSiteList = $Crystal->GetCBravaisLatticeAsymmetricAtomSiteList(); $nTotalExpandedAtomSite = @ExpandedAtomSiteList; $BravaisLattice = $Crystal->GetBravaisLattice(); $iPWSCFBravaisLattice = $this->GetiPWSCFBravaisLattice($BravaisLattice); $iPWSCFBravaisLattice = 14 if(!defined $iPWSCFBravaisLattice); print "

Use Bravais Lattice [$BravaisLattice: Reduced to ibrav = $iPWSCFBravaisLattice]

\n"; # print " Atomic sites are reduced to $nTotalExpandedAtomSite.
\n"; print "\n"; } #print "nAS=$nTotalExpandedAtomSite\n"+ #exit; # my $nAsymmetricAtomSite = &GetCIFValueByKey("nAsymmetricAtomSite"); print OUT " ibrav = $iPWSCFBravaisLattice,\n"; # celldm()で指定するときは、a.u.。 A,B,Cの時はオングストローム if($PWSCFUseCELLDM) { my $k = $a0 * 1.0e10; #print "latt=$a,$b,$c\n"; $a /= $k; $b /= $k; $c /= $k; if($iPWSCFBravaisLattice == 5) { # Trigonal R my $aR = $a; if(abs($cosA) < 1.0e-6) { print "This is a hexagonal unit cell [a=$a, c=$c bohr].
\n"; $aR = sqrt(3.0 * $a*$a + $c*$c) / 3.0; print " Convert to a rhombohedral lattice [aR=$aR bohr, "; printf OUT " celldm(1) = %10.6f,\n", $aR; } } else { printf OUT " celldm(1) = %10.6f,\n", $a; } if(1 <= $iPWSCFBravaisLattice and $iPWSCFBravaisLattice <= 3) { } elsif($iPWSCFBravaisLattice == 4 or $iPWSCFBravaisLattice == 6 or $iPWSCFBravaisLattice == 7) { # Hexagonal and Trigonal P, Tetragonal P, I printf OUT " celldm(3) = %10.6f,\n", $c / $a; } elsif($iPWSCFBravaisLattice == 5) { # Trigonal R my $cosAR = $cosA; if(abs($cosA) < 1.0e-6) { my $ca = $c / $a; my $sina2 = 1.5 / sqrt(3.0 + $ca*$ca); my $alpha = asin($sina2) * 2.0; my $alphadegree = $alpha * $todeg; $cosAR = cos($alpha); print "alpha=$alphadegree].
\n"; print "\n"; } printf OUT " celldm(4) = %10.6f,\n", $cosAR; } elsif(8 <= $iPWSCFBravaisLattice and $iPWSCFBravaisLattice <= 11) { # Orthorhombic P, base/face/body-centered printf OUT " celldm(2) = %10.6f,\n", $b / $a; printf OUT " celldm(3) = %10.6f,\n", $c / $a; } elsif($iPWSCFBravaisLattice == 12 or $iPWSCFBravaisLattice == 13) { # Monoclinic P, base-centered printf OUT " celldm(2) = %10.6f,\n", $b / $a; printf OUT " celldm(3) = %10.6f,\n", $c / $a; printf OUT " celldm(4) = %10.6f,\n", $cosB; } else { printf OUT " celldm(2) = %10.6f,\n", $b / $a; printf OUT " celldm(3) = %10.6f,\n", $c / $a; printf OUT " celldm(4) = %10.6f,\n", $cosA; printf OUT " celldm(5) = %10.6f,\n", $cosB; printf OUT " celldm(6) = %10.6f,\n", $cosG; } } else { printf OUT " A = %10.6f,\n", $a; printf OUT " B = %10.6f,\n", $b; printf OUT " C = %10.6f,\n", $c; printf OUT " cosAB = %10.6f,\n", $cosG; printf OUT " cosAC = %10.6f,\n", $cosB; printf OUT " cosBC = %10.6f,\n", $cosA; } print OUT " nat = $nTotalExpandedAtomSite,\n"; print OUT " nspin = $args{SpinPolarized},\n"; print OUT " ntyp = $nAtomType,\n"; print OUT " ecutwfc = $args{ecutwfc},\n"; print OUT " ecutrho = $args{ecutrho},\n"; print OUT " nosym = .False.,\n"; print OUT " noinv = .False.,\n"; print OUT " tot_charge = 0,\n"; print OUT " nbnd = $args{nbnd},\n"; # print OUT " starting_magnetization(1)=0.5,\n"; print OUT " occupations = 'smearing',\n"; print OUT " smearing = 'mp',\n"; # print OUT " smearing = 'methfessel-paxton',\n"; print OUT " degauss = 0.02,\n"; print OUT " /\n"; print OUT " &ELECTRONS\n"; print OUT " conv_thr = $args{conv_thr},\n"; print OUT " mixing_beta = 0.7,\n"; print OUT " mixing_mode = 'plain',\n"; print OUT " electron_maxstep = 100,\n"; print OUT " diagonalization = 'cg',\n"; print OUT " /\n"; print OUT "#ion_dynamics: damp for relax, verlet for md\n"; print OUT " &IONS\n"; if($Function =~ /relax/i) { print OUT " ion_dynamics = 'damp',\n"; } elsif($Function =~ /md/i) { print OUT " ion_dynamics='verlet',\n"; print OUT " ion_temperature='rescaling',\n"; print OUT " tempw=600.D0,\n"; print OUT " refold_pos=.TRUE.,\n"; } else { print OUT " ion_dynamics='damp',\n"; } print OUT " /\n"; print OUT "#cell_dofree: all, none, bfgs, cg, sd, damp-w\n"; if($Function =~ /md/i or $Function =~ /vc.*relax/i) { print OUT " &CELL\n"; print OUT " cell_dofree = 'all',\n"; # print OUT " cell_dynamics = 'none',\n"; print OUT " cell_dynamics = 'bfgs',\n"; # print OUT " cell_dynamics = 'sd',\n"; # print OUT " cell_dynamics = 'damp-w',\n"; print OUT " press = $args{press},\n"; print OUT " press_conv_thr = $args{press_conv_thr},\n"; print OUT " wmass = 0.20,\n"; print OUT " cell_factor = 2.0,\n"; print OUT " /\n"; } if($Function =~ /phonon/i) { print OUT " &phonon\n"; print OUT " xqq(1) = .00, xqq(2) = .00, xqq(3) = 1.00\n"; print OUT " /\n"; } print OUT "ATOMIC_SPECIES\n"; for(my $i = 0 ; $i < $nAtomType ; $i++) { my $atom = $AtomTypeList[$i]; my $name = $atom->AtomNameOnly(); my ($mass, $charge, $ai, $bi, $ci, $rad) = AtomType::GetBusingParameter($name); my $PPURL = $PWSCFPPURL; $PPURL =~ s/{Atom}/$name/g; push(@Files, $PPURL); if($PPCopyMode eq 'All' or $PPCopyMode eq 'Selected') { my $SourcePPPath = Deps::MakePath($PWSCFPPDir, $pPPFiles->{$name}); my $DestPPPath = Deps::MakePath($SavePPDir, $pPPFiles->{$name}); unless(Utils::CopyFile($SourcePPPath, $DestPPPath)) { print "Error in PWSCF::SavePWSCFInpFile: " . "Can not copy [$SourcePPPath] to [$DestPPPath]$LF"; } push(@Files, $DestPPPath); } printf OUT " %4s %10.5f %s \n", uc($name), $mass, $pPPFiles->{$name}; } print OUT "\n"; print OUT "ATOMIC_POSITIONS crystal \n"; # if($PWSCFUseBravaisLattice) { # print OUT "ATOMIC_POSITIONS alat \n"; # } # else { # print OUT "ATOMIC_POSITIONS crystal \n"; # } #Occupancyが1のサイト for(my $i = 0 ; $i < @ExpandedAtomSiteList ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); my $charge = $atom->Charge(); my ($x,$y,$z) = $atom->Position(1); my $occupancy = $atom->Occupancy(); next if($occupancy < 0.9999); # my ($xc,$yc,$zc) = $Crystal->FractionalToCartesian($x,$y,$z); printf OUT " %4s %14.8f %14.8f %14.8f\n", uc($atomname), $x, $y, $z; # printf OUT " %4s %14.8f %14.8f %14.8f %2d %2d %2d\n", # uc($atomname), $x, $y, $z, 1, 1, 1; } #Occupancyが1未満のサイト for(my $i = 0 ; $i < @ExpandedAtomSiteList ; $i++) { my $atom = $ExpandedAtomSiteList[$i]; my $atomname = $atom->AtomNameOnly(); my $charge = $atom->Charge(); my ($x,$y,$z) = $atom->Position(1); my $occupancy = $atom->Occupancy(); next if($occupancy >= 0.9999); # my ($xc,$yc,$zc) = $Crystal->FractionalToCartesian($x,$y,$z); printf OUT " %4s %14.8f %14.8f %14.8f\n", uc($atomname), $x, $y, $z; } print OUT "\n"; if($Function =~ /bands/i) { my $pKList = $this->MakeKPOINTSForBand($Crystal, $kListFile, $args{KPoints}, $args{nk}); print OUT "K_POINTS {tpiba_b} \n"; # print OUT "K_POINTS {crystal} \n"; my $nk = @$pKList; print OUT "$nk\n"; for(my $i = 0 ; $i < @$pKList ; $i++) { my $p = $pKList->[$i]; # print OUT " $i: $p->{name}: ($p->{kx}, $p->{ky}, $p->{kz})\n"; printf OUT " %9.6f %9.6f %9.6f %d\n", $p->{kx}, $p->{ky}, $p->{kz}, $args{nk}; } # print OUT "K_POINTS {crystal_b} \n"; # print OUT "11\n"; # print OUT "X 20\n"; # print OUT "gG 20\n"; # print OUT "Y 0\n"; # print OUT "L 20\n"; # print OUT "Z 0\n"; # print OUT "N 20\n"; # print OUT "gG 20\n"; # print OUT "M 0\n"; # print OUT "R 20\n"; # print OUT "gG 0\n"; } else { print OUT "K_POINTS {automatic} \n"; print OUT " $nkx $nky $nkz 1 1 1 \n"; } close(OUT); my $TemplateDir = Deps::MakePath($PWSCFDir, 'Template', 0); if($Function =~ /band/i) { my $Source = Deps::MakePath($TemplateDir, 'bands.in', 0); my $Target = 'bands.in'; print "Copy [$Source] to [$Target]\n"; if(Utils::CopyFile($Source, $Target) <= 0) { print "\nError in PWSCF::SaveInputFiles: Can not copy [$Source] to [$Target].\n\n\n"; exit; } } elsif($Function =~ /do/i) { my $Source = Deps::MakePath($TemplateDir, 'dos.in', 0); my $Target = 'dos.in'; print "Copy [$Source] to [$Target]\n"; if(Utils::CopyFile($Source, $Target) <= 0) { print "\nError in PWSCF::SaveInputFiles: Can not copy [$Source] to [$Target].\n\n\n"; exit; } $Source = Deps::MakePath($TemplateDir, 'projwfc.in', 0); $Target = 'projwfc.in'; print "Copy [$Source] to [$Target]\n"; if(Utils::CopyFile($Source, $Target) <= 0) { print "\nError in PWSCF::SaveInputFiles: Can not copy [$Source] to [$Target].\n\n\n"; exit; } } return ($filename, @Files); } sub GetInpFileName { my ($this, $App, $path) = @_; my @filenames = fileparse($path, "\.[^\.]+"); my $infile = $filenames[0] . ".winp"; $infile = $filenames[0] . ".inp" if(!-e $infile); return $infile; }; sub GetnFrameInOutput { my ($this, $App, $InpFile) = @_; my $in = JFile->new($InpFile, "r") or die "$!: Can not read [$InpFile].\n"; my $nStep = 0; while(1) { my $line = $in->ReadLine(); last if(!defined $line); $nStep++ if($line =~ /ATOMIC_POSITIONS/); } $in->Close(); return $nStep; } sub ReadNextCrystalStructureFromOutput { my ($this, $App, $in, , $iStep, $Crystal, $PrintStructures) = @_; $PrintStructures = 1 if(!defined $PrintStructures); print "\nRead Next crystal structure and properties: Step $iStep\n" if($PrintStructures); my $pHash = {}; my $line; my $iter = 0; my ($PrevE, $TotE) = (0); my @EConvergence; if($PrintStructures) { print " Iteration $iter: Total energy dE Ry\n"; } while(1) { $line = $in->ReadLine(); return undef if(!$line); if($line =~ /!\s*total energy\s*=\s*([+\-0-9\.eEdD]+)/) { $TotE = $1; $EConvergence[$iter] = $TotE; my $dE = $TotE - $PrevE; $PrevE = $TotE; if($PrintStructures) { printf " %04d %16.8e %10.4e\n", $iter, $TotE, $dE; } $iter++; } if($line =~ /Forces acting on atoms/) { last; } } $pHash->{TotalEnergy} = $TotE; $pHash->{pEConvergence} = \@EConvergence; # $line = $in->SkipTo('Forces acting on atoms'); #print "line [$line]\n"; return undef if(!defined $line or $line eq ''); #次のデータがあることを確認してからリストをクリアー my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my $nAtomSite = @AtomSiteList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList(); my $nTotalExpandedAtomSite = @ExpandedAtomSiteList; $Crystal->ClearAtomTypeList(); $Crystal->ClearAtomSiteList(); $line = $in->SkipTo('atom '); my (@fx, @fy, @fz); my $nAtomSite = 0; while(1) { #print "$nAtomSite: line [$line]\n"; ($fx[$nAtomSite], $fy[$nAtomSite], $fz[$nAtomSite]) = ($line =~ /force\s*=\s*([+-]?[\d\.eEdD]+)\s+([+-]?[\d\.eEdD]+)\s+([+-]?[\d\.eEdD]+)/); last if(!defined $fz[$nAtomSite]); $fx[$nAtomSite] =~ s/d/e/i; $fy[$nAtomSite] =~ s/d/e/i; $fz[$nAtomSite] =~ s/d/e/i; #print "$nAtomSite: F=($fx[$nAtomSite], $fy[$nAtomSite], $fz[$nAtomSite])\n"; $nAtomSite++; $line = $in->ReadLine(); Utils::DelSpace($line); last if($line eq ''); } if($PrintStructures) { print "nAtomSite = $nAtomSite\n"; } my $pos = $in->tell(); my $line = $in->SkipTo('CELL_PARAMETERS'); if(!$line) { $in->seek($pos, 0); } else { my ($alat) = ($line =~ /alat\s*=\s*([+\-0-9\.eEdD]+)/); #print "line: $line"; #print "alat=$alat\n"; my ($a11, $a12, $a13) = Utils::Split("\\s+", $in->ReadLine()); my ($a21, $a22, $a23) = Utils::Split("\\s+", $in->ReadLine()); my ($a31, $a32, $a33) = Utils::Split("\\s+", $in->ReadLine()); $a11 *= $a0*1.0e10 * $alat; $a12 *= $a0*1.0e10 * $alat; $a13 *= $a0*1.0e10 * $alat; $a21 *= $a0*1.0e10 * $alat; $a22 *= $a0*1.0e10 * $alat; $a23 *= $a0*1.0e10 * $alat; $a31 *= $a0*1.0e10 * $alat; $a32 *= $a0*1.0e10 * $alat; $a33 *= $a0*1.0e10 * $alat; if($PrintStructures) { print "Base lattice parameter: $alat a.u.\n"; print " (a11, a12, a13) = ($a11, $a12, $a13)\n"; print " (a21, a22, a23) = ($a21, $a22, $a23)\n"; print " (a31, a32, a33) = ($a31, $a32, $a33)\n"; } $Crystal->SetLatticeVector($a11, $a12, $a13, $a21, $a22, $a23, $a31, $a32, $a33); my ($a, $b, $c, $alpha, $beta, $gamma) = $Crystal->LatticeParameters(); if($PrintStructures) { print " Lattice parameters: $a, $b, $c, $alpha, $beta, $gamma\n"; } } my $line = $in->SkipTo('ATOMIC_POSITIONS'); #print "line: $line"; my $iatom = 0; my %iAtom; for(my $i = 0 ; $i < $nAtomSite ; $i++) { $line = $in->ReadLine(); last if(!defined $line); #print "line [$line]\n"; my ($atomname, $x, $y, $z) = ($line =~ /(\w+)\s+([+-]?[\d\.eEdD]+)\s+([+-]?[\d\.eEdD]+)\s+([+-]?[\d\.eEdD]+)/); $atomname = ucfirst(lc($atomname)); $iAtom{$atomname}++; $Crystal->AddAtomSite($atomname . $iAtom{$atomname}+1, $atomname, $x, $y, $z, 1.0, $fx[$i], $fy[$i], $fz[$i]); if($PrintStructures) { print "$i: $atomname ($x, $y, $z) F=($fx[$i], $fy[$i], $fz[$i])\n"; } $iatom++; } $Crystal->CalMetrics(); $Crystal->ExpandCoordinates(); $pHash->{pCrystal} = $Crystal; return $pHash; }; sub ReadFinalCrystalStructureFromOutput { my ($this, $App, $InpFile, $WoutFile, $PrintStructures) = @_; $PrintStructures = 0 if(!defined $PrintStructures); my $pCrystalArray = $this->ReadCrystalStructuresFromOutput( $App, $InpFile, $WoutFile, $PrintStructures); my $n = @$pCrystalArray; my $p = $pCrystalArray->[$n-1]; #print "n=$n p=$p\n"; #my @latt = $p->LatticeParameters(); #print "latt: ", join(', ', @latt), "\n"; return $p; } sub ReadCrystalStructuresFromOutput { my ($this, $App, $InpFile, $WoutFile, $PrintStructures) = @_; $PrintStructures = 1 if(!defined $PrintStructures); $App->print("Read Crystal Structures From Output:\n"); $App->print("Input File : $InpFile\n"); $App->print("Output File: $WoutFile\n"); $App->print("\n"); my @CrystalArray; my $Crystal = new Crystal; $App->print("\nRead initial crystal structure from input [$InpFile].\n"); $this->ReadCrystalStructureFromInput($App, $InpFile, $Crystal, $PrintStructures); $App->print("\nRead relaxed/md crystal structures from output [$WoutFile].\n"); my $nStep = $this->GetnFrameInOutput($App, $WoutFile); $App->print("\nStep in [$WoutFile]: $nStep\n"); my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my $nAtomSite = @AtomSiteList; $App->printf("nAtomSites: %d nAtomType: %d\n", $nAtomSite, $nAtomType); my $in = JFile->new($WoutFile, "r") or die "$!: Can not read [$WoutFile].\n"; for(my $i = 0 ; $i < $nStep ; $i++) { my $NewCrystal = $Crystal->Duplicate(); my $ret = $this->ReadNextCrystalStructureFromOutput( $App, $in, $i, $NewCrystal, $PrintStructures); last if($ret <= 0); $CrystalArray[$i] = $NewCrystal; # %{$CrystalArray[$i]} = %$NewCrystal; } $in->Close(); return \@CrystalArray; } sub ReadCrystalStructureFromInput { my ($this, $App, $InpFile, $Crystal, $PrintStructures) = @_; $PrintStructures = 1 if(!defined $PrintStructures); #print "PrintStructures=$PrintStructures\n"; #exit; print "ReadCrystalStructureFromInput: from [$InpFile]\n"; my $in = JFile->new($InpFile, "r") or die "$!: Can not read [$InpFile].\n"; my $line = $in->SkipTo("title\\s*="); #print "l:$line\n"; my ($s) = ($line =~ /=(.*)$/); Utils::DelSpace($s); Utils::DelQuote($s); $Crystal->SetCrystalName($s); print "title: $s\n"; my $CoordinateUnit; my $UseCELLPARAMETERS = 0; my ($ibrav, @latt, @celldm); print "Search CELL_PARAMETERS:\n"; $in->rewind(); my $line = $in->SkipTo("CELL_PARAMETERS"); if($line) { $line =~ /CELL_PARAMETERS\s+(\S+)/i; my $unit = $1; $CoordinateUnit = $unit if(defined $unit); $UseCELLPARAMETERS = 1; my ($a11, $a12, $a13) = Utils::Split("\\s+", $in->ReadLine()); my ($a21, $a22, $a23) = Utils::Split("\\s+", $in->ReadLine()); my ($a31, $a32, $a33) = Utils::Split("\\s+", $in->ReadLine()); my $k = 1.0; if($CoordinateUnit eq 'bohr') { $k = $a0 * 1.0e10; } $a11 *= $k; $a12 *= $k; $a13 *= $k; $a21 *= $k; $a22 *= $k; $a23 *= $k; $a31 *= $k; $a32 *= $k; $a33 *= $k; $Crystal->SetLatticeVector($a11, $a12, $a13, $a21, $a22, $a23, $a31, $a32, $a33); ($latt[0], $latt[1], $latt[2], $latt[3], $latt[4], $latt[5]) = $Crystal->LatticeParameters(); if($PrintStructures) { print " Lattice parameters: $latt[0], $latt[1], $latt[2], $latt[3], $latt[4], $latt[5]\n"; print " Lattice vectors:\n"; print " (a11, a12, a13) = ($a11, $a12, $a13)\n"; print " (a21, a22, a23) = ($a21, $a22, $a23)\n"; print " (a31, a32, a33) = ($a31, $a32, $a33)\n"; } } if($PrintStructures) { print "Atom Types:\n"; } $in->rewind(); my $line = $in->SkipTo("ATOMIC_SPECIES"); my $natomtypes = 0; while(1) { $line = Utils::DelSpace($in->ReadLine()); #print "l:$line"; last if(!defined $line or $line eq ''); last if($line =~ /ATOMIC_POSITIONS/); # my ($name, $mass, $ppfile) = ($line =~ /(\w+)\s+([\.0-9eEdD]+)/); my ($name, $mass, $ppfile) = ($line =~ /(\w+)\s+([\.0-9eEdD]+)\s+(\S.*)$/); last if(!defined $ppfile); $name = ucfirst(lc($name)); if($PrintStructures) { print "$natomtypes: $name M=$mass PP=$ppfile\n"; } $Crystal->AddAtomType($name, 1, 1.0); $natomtypes++; } $in->rewind(); my $line = $in->SkipTo("&SYSTEM"); while(1) { $line = $in->ReadLine(); last if(!defined $line); last if($line =~ /\//); #print "l:$line"; if($line =~ /^\s*ibrav\s*=\s*(\S+)\s*,/) { $ibrav = $1; if($PrintStructures) { print "ibrav=$ibrav\n"; } } elsif($line =~ /^\s*celldm\((\d+)\)\s*=\s*(\S+)\s*,/) { my $idx = $1; my $idx0 = $idx-1; $celldm[$idx0] = $2; if($PrintStructures) { print "celldm($idx)=$celldm[$idx0]\n"; } } elsif($line =~ /^\s*A\s*=\s*(\S+)\s*,/) { $latt[0] = $1; #print "A=$1, $latt[0]\n"; } elsif($line =~ /^\s*B\s*=\s*(\S+)\s*,/) { $latt[1] = $1; #print "B=$1, $latt[1]\n"; } elsif($line =~ /^\s*C\s*=\s*(\S+)\s*,/) { $latt[2] = $1; #print "C=$1, $latt[2]\n"; } elsif($line =~ /^\s*cosBC\s*=\s*(\S+)\s*,/) { $latt[3] = Utils::Round(Sci::acos($1) * $todeg, 4, 0); #print "cosBC=$1, $latt[3]\n"; } elsif($line =~ /^\s*cosAC\s*=\s*(\S+)\s*,/) { $latt[4] = Utils::Round(Sci::acos($1) * $todeg, 4, 0); #print "cosAC=$1, $latt[4]\n"; } elsif($line =~ /^\s*cosAB\s*=\s*(\S+)\s*,/) { $latt[5] = Utils::Round(Sci::acos($1) * $todeg, 4, 0); #print "cosAB=$1, $latt[5]\n"; } } #print " latt: ", join(', ', @latt), "\n"; #print " celldm: ", join(', ', @celldm), "\n"; #exit; # celldm()で指定するときは、a.u.。 A,B,Cの時はオングストローム if(defined $celldm[0]) { #printf OUT " celldm(2) = %10.6f,\n", $b / $a; #printf OUT " celldm(3) = %10.6f,\n", $c / $a; #printf OUT " celldm(4) = %10.6f,\n", $cosA; #printf OUT " celldm(5) = %10.6f,\n", $cosB; #printf OUT " celldm(6) = %10.6f,\n", $cosG; my $k = $a0 * 1.0e10; $latt[0] = $k * $celldm[0]; #print "k=$k $a0 $latt[0], $celldm[0]\n"; if(defined $celldm[1]) { $latt[1] = $k* $celldm[1] * $celldm[0]; } else { $latt[1] = $latt[0]; } if(defined $celldm[2]) { $latt[2] = $k* $celldm[2] * $celldm[0]; } else { $latt[2] = $latt[0]; } if(defined $celldm[3]) { $latt[3] = Utils::Round(Sci::acos($celldm[3]) * $todeg, 4, 0); } else { $latt[3] = 90.0; } if(defined $celldm[4]) { $latt[4] = Utils::Round(Sci::acos($celldm[3]) * $todeg, 4, 0); } else { $latt[4] = 90.0; } if(defined $celldm[5]) { $latt[5] = Utils::Round(Sci::acos($celldm[3]) * $todeg, 4, 0); } else { $latt[5] = 90.0; } if($ibrav == 4) { #Hexagonal $latt[5] = 120.0; } } if(!$UseCELLPARAMETERS) { print "Lattice parameters: $latt[0], $latt[1], $latt[2], $latt[3], $latt[4], $latt[5]\n"; print "\n"; $Crystal->SetLatticeParameters($latt[0], $latt[1], $latt[2], $latt[3], $latt[4], $latt[5]); #print "latt: $latt[0], $latt[1], $latt[2], $latt[3], $latt[4], $latt[5]\n"; } if($PrintStructures) { print "Asymmetric Atom Sites:\n"; } $in->rewind(); my $line = $in->SkipTo("ATOMIC_POSITIONS"); my $natoms = 0; my %iSite; while(1) { $line =~ /ATOMIC_POSITIONS\s+(\S+)/i; my $unit = lc($1); my $k = 1.0; if($unit eq 'crystal') { } elsif($unit eq 'bohr') { $k = $a0 * 1.0e10; } $line = Utils::DelSpace($in->ReadLine()); #print "l:$line"; last if(!defined $line or $line eq ''); last if($line =~ /K_POINTS/); my ($name, $x, $y, $z) = ($line =~ /(\w+)\s+([+-\.0-9eEdD]+)\s+([+-\.0-9eEdD]+)\s+([+-\.0-9eEdD]+)/); last if(!defined $z); $name = ucfirst(lc($name)); $x = Utils::Reduce01($x); $y = Utils::Reduce01($y); $z = Utils::Reduce01($z); if($unit eq 'bohr') { $x = $x / ($latt[0] / $k); $y = $z / ($latt[0] / $k); $z = $y / ($latt[0] / $k); } if($PrintStructures) { print "$natoms: $name ($x, $y, $z)\n"; } $iSite{$name}++; $Crystal->AddAtomSite($name . $iSite{$name}+1, $name, $x, $y, $z, 1.0); if($ibrav == 2 or $ibrav == 10) { #FCC, FCO $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x+0.5, $y+0.5, $z, 1.0); $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x+0.5, $y, $z+0.5, 1.0); $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x, $y+0.5, $z+0.5, 1.0); } elsif($ibrav == 3 or $ibrav == 7 or $ibrav == 11) { #BCC, BCT, BCO $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x+0.5, $y+0.5, $z+0.5, 1.0); } elsif($ibrav == -9) { #Orth A-centerd $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x, $y+0.5, $z+0.5, 1.0); } elsif($ibrav == 9 or $ibrav == 13) { #Orth C-centerd, Mono C-centered $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x+0.5, $y+0.5, $z, 1.0); } elsif($ibrav == -13) { #Mono unique axis b $Crystal->AddAtomSite($name . ++$iSite{$name}, $name, $x+0.5, $y, $z+0.5, 1.0); } $natoms++; } $in->Close(); $Crystal->CalMetrics(); $Crystal->ExpandCoordinates(); return $Crystal; }; sub ReadOutputToHash { my ($this, $OutFile, $IsPrint) = @_; $IsPrint = 0 if(!defined $IsPrint); #$IsPrint=1; my $in = JFile->new($OutFile, "r"); if(!$in) { print "Error in PWSCF::ReadOutputToHash: Can not read [$OutFile].\n"; return 0; } my %hash; while(1) { my $line = $in->ReadLine(); #print "l:$line"; last if(!defined $line); if($line =~ /^\s*Title:/) { $line = $in->ReadLine(); $hash{Title} = Utils::DelSpace($line); } elsif($line =~ /^\s*celldm\(/) { $line = $in->ReadLine(); ($hash{celldm1}) = ($line =~ /celldm\(1\)\s*=\s*(\S+)/); ($hash{celldm2}) = ($line =~ /celldm\(2\)\s*=\s*(\S+)/); ($hash{celldm3}) = ($line =~ /celldm\(3\)\s*=\s*(\S+)/); $line = $in->ReadLine(); ($hash{celldm4}) = ($line =~ /celldm\(4\)\s*=\s*(\S+)/); ($hash{celldm5}) = ($line =~ /celldm\(5\)\s*=\s*(\S+)/); ($hash{celldm6}) = ($line =~ /celldm\(6\)\s*=\s*(\S+)/); } elsif($line =~ /^\s*crystal axes:/) { $line = $in->ReadLine(); ($hash{a11}, $hash{a12}, $hash{a13}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); ($hash{a21}, $hash{a22}, $hash{a23}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); ($hash{a31}, $hash{a32}, $hash{a33}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); } elsif($line =~ /^\s*reciprocal axes:/) { $line = $in->ReadLine(); ($hash{Ra11}, $hash{Ra12}, $hash{Ra13}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); ($hash{Ra21}, $hash{Ra22}, $hash{Ra23}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); ($hash{Ra31}, $hash{Ra32}, $hash{Ra33}) = ($line =~ /\(\s*(\S+)\s*(\S+)\s*(\S+)/); } elsif($line =~ /^\s*the Fermi energy is/) { ($hash{EF}) = ($line =~ /is\s+(\S+)/); $hash{EFRy} = $hash{EF} / $RyToeV; print "EF = $hash{EF} eV\n" if($IsPrint); } elsif($line =~ /^!\s*total\s+energy\s*=/) { ($hash{EtotRy}) = ($line =~ /=\s*(\S+)/); $hash{Etot} = $hash{EtotRy} * $RyToeV; print "Etot = $hash{EtotRy} Ry $hash{Etot} eV\n" if($IsPrint); } elsif($line =~ /^\s*total\s+stress\s*\(Ry/) { ($hash{Pkbar}) = ($line =~ /P\s*=\s*(\S+)/); $hash{PGPa} = $hash{Pkbar} * 0.1; my ($a1, $a2, $a3); ($a1, $a2, $a3, $hash{P11kbar}, $hash{P12kbar}, $hash{P13kbar}) = Utils::Split("\\s+", $in->ReadLine()); ($a1, $a2, $a3, $hash{P21kbar}, $hash{P22kbar}, $hash{P23kbar}) = Utils::Split("\\s+", $in->ReadLine()); ($a1, $a2, $a3, $hash{P31kbar}, $hash{P32kbar}, $hash{P33kbar}) = Utils::Split("\\s+", $in->ReadLine()); if($IsPrint) { print "P = $hash{Pkbar} kbar $hash{PGPa} GPa\n"; printf " (%12.4g %12.4g %12.4g)\n", $hash{P11kbar}, $hash{P12kbar}, $hash{P13kbar}; printf " (%12.4g %12.4g %12.4g)\n", $hash{P21kbar}, $hash{P22kbar}, $hash{P23kbar}; printf " (%12.4g %12.4g %12.4g)\n", $hash{P31kbar}, $hash{P32kbar}, $hash{P33kbar}; } } elsif($line =~ /The maximum number of steps has been reached/) { $hash{RelaxationStatus} = "Error: " . Utils::DelSpace($line); print "Error: Relaxation not converged\n" if($IsPrint); } elsif($line =~ /convergence has been achieved/) { $hash{SCFStatus} = "Completed: converged in " ."$hash{nRelaxationConvergenceStep} steps\n"; ($hash{nRelaxationConvergenceStep}) = ($line =~ /in\s+(\d+)/); print "Completed: SCF converged in $hash{nRelaxationConvergenceStep} step\n" if($IsPrint); } } $in->Close(); return \%hash; } sub ReadEtotIneV { my ($this, $OutFile) = @_; my $in = JFile->new($OutFile, "r") or die "$!: Can not read [$OutFile].\n\n"; my $Etot; while(1) { my $line = $in->SkipTo("!\\s*total\\s+energy\\s*="); last if(!defined $line); ($Etot) = ($line =~ /=\s*([+\-\.\d]+)/); } $in->Close(); #print "Etot=$Etot\n"; $Etot *= $RyToeV; return $Etot; } sub UpdateInpFile { my ($this, $App, $InpFile, $NewInpFile, $Crystal) = @_; $App->print("Update PWSCF Input File:\n"); $App->print("Input File : $InpFile\n"); $App->print("Output File: $NewInpFile\n"); $App->print("\n"); my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParameters(); my @AtomTypeList = $Crystal->GetCAtomTypeList(); my $nAtomType = @AtomTypeList; my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList(); my $nAsymmetricAtomSite = @AtomSiteList; my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList(); my $nTotalExpandedAtomSite = $Crystal->nTotalExpandedAtomSite(); my $in = JFile->new($InpFile, "r") or die "$!: Can not read [$InpFile].\n"; my $out = JFile->new($NewInpFile, "wb") or die "$!: Can not write to [$NewInpFile].\n"; #ファイル作製開始 $out->print(" &CONTROL\n"); while(1) { my $line = $in->ReadLine(); last if(!defined $line); if($line =~ /^\s*A\s*=/) { $out->printf(" A = %14.10f,\n", $a); } elsif($line =~ /^\s*B\s*=/) { $out->printf(" B = %14.10f,\n", $c); } elsif($line =~ /^\s*C\s*=/) { $out->printf(" C = %14.10f,\n", $c); } elsif($line =~ /^\s*cosAB\s*=/) { $out->printf(" cosAB = %14.10f,\n", cos($torad*$gamma)); } elsif($line =~ /^\s*cosAC\s*=/) { $out->printf(" cosAC = %14.10f,\n", cos($torad*$beta)); } elsif($line =~ /^\s*cosBC\s*=/) { $out->printf(" cosBC = %14.10f,\n", cos($torad*$alpha)); } elsif($line =~ /^\s*ATOMIC_POSITIONS/) { $out->printf("%s", $line); for(my $i = 0 ; $i < $nAsymmetricAtomSite ; $i++) { $line = $in->ReadLine(); my $atom = $AtomSiteList[$i]; my ($x, $y, $z) = $atom->Position(); my $atomtype = $atom->AtomName(); $out->printf(" %6s %14.10f %14.10f %14.10f\n", $atomtype, $x, $y, $z); } } else { $out->printf("%s", $line); } } $out->Close(); $in->Close(); return 1; }; 1;