#=============================================== # TkCV #=============================================== package TkCV; use clib::TkFittingCommon; @ISA = qw(TkFittingCommon); use strict; use Utils; use Sci qw($pi $kB $c $e $e0 $me $mp $mn $h $hbar); use Sci::Material; use Sci::TFT; use MyTk::GraphFrameArray; my $material = new Material; #============================================================ # 変数等取得関数 #============================================================ #============================================================ # コンストラクタ、デストラクタ #============================================================ #呼び出されることはない sub new { my ($module, $app) = @_; # my ($module, $app, $canvas) = @_; my $this = {}; bless $this; $this->SetApplication($app); # $this->SetCanvas($canvas); return $this; } sub DESTROY { my $this = shift; $this->SUPER::DESTROY(@_); } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub CreateLeftFrame { my ($this, $ConfigSide, @args) = @_; # return $this->SUPER::CreateLeftFrame(); return undef; } sub CreateSelectFilePane { my ($this) = @_; # return $this->SUPER::CreateSelectFilePane(); return undef; } sub CreateFileContentPane { return undef; } sub CreateWidgets { my ($this, $DoSuperOnly) = @_; $DoSuperOnly = 0 if(!defined $DoSuperOnly); my $mw = $this->mw(); my $Program = "CV Fit2007"; $this->{ini} = new TFT(); $this->{dini} = new TFT(); $this->InitializeParameters($this->{ini}, $this->{dini}); $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $mw->SetTitle("$Program / TkPlot"); $this->App()->SetProgram("$Program / TkPlot"); #=================================================== # TFTペインを作製 #=================================================== 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'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'LFSampleCSV', 'LF:', $this->{ini}->pVariable("LFSampleCSVFile", ""), '&Choose', sub { $this->ChooseFile(@_); }, "ChooseLFSampleFile"); $this->{EditDataButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditLFSampleCSV'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{ChooseLFXListBox} = $Frame->MyBrowseEntry( -label => "X:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseLFXListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseLFXListBox}); } ); $this->{ChooseLFY1ListBox} = $Frame->MyBrowseEntry( -label => "Y1:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 1, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseLFY1ListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseLFXListBox}); } ); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'HFSampleCSV', 'HF:', $this->{ini}->pVariable("HFSampleCSVFile", ""), '&Choose', sub { $this->ChooseFile(@_); }, "ChooseHFSampleFile"); $this->{EditDataButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditHFSampleCSV'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{ChooseHFXListBox} = $Frame->MyBrowseEntry( -label => "X:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseHFXListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseHFXListBox}); } ); $this->{ChooseHFY1ListBox} = $Frame->MyBrowseEntry( -label => "Y1:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 1, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseHFY1ListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseLFXListBox}); } ); $Frame = $mw->MyFrame()->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "Vg0", "Vg:", $this->{ini}->pVariable('Vg0', -1.0), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "Vg1", "-", $this->{ini}->pVariable('Vg1', 1.0), "%g", $EntryWidth, "", 0, 1); $this->MakeLabelEntry($Frame, "VgStep", ",", $this->{ini}->pVariable('VgStep', 0.1), "%g", $EntryWidth, "V", 0, 2); $Frame = $mw->MyFrame()->pack(-anchor => 'nw'); $this->{ChoosePlotTypeListBox} = $Frame->MyBrowseEntry( -label => "Plot:", -state => "readonly", -takefocus => 1, -Selections => ["Vg-C", "Vg-C(E)", "Vg-C(Q)", "x-Q", "E-D(E)"], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseModelListBox} = $Frame->MyBrowseEntry( -label => "Model:", -state => "readonly", -takefocus => 1, -width => 20, -Selections => ["MOS", "TFT"], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseModelListBox}->configure( -browsecmd => sub { $this->SelChangeListBox("Model", $this->{ChooseModelListBox}); } ); $Frame = $mw->MyLabFrame( -label => 'Common', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "T", "T:", $this->{ini}->pVariable('T', 300.0), "%g", $EntryWidth, "", 0, 0); $this->MakeCheckEntry($Frame, "VFB", "VFB:", $this->{ini}->pVariable('VFBcheck', 0), $this->{ini}->pVariable('VFB', 0.0), "%g", $EntryWidth, "V", 1, 0); $this->MakeLabelEntry($Frame, "Sox", "Area(ox):", $this->{ini}->pVariable('Sox', 1.0e-2), "%g", $EntryWidth, "cm2", 2, 0); $this->MakeLabelEntry($Frame, "Ss", "Area(s):", $this->{ini}->pVariable('Ss', 1.0e-2), "%g", $EntryWidth, "cm2", 2, 1); $Frame = $mw->MyLabFrame( -label => 'insulator', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "Epsi", "er:", $this->{ini}->pVariable('Epsicheck', 0), $this->{ini}->pVariable('Epsi', 4.0), "%g", $EntryWidth, "e0", 0, 0); $this->MakeCheckEntry($Frame, "dgate", "d(gate):", $this->{ini}->pVariable('dgatecheck', 0), $this->{ini}->pVariable('dgate', 100.0), "%g", $EntryWidth, "nm", 1, 0); $this->MakeLabelEntry($Frame, "Cox", "Cox:", $this->{ini}->pVariable('Cox', 0.0), "%g", $EntryWidth, "F", 1, 1, "disabled"); $Frame = $mw->MyLabFrame( -label => 'semiconductor', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "EFs", "EF:", $this->{ini}->pVariable('EFscheck', 0), $this->{ini}->pVariable('EFs', 3.3), "%g", $EntryWidth, "eV", 0, 0); $this->MakeLabelEntry($Frame, "Epss", "er:", $this->{ini}->pVariable('Epss', 11.9), "%g", $EntryWidth, "e0", 0, 1); $this->MakeCheckEntry($Frame, "ds", "d(s):", $this->{ini}->pVariable('dscheck', 0), $this->{ini}->pVariable('ds', 100.0), "%g", $EntryWidth, "nm", 1, 0); $this->MakeLabelEntry($Frame, "Cs", "Cs:", $this->{ini}->pVariable('Cs', 0.0), "%g", $EntryWidth, "F", 1, 1, "disabled"); $this->MakeLabelEntry($Frame, "ECs", "EC:", $this->{ini}->pVariable('ECs', 3.0), "%g", $EntryWidth, "eV", 2, 0); $this->MakeLabelEntry($Frame, "EVs", "EV:", $this->{ini}->pVariable('EVs', 4.0), "%g", $EntryWidth, "eV", 2, 1); $this->MakeLabelEntry($Frame, "Egs", "Eg:", $this->{ini}->pVariable('Egs', 0.0), "%g", $EntryWidth, "eV", 3, 0, "disabled"); $this->MakeLabelEntry($Frame, "mes", "me:", $this->{ini}->pVariable('mes', 0.35), "%g", $EntryWidth, "me", 4, 0); $this->MakeLabelEntry($Frame, "mhs", "mh:", $this->{ini}->pVariable('mhs', 1.5), "%g", $EntryWidth, "me", 4, 1); $this->MakeLabelEntry($Frame, "NCs", "NC:", $this->{ini}->pVariable('NCs', 8.5e18), "%g", $EntryWidth, "cm-3", 5, 0, "disabled"); $this->MakeLabelEntry($Frame, "NVs", "NV:", $this->{ini}->pVariable('NVs', 8.5e20), "%g", $EntryWidth, "cm-3", 5, 1, "disabled"); $this->MakeLabelEntry($Frame, "Eis", "Ei:", $this->{ini}->pVariable('Eis', 0.0), "%g", $EntryWidth, "eV", 6, 0, "disabled"); $this->MakeLabelEntry($Frame, "Nis", "Ni:", $this->{ini}->pVariable('Nis', 0.0), "%g", $EntryWidth, "cm-3", 6, 1, "disabled"); $this->MakeLabelEntry($Frame, "Nes", "Ne:", $this->{ini}->pVariable('Nes', 1.0e16), "%g", $EntryWidth, "cm-3", 7, 0, "disabled"); $this->MakeLabelEntry($Frame, "Nhs", "Nh:", $this->{ini}->pVariable('Nhs', 1.0e15), "%g", $EntryWidth, "cm-3", 7, 1, "disabled"); $this->MakeLabelEntry($Frame, "LDe", "LDe:", $this->{ini}->pVariable('LDe', 0.0), "%g", $EntryWidth, "nm", 8, 0, "disabled"); $this->MakeLabelEntry($Frame, "LDh", "LDh:", $this->{ini}->pVariable('LDh', 0.0), "%g", $EntryWidth, "nm", 8, 1, "disabled"); $Frame = $mw->MyLabFrame( -label => 'x-Q', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "nx", "nx:", $this->{ini}->pVariable('nx', 501), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "Vs", "Vs:", $this->{ini}->pVariable('Vs', 0.0), "%g", $EntryWidth, "V", 0, 1); $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'); #ツールバーのOpenボタンをファイル読み込みにバインドする $mw->{OpenButton}->configure( -command => sub { $this->ChooseVdsIdsFile($this->{VdsIdsFileEntry}); }, ) if($mw->{OpenButton}); $this->UpdateParameters(); } sub ChooseFile { my ($this, $type, $widget, $Option) = @_; #print "ChooseFile: type=$type Option=$Option\n"; my $mode = 'open'; # 'save' my $fmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft'; $fmask = '*.prm' if($Option eq 'ChooseParameterFile'); my $filepath = $this->SUPER::ChooseAFile($type, $mode, $fmask, '', "Choose file", $widget, $Option); my $ret; if($type eq 'Param') { $ret = $this->ReadParameterFile($filepath); } elsif($type eq 'LFSampleCSV') { $ret = $this->ReadSampleDataFile($filepath, "LF"); } elsif($type eq 'HFSampleCSV') { $ret = $this->ReadSampleDataFile($filepath, "HF"); } return undef unless($ret); $this->CreateGraphFrame(); $this->AssignGraphData(); $this->Draw(); return $ret; } sub ButtonPressed { my ($this, $event, $type) = @_; if($type eq 'Recalc') { $this->Recalc(); $this->CreateGraphFrame() if(!defined $this->{GraphFrameArray}); $this->AssignGraphData(1); $this->Draw(); } else { $this->SUPER::ButtonPressed($event, $type); } } sub UpdateParameters { my ($this) = @_; my $ini = $this->{ini}; my $T = $ini->{T}; my $Epsi = $ini->{Epsi}; my $Epss = $ini->{Epss}; my $ECs = $ini->{ECs}; my $EVs = $ini->{EVs}; my $mes = $ini->{mes}; my $mhs = $ini->{mhs}; my $EFm = $ini->{EFm}; my $EFs = $ini->{EFs}; my $EFi = $ini->{EFi}; my $dgate = $ini->{dgate}*1.0e-9; my $ds = $ini->{ds}*1.0e-9; my $Egs = $ini->{Egs} = -($ini->{ECs} - $ini->{EVs}); my $NCs = $ini->{NCs} = $material->Nc($mes*$me, 1.0, $T) * 1.0e-6; # cm-3 my $NVs = $ini->{NVs} = $material->Nv($mhs*$me, 1.0, $T) * 1.0e-6; # cm-3 my $Nis = $ini->{Nis} = sqrt($NCs * $NVs) * exp(-0.5 * $Egs / $kB / $T * $e); # cm-3 my $Eis = $ini->{Eis} = ($ECs+$EVs)*0.5 + 0.75*$kB*$T/$e * log($mhs/$mes); # my $Eis = $ini->{Eis} = ($ECs+$EVs)*0.5 + 0.5*$kB*$T/$e * log($NVs/$NCs); $ini->{Nes} = $NCs * exp(-($EFs-$ECs)/$kB/$T*$e); $ini->{Nhs} = $NVs * exp(-($EVs-$EFs)/$kB/$T*$e); my $Nes = $ini->{Nes} * 1.0e6; my $Nhs = $ini->{Nhs} * 1.0e6; $ini->{Cox} = $material->CalCapacitance($Epsi, $ini->{Sox} * 1.0e-4, $dgate); # F $ini->{Cs} = $material->CalCapacitance($Epss, $ini->{Ss} * 1.0e-4, $ds); # F $ini->{LDe} = $material->CalMISCVDebyeLength($T, $Nes, $Epss) * 1.0e9; $ini->{LDh} = $material->CalMISCVDebyeLength($T, $Nhs, $Epss) * 1.0e9; $this->SUPER::UpdateParameters(); } sub EntryFocusedIn { my ($this, $obj, $event, $type) = @_; # $this->{PrevValue} = $obj->GetText(); $this->SUPER::EntryFocusedIn($obj, $event, $type); } sub EntryFocusedOut { my ($this, $obj, $event, $type) = @_; return if($obj->{PrevValue} eq $obj->GetText()); if($event eq 'FocusOut') { # if($type eq 'T') { # } $this->UpdateParameters(); return $this->SUPER::EntryFocusedOut($obj, $event, $type); } else { return $this->SUPER::EntryFocusedOut($obj, $event, $type); } } #=================================================== # データ処理 #=================================================== sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{Optimize} = undef; if($InitializeParameterFile) { $this->{ini}->{LFSampleCSVFile} = ''; $this->{ini}->{HFSampleCSVFile} = ''; $this->{LFDataFile} = undef; $this->{HFDataFile} = undef; } if($InitializeData) { $this->{pEArray} = undef; $this->{pCalx} = undef; $this->{pCalE} = undef; $this->{pCalV} = undef; $this->{pCalQ} = undef; $this->{pCalVg} = undef; $this->{pCalVs} = undef; $this->{pCalVox} = undef; $this->{pCalQs} = undef; $this->{pCalLFCg} = undef; $this->{pCalHFCg} = undef; $this->{pCalECs} = undef; $this->{pCalEVs} = undef; $this->{pCalEFs} = undef; $this->{pCalEis} = undef; } } sub InitializeParameters { my ($this, $ini, $dini) = @_; $this->AddParameters($ini, $dini, "VFB", 0.0, 0, 0.5, '', ''); $this->AddParameters($ini, $dini, "Epsi", 3.9, 0, 1.0, 0.0, ''); $this->AddParameters($ini, $dini, "dgate", 100.0, 0, 10.0, 0.0, ''); $this->AddParameters($ini, $dini, "EFs", 3.5, 0, 0.5, '', ''); $this->AddParameters($ini, $dini, "Epss", 3.5, 0, 1.0, 0.0, ''); $this->AddParameters($ini, $dini, "ds", 100.0, 0, 10.0, 0.0, ''); } sub Recalc { my ($this) = @_; $this->print("\nRecalc\n"); $this->UpdateParameters(); my $Plot = $this->{ChoosePlotTypeListBox}->GetText(); if($Plot eq 'x-Q') { $this->RecalcxQ(); } elsif($Plot eq 'E-D(E)') { $this->RecalcDOS(); } else { $this->RecalcCV(); } } sub RecalcDOS { my ($this) = @_; my $ini = $this->{ini}; $this->print("\nCalc DOS\n"); my $Model = $this->{ChooseModelListBox}->GetText(); my $T = $ini->{T}; my $VFB = $ini->{VFB}; my $EFs = $ini->{ECs} - $ini->{EFs}; my $Epss = $ini->{Epss} * $e0; my $Epsi = $ini->{Epsi} * $e0; my $dgate = $ini->{dgate} * 1.0e-9; my $ds = $ini->{ds} * 1.0e-9; my $Cox = $ini->{Cox}; my $Cs = $ini->{Cs}; my $Ss = $ini->{Ss} * 1.0e-4; # m2 my $LFXLabel = $this->{ChooseLFXListBox}->GetText(); my $LFY1Label = $this->{ChooseLFY1ListBox}->GetText(); my $pX = $this->{LFDataFile}->GetData($LFXLabel) if($LFXLabel); my $pY1 = $this->{LFDataFile}->GetData($LFY1Label) if($LFY1Label); my $nData = @$pX; my $CdMax = 0.0; my @Cd; my @Vg; my @du = (0.0); my @u = (0.0); my @dQ = (0.0); my @Q = (0.0); my @Ei = (0.0); my @NE = (0.0); printf("Cox=%f pF\n", $Cox * 1.0e12); for(my $i = 0 ; $i < $nData ; $i++) { last if($i > 0 and $pX->[$i] - $pX->[$i-1] <= 0.0); my $Cg = $pY1->[$i]; last if($Cg > $Cox); $Vg[$i] = $pX->[$i]; #printf("%d: Vg=%6.3f V Cg=%8.4g ", $i, $Vg[$i], $Cg*1.0e12); # $Cd[$i] = $CdMax; # if($Cg < $Cox) { $Cd[$i] = $Cox * $Cg / ($Cox - $Cg); # } #printf("Cd=%8.4g pF\n", $Cd[$i]*1.0e12); if($i > 0) { my $dV = $Vg[$i] - $pX->[$i-1]; $du[$i] = (1.0 - ($Cg + $pY1->[$i-1]) / 2.0 / $Cox) * $dV; $u[$i] = $u[$i-1] + $du[$i]; $dQ[$i] = ($Cd[$i] + $Cd[$i-1]) * $du[$i] / 2.0; $Q[$i] = $Q[$i-1] + $dQ[$i]; $Ei[$i] = $EFs + ($u[$i] + $u[$i-1]) / 2.0; # if($du[$i] == 0.0) { # $NE[$i] = $NE[$i-1]; # } # else { $NE[$i] = ($Q[$i]*$Cd[$i] - $Q[$i-1]*$Cd[$i-1]) / $Epss / $e / $du[$i] / $Ss; # } } #printf(" u=%6.3f eV Q=%g C Ei=%6.3f eV NE=%g e\n", $u[$i], $Q[$i], $Ei[$i], $NE[$i]); printf("Vg=%6.3f V Cg=%6.3g Ei=%6.3f eV NE=%g e\n", $Vg[$i], $Cg*1.0e12, $Ei[$i], $NE[$i]); $CdMax = $Cd[$i] if($Cd[$i] > $CdMax); } my $pData = new MultiColumnData(); $pData->SetpX(\@Vg); $pData->SetpY(\@Ei); my $CorrectEiFB = -$pData->YVal($VFB) + $EFs; print "Correct Ei by $CorrectEiFB eV at Vg=$VFB V\n"; for(my $i = 0 ; $i < @Ei ; $i++) { $Ei[$i] += $CorrectEiFB; } $this->{pCalEi} = \@Ei; $this->{pCalNE} = \@NE; } sub RecalcxQ { my ($this) = @_; my $ini = $this->{ini}; my $Model = $this->{ChooseModelListBox}->GetText(); my $iModel = 0; if($Model eq 'TFT') { $iModel = 1; } my $T = $ini->{T}; my $VFB = $ini->{VFB}; my $Epss = $ini->{Epss} * $e0; my $Epsi = $ini->{Epsi} * $e0; my $dgate = $ini->{dgate} * 1.0e-9; my $ds = $ini->{ds} * 1.0e-9; my $Cox = $ini->{Cox}; my $Cs = $ini->{Cs}; my $ECs = $ini->{ECs}; my $EVs = $ini->{EVs}; my $EFs = $ini->{EFs}; my $Eis = $ini->{Eis}; my $LD = $ini->{LDh} * 1.0e-9; my $LDe = $ini->{LDe} * 1.0e-9; my $LDh = $ini->{LDh} * 1.0e-9; my $n0 = $ini->{Nes} * 1.0e6; my $p0 = $ini->{Nhs} * 1.0e6; printf"n0=%g p0=%g cm-3\n", $n0*1.0e-6, $p0*1.0e-6; $n0 = 1e-100 if($n0 < 1e-100); $p0 = 1e-100 if($p0 < 1e-100); my $n0p0 = $n0 / $p0; my $Ss = $ini->{Ss} * 1.0e-4; my $x0 = 0.0; my $x1 = $ini->{ds}; my $nx = $ini->{nx}; my $xStep = ($x1 - $x0) / ($nx - 1); my $Vs = $ini->{Vs}; my $b = $e / $kB / $T; my $KE = 2.0 * $kB * $T / $e / $LD; my $bVs = -$b * $Vs; my $Fs2 = exp(-$bVs) + $bVs - 1.0 + $n0p0 * (exp($bVs) - $bVs - 1.0); my $Fs = sqrt($Fs2); $Fs = -$Fs if($Vs < 0.0); my $Es = $KE * $Fs; my $Qs = -$Epss / $e * $Es * 1.0e-4; # 2.0 * $kB * $T / $e / $LD * $Fs * $Epss / $e; printf "Es = %g V/m Qs = %g electrons/cm2\n", $Es, $Qs; my (@xCal, @ECal, @VCal, @QCal); $xCal[0] = $x0; $VCal[0] = $Vs; my $bV = -$b * $VCal[0]; my $F2 = exp(-$bV) + $bV - 1.0 + $n0p0 * (exp($bV) - $bV - 1.0); my $F = sqrt($F2); $F = -$F if($VCal[0] < 0.0); $ECal[0] = $KE * $F; printf "x=%6.3g nm: V=%6.3g V E=%g V/m\n", $x0, $VCal[0], $ECal[0]; for(my $i = 1 ; $i < $nx ; $i++) { my $x = $x0 + $i * $xStep; my $i1 = $i - 1; $bV = -$b * $VCal[$i1]; $F2 = exp(-$bV) + $bV - 1.0 + $n0p0 * (exp($bV) - $bV - 1.0); $F = sqrt($F2); $F = -$F if($VCal[$i1] < 0.0); $ECal[$i] = $KE * $F; $VCal[$i] = $VCal[$i1] - ($ECal[$i]+$ECal[$i1]) / 2.0 * $xStep * 1.0e-9; $bV = -$b * $VCal[$i]; $F2 = exp(-$bV) + $bV - 1.0 + $n0p0 * (exp($bV) - $bV - 1.0); $F = sqrt($F2); $F = -$F if($VCal[$i] < 0.0); $xCal[$i] = $x; $ECal[$i] = $KE * $F; $VCal[$i] = $VCal[$i1] - ($ECal[$i]+$ECal[$i1]) / 2.0 * $xStep * 1.0e-9; $QCal[$i] = $Epss / $e * ($ECal[$i] - $ECal[$i1]) / ($xStep*1.0e-9) * 1.0e-6; printf "x=%6.3g nm: V=%6.3g V E=%g V/m Q=%g cm-3\n", $x, $VCal[$i], $ECal[$i], $QCal[$i] if($i == 1 or $i % 10 == 0); } $QCal[0] = $Epss / $e * ($ECal[1] - $ECal[0]) / ($xStep*1.0e-9) * 1.0e-6; printf "x=%6.3g nm: V=%6.3g V E=%g V/m Q=%g cm-3\n", $x0, $VCal[0], $ECal[0], $QCal[0]; my $Qtot = 0.0; for(my $i = 1 ; $i < $nx ; $i++) { my $i1 = $i - 1; $Qtot += ($QCal[$i]+$QCal[$i1])/2.0 * ($xStep*1.0e-7); } printf "Qtot=%g cm-2\n", $Qtot; $this->{pCalx} = \@xCal; $this->{pCalE} = \@ECal; $this->{pCalV} = \@VCal; $this->{pCalQ} = \@QCal; } sub RecalcCV { my ($this) = @_; my $ini = $this->{ini}; my $Model = $this->{ChooseModelListBox}->GetText(); my $iModel = 0; if($Model eq 'TFT') { $iModel = 1; } my $T = $ini->{T}; my $VFB = $ini->{VFB}; my $Epss = $ini->{Epss} * $e0; my $Epsi = $ini->{Epsi} * $e0; my $dgate = $ini->{dgate} * 1.0e-9; my $ds = $ini->{ds} * 1.0e-9; my $Cox = $ini->{Cox}; my $Cs = $ini->{Cs}; my $ECs = $ini->{ECs}; my $EVs = $ini->{EVs}; my $EFs = $ini->{EFs}; my $Eis = $ini->{Eis}; my $LD = $ini->{LDh} * 1.0e-9; my $LDe = $ini->{LDe} * 1.0e-9; my $LDh = $ini->{LDh} * 1.0e-9; my $n0 = $ini->{Nes} * 1.0e6; my $p0 = $ini->{Nhs} * 1.0e6; printf"n0=%g p0=%g cm-3\n", $n0*1.0e-6, $p0*1.0e-6; $n0 = 1e-100 if($n0 < 1e-100); $p0 = 1e-100 if($p0 < 1e-100); my $n0p0 = $n0 / $p0; my $Ss = $ini->{Ss} * 1.0e-4; my $Vg0 = $ini->{Vg0}; my $Vg1 = $ini->{Vg1}; my $VgStep = $ini->{VgStep}; my $c = 0; my (@VgCal, @LFCgCal, @HFCgCal, @LFCdCal, @HFCdCal); my (@VsCal, @VoxCal, @ECal, @QsCal, @ECsCal, @EVsCal, @EFsCal, @EisCal); my ($Vs, $Vox, $EField, $Qs, $HFCg, $LFCg, $HFCd, $LFCd); for(my $i = 0 ; ; $i++) { my $Vg = $Vg0 + $i * $VgStep; last if($Vg > $Vg1 + 1.0e-6); ($Vs, $Vox, $EField, $Qs, $HFCg, $LFCg, $HFCd, $LFCd) = $material->CalMISCV($T, $Vg, $VFB, $Epss, $Epsi, $dgate, $ds, $Cox, $Cs, $Ss, $LDe, $LDh, $LD, $n0, $p0, $iModel, 1.0e-6, 100, $Vs, 1.0e-4); next if($Vg < $Vg0); last if($Vg1 < $Vg); printf("Vg=%5.2f(Vs=%5.2f,Vox=%5.2f) Qs=%9.3g C=%5.2f Cox=%5.2f Cd=%7.3f\n", $Vg, $Vs, $Vox, $Qs / $e, $LFCg*1.0e12, $Cox*1.0e12, $LFCd*1.0e12); $VgCal[$c] = $Vg; $VsCal[$c] = $Vs; $VoxCal[$c] = $Vox; $ECal[$c] = $EField; $QsCal[$c] = $Qs / $e * 1.0e-4; $LFCgCal[$c] = $LFCg; $HFCgCal[$c] = $HFCg; $LFCdCal[$c] = $LFCd; $HFCdCal[$c] = $HFCd; $ECsCal[$c] = -$ECs + $EFs; $EVsCal[$c] = -$EVs + $EFs; $EFsCal[$c] = -$EFs + $EFs; $EisCal[$c] = -$Eis + $EFs; $c++; } $this->{pCalVg} = \@VgCal; $this->{pCalVs} = \@VsCal; $this->{pCalVox} = \@VoxCal; $this->{pCalE} = \@ECal; $this->{pCalQs} = \@QsCal; $this->{pCalLFCg} = \@LFCgCal; $this->{pCalHFCg} = \@HFCgCal; $this->{pCalLFCd} = \@LFCdCal; $this->{pCalHFCd} = \@HFCdCal; $this->{pCalECs} = \@ECsCal; $this->{pCalEVs} = \@EVsCal; $this->{pCalEFs} = \@EFsCal; $this->{pCalEis} = \@EisCal; } sub SaveParameterFile { my ($this, $filepath) = @_; $this->{ini}->{LFX} = $this->{ChooseLFXListBox}->GetText(); $this->{ini}->{LFY1} = $this->{ChooseLFY1ListBox}->GetText(); $this->{ini}->{HFX} = $this->{ChooseHFXListBox}->GetText(); $this->{ini}->{HFY1} = $this->{ChooseHFY1ListBox}->GetText(); $this->{ini}->{PlotType} = $this->{ChoosePlotTypeListBox}->GetText() if($this->{ChoosePlotTypeListBox}); $this->{ini}->{Model} = $this->{ChooseModelListBox}->GetText() if($this->{ChooseModelListBox}); $filepath = $this->ChooseASaveFile($filepath, 'save.prm', '*.prm'); return undef if(!defined $filepath); $this->{ini}->{ParameterFile} = $filepath; $this->{ini}->SetIniFile($filepath, undef, 1); $this->App()->print("\nSaveParameterFile: [$filepath]\n"); $this->ComposeParameters($this->{dini}, $this->{ini}); $this->{ini}->WriteAll(); $this->DecomposeParameters($this->{ini}, $this->{dini}); } sub ReadParameterFile { my ($this, $ParameterFilePath) = @_; $this->Initialize(1, 1); $this->App()->print("\nRead paramter from [$ParameterFilePath].\n"); $this->{ini}->ReadAll($ParameterFilePath); $this->DecomposeParameters($this->{ini}, $this->{dini}); my $ret; foreach my $type ('LF', 'HF') { my $path = $this->{ini}->{"${type}SampleCSVFile"}; next if(!defined $path or $path eq ''); $path = $this->GetValidDataPath($path, $ParameterFilePath, $this->{ini}->{ParameterFile}); $ret = $this->ReadSampleDataFile($path, $type, 1, 0, 0); if($ret) { $this->{ini}->{"${type}SampleCSVFile"} = $path; } else { # $this->print("Error: Can not read [$path].\n"); } } $this->{ini}->{ParameterFile} = $ParameterFilePath; $this->{ChoosePlotTypeListBox}->SetText($this->{ini}->{PlotType}); $this->{ChooseModelListBox}->SetText($this->{ini}->{Model}); $this->{ChooseLFXListBox}->SetText($this->{ini}->{LFX}); $this->{ChooseLFY1ListBox}->SetText($this->{ini}->{LFY1}); $this->{ChooseHFXListBox}->SetText($this->{ini}->{HFX}); $this->{ChooseHFY1ListBox}->SetText($this->{ini}->{HFY1}); return 1; } sub ReadSampleDataFile { my ($this, $filepath, $type, $IsPrint, $UpdateRange) = @_; $UpdateRange = 1 if(!defined $UpdateRange); my $App = $this->App(); #print "filepath=$filepath\n"; $this->Initialize(0, 1); $this->{"${type}Path"} = $filepath; $this->{"${type}DataFile"} = new MultiColumnData; my ($nData, $pLabelArray, @pDataArray) = $this->ReadASampleDataFile($filepath, $this->{"${type}DataFile"}, [$this->{"Choose${type}XListBox"}, $this->{"Choose${type}Y1ListBox"}], ); if(!defined $nData) { $App->print("Error: Can not read [$filepath].\n"); return $this->{"${type}Path"} = undef; } $this->{"Choose${type}XListBox"}->SetCurSel('Vg.*', 'V.*'); $this->{"Choose${type}Y1ListBox"}->SetCurSel('C.*'); if($UpdateRange or !defined $this->{ini}->{FitXMin}) { ($this->{ini}->{FitXMin}, $this->{ini}->{FitXMax}) = Utils::CalMinMax($pDataArray[0]); ($this->{ini}->{Vg0}, $this->{ini}->{Vg1}) = Utils::CalMinMax($pDataArray[0]); } return $filepath; } sub CreateGraphFrame { my ($this, $canvas, $TargetData) = @_; my ($GraphFrameArray, @GraphFrame) = $this->SUPER::CreateGraphFrame($canvas, $TargetData, 2); my $XScale0 = $GraphFrame[0]->GetXScale(0); my $YScale0 = $GraphFrame[0]->GetYScale(0); my $XScale1 = $GraphFrame[1]->GetXScale(0); my $YScale1 = $GraphFrame[1]->GetYScale(0); $GraphFrame[0]->SetXCaption(""); $GraphFrame[0]->SetYCaption("C / F"); $GraphFrame[1]->SetXCaption("Vg / V"); $GraphFrame[1]->SetYCaption(""); $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); $XScale1->SetScaleStringVisible(1); $XScale1->SetCaptionVisible(1); return ($GraphFrameArray, @GraphFrame); } sub ShowScaleDialog { my ($this, $GraphFrame, $command, $Title, @a) = @_; #$command: "XScale" "YScale" #最初の4つのundefはViewRangeに現在値を使う #次の2つのundefはPlotTypeに現在値を使う設定 #そのあとの1,0は、X,Y軸のPlotTypeの同期をおこなうかどうか #最後の1は、ScaleDialogでOKを押されたらグラフの再描画を行う #  Y軸のViewRangeは同期するが、PlotTypeの同期は無視する return $GraphFrame->ShowScaleDialog($Title, undef, undef, undef, undef, undef, undef, 1, 0, 1); } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $FileType = $this->FileType(); # if($FileType =~ /(Ids)/i) { # } } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $GraphFrame0->ClearAllData() if($GraphFrame0); $GraphFrame1->ClearAllData() if($GraphFrame1); my $Plot = $this->{ChoosePlotTypeListBox}->GetText(); my $Model = $this->{ChooseModelListBox}->GetText(); my $LFXLabel = $this->{ChooseLFXListBox}->GetText(); my $LFY1Label = $this->{ChooseLFY1ListBox}->GetText(); my $HFXLabel = $this->{ChooseHFXListBox}->GetText(); my $HFY1Label = $this->{ChooseHFY1ListBox}->GetText(); #print "Plot: $Plot\n"; if($Plot eq 'x-Q') { if($this->{ini}->{ShowCalcPlot}) { my $pCalx = $this->{pCalx}; my $pCalE = $this->{pCalE}; my $pCalV = $this->{pCalV}; my $pCalQ = $this->{pCalQ}; if($pCalx) { $GraphFrame0->AddGraphData($pCalx, $pCalQ, 1, "black", "", 6, "black", 0, "black", "XAutoSkip", "x", "Q (cal)") if($pCalQ); $GraphFrame1->AddGraphData($pCalx, $pCalV, 1, "black", "", 6, "black", 0, "black", "XAutoSkip", "x", "V (cal)") if($pCalV); } } $GraphFrame0->SetYCaption("Q / e"); $GraphFrame1->SetYCaption("Vs / V"); if($GraphFrame1) { $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); $GraphFrame1->SetXCaption("x / nm"); } if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 0, 0); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 1, 0); $GraphFrame0->SetViewYRange(0); } } elsif($Plot eq 'E-D(E)') { if($this->{ini}->{ShowCalcPlot}) { my $pCalEi = $this->{pCalEi}; my $pCalNE = $this->{pCalNE}; $GraphFrame0->AddGraphData($pCalEi, $pCalNE, 1, "black", "", 6, "black", 0, "black", "XAutoSkip", "Ei", "NE (cal)") if($pCalNE); } if($GraphFrame1) { $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); $GraphFrame1->SetXCaption("Ei / eV"); } if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 0, 0); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 1, 0); } } else { if($this->{LFDataFile} and $this->{ini}->{ShowSamplePlot}) { my $pX = $this->{LFDataFile}->GetData($LFXLabel) if($LFXLabel); my $pY1 = $this->{LFDataFile}->GetData($LFY1Label) if($LFY1Label); # my $nData = $this->{LFDataFile}->nData(); if($pX) { $GraphFrame0->AddGraphData($pX, $pY1, 0, "black", "circle", 3, "black", 0, "black", "XAutoSkip", "$LFXLabel", "$LFY1Label") if($pY1); } } if($this->{HFDataFile} and $this->{ini}->{ShowSamplePlot}) { my $pX = $this->{HFDataFile}->GetData($HFXLabel) if($HFXLabel); my $pY1 = $this->{HFDataFile}->GetData($HFY1Label) if($HFY1Label); # my $nData = $this->{HFDataFile}->nData(); if($pX) { $GraphFrame0->AddGraphData($pX, $pY1, 0, "black", "square", 3, "cyan", 0, "cyan", "XAutoSkip", "$HFXLabel", "$HFY1Label") if($pY1); } } $GraphFrame0->SetYCaption("Cg / F"); $GraphFrame1->SetYCaption("E / V"); if($this->{ini}->{ShowCalcPlot}) { my $pCalVg = $this->{pCalVg}; my $pCalVs = $this->{pCalVs}; my $pCalVox = $this->{pCalVox}; my $pCalE = $this->{pCalE}; my $pCalQs = $this->{pCalQs}; my $pCalLFCg = $this->{pCalLFCg}; my $pCalHFCg = $this->{pCalHFCg}; my $pCalLFCd = $this->{pCalLFCd}; my $pCalHFCd = $this->{pCalHFCd}; my $pCalECs = $this->{pCalECs}; my $pCalEVs = $this->{pCalEVs}; my $pCalEFs = $this->{pCalEFs}; my $pCalEis = $this->{pCalEis}; $GraphFrame0->AddGraphData($pCalVg, $pCalHFCg, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Cg(HF) (cal)") if($pCalHFCg); $GraphFrame0->AddGraphData($pCalVg, $pCalLFCg, 1, "red", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Cg(LF) (cal)") if($pCalLFCg); # $GraphFrame0->AddGraphData($pCalVg, $pCalLFCd, # 1, "cyan", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Cs(LF) (cal)") if($pCalLFCd); if($pCalVg and $Plot =~ /(E)/) { $GraphFrame1->AddGraphData($pCalVg, $pCalE, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "E (cal)") if($pCalE); $GraphFrame1->SetYCaption("E / V/m"); } elsif($pCalVg and $Plot =~ /(Q)/) { $GraphFrame1->AddGraphData($pCalVg, $pCalQs, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Qs (cal)") if($pCalQs); $GraphFrame1->SetYCaption("Qs / e"); } else { $GraphFrame1->AddGraphData($pCalVg, $pCalECs, 1, "cyan", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "EC (cal)") if($pCalECs); $GraphFrame1->AddGraphData($pCalVg, $pCalEVs, 1, "cyan", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "EV (cal)") if($pCalEVs); $GraphFrame1->AddGraphData($pCalVg, $pCalEFs, 1, "green", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "EF (cal)") if($pCalEFs); $GraphFrame1->AddGraphData($pCalVg, $pCalEis, 1, "gray", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Ei (cal)") if($pCalEis); $GraphFrame1->AddGraphData($pCalVg, $pCalVs, 1, "red", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Vs (cal)") if($pCalVs); $GraphFrame1->AddGraphData($pCalVg, $pCalVox, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "Vg", "Vox (cal)") if($pCalVox); } } if($GraphFrame1) { $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); $GraphFrame1->SetXCaption("V / V"); } if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 0, 0); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 1, 0); } } } 1;