光学薄膜設計ソフトの設計 その29 - 薄膜を表現するオブジェクト [考え中 - 光学薄膜設計]
ちょっと間が空いてしまった光学薄膜設計ソフト用の計算エンジンの実装の話。具体的な計算のためのオブジェクトの設計を進めよう。
層を表現するオブジェクト
ひとつの層を表すクラスをOTFLayerとする。これが計算の中心になる。これはOTFVariableと同じようにOTFMergableを継承する。
OTFLayerのinterface
Interfaceのはじめは
#import "OTFVariable.h" #import "OTFRefractiveIndex.h" #import "OTFSnellCoefficient.h" @class OTFLayerComposition; @interface OTFLayer : OTFMergable { OTFLayerComposition *lc; OTFVariable *lambda; OTFSnellCoefficient *snellCoef; OTFVariable *polar; OTFVariable *thickness; OTFRefractiveIndex *reflIndex; characteristicMatrix cmat; }と言う感じ。計算に必要な変数をOTFVariableとして保持している。このうち
- 波長(lambda)
- スネル係数(入射角と同等、snellCoef)
- 偏光(polar)
層独自の変数として
- 膜厚(thickness)
- 媒質の屈折率(reflIndex)
これを自動的に実現するために、違うOTFLayerオブジェクトでも同じ膜厚、同じ媒質オブジェクトを使うようにするためである。
ということでinit...メソッドは
- (id)initWihLayerComposition:(OTFLayerComposition *)lCompo andVariablesThickness:(OTFVariable *)thicknessVar reflactiveIndex:(OTFRefractiveIndex *)rIndex;という形だけにする。
このとき、媒質の屈折率オブジェクトであるrIndexは、同じ波長変数を参照している必要があるが、これを自動的にそうなるようにするかどうかは考えどころ。
OTFLayerの持つメソッドとしては
- (characteristicMatrix *)characteristicMatrix;があるだけ。もちろんプライベートなメソッドはいくつか実装しなければいけないけど、変数の値に従ってマトリクスを計算すると言うのが一番の仕事で、それ以外にはない。
OTFLayerのimplementation
まず、OTFMergableとして動作させるためのいくつかのメソッドが必要になる。これは他のOTFMergableを継承したクラスと全く同じ。
static NSMutableSet *allocatedObjects = nil; + (void)initialize { if (!allocatedObjects) allocatedObjects = [[NSMutableSet alloc] initWithCapacity:0]; } + (NSMutableSet *)allocatedObjects { return allocatedObjects; } - (BOOL)isMergableTo:(id)obj { return ((lc == [obj layerComposition]) && (reflIndex == [obj refractiveIndex]) && (thickness == [(OTFLayer *)obj thickness])); }isMergableTo:メソッドは同じOTFLayerCompositionに属して、同じ屈折率と同じ膜厚を参照していれば同じと見なす、ということになってOTFMergableのメカニズムによってisMergableTo:にYESを返すオブジェクトは破棄されて、先にあった方が使い回される。
init...とdeallocメソッドは
- (id)initWihLayerComposition:(OTFLayerComposition *)lCompo andVariablesThickness:(OTFVariable *)thicknessVar reflactiveIndex:(OTFRefractiveIndex *)rIndex { self = [super init]; lc = lCompo; lambda = [super setDependOn:[lCompo lambdaVariable]]; snellCoef = [super setDependOn:[lCompo snellCoefVariable]]; polar = [super setDependOn:[lCompo polarizationVariable]]; thickness = [super setDependOn:thicknessVar]; reflIndex = [super setDependOn:rIndex]; cmat = *(matrixInvalid()); return [self merge]; } - (void)dealloc { [super resetDependOn:lambda]; [super resetDependOn:snellCoef]; [super resetDependOn:polar]; [super resetDependOn:thickness]; [super resetDependOn:reflIndex]; [super dealloc]; }で、依存関係を設定して、結果のマトリクスを無効なマトリクスに設定している。これは単なるデバグのため。最後の行で同じものがあればマージされる。
deallocは依存を解くだけ。
値の要求に受けるメソッドは
- (characteristicMatrix *)characteristicMatrix { if ([super isRevised]) { [self updateValue]; [super resetRevised]; } return &cmat; }で、OTFSuccessorのメカニズムで依存している変数に変更があった場合、isRevisedにYESが返るのでそのときには値を更新する。これもOTFDependedVariableと全く同じコード。
計算の実体はupdatevalueメソッドの中に書く。
ちょっと面倒だけど、昔まとめた数学に従って書き下ろすだけ。
- (void)updateValue { double lam = [lambda realValue]; double pol = [polar realValue]; double thick = [thickness realValue]; double complex ind = [reflIndex complexValue]; double complex cost = [snellCoef cosValueForReflactiveIndex:ind]; double complex cosd, sind; double complex eta = isSenkrecht(pol) ? ind * cost : ind / cost; if (isPureReal(ind)) { double rind = creal(ind); double costr = creal(cost); double deltar = 2.0 * pi * rind * thick * costr / lam; cosd = cos(deltar); sind = I * sin(deltar); } else { double complex deltar = 2.0 * pi * thick * ind * cost / lam; cosd = ccos(deltar); sind = csin(deltar) * I; } cmat.e00 = cosd; cmat.e11 = cosd; cmat.e01 = sind / eta; cmat.e10 = sind * eta; }とする。媒質の屈折率が実数の場合と複素数の場合に分けているのは、実数の方が計算はずっと簡単で速いから。屈折率の虚数部はその層での吸収に対応するので、あまり出現率は多くないはず。
OTFLayerの実装はこれで全部。
ま、こんなもんだろ。
2009-02-10 23:08
nice!(0)
コメント(0)
トラックバック(0)
コメント 0