#=============================================== # Arrhenius #=============================================== package Arrhenius; use TkFittingSimple; @ISA = qw(TkFittingSimple); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use MultiColumnData; use Sci qw($pi $kB $e $e0 $me $h $hbar $KToeV erfc); use Sci::ConductingMaterial; use Sci::Optimize; #============================================================ # 大域変数・変数等取得関数 #============================================================ my $ProgramName = "Arrhenius plot/2011"; my @Vars = ( { Name => "m0", Val => 0, ID => 0, Scale => 0.1, Min => '', Max => '' }, { Name => "c0", Val => 0.0, ID => 1, Scale => 0.1, Min => '', Max => '' }, { Name => "m1", Val => 1, ID => 0, Scale => 0.1, Min => '', Max => '' }, { Name => "c1", Val => 0.0, ID => 1, Scale => 0.1, Min => '', Max => '' }, { Name => "m2", Val => 2, ID => 0, Scale => 0.1, Min => '', Max => '' }, { Name => "c2", Val => 0.0, ID => 1, Scale => 0.1, Min => '', Max => '' }, ); #============================================================ # コンストラクタ、デストラクタ #============================================================ #呼び出されることはない sub new { my ($class, $app, @a) = @_; my $self = TkFittingSimple->new($app, $ProgramName, @a); my $this = bless $self, $class; $this->{nm} = 3; $this->{ini} = new ConductingMaterial(); $this->{dini} = new ConductingMaterial(); $this->InitializeParameters($this->{ini}, $this->{dini}); $this->{DataFile} = new MultiColumnData; $this->AddParameters2(\@Vars, nCheckEntryColumn => 2); return $this; } sub DESTROY { my $this = shift; $this->SUPER::DESTROY(@_); } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub BuildMainPane { my ($this, $MainPaneFrame, $EntryWidth) = @_; my $App = $this->App(); my $args = $App->Args(); my $mw = $MainPaneFrame; # $this->SUPER::CreateWidgets(); #=================================================== # ペインを作製 #=================================================== my $EntryWidth = 12; my $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); # $this->MakeChooseFileEntry($Frame, 'Param', 'Param:', $this->{ini}->pVariable("ParameterFile", ""), # '&Choose', sub { $this->ChooseFile(@_); }, "ChooseParameterFile"); # $this->{SaveParamButton} = $Frame->MyButton( # -text => '&Save', # -takefocus => 1, # -command => sub { $this->ButtonPressed('RButtonDown', 'SaveParam'); }, # )->pack(-side => 'left'); # $this->{EditParamButton} = $Frame->MyButton( # -text => 'ed', # -takefocus => 1, # -command => sub { $this->ButtonPressed('RButtonDown', 'EditParam'); }, # )->pack(-side => 'left'); my $savefmask = '*.prm'; $this->{ParameterFileFrame} = $this->MakeChooseFileEntry( $Frame, 'Param', 'Param:', $this->{ini}->pVariable("ParameterFile", ""), '&Choose', sub { $this->ChooseFile("save", $savefmask, "ChooseParameterFile", @_); }, 1, sub { $this->SaveParameterFile("SaveParam", '', @_); }, 1, sub { $this->EditFile('EditParam', @_); }, [] ); $this->{ParameterFileFrame}->pack(-anchor => 'nw', -fill => 'x'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); # $this->MakeChooseFileEntry($Frame, 'SampleCSV', 'Sample:', $this->{ini}->pVariable("SampleCSVFile", ""), # '&Choose', sub { $this->ChooseFile(@_); }, "ChooseSampleFile"); # $this->{EditDataButton} = $Frame->MyButton( # -text => 'ed', # -takefocus => 1, # -command => sub { $this->ButtonPressed('RButtonDown', 'EditSampleCSV'); }, # )->pack(-side => 'left'); my $Samplefmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft'; $this->{SampleFileFrame} = $this->MakeChooseFileEntry( $Frame, 'SampleCSV', 'Sample:', $this->{ini}->pVariable("SampleCSVFile", ""), '&Choose', sub { $this->{SampleCSV} = $this->ChooseFile("open", $Samplefmask, "ChooseSampleFile", @_); $this->AssignGraphData(); $this->Draw(); }, 0, sub {}, 1, sub { $this->EditFile('EditSampleCSV', @_); }, ['X1', 'Y1'] ); $this->{SampleFileFrame}->pack(-anchor => 'nw', -fill => 'x'); $this->{SampleFileFrame}->{pXDataLabel} = ['T.*', '1/T.*']; $this->{SampleFileFrame}->{pYDataLabel} = ['sigma.*', 'ue.*', 'mobility.*', '.*']; # $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); # $this->{ChooseXListBox} = $Frame->MyBrowseEntry( # -label => "X:", # -state => "readonly", # -takefocus => 1, # -width => 5, # -Selections => [], # -SelIndex => 0, # )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); # $this->{ChooseXListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseXListBox}); } ); # $this->{ChooseY1ListBox} = $Frame->MyBrowseEntry( # -label => "Y1:", # -state => "readonly", # -takefocus => 1, # -width => 5, # -Selections => [], # -SelIndex => 1, # )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeLabelEntry($Frame, "XMin", "XMin(cal):", $this->{ini}->pVariable('XMin', ''), "%s", $EntryWidth-2, "", 0, 0); $this->MakeLabelEntry($Frame, "XMin", "XMax:", $this->{ini}->pVariable('XMax', ''), "%s", $EntryWidth-2, "", 0, 1); $this->MakeLabelEntry($Frame, "XStep", "Step:", $this->{ini}->pVariable('XStep', 0), "%s", $EntryWidth-2, "", 0, 2); $this->MakeLabelEntry($Frame, "FitXMin", "XMin(fit):", $this->{ini}->pVariable('FitXMin', ''), "%s", $EntryWidth-2, "", 1, 0); $this->MakeLabelEntry($Frame, "FitXMin", "XMax:", $this->{ini}->pVariable('FitXMax', ''), "%s", $EntryWidth-2, "", 1, 1); $this->MakeLabelEntry($Frame, "nSkipData", "nSkip:", $this->{ini}->pVariable('nSkipData', 0), "%d", $EntryWidth-2, "", 1, 2); $Frame = $mw->MyLabFrame( -label => 'LSQ', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); my $Frame2 = $Frame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{ChooseLSQMethodListBox} = $Frame2->MyBrowseEntry( -label => "LSQ Method:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => ['Amoeba::Simplex', 'PDL::Simplex', 'ModifiedNewton'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseModelListBox} = $Frame2->MyBrowseEntry( -label => "Model:", -state => "readonly", -takefocus => 1, -width => 10, -Selections => ['log(|y|)-1/T'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $Frame2 = $Frame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeLabelEntry($Frame2, "EPS", "EPS:", $this->{ini}->pVariable('EPS', 1.0e-5), "%12.4g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame2, "nMaxIter", "MaxIter:", $this->{ini}->pVariable('nMaxIter', 1000), "%d", $EntryWidth, "", 0, 1); $this->MakeLabelEntry($Frame2, "nSaveSpectraInterval", "SaveIntvl:", $this->{ini}->pVariable('nSaveSpectraInterval', 100), "%d", $EntryWidth, "", 1, 0); $this->BuildVariablesFrame($MainPaneFrame, 'Polynomial'); $this->UpdateParameters(); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{RecalcButton} = $Frame->MyButton( -text => 'Re&calc', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'Recalc'); }, )->pack(-side => 'left'); $this->{FitButton} = $Frame->MyButton( -text => '&Fit', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'Fit'); }, )->pack(-side => 'left'); #ツールバーのOpenボタンをファイル読み込みにバインドする $mw->{OpenButton}->configure( -command => sub { $this->ChooseFile('SampleCSV', $this->{SPEFileFileEntry}); }, ) if($mw->{OpenButton}); } sub ReadSampleDataFile { my ($this, $filepath, $IsPrint, $UpdateRange) = @_; my $ret = $this->SUPER::ReadSampleDataFile($filepath, $IsPrint, $UpdateRange); if($UpdateRange or !defined $this->{ini}->{FitXMin}) { ($this->{ini}->{XMin}, $this->{ini}->{XMax}) = ($this->{ini}->{FitXMin}, $this->{ini}->{FitXMax}); $this->{ini}->{XStep} = ($this->{ini}->{XMax} - $this->{ini}->{XMin}) / 20; $this->{ini}->{XMin} = int($this->{ini}->{XMin}); $this->{ini}->{XMax} = int($this->{ini}->{XMax} + $this->{ini}->{XStep}); $this->{ini}->{XStep} = ($this->{ini}->{XMax} - $this->{ini}->{XMin}) / 20; } return $ret; } sub PrintCoefficient { my ($this) = @_; my $ini = $this->{ini}; my $Model = $this->{ChooseModelListBox}->GetText(); if($Model eq 'log(|y|)-1/T') { for(my $i = 0 ; $i < $this->{nm} ; $i++) { if(abs($ini->{"m$i"} - 0) < 1.0e-3) { my $A0 = exp($ini->{"c$i"}); print " A0=exp(c$i): $A0\n"; } elsif(abs($ini->{"m$i"} - 1) < 1.0e-3) { my $Ea = -$ini->{"c$i"} * $kB / $e; print " Ea=-c$i*kB/e: $Ea eV\n"; } elsif(abs($ini->{"m$i"} - 2) < 1.0e-3) { my $dE2 = $ini->{"c$i"} * 2.0 * $kB / $e * $kB / $e; my $dE = ($dE2 < 0.0)? "i*" . sqrt(-$dE2) : sqrt($dE2); print " dE=sqrt(2c$i*kB^2/e-2): $dE eV\n"; } elsif(abs($ini->{"m$i"} - 0.25) < 1.0e-3) { my $ci = -$ini->{"c$i"}; print " c(T^-1/4)=-c$i: $ci\n"; } } } } sub CalY { my ($this, $x, $pVars) = @_; $x = 1.0 / $x; my $y = 0.0; for(my $j = 0 ; $j < @$pVars ; $j += 2) { if(abs($pVars->[$j]) < 1.0e-6) { $y += $pVars->[$j+1]; } elsif(abs($pVars->[$j]-1.0) < 1.0e-6) { $y += $pVars->[$j+1] * $x; } else { $y += $pVars->[$j+1] * ($x**$pVars->[$j]); } } return exp($y); } sub Recalc { my ($this) = @_; return if(!defined $this->{DataFile}); $this->SUPER::Recalc(); $this->PrintCoefficient(); } sub Fit { my ($this) = @_; return if(!defined $this->{DataFile}); $this->SUPER::Fit(); # $this->PrintCoefficient(); } sub CalS2 { my ($this, $pX, $pY, $pVars, $iPrintLevel) = @_; #print "pVars=", join(',', @$pVars), "\n"; my $optimize = $this->{Optimize}; my $ini = $this->{ini}; my $Model = $this->{ChooseModelListBox}->GetText(); $optimize->RecoverParameters($pVars); my $S2 = 0.0; my $c = 0; for(my $i = 0 ; $i < @$pX ; $i++) { my $x = $pX->[$i]; my $YCal = $this->CalY($x, $pVars); if($Model eq 'log(|y|)-1/T') { my $d = log(abs($YCal)) - log(abs($pY->[$i])); $S2 += $d*$d; } $c++; } $S2 = sqrt($S2 / $c) if($c > 0); $optimize->IncrementnS2(); my $nS2 = $optimize->nS2Calculation(); my $nS2Interval = $ini->{nSaveSpectraInterval}; print "S2[$nS2] = $S2 / "; $S2 += $optimize->CalPenalty(1.0e10, $pVars, 1); print "$S2\n"; $optimize->PrintParameters(1, $pVars, $S2, 0); if($nS2Interval > 0 and $nS2 % $nS2Interval == 0) { $this->SetS2($S2); $this->Recalc(); $this->RePlot(); } $this->UpdateParameters(); $this->mw()->update(); return $S2; } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); $GraphFrame0->ClearAllData(); my $Model = $this->{"ChooseModelListBox"}->GetText(); my ($X1Label, $Y1Label); my $DataKey = "DataFile"; my $FrameKey = "SampleFileFrame"; my $pData = $this->{$DataKey}; return if(!defined $pData); my $nData = $pData->nData(); return if($nData <= 0); my $Frame = $this->{$FrameKey}; $X1Label = $Frame->{X1ListBox}->GetText(); $Y1Label = $Frame->{Y1ListBox}->GetText(); $X1Label = 'X' if(!$X1Label); $Y1Label = 'Y1' if(!$Y1Label); $GraphFrame0->SetXCaption($X1Label); $GraphFrame0->SetYCaption($Y1Label); my $pX1 = $pData->GetData($X1Label) if($X1Label); my $pY1 = $pData->GetData($Y1Label) if($Y1Label); if($pX1) { $GraphFrame0->AddGraphData($pX1, $pY1, 0, "black", "circle", 6, "black", 0, "black", "XAutoSkip", "1/T(K)", "log({${Y1Label}|)") if($pY1); } my $pCalX1 = $this->{pCalX}; my $pCalY1 = $this->{pCalY}; if($pCalX1) { $GraphFrame0->AddGraphData($pCalX1, $pCalY1, 1, "red", "", 6, "red", 0, "red", "XAutoSkip", "1/T(K)", "log(|${Y1Label}|)(cal)") if($pCalY1); } if($Model eq 'log(|y|)-1/T') { # $GraphFrame0->SetXCaption("1/$XLabel"); # $GraphFrame0->SetYCaption("log(|${Y1Label}|)"); # $GraphFrame0->SetXScalePlotType('1/x'); # $GraphFrame0->SetYScalePlotType('log(|x|)'); } if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); # $GraphFrame0->SetViewYRange(0); } } 1;