package TSPACE;
use Exporter;
@ISA = qw(Exporter);
#公開したいサブルーチン
@EXPORT = qw();
#use lib "d:/Programs/Perl/lib";
use strict;
use File::Basename;
use ProgVars;
use Utils;
#===============================================
# スクリプト大域変数
#===============================================
my %TSPACELatticeTypeHash = (
0 => "Simple hexagonal",
1 => "Other simple lattices",
2 => "Face centered",
3 => "Body centered",
4 => "C centered",
-1 => "Trigonal in rhomb lattice",
);
my @TSPACELatticeTypeList = (
0 => "Simple hexagonal",
1 => "Other simple lattices",
2 => "Face centered",
3 => "Body centered",
4 => "C centered",
-1 => "Trigonal in rhomb lattice",
);
my %PointGroupDB = {
Oh => {LatticeSystem => 'cubic', RotationOperation => 'Oh'},
O => {LatticeSystem => 'cubic', RotationOperation => 'Oh'},
Td => {LatticeSystem => 'cubic', RotationOperation => 'Oh'},
Th => {LatticeSystem => 'cubic', RotationOperation => 'Oh'},
T => {LatticeSystem => 'cubic', RotationOperation => 'Oh'},
D4h => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
D4 => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
D2d => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
C4v => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
C4h => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
S4 => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
C4 => {LatticeSystem => 'tetragonal', RotationOperation => 'Oh'},
D2h => {LatticeSystem => 'orthogonal', RotationOperation => 'Oh'},
D2 => {LatticeSystem => 'orthogonal', RotationOperation => 'Oh'},
C2v => {LatticeSystem => 'orthogonal', RotationOperation => 'Oh'},
D6h => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
D6 => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
D3h => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
C6v => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
C6h => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
C3h => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
C6 => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
# D3d => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
# D3 => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
# C3v => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
# S6 => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
# C3 => {LatticeSystem => 'hexagonal', RotationOperation => 'D6h'},
D3d => {LatticeSystem => 'trigonal', RotationOperation => 'D6h'},
D3 => {LatticeSystem => 'trigonal', RotationOperation => 'D6h'},
C3v => {LatticeSystem => 'trigonal', RotationOperation => 'D6h'},
S6 => {LatticeSystem => 'trigonal', RotationOperation => 'D6h'},
C3 => {LatticeSystem => 'trigonal', RotationOperation => 'D6h'},
C2h => {LatticeSystem => 'monoclinic', RotationOperation => 'Oh'},
Cs => {LatticeSystem => 'monoclinic', RotationOperation => 'Oh'},
C2 => {LatticeSystem => 'monoclinic', RotationOperation => 'Oh'},
Ci => {LatticeSystem => 'triclinic', RotationOperation => 'Oh'},
C1 => {LatticeSystem => 'triclinic', RotationOperation => 'Oh'},
};
#===============================================
# パス(読み込みDB)
# Web関係変数
# CGI の仮想パス
# プログラム名
#===============================================
my $Program = ProgVars::Program();
my $ProgramDir = ProgVars::ProgramDir();
my $ProgramOldDir = ProgVars::ProgramOldDir();
my $BinDir = Deps::MakePath($TSPACEDir, "bin", 0);
my $WYCOFFPath = Deps::MakePath($TSPACEDBDir, "WYCOFF", 0);
my $GENERATORPath = Deps::MakePath($TSPACEDBDir, "GENERATOR", 0);
my $D6hRotationOperationTablePath = Deps::MakePath($TSPACEDBDir, "D6hRotationOperationTable.txt", 0);
my $OhRotationOperationTablePath = Deps::MakePath($TSPACEDBDir, "OhRotationOperationTable.txt", 0);
#============================================================
# 静的関数
#============================================================
sub GetTSPACELatticeTypeHash
{
return \%TSPACELatticeTypeHash;
}
sub GetTSPACELatticeTypeList
{
return \@TSPACELatticeTypeList;
}
#============================================================
# 変数等取得、再定義関数
#============================================================
sub GetRotationOperationTable
{
my ($this, $Sym, $Type) = @_;
if($Type eq 'List') {
return $this->{"p${Sym}RotationOperationTableList"};
}
else {
$this->{"p${Sym}RotationOperationTableHash"};
}
}
sub GetWycoffPositionList
{
my ($this) = @_;
return $this->{pWycoffPositionList};
}
sub GetWycoffPositionHash
{
my ($this, $iSPG, $iSet) = @_;
$iSet = 1 if(!defined $iSet);
my $p = $this->{pWycoffPositionList};
return $p->[$iSPG][$iSet];
}
sub GetGeneratorList
{
my ($this) = @_;
return $this->{pGeneratorList};
}
sub GetGeneratorHash
{
my ($this, $iSPG, $iSet) = @_;
$iSet = 1 if(!defined $iSet);
my $p = $this->{pGeneratorList};
return $p->[$iSPG][$iSet];
}
sub GetSPGName
{
my ($this, $iSPG, $iSet) = @_;
$iSet = 1 if(!defined $iSet);
my $p = $this->{pGeneratorList};
return ('', '') if(!defined $p);
my $h = $p->[$iSPG][$iSet];
return ($h->{PointGroup}, $h->{SpaceGroup});
}
sub GetRotationOperationGroup
{
my ($this, $PointGroup) = @_;
if($PointGroupDB{$PointGroup}) {
return $PointGroupDB{$PointGroup}->{RotationOperation};
}
if($PointGroup eq 'Cs3') {
return 'Oh';
}
if($PointGroup =~ /4/) {
return 'Oh';
}
if($PointGroup =~ /^[A-Z]3/ or $PointGroup =~ /^[A-Z]6/) {
return 'D6h';
}
return 'Oh';
}
#============================================================
# 継承クラスで定義しなおす関数
#============================================================
#============================================================
# コンストラクタ、デストラクタ
#============================================================
sub new
{
my ($module) = @_;
my $this = {};
bless $this;
$this->ReadDatabases();
return $this;
}
sub DESTROY { my $this = shift; }
#============================================================
# ファイル読み込み関数
#============================================================
sub ReadDatabases
{
my ($this) = @_;
$this->ReadRotationOperationTable('D6h');
$this->ReadRotationOperationTable('Oh');
$this->ReadGeneratorDB();
$this->ReadWycoffPositions();
}
sub ReadWycoffPositions
{
my ($this) = @_;
my $in = JFile->new($WYCOFFPath, "r");
if(!$in) {
print("Error in TSPACE::ReadWycoffPositions: Can not read [$WYCOFFPath].\n");
return;
}
my @List;
my $iPrevSPG = 1;
my $iSet = 1;
while(1) {
my $line = $in->ReadLine();
Utils::DelSpace($line);
last if($line eq '');
my ($iSPG, $nWycoff) = Utils::Split("\\s+", $line);
if($iSPG == $iPrevSPG) {
$iSet++;
}
else {
$iPrevSPG = $iSPG;
$iSet = 1;
}
#print "SPG=$iSPG [$iSet]: nW = $nWycoff
\n";
my @Pos;
for(my $i = 0 ; $i < $nWycoff ; $i++) {
$line = $in->ReadLine();
my ($w, $x, $y, $z) = Utils::Split("\\s+", $line);
$Pos[$i] = {
Name => $w,
x => $x,
y => $y,
z => $z,
};
#print " $w: ($x, $y, $z)
\n";
}
$List[$iSPG][$iSet] = {
iSPG => $iSPG,
iSet => $iSet,
nWycoffPositions => $nWycoff,
pPositions => \@Pos,
};
}
$in->Close();
$this->{pWycoffPositionList} = \@List;
}
sub ReadGeneratorDB
{
my ($this) = @_;
my $in = JFile->new($GENERATORPath, "r");
if(!$in) {
print("Error in TSPACE::ReadGeneratorDB: Can not read [$GENERATORPath].\n");
return;
}
my @List;
my $iPrevSPG = 0;
my $iSet = 1;
while(1) {
my $line = $in->ReadLine();
Utils::DelSpace($line);
last if($line eq '');
my ($iSPG, $idx, $nGen, $PGName, $SPGName) = ($line =~ /(\d+)\s+([-\d]+)\s+(\d+)\s+(\S+)\s+(.*)\s*$/);
if($iSPG == $iPrevSPG) {
$iSet++;
}
else {
$iPrevSPG = $iSPG;
$iSet = 1;
}
#print "SPG=$iSPG [$iSet]: $idx, nGen=$nGen: $PGName: $SPGName
\n";
my @Gen;
for(my $i = 0 ; $i < $nGen ; $i++) {
$line = $in->ReadLine();
my ($iRot, $a1, $b1, $a2, $b2, $a3, $b3) = Utils::Split("\\s+", $line);
$Gen[$i] = {
iRotation => $iRot,
a1 => $a1,
b1 => $b1,
v1 => $a1 / $b1,
a2 => $a2,
b2 => $b2,
v2 => $a2 / $b2,
a3 => $a3,
b3 => $b3,
v3 => $a3 / $b3,
};
#print " $iRot, $a1/$b1, $a2/$b2, $a3/$b3
\n";
}
$List[$iSPG][$iSet] = {
iSPG => $iSPG,
iSet => $iSet,
nGenerator => $nGen,
PointGroup => $PGName,
SpaceGroup => $SPGName,
pGenerators => \@Gen,
};
}
$in->Close();
$this->{pGeneratorList} = \@List;
}
sub ReadRotationOperationTable
{
my ($this, $Sym) = @_;
my $InFile;
if($Sym eq 'D6h') {
$InFile = $D6hRotationOperationTablePath;
}
else {
$InFile = $OhRotationOperationTablePath;
}
my $in = JFile->new($InFile, "r");
if(!$in) {
print("Error in TSPACE::ReadRotationOperationTable: Can not read [$InFile].\n");
return;
}
my @Op;
my %OpHash;
$in->SkipTo("TABLE OF OPERATION CODE");
for(my $i = 0 ; ; $i++) {
my $line = $in->ReadLine();
last if(!defined $line);
my ($idx, $name, $x, $y, $z) = Utils::Split("\\s+", $line);
last if(!defined $z);
$x =~ s/-W/-X+Y/;
$y =~ s/-W/-X+Y/;
$z =~ s/-W/-X+Y/;
$x =~ s/W/X-Y/;
$y =~ s/W/X-Y/;
$z =~ s/W/X-Y/;
#$App->print(" $idx: $name: ($x $y $z)\n");
$Op[$idx] = {Name => $name, x => $x, y => $y, z => $z};
$OpHash{$name} = {ID => $idx, x => $x, y => $y, z => $z};
}
$this->{"p${Sym}RotationOperationTableList"} = \@Op;
$this->{"p${Sym}RotationOperationTableHash"} = \%OpHash;
$in->SkipTo("GROUP TABLE FOR");
my $line = $in->ReadLine();
my @idx1 = Utils::Split("\\s+", $line);
my $nOp = @idx1;
#$App->print("\n");
#$App->H3("# of operation without inversion: $nOp\n");
#$App->BeginTable(1);
#$App->BeginRow();
for(my $i = 0 ; $i < $nOp ; $i++) {
my $ip1 = $i+1;
#$App->TableCell("$Op[$ip1]->{Name}");
}
#$App->EndRow();
for(my $i = 0 ; ; $i++) {
my $line = $in->ReadLine();
last if(!defined $line);
my ($idx, @a) = Utils::Split("\\s+", $line);
last if(@a < $nOp-1);
#$App->BeginRow();
#$App->TableCell("$Op[$idx]->{Name}");
for(my $j = 0 ; $j < @a ; $j++) {
my $idx2 = $a[$j];
#$App->TableCell($Op[$idx2]->{Name});
}
#$App->EndRow();
}
#$App->EndTable();
$in->SkipTo("INVERS ELEMENTS");
my @InvOp;
for(my $i = 0 ; ; $i++) {
my $line = $in->ReadLine();
last if(!defined $line);
my @a = Utils::Split("\\s+", $line);
last if(@a == 0);
push(@InvOp, @a);
}
#$App->print("\n");
#$App->print("Inverse elements\n");
for(my $i = 0 ; $i < @InvOp ; $i++) {
my $ip1 = $i+1;
#$App->print("$Op[$ip1]->{Name}=>$Op[$InvOp[$i]]->{Name} ");
}
#$App->print("\n");
$in->Close();
}
1;