#=============================================== # EnergyBand #=============================================== package EnergyBand; #use Exporter; #@ISA = qw(Exporter); use strict; sub SetCrystal { my ($this,$crystal) = @_; return $this->{'Crystal'} = $crystal; } sub Crystal { return shift->{'Crystal'}; } sub SetXName { my ($this,$name)=@_; return $this->{'XName'} = $name; } sub XName { return shift->{'XName'}; } sub GetXName { return shift->{'XName'}; } sub SetYName { my ($this,$name)=@_; return $this->{'YName'} = $name; } sub YName { return shift->{'YName'}; } sub GetYName { return shift->{'YName'}; } sub GetXMinMax { my $this = shift; return ($this->{'XMin'}, $this->{'XMax'}); } sub GetYMinMax { my $this = shift; return ($this->{'YMin'}, $this->{'YMax'}); } sub GetMinMax { my $this = shift; return ($this->{'XMin'}, $this->{'XMax'}, $this->{'YMin'}, $this->{'YMax'}); } sub nData { my $a=shift->{'kx'}; return scalar @$a; } sub kx { my ($this,$i)=@_; return $this->{'kx'}->[$i]; } sub ky { my ($this,$i)=@_; return $this->{'ky'}->[$i]; } sub kz { my ($this,$i)=@_; return $this->{'kz'}->[$i]; } sub Distance { my ($this,$i)=@_; return $this->{'distance'}->[$i]; } sub Energy { my ($this,$i)=@_; return $this->{'Energy'}->[$i]; } sub Ne { my ($this,$i)=@_; return $this->{'Ne'}->[$i]; } sub GetData { my ($this, $i) = @_; return ($this->{kx}->[$i], $this->{ky}->[$i], $this->{kz}->[$i], $this->{distance}->[$i], $this->{Energy}->[$i], $this->{Ne}->[$i]); } sub pkx { return shift->{'kx'}; } sub pky { return shift->{'ky'}; } sub pkz { return shift->{'kz'}; } sub pDistance { return shift->{'distance'}; } sub pEnergy { return shift->{'Energy'}; } sub pNe { return shift->{'Ne'}; } sub Unit { return shift->{'Unit'}; } sub SetUnit { my ($this,$u)=@_; return $this->{'Unit'} = $u; } #============================================================ # コンストラクタ、デストラクタ #============================================================ sub new { my ($module) = @_; my $this = {}; bless $this; my @kx; my @ky; my @kz; my @distance; my @Energy; my @Ne; $this->{'kx'} = \@kx; $this->{'ky'} = \@ky; $this->{'kz'} = \@kz; $this->{'distance'} = \@distance; $this->{'Energy'} = \@Energy; $this->{'Ne'} = \@Ne; my $nData = $this->nData(); return $this; } sub DESTROY { my $this = shift; } sub GetBandBoundary { my ($this, $fRecalc) = @_; $fRecalc = 0 if(not defined $fRecalc); $fRecalc = 1 if(not defined $this->{'BoundaryPositions'}); unless($fRecalc) { return ($this->{'BoundaryDistances'}, $this->{'BoundaryPositions'}); } # my $eps = 1.0e-6; my $pkx = $this->{'kx'}; my $pky = $this->{'ky'}; my $pkz = $this->{'kz'}; my $pDistance = $this->{'distance'}; my $nData = @$pkx; return undef if($nData < 2); my @BoundaryDistances; my @BoundaryPositions; #print "nData: $nData\n"; my $dx0 = $pkx->[1] - $pkx->[0]; my $dy0 = $pky->[1] - $pky->[0]; my $dz0 = $pkz->[1] - $pkz->[0]; my $r20 = $dx0*$dx0 + $dy0*$dy0 + $dz0*$dz0; push(@BoundaryDistances, 0); push(@BoundaryPositions, "$pkx->[0],$pky->[0],$pkz->[0]"); #print "nData=$nData\n"; for(my $i = 1 ; $i+1 < $nData ; $i++) { my $dx1 = $pkx->[$i+1] - $pkx->[$i]; my $dy1 = $pky->[$i+1] - $pky->[$i]; my $dz1 = $pkz->[$i+1] - $pkz->[$i]; #print " d: $dx1 $dy1 $dz1\n"; my $r21 = $dx1*$dx1 + $dy1*$dy1 + $dz1*$dz1; my $rr12 = $dx0*$dx1 + $dy0*$dy1 + $dz0*$dz1; next if($r20 == 0.0 or $r21 == 0.0); # my $cosQ2 = abs($rr12*$rr12 / $r20 / $r21); my $cosQ2 = $rr12 / sqrt($r20*$r21); #print " i=$i: ($dx0,$dy0,$dz0)->($dx1,$dy1,$dz1) cosQ2=$cosQ2\n"; # if(abs($cosQ2) < 0.99) { if($cosQ2 < 0.99) { #print "k vector changed at i=$i: ($dx0,$dy0,$dz0)->($dx1,$dy1,$dz1) cosQ2=$cosQ2\n"; push(@BoundaryDistances, $pDistance->[$i]); push(@BoundaryPositions, "$pkx->[$i],$pky->[$i],$pkz->[$i]"); } $dx0 = $dx1; $dy0 = $dy1; $dz0 = $dz1; $r20 = $r21; } my $last = $nData-1; push(@BoundaryDistances, $pDistance->[$last]); push(@BoundaryPositions, "$pkx->[$last], $pky->[$last], $pkz->[$last]"); $this->{'BoundaryDistances'} = \@BoundaryDistances; $this->{'BoundaryPositions'} = \@BoundaryPositions; return (\@BoundaryDistances, \@BoundaryPositions);; } sub GetDistance { my ($this, $kx0, $ky0, $kz0, $kx1, $ky1, $kz1, $crystal) = @_; $crystal = $this->Crystal() if(not defined $crystal); return 0.0 if(not defined $kx0); return 0.0 if(not defined $kx1); #print "Crystal: $crystal\n"; if($crystal) { return $crystal->GetReciprocalDistanceFromK( $kx0, $ky0, $kz0, $kx1, $ky1, $kz1); } return sqrt(($kx1-$kx0)^2+($ky1-$ky0)^2+($kz1-$kz0)^2); } sub GetDistanceToPrevK { my ($this, $i) = @_; return 0.0 if($i == 0); my $pkx = $this->pkx(); my $pky = $this->pky(); my $pkz = $this->pkz(); my $pd = $this->pDistance(); my $kx = $pkx->[$i]; my $ky = $pky->[$i]; my $kz = $pkz->[$i]; my $prevkx = $pkx->[$i-1]; my $prevky = $pky->[$i-1]; my $prevkz = $pkz->[$i-1]; my $prevd = $pd ->[$i-1]; return $prevd + $this->GetDistance( $kx, $ky, $kz, $prevkx, $prevky, $prevkz); } sub AddByKDE { my ($this, $kx, $ky, $kz, $d, $e) = @_; my $i = $this->nData(); my $pkx = $this->pkx(); my $pky = $this->pky(); my $pkz = $this->pkz(); my $pd = $this->pDistance(); my $pe = $this->pEnergy(); #print "i=$i: $kx, $ky, $kz: $e\n"; $pkx->[$i] = $kx; $pky->[$i] = $ky; $pkz->[$i] = $kz; $d = $this->GetDistanceToPrevK($i) if(not defined $d); # if($d == 0.0) { # undef $pkx->[$i]; # undef $pky->[$i]; # undef $pkz->[$i]; # return $i; # } $pd ->[$i] = $d; $pe ->[$i] = $e; return $i+1; } sub AddByKDEN { my ($this, $kx, $ky, $kz, $d, $e, $ne) = @_; my $i = $this->nData(); #print "i=$i: $kx, $ky, $kz: $e\n"; my $pkx = $this->pkx(); my $pky = $this->pky(); my $pkz = $this->pkz(); my $pd = $this->pDistance(); my $pe = $this->pEnergy(); my $pne = $this->pNe(); $pkx->[$i] = $kx; $pky->[$i] = $ky; $pkz->[$i] = $kz; $d = $this->GetDistanceToPrevK($i) if(not defined $d); $pd ->[$i] = $d; $pe ->[$i] = $e; $pne->[$i] = $ne; return $i+1; } sub CalXMinMax { my ($this) = @_; my $pd = $this->pDistance(); return unless($pd); my $nData = $this->nData(); return if($nData <= 0); my $min = $pd->[0]; my $max = $min; for(my $i = 1 ; $i < $nData ; $i++) { $min = $pd->[$i] if($min > $pd->[$i]); $max = $pd->[$i] if($max < $pd->[$i]); } $this->{'XMin'} = $min; $this->{'XMax'} = $max; return ($min, $max); } sub CalYMinMax { my ($this) = @_; my $pe = $this->pEnergy(); return unless($pe); my $nData = $this->nData(); return if($nData <= 0); my $min = $pe->[0]; my $max = $min; for(my $i = 1 ; $i < $nData ; $i++) { $min = $pe->[$i] if($min > $pe->[$i]); $max = $pe->[$i] if($max < $pe->[$i]); } $this->{'YMin'} = $min; $this->{'YMax'} = $max; return ($min, $max); } sub CalMinMax { my ($this) = @_; my ($xmin, $xmax) = $this->CalXMinMax(); my ($ymin, $ymax) = $this->CalYMinMax(); return 1; } 1;