SSブログ

光学薄膜設計ソフトの設計 その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として保持している。このうち
  1. 波長(lambda)
  2. スネル係数(入射角と同等、snellCoef)
  3. 偏光(polar)
は、OTFlayerを保持しているOTFLayerCompositionからもらうことで、どの層も同じOTFLayerCompositionに属する層はすべて同じ変数を参照することを保証する。

層独自の変数として

  1. 膜厚(thickness)
  2. 媒質の屈折率(reflIndex)
を持つ。これは層専用のものだけど、逆に外から与える(OTFLayerが生成しない)ことにする。なぜかというと例えば反射防止膜を設計することを考えたとき、波長ごとにOTFLayerオブジェクトを生成してマルチコアに対応させようとすると、OTFLayerはコアごとに別のオブジェクトでないといけない(計算する波長が違うので特性マトリクスの値が異なる)けど、同じ層を表すOTFLayerは最適化の間中同じ膜厚、同じ媒質でなければならない。

これを自動的に実現するために、違う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の実装はこれで全部。

ま、こんなもんだろ。


nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

献立02/10献立02/11 ブログトップ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。