package DiodeRsRshJpv; use Exporter; @ISA = qw(Exporter); #公開したいサブルーチン @EXPORT = qw(); use strict; use File::Basename; use Utils; use Sci qw($pi $kB $R $NA $c $e $e0 $u0 $me $mp $mn $h $hbar $torad $todeg); use Sci::Optimize; #============================================================ # 変数等取得、再定義関数 #============================================================ sub SetTemperature { my ($this, $T) = @_; $this->{T} = $T; $this->{ekT} = $e / ($kB * $T); } #============================================================ # コンストラクタ、デストラクタ #============================================================ sub new { my ($module) = @_; my $this = {}; bless $this; $this->SetTemperature(300.0); return $this; } sub DESTROY { my $this = shift; } #============================================================ # 一般関数 #============================================================ sub CalSCFTotalIV { my ($this, $Vtarget, $J0, $n, $Rs, $Rsh, $Jpv, $LSQMethod, $EPS, $nMaxIter, $iPrintLevel) = @_; $LSQMethod = "ModifiedNewton" if(!defined $LSQMethod); $EPS = 1.0e-4 if(!defined $EPS); $nMaxIter = 100 if(!defined $nMaxIter); $iPrintLevel = 0 if(!defined $iPrintLevel); if($Rs == 0.0) { my ($Vtotal, $Jtotal) = &CalDiodeIV($Vtarget, $J0, $n, $Rs); return ($Vtotal, $Jtotal); } my $Opt = new Optimize; my @Guess = ($Vtarget); my @OptId = ( 1); my @Scale = ( 0.1); my ($OptVars, $MinVal) = $Opt->Optimize($LSQMethod, \@Guess, \@OptId, \@Scale, $EPS, $nMaxIter, $iPrintLevel, sub { $this->MinimizationFuncIVDiode($Vtarget, $J0, $n, $Rs, $Rsh, $Jpv, @_); }, sub { }, sub { Optimize::BuildDifferentialMatrixes(@_); }, ); my ($Vdiode) = @$OptVars; if($MinVal > $EPS) { print "Error i Cal: Could not get convergence for V=$Vtarget (MinVal=$MinVal)\n"; # exit; } my ($Vtotal, $Jtotal) = $this->CalDiodeIV($Vdiode, $J0, $n, $Rs, $Rsh, $Jpv); return ($Vdiode, $Jtotal); } sub CalDiodeIV { my ($this, $Vdiode, $J0, $n, $Rs, $Rsh, $Jpv) = @_; my $Jdiode = $J0 * (exp($this->{ekT} * $Vdiode / $n) - 1.0) - $Jpv; my $Jtotal = $Jdiode + $Vdiode / $Rsh; # my $Jtotal = ($Rsh == 0.0)? $Jdiode : $Jdiode + $Vdiode / $Rsh; my $Vtotal = $Vdiode + $Rs * $Jtotal; return ($Vtotal, $Jtotal); } sub MinimizationFuncIVDiode { my ($this, $Vtarget, $J0, $n, $Rs, $Rsh, $Jpv, $pVars, $iPrintLevel) = @_; my $S = 0.0; my ($Vdiode) = @$pVars; my ($Vtotal, $Jtotal) = $this->CalDiodeIV($Vdiode, $J0, $n, $Rs, $Rsh, $Jpv); return ($Vtotal - $Vtarget)**2; } 1;