Exemplo n.º 1
0
        /// <summary>
        /// ロッドを追加する
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <returns></returns>
        public static uint AddRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv)
        {
            List <CVector2D> pts = new List <CVector2D>();

            {
                // メッシュ形状を整えるためにロッドの中心に頂点を追加
                uint id_v_center = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x0, y0)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_center != 0);
            }
            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 0; itheta < rodCircleDiv; itheta++)
                {
                    double theta    = itheta * 2.0 * pi / rodCircleDiv;
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッド
            for (int itheta = 0; itheta < rodCircleDiv; itheta++)
            {
                double theta = itheta * 2.0 * pi / rodCircleDiv;
                double x     = x0 + rodRadius * Math.Cos(theta);
                double y     = y0 + rodRadius * Math.Sin(theta);
                pts.Add(new CVector2D(x, y));
            }
            uint lId = cad2d.AddPolygon(pts, baseLoopId).id_l_add;

            System.Diagnostics.Debug.Assert(lId != 0);
            return(lId);
        }
Exemplo n.º 2
0
        ////////////////////////////////////////////////////////////////////////
        // 型
        ////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// 境界を分割する
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="id_e"></param>
        /// <param name="ndiv"></param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        public static void DivideBoundary(CCadObj2D cad2d, uint id_e, int ndiv, double x1, double y1, double x2, double y2)
        {
            double signedWidthX = x2 - x1;
            double signedWidthY = y2 - y1;

            for (int i = ndiv - 1; i >= 1; i--)
            {
                double x = x1 + i * signedWidthX / ndiv;
                double y = y1 + i * signedWidthY / ndiv;
                CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x, y));
                uint id_v_add = resAddVertex.id_v_add;
                uint id_e_add = resAddVertex.id_e_add;
                System.Diagnostics.Debug.Assert(id_v_add != 0);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// PC導波路 60°三角形格子 ダブルベンド
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            int propModeCntToSolve = 3;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            // 高次モード入射
            //int incidentModeIndex = 1;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0.0;
            // 最大屈折率
            double maxEffN = 0.0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0;
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a air hole
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5;
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a air hole

            // 入出力導波路が同じ?
            //IsInoutWgSame = true; // 同じ
            //IsInoutWgSame = false; // 同じでない
            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false;
            //bool isShift180 = true;
            // Y方向周期をずらす
            bool isShiftY = false; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            //bool isShiftY = true; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_Bend == 1
            //bool isShiftY = true; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            // ロッドの数(半分)
            //const int rodCntHalf = 5; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 3;
            System.Diagnostics.Debug.Assert(rodCntHalf % 2 == 1); // 奇数を指定(図面の都合上)
            // 欠陥ロッド数
            // for latticeTheta = 60 r = 0.30a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            double latticeTheta = 60.0;
            // ロッドの半径
            //double rodRadiusRatio = 0.35; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_Bend == 1
            //double rodRadiusRatio = 0.28; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            double rodRadiusRatio = 0.344; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            // ロッドの比誘電率
            //double rodEps = 2.80 * 2.80; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_Bend == 1
            //double rodEps = 2.80 * 2.80; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            double rodEps = 2.95 * 2.95; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.35a air hole
            //const int ndivForOneLattice = 8; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            const int ndivForOneLattice = 8;// 8;// 9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 0; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            //const int rodCntDiscon = 1; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            const int rodCntDiscon = 1;
            // ベンド部のロッド数(半分)
            const int rodCntHalf_Bend = 5;
            // ベンド部の欠陥ロッド数
            //const int defectRodCnt_Bend = 1; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_Bend == 1
            //const int defectRodCnt_Bend = 3; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            const int defectRodCnt_Bend = 5; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            // ベンド部の長さ
            //const int rodCntY_Bend = 9; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_Bend == 1
            //const int rodCntY_Bend = 11;//19; // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            //const int rodCntY_Bend = 7; // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            const int rodCntY_Bend = 7;

            // 格子の数
            const int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // 入出力導波路の不連続部の長さ
            double disconLength = rodCntDiscon * rodDistanceX;
            // ベンド部のX方向長さ
            double bendLengthX = (rodCntHalf_Bend * 2 + defectRodCnt_Bend) * (rodDistanceX * 0.5);
            // ベンド部のY方向長さ
            double bendLengthY = (rodCntY_Bend + rodCntHalf * 2 + defectRodCnt * 2) * rodDistanceY;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            // for latticeTheta = 60 r = 0.35a air hole
            //NormalizedFreq1 = 0.294;//0.295;// 0.280;
            //NormalizedFreq2 = 0.315;//0.320;// 0.3301;
            //FreqDelta = 0.001;
            //GraphFreqInterval = 0.002;// 0.010;
            // for latticeTheta = 60 r = 0.28a air hole defectRodCnt_Bend == 3
            //NormalizedFreq1 = 0.260;
            //NormalizedFreq2 = 0.2901;
            //FreqDelta = 0.0005;
            //GraphFreqInterval = 0.005;
            // for latticeTheta = 60 r = 0.344a air hole defectRodCnt_Bend == 5
            NormalizedFreq1 = 0.265;
            NormalizedFreq2 = 0.3201;
            FreqDelta = 0.0005;
            GraphFreqInterval = 0.005;

            //minEffN = 0.0;
            //maxEffN = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN_port2 = minWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            //maxEffN_port2 = maxWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;// 1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
                //isMagneticWall = true;
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
                incidentModeIndex = 0;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            const uint portCnt = 2;

            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            int ndivPlus_port1 = 0;
            int ndivPlus_port2 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            IList<uint> id_e_F1_Bend = new List<uint>();
            IList<uint> id_e_F2_Bend = new List<uint>();

            if (!isShiftY)
            {
                System.Diagnostics.Debug.Assert(rodCntDiscon > 0);
            }
            // ベンド下側角
            double bendX1 = inputWgLength + disconLength + (rodDistanceX * 0.5) + bendLengthX;
            if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
            {
                bendX1 += rodDistanceX * 0.5;
            }
            double bendY1 = 0.0;
            // 出力部境界
            double port2_X = bendX1 + disconLength + inputWgLength;
            if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
            {
                port2_X += rodDistanceX * 0.5;
            }
            double port2_Y = bendY1 + bendLengthY;
            // ベンド部上側角
            double bendX2 = inputWgLength + disconLength;
            if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
            {
                bendX2 += rodDistanceX * 0.5;
            }

            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(bendX1, bendY1)); // 頂点4
                    pts.Add(new CVector2D(bendX1, port2_Y - WaveguideWidth)); // 頂点5
                    pts.Add(new CVector2D(port2_X - inputWgLength, port2_Y - WaveguideWidth)); // 頂点6
                    pts.Add(new CVector2D(port2_X, port2_Y - WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(port2_X, port2_Y)); // 頂点8
                    pts.Add(new CVector2D(port2_X - inputWgLength, port2_Y)); // 頂点9
                    pts.Add(new CVector2D(bendX2, port2_Y)); // 頂点10
                    pts.Add(new CVector2D(bendX2, WaveguideWidth)); // 頂点11
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点12
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 12).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(6, 9).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys_port1 = new List<double>();
                IList<double> ys_rod_port1 = new List<double>();
                IList<double> ys_port2 = new List<double>();
                IList<double> ys_rod_port2 = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    int cur_rodCntHalf = 0;
                    int cur_defectRodCnt = 0;
                    int cur_ndivForOneLattice = 0;
                    double cur_WaveguideWidth = 0.0;
                    double cur_rodDistanceY = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;
                    if (portIndex == 0)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port1;
                        ys_rod = ys_rod_port1;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 1)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port2;
                        ys_rod = ys_rod_port2;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }

                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    double radiusMargin = cur_rodDistanceY * 0.01;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }

                    // 境界上にロッドのない格子
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == 0 && k == 0) continue;
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == (cur_rodCntHalf - 1) && k == cur_ndivForOneLattice) continue;
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    // 欠陥部
                    for (int i = 0; i <= (cur_defectRodCnt * cur_ndivForOneLattice); i++)
                    {
                        if (!isShift180 && (i == 0 || i == (cur_defectRodCnt * cur_ndivForOneLattice))) continue;
                        double y_divpt = cur_rodDistanceY * (cur_rodCntHalf + cur_defectRodCnt) - i * (cur_rodDistanceY / cur_ndivForOneLattice);
                        ys.Add(y_divpt);
                    }

                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (portIndex == 0)
                    {
                        ndivPlus_port1 = cur_ndivPlus;
                    }
                    else if (portIndex == 1)
                    {
                        ndivPlus_port2 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    // 入力導波路 外側境界
                    // 入力導波路 内部側境界
                    // 出力導波路 外側境界
                    // 出力導波路 内部側境界
                    for (int boundaryIndex = 0; boundaryIndex < 2;  boundaryIndex++)
                    {
                        bool isInRod = false;
                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            double x_pt = 0.0;
                            double y_pt = 0.0;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (portIndex == 0 && boundaryIndex == 0)
                            {
                                // 入力導波路 外側境界
                                id_e = 1;
                                x_pt = 0.0;
                                y_pt = yAry[i];
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B1;
                                work_id_v_list_rod_B = id_v_list_rod_B1;
                            }
                            else if (portIndex == 0 && boundaryIndex == 1)
                            {
                                // 入力導波路 内側境界
                                id_e = 13;
                                x_pt = inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B2;
                                work_id_v_list_rod_B = id_v_list_rod_B2;
                            }
                            else if (portIndex == 1 && boundaryIndex == 0)
                            {
                                // 出力導波路 外側境界
                                id_e = 7;
                                x_pt = port2_X - inputWgLength;
                                y_pt = port2_Y - WaveguideWidth + yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (portIndex == 1 && boundaryIndex == 1)
                            {
                                // 出力導波路 内側境界
                                id_e = 14;
                                x_pt = port2_X;
                                y_pt = port2_Y - WaveguideWidth + yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y_pt));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                    }
                }
                int bRodCntHalf_port1 = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));

                int rodCntHalf_port2 = rodCntHalf;
                int bRodCntHalf_port2 = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1));

                // ロッドを追加
                /////////////////////////////////////////////////////////////
                // 入力導波路側ロッド
                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }
                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央のロッド (入力導波路)
                int periodCntInputWg1 = 1;
                int periodCntX_port1 = periodCntInputWg1 + rodCntDiscon;
                for (int col = 1; col <= (periodCntX_port1 * 2 + 1); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                    }
                    else
                    {
                        if (col > (periodCntX_port1 * 2)) continue;
                    }
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    // 中央のロッド
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                    // 中央のロッド
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = rodCntHalf * rodDistanceY - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                // ベンド部
                int periodCntX_Bend = (rodCntHalf_Bend * 2 + defectRodCnt_Bend) / 2;
                int rodCntY_All_Bend = rodCntHalf * 2 + defectRodCnt * 2 + rodCntY_Bend;
                for (int col = (periodCntX_port1 * 2 + 1); col <= (periodCntX_port1 * 2 + periodCntX_Bend * 2 + 2); col++)
                {
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                        if (col < (periodCntX_port1 * 2 + 2)) continue;
                    }
                    else
                    {
                        if (col > (periodCntX_port1 * 2 + periodCntX_Bend * 2 + 1)) continue;
                    }

                    uint baseLoopId = 2;

                    // 中央のロッド
                    for (int i = 0; i < rodCntY_All_Bend; i++)
                    {
                        // ロッドの半径
                        double rr = rodRadius;
                        // ロッドの半径方向分割数
                        const int nr_nearWg = 3;// rodRadiusDiv;
                        const int nr_farFromWg = 2;
                        // ロッドの半径方向分割数
                        int nr = nr_farFromWg;
                        // ロッドの周方向分割数
                        int nc = rodCircleDiv;
                        // ずらす距離
                        double ofs_x_rod = 0.0;
                        double ofs_y_rod = 0.0;

                        int work_col = col;
                        if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                        {
                            work_col -= 1;
                        }
                        // 出力導波路
                        if ((work_col >= (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1))
                            && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                        {
                            if (defectRodCnt_Bend == 1)
                            {
                                if (isShiftY
                                    && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1))
                                {
                                    // 結合部
                                    rr = 0.16 * latticeA;
                                    nr = nr_nearWg;
                                }
                                else if (!isShiftY
                                    && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 2))
                                {
                                    // ベンド部共振器
                                    nr = nr_nearWg;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else if (defectRodCnt_Bend == 3)
                            {
                                continue;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        // 入力導波路
                        if ((work_col <= (periodCntX_port1 * 2 + rodCntHalf_Bend))
                            && (i >= (rodCntY_All_Bend - rodCntHalf - defectRodCnt) && i <= (rodCntY_All_Bend - rodCntHalf - 1)))
                        {
                            if (defectRodCnt_Bend == 1)
                            {
                                if (isShiftY
                                    && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend))
                                {
                                    // 結合部
                                    rr = 0.16 * latticeA;
                                    nr = nr_nearWg;
                                }
                                else if (!isShiftY
                                    && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend - 1))
                                {
                                    // ベンド部共振器
                                    nr = nr_nearWg;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            else if (defectRodCnt_Bend == 3)
                            {
                                continue;
                            }
                            else
                            {
                                continue;
                            }
                        }

                        // 中央導波路
                        if ((work_col >= (periodCntX_port1 * 2 + rodCntHalf_Bend + 1) && work_col <= (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend))
                            && (i >= (rodCntHalf) && i <= (rodCntY_All_Bend - rodCntHalf - 1)))
                        {
                            continue;
                        }

                        if (defectRodCnt_Bend == 5 && !isShiftY)
                        {
                            // 広帯域構造 ベンド部に円弧エアホールと重なるロッドを除去
                            // 出力部
                            if (i == (rodCntHalf - 1)
                                && (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend - 3)
                                    || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend - 1)
                                    /*|| work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1)*/)
                                )
                            {
                                continue;
                            }
                            // 入力部
                            if (i == (rodCntY_All_Bend - rodCntHalf)
                                && (/*work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend)
                                    ||*/ work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + 2)
                                    || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + 4))
                                )
                            {
                                continue;
                            }
                            // 右
                            if (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1)
                                && (i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 1)
                                    || i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 3))
                                )
                            {
                                continue;
                            }
                            if (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 2)
                                && i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 2))
                            {
                                continue;
                            }
                            // 左
                            if (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend)
                                && (i == (rodCntHalf + defectRodCnt)
                                    || i == (rodCntHalf + defectRodCnt + 2))
                                )
                            {
                                continue;
                            }
                            if (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend - 1)
                                && i == (rodCntHalf + defectRodCnt + 1))
                            {
                                continue;
                            }
                        }

                        // 導波路上下のロッドだけ半径方向分割数を指定する
                        //  出力導波路上下
                        if (work_col >= (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1)
                            && (i == (rodCntHalf - 1) || i == (rodCntHalf + defectRodCnt)))
                        {
                            nr = nr_nearWg;
                        }
                        //  入力導波路上下
                        if ((work_col <= (periodCntX_port1 * 2 + rodCntHalf_Bend))
                            && (i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 1) || i == (rodCntY_All_Bend - rodCntHalf)))
                        {
                            nr = nr_nearWg;
                        }
                        //  中央導波路上下
                        if ((work_col >= (periodCntX_port1 * 2 + rodCntHalf_Bend) && work_col <= (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1))
                            && (i == (rodCntHalf + defectRodCnt - 2) || i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt+ 1)))
                        {
                            nr = nr_nearWg;
                        }
                        //  中央導波路左右
                        if ((work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend)
                                || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend - 1)
                                || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1)
                                || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 2)
                                )
                            && (i >= rodCntHalf && i <= (rodCntY_All_Bend - rodCntHalf - defectRodCnt)))
                        {
                            if (defectRodCnt_Bend == 3 && isShiftY)
                            {
                                nr = nr_nearWg;

                                /*
                                //double work_r1 = 0.12 * latticeA; // r1 = 52 nm (a : 430 nm)
                                double work_r1 = 0.116 * latticeA; // r1 = 50 nm (a : 430 nm)
                                int work_nr1 = 1;
                                //double work_r2 = 0.28 * latticeA;  // r2 : 120 nm (a : 430 nm)
                                //double work_r2 = 0.30 * latticeA;  // r2 : 130 nm (a : 430 nm)
                                //double work_r2 = 0.35 * latticeA;  // r2 : 150 nm (a : 430 nm)
                                //double work_r2 = 0.40 * latticeA;  // r2 : 170 nm (a : 430 nm)
                                //double work_r2 = 0.44 * latticeA;  // r2 : 190 nm (a : 430 nm)
                                double work_r2 = 0.44 * latticeA;
                                int work_nr2 = 4;
                                // 中央導波路の広帯域化
                                if (i == (rodCntHalf + defectRodCnt) && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 2))
                                {
                                    rr = work_r1;
                                    nr = work_nr1;
                                }
                                else if (i == (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 1) && work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend - 1))
                                {
                                    rr = work_r1;
                                    nr = work_nr1;
                                }
                                else if (i >= (rodCntHalf + defectRodCnt + 1) && i <= (rodCntY_All_Bend - rodCntHalf - defectRodCnt - 2))
                                {
                                    if (work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend)
                                        || work_col == (periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend + 1))
                                    {
                                        rr = work_r1;
                                        nr = work_nr1;
                                    }
                                    else
                                    {
                                        rr = work_r2;
                                        nr = work_nr2;
                                    }
                                }
                                 */
                            }
                            else
                            {
                                nr = nr_nearWg;
                            }
                        }

                        if ((col % 2 == 1 && ((rodCntY_All_Bend - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntY_All_Bend - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = port2_Y - i * rodDistanceY - rodDistanceY * 0.5;
                            //uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            x0 += ofs_x_rod;
                            y0 += ofs_y_rod;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, nc, nr);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                /////////////////////////////////////////////////////////////
                // 出力導波路側ロッド
                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 外側
                        x_B = port2_X;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else if (colIndex == 1)
                    {
                        // 出力境界内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port2 - 1 - (int)((rodCntHalf_port2 - 1 - i) / 2);
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = port2_Y - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = port2_Y - WaveguideWidth + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port2 - 1 - (int)((rodCntHalf_port2 - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = port2_Y - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = port2_Y - WaveguideWidth + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド (出力導波路)
                int periodCntInputWg2 = 1;
                int periodCntX_port2 = periodCntInputWg2 + rodCntDiscon;

                // 中央のロッド(出力導波路)(左右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();

                // 中央のロッド (出力導波路)
                for (int col = 1; col <= (periodCntX_port2 * 2 + 1); col++)
                {
                    if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                    }
                    else
                    {
                        if (col > (periodCntX_port2 * 2)) continue;
                    }

                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg2 * 2))
                    {
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }

                    // 中央のロッド(出力導波路)
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((col % 2 == 1 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = port2_X - rodDistanceX * 0.5 * col;
                            double y0 = port2_Y - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((col % 2 == 1 && (i % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = port2_X - rodDistanceX * 0.5 * col;
                            double y0 = port2_Y - WaveguideWidth + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(ベンド部分)(左の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_Bend = new List<uint>();
                int rodCntY_F1_Bend = rodCntY_All_Bend - (rodCntHalf * 2 + defectRodCnt);
                for (int i = (rodCntY_F1_Bend - 1); i >= 0; i--)
                {
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                        isRodLattice = (i % 2 == 0);
                    }
                    else
                    {
                        isRodLattice = (i % 2 == 1);
                    }
                    if (isRodLattice)
                    {
                        uint id_e = 10;
                        double x0 = bendX2;
                        double y0 = port2_Y - rodDistanceY * i - rodDistanceY * 0.5;
                        double x_cross = bendX2;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_Bend.Add(id_v_add);
                            id_e_F1_Bend.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、左境界と接する半円)
                for (int i = 0; i < rodCntY_F1_Bend; i++)
                {
                    // 不連続領域
                    uint baseLoopId = 2;
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                        isRodLattice = (i % 2 == 0);
                    }
                    else
                    {
                        isRodLattice = (i % 2 == 1);
                    }
                    if (isRodLattice)
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(右半分)を追加
                            double x0 = bendX2;
                            double y0 = port2_Y - rodDistanceY * i - rodDistanceY * 0.5;
                            int row2 = (rodCntY_F1_Bend - 1 - i) / 2;
                            System.Diagnostics.Debug.Assert(row2 >= 0);
                            uint id_v0 = id_v_list_F1_Bend[row2 * 3 + 0];
                            uint id_v1 = id_v_list_F1_Bend[row2 * 3 + 1];
                            uint id_v2 = id_v_list_F1_Bend[row2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                90.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(ベンド部分)(右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F2_Bend = new List<uint>();
                int rodCntY_F2_Bend = rodCntY_All_Bend - (rodCntHalf * 2 + defectRodCnt);
                for (int i = 0; i < rodCntY_F2_Bend; i++)
                {
                    bool isRodLattice = false;
                    // 右の強制境界と交差するロッド
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                        isRodLattice = ((rodCntY_F2_Bend - 1 - i) % 2 == 0);
                    }
                    else
                    {
                        isRodLattice = ((rodCntY_F2_Bend - 1 - i) % 2 == 1);
                    }
                    if (isRodLattice)
                    {
                        uint id_e = 4;
                        double x0 = bendX1;
                        double y0 = port2_Y - WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                        double x_cross = bendX1;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_Bend.Add(id_v_add);
                            id_e_F2_Bend.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、右境界と接する半円)
                for (int i = 0; i < rodCntY_F2_Bend; i++)
                {
                    // 不連続領域
                    uint baseLoopId = 2;
                    // 右の強制境界と交差するロッド
                    bool isRodLattice = false;
                    if (/*defectRodCnt_Bend == 1 &&*/ isShiftY)
                    {
                        isRodLattice = ((rodCntY_F2_Bend - 1 - i) % 2 == 0);
                    }
                    else
                    {
                        isRodLattice = ((rodCntY_F2_Bend - 1 - i) % 2 == 1);
                    }
                    if (isRodLattice)
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(左半分)を追加
                            double x0 = bendX1;
                            double y0 = port2_Y - WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                            int row2 = i / 2;
                            System.Diagnostics.Debug.Assert(row2 >= 0);
                            uint id_v0 = id_v_list_F2_Bend[row2 * 3 + 0];
                            uint id_v1 = id_v_list_F2_Bend[row2 * 3 + 1];
                            uint id_v2 = id_v_list_F2_Bend[row2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                270.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }
                if (defectRodCnt_Bend == 5)
                {
                    // 広帯域化: 円弧形状エアホールを追加
                    double arcWidth = 0.6 * latticeA;
                    double arc_r1 = (defectRodCnt_Bend + 1) * rodDistanceX * 0.5 - rodDistanceX * 0.25 + arcWidth * 0.5;
                    double arc_r2 = arc_r1 - arcWidth;
                    // 上部ベンドの1/4リング
                    {
                        uint baseLoopId = 2;
                        int col = periodCntX_port1 * 2 + rodCntHalf_Bend + defectRodCnt_Bend;
                        double x0 = rodDistanceX * 0.5 * col + rodDistanceX * 0.25;
                        double y0 = port2_Y - (rodCntHalf - 1) * rodDistanceY - 0.5 * rodDistanceY + arcWidth * 0.5 - arc_r1 ;
                        //double endAngle = 180.0 - 8.0; // 左2列目ロッドに接する構造
                        //double endAngle = 180.0 + 7.0; // 左1列目ロッドに接する構造
                        double endAngle = 180.0 + 30.0; // トポロジー最適化構造に近い?構造
                        double startAngle = 90 + 3.0;
                        uint lId = addArcRod(cad2d, baseLoopId, x0, y0, arc_r1, arc_r2, startAngle, endAngle, false);
                        rodLoopIds.Add(lId);
                    }
                    // 下部ベンドの1/4リング
                    {
                        uint baseLoopId = 2;
                        int col = periodCntX_port1 * 2 + rodCntHalf_Bend + 1;
                        double x0 = rodDistanceX * 0.5 * col - rodDistanceX * 0.25;
                        double y0 = (rodCntHalf - 1) * rodDistanceY + rodDistanceY * 0.5 - arcWidth * 0.5 + arc_r1;
                        //double endAngle = 360.0 -8.0; // 右2列目ロッドに接する構造
                        //double endAngle = 360.0 + 7.0; // 右1列目ロッドに接する構造
                        double endAngle = 360.0 + 30.0; // トポロジー最適化構造に近い?構造
                        double startAngle = 270 + 3.0;
                        uint lId = addArcRod(cad2d, baseLoopId, x0, y0, arc_r1, arc_r2, startAngle, endAngle, false);
                        rodLoopIds.Add(lId);
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    //check
                    //for (int i = 0; i < ((ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2); i++)
                    //{
                    //    uint eId = (uint)(14 + i + 1);
                    //    cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 1.0 });
                    //}
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[3 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 3] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[3 + rodLoopIds.Count];
                for (int i = 0; i < 3; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 3] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 2ポート情報リスト作成
            //const uint portCnt = 2;
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[10 + id_e_F1.Count + id_e_F2.Count + id_e_F1_Bend.Count + id_e_F2_Bend.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 5;
                eId_cad_list[4] = 6;
                eId_cad_list[5] = 8;
                eId_cad_list[6] = 9;
                eId_cad_list[7] = 10;
                eId_cad_list[8] = 11;
                eId_cad_list[9] = 12;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[10 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[10 + id_e_F1.Count + i] = id_e_F2[i];
                }
                for (int i = 0; i < id_e_F1_Bend.Count; i++)
                {
                    eId_cad_list[10 + id_e_F1.Count + id_e_F2.Count + i] = id_e_F1_Bend[i];
                }
                for (int i = 0; i < id_e_F2_Bend.Count; i++)
                {
                    eId_cad_list[10 + id_e_F1.Count + id_e_F2.Count + id_e_F1_Bend.Count + i] = id_e_F2_Bend[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 7;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(14 + (ndivPlus_port1 - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(14 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 13;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 14;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(14 + (ndivPlus_port1 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(14 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                if (portIndex == 0 || portIndex == 1)
                {
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf))
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - (0.5 * rodDistanceY - rodRadius)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + (0.5 * rodDistanceY - rodRadius))) // dielectric rod
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        if ((portIndex == 0 &&
                                (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            || (portIndex == 1 &&
                                (coord[1] >= (port2_Y - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (port2_Y - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            )
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 4
0
 /// <summary>
 /// ロッドを追加する
 /// </summary>
 /// <param name="cad2d"></param>
 /// <param name="baseLoopId"></param>
 /// <param name="x0"></param>
 /// <param name="y0"></param>
 /// <param name="rodRadius"></param>
 /// <param name="rodCircleDiv"></param>
 /// <param name="rodRadiusDiv"></param>
 /// <returns></returns>
 public static uint AddRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv)
 {
     List<CVector2D> pts = new List<CVector2D>();
     {
         // メッシュ形状を整えるためにロッドの中心に頂点を追加
         uint id_v_center = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x0, y0)).id_v_add;
         System.Diagnostics.Debug.Assert(id_v_center != 0);
     }
     // ロッドの分割数調整
     for (int k = 1; k < rodRadiusDiv; k++)
     {
         for (int itheta = 0; itheta < rodCircleDiv; itheta++)
         {
             double theta = itheta * 2.0 * pi / rodCircleDiv;
             double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
             double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
             uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
             System.Diagnostics.Debug.Assert(id_v_add != 0);
         }
     }
     // ロッド
     for (int itheta = 0; itheta < rodCircleDiv; itheta++)
     {
         double theta = itheta * 2.0 * pi / rodCircleDiv;
         double x = x0 + rodRadius * Math.Cos(theta);
         double y = y0 + rodRadius * Math.Sin(theta);
         pts.Add(new CVector2D(x, y));
     }
     uint lId = cad2d.AddPolygon(pts, baseLoopId).id_l_add;
     System.Diagnostics.Debug.Assert(lId != 0);
     return lId;
 }
Exemplo n.º 5
0
        /// <summary>
        /// 誘電体のボックス装荷導波管
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="timeLoopCnt"></param>
        /// <param name="timeDelta"></param>
        /// <param name="gaussianT0"></param>
        /// <param name="gaussianTp"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcIdList"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            ref double WaveguideWidth,
            ref int timeLoopCnt,
            ref double timeDelta,
            ref double gaussianT0,
            ref double gaussianTp,
            ref double NormalizedFreqSrc,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double GraphFreqInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPortBcIdList,
            ref IList<uint> VIdRefList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            WaveguideWidth = 3.0e-3 * 20 * 4;

            // 誘電体のボックス装荷導波管
            // メッシュの分割長さ
            //double meshL = WaveguideWidth * 0.05;
            //double meshL = WaveguideWidth * 0.10;
            double meshL = WaveguideWidth * 0.09;

            // 導波管不連続領域の長さ
            double inputWgLength = 1.0 * WaveguideWidth;
            double disconWgWidth = (10.0 / 20.0) * WaveguideWidth;
            double dielectricBoxWidth = (7.0 / 20.0) * WaveguideWidth;
            double dielectricBoxHeight = (6.0 / 20.0) * WaveguideWidth;
            double disconLength = (19.0 / 20.0) * WaveguideWidth;
            // 形状設定で使用する単位長さ
            double unitLen = WaveguideWidth / 20.0;
            // 励振位置
            double srcPosX = 5 * unitLen;
            // 観測点
            int port1OfsX = 5;
            int port2OfsX = 5;
            double port1PosX = srcPosX + port1OfsX * unitLen;
            double port1PosY = WaveguideWidth * 0.5;
            double port2PosX = inputWgLength * 2 + disconLength - port2OfsX * unitLen;
            double port2PosY = WaveguideWidth * 0.5;

            // 時間領域
            //double courantNumber = 0.5;
            double courantNumber = 0.5;
            //timeLoopCnt = 3000;
            timeLoopCnt = 3000;
            // 時刻刻み
            timeDelta = courantNumber * meshL / (c0 * Math.Sqrt(2.0));

            // モード計算規格化周波数(搬送波規格化周波数)
            //NormalizedFreqSrc = 2.0;
            //NormalizedFreqSrc = 1.5;
            NormalizedFreqSrc = 2.0; // 正弦波変調ガウシアンパルス

            /*
            // ガウシアンパルス
            //gaussianT0 = 30 * timeDelta;
            //gaussianT0 = 40 * timeDelta;
            gaussianT0 = 20 * timeDelta;
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0) * 4.0);
             */

            // 正弦波変調ガウシアンパルス
            // 波数
            double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
            // 波長
            double waveLengthSrc = 2.0 * pi / k0Src;
            // 周波数
            double freqSrc = c0 / waveLengthSrc;
            // 角周波数
            double omegaSrc = 2.0 * pi * freqSrc;
            // 搬送波の振動回数
            int nCycle = 5;
            //gaussianT0 = (1.0 / freqSrc) * nCycle / 2;
            //gaussianT0 = 0.5 * (1.0 / freqSrc) * nCycle / 2;
            gaussianT0 = 0.67 * (1.0 / freqSrc) * nCycle / 2;
            gaussianTp = gaussianT0 / (2.0 * Math.Sqrt(2.0 * Math.Log(2.0)));

            // 周波数領域
            NormalizedFreq1 = 1.0;
            //NormalizedFreq2 = 2.0;
            NormalizedFreq2 = 3.0;
            GraphFreqInterval = 0.2;

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            MediaInfo mediaVacumn = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 1.0, 0.0, 0.0 },
                   { 0.0, 1.0, 0.0 },
                   { 0.0, 0.0, 1.0 }
                }
            );
            MediaInfo mediaDielectricBox = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 2.62,  0.0,  0.0 },
                   {  0.0, 2.62,  0.0 },
                   {  0.0,  0.0, 2.62 }
                }
            );
            Medias.Add(mediaVacumn);
            Medias.Add(mediaDielectricBox);

            // 図面作成、メッシュ生成
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                double yOfs_cutoffWg = (WaveguideWidth - disconWgWidth) * 0.5;
                {
                    // ループ1
                    IList<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(srcPosX, 0.0)); // 頂点3
                    pts.Add(new CVector2D(inputWgLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(inputWgLength, yOfs_cutoffWg)); // 頂点5
                    pts.Add(new CVector2D(inputWgLength + disconLength, yOfs_cutoffWg)); // 頂点6
                    pts.Add(new CVector2D(inputWgLength + disconLength, 0.0)); // 頂点7
                    pts.Add(new CVector2D(inputWgLength * 2 + disconLength, 0.0)); // 頂点8
                    pts.Add(new CVector2D(inputWgLength * 2 + disconLength, WaveguideWidth)); // 頂点9
                    pts.Add(new CVector2D(inputWgLength + disconLength, WaveguideWidth)); // 頂点10
                    pts.Add(new CVector2D(inputWgLength + disconLength, yOfs_cutoffWg + disconWgWidth)); // 頂点11
                    pts.Add(new CVector2D(inputWgLength, yOfs_cutoffWg + disconWgWidth)); // 頂点12
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点13
                    pts.Add(new CVector2D(srcPosX, WaveguideWidth)); // 頂点14
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                    uint lId2 = cad2d.ConnectVertex_Line(3, 14).id_l_add;
                    System.Diagnostics.Debug.Assert(lId1 == 1);
                    System.Diagnostics.Debug.Assert(lId2 == 2);
                }
                {
                    // ループ2
                    // ループの親ID
                    uint parent_id_l_cad = 2;
                    IList<CVector2D> pts = new List<CVector2D>();
                    double x1_dielectricBox = inputWgLength + (disconLength - dielectricBoxWidth) * 0.5;
                    double y1_dielectricBox = yOfs_cutoffWg + (disconWgWidth - dielectricBoxHeight) * 0.5;
                    pts.Add(new CVector2D(x1_dielectricBox, y1_dielectricBox + dielectricBoxHeight)); // 頂点15
                    pts.Add(new CVector2D(x1_dielectricBox, y1_dielectricBox)); // 頂点16
                    pts.Add(new CVector2D(x1_dielectricBox + dielectricBoxWidth, y1_dielectricBox)); // 頂点17
                    pts.Add(new CVector2D(x1_dielectricBox + dielectricBoxWidth, y1_dielectricBox + dielectricBoxHeight)); // 頂点18
                    uint id_l_add_cad = cad2d.AddPolygon(pts, parent_id_l_cad).id_l_add;
                    System.Diagnostics.Debug.Assert(id_l_add_cad == 3);
                }
                {
                    uint parent_id_l_cad = 2;
                    // 観測点
                    cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port1PosX, port1PosY)); // 頂点19
                    cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port2PosX, port2PosY)); // 頂点20
                 }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list  = {1, 2, 3};
                int[] mediaIndex_list = new int[loopId_cad_list.Length];
                mediaIndex_list[0] = Medias.IndexOf(mediaVacumn);
                mediaIndex_list[1] = Medias.IndexOf(mediaVacumn);
                mediaIndex_list[2] = Medias.IndexOf(mediaDielectricBox);

                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    uint loopId_cad = loopId_cad_list[i];
                    int mediaIndex = mediaIndex_list[i];
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, mediaIndex);
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = {2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14};
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcIdList.Clear();
            uint[] eId_cad_port = { 1, 8, 15 };
            for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++) // ポート + 励振境界
            {
                uint eId_cad = eId_cad_port[portIndex];
                uint eId;
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                aEA.Add(eId);
                {
                    wg2d.World.Edge edge = new wg2d.World.Edge();
                    edge.Set(eId, Medias.IndexOf(mediaVacumn));
                    EdgeDic.Add(eId, edge);
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                FieldPortBcIdList.Add(workFieldPortBcId);
            }

            // 観測点
            VIdRefList.Clear();
            uint[] vId_cad_refPort = { 19, 20 };
            foreach (uint vId_cad in vId_cad_refPort)
            {
                uint vId = conv.GetIdEA_fromCad(vId_cad, CAD_ELEM_TYPE.VERTEX);
                VIdRefList.Add(vId);
            }

            return true;
        }
Exemplo n.º 6
0
        /// <summary>
        /// 三角形格子 PC欠陥導波路 2チャンネル
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="Beta1"></param>
        /// <param name="Beta2"></param>
        /// <param name="BetaDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinNormalizedFreq"></param>
        /// <param name="MaxNormalizedFreq"></param>
        /// <param name="GraphBetaInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="IsPCWaveguide"></param>
        /// <param name="latticeA"></param>
        /// <param name="periodicDistance"></param>
        /// <param name="PCWaveguidePorts"></param>
        /// <param name="CalcModeIndex"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcId1"></param>
        /// <param name="FieldPortBcId2"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double Beta1,
            ref double Beta2,
            ref double BetaDelta,
            ref double GraphFreqInterval,
            ref double MinNormalizedFreq,
            ref double MaxNormalizedFreq,
            ref double GraphBetaInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref bool IsPCWaveguide,
            ref double latticeA,
            ref double periodicDistance,
            ref IList<IList<uint>> PCWaveguidePorts,
            ref int CalcModeIndex,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref uint FieldPortBcId1,
            ref uint FieldPortBcId2,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // PC導波路?
            IsPCWaveguide = true;
            // フォトニック結晶導波路(三角形格子)(TEモード)
            // 基本モードを計算する
            //CalcModeIndex = 0;
            // 高次モードを指定する
            //CalcModeIndex = 3; // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 odd 1st above decoupling point
            //CalcModeIndex = 2; // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 even 1st above decoupling point
            //CalcModeIndex = 1; // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 even 1st below coupling point
            //CalcModeIndex = 1; // for latticeTheta = 60 r = 0.30a air hole  n = 3.4 even 2nd  n = 3.4

            //CalcModeIndex = 2; // for latticeTheta = 60 r = 0.30a  n = 2.76 even 1st above & below coupling point a/lambda = 0.16 to 0.48
            //CalcModeIndex = 3; // for latticeTheta = 60 r = 0.30a  n = 2.76 odd 1st above coupling point a/lambda = 0.16 to 0.26
            CalcModeIndex = 1; // for latticeTheta = 60 r = 0.30a n = 2.76 even 1st below coupling point a/lambda = 0.28 to 0.48
            //CalcModeIndex = 0; // for latticeTheta = 60 r = 0.30a n = 2.76 odd 1st below coupling point a/lambda = 0.28 to 0.48

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0;
            // 考慮する波数ベクトルの最大値
            double maxWaveNum = 0.5;
            //double maxWaveNum = 1.0; // for latticeTheta = 30 r = 0.35a air hole

            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false; // for latticeTheta = 60 r = 0.30a air hole
            //bool isShift180 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
            // X方向周期の数
            //const int periodCnt = 1;
            const int periodCnt = 1;
            // ロッドの数(半分)
            //const int rodCntHalf = 5; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 5;
            // 欠陥ロッド数
            const int defectRodCnt = 1;
            // ロッドの数(中央)
            const int rodCntMiddle = 2;
            // 三角形格子の内角
            double latticeTheta = 60.0; // for latticeTheta = 60 r = 0.30a air hole n = 3.4
            // ロッドの半径
            //double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole n = 3.4
            double rodRadiusRatio = 0.30;
            // ロッドの比誘電率
            //double rodEps = 3.4 * 3.4; // for latticeTheta = 60 r = 0.30a dielectric rod
            double rodEps = 2.76 * 2.76;
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.30a
            const int ndivForOneLattice = 9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;

            // ロッドが1格子を超える?
            //bool isLargeRod = (rodRadiusRatio >= 0.25);
            bool isLargeRod = (rodRadiusRatio >= 0.5 * Math.Sin(latticeTheta * pi / 180.0));
            // 格子の数
            int latticeCnt = rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            if (isLargeRod)
            {
                rodDistanceY = WaveguideWidth / (double)(latticeCnt - 1);
            }
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            Beta1 = 0.0;
            Beta2 = maxWaveNum * (2.0 * pi / periodicDistance) + 1.0e-06;
            BetaDelta = 0.02 * (2.0 * pi / periodicDistance);
            //BetaDelta = 0.01 * (2.0 * pi / periodicDistance);
            GraphBetaInterval = 0.1 * (2.0 * pi / periodicDistance);

            // フォトニック結晶導波路の場合、a/λを規格化周波数とする
            if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit
                    || Math.Abs(latticeTheta - 30.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 60 r = 0.30a air hole n = 3.4
                //MinNormalizedFreq = 0.210;
                //MaxNormalizedFreq = 0.2801;
                //GraphFreqInterval = 0.01;
                // for latticeTheta = 60 r = 0.30a air hole n = 2.76
                MinNormalizedFreq = 0.260;
                MaxNormalizedFreq = 0.330;
                GraphFreqInterval = 0.01;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            // 波のモード
            //WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // Cad
            uint baseLoopId = 0;
            IList<uint> rodLoopIds = new List<uint>();
            int ndivPlus = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // ToDo: 周期境界1, 2上の分割が同じになるように設定する必要がある
                //
                // 領域を追加
                {
                    List<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));
                    pts.Add(new CVector2D(0.0, 0.0));
                    pts.Add(new CVector2D(rodDistanceX * periodCnt, 0.0));
                    pts.Add(new CVector2D(rodDistanceX * periodCnt, WaveguideWidth));
                    // 多角形追加
                    uint lId = cad2d.AddPolygon(pts).id_l_add;
                    baseLoopId = lId;
                }
                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys = new List<double>();
                IList<double> ys_rod = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                int outofAreaRodPtCnt_row_top = 0;
                int outofAreaRodPtCnt_row_bottom = 0;
                // 境界上にロッドのある格子
                // 境界上のロッドの頂点
                for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                {
                    if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                    if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                    if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY;
                    if (isLargeRod)
                    {
                        y0 += 0.5 * rodDistanceY;
                    }
                    if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                    {
                        ys_rod.Add(y0);
                    }
                    else
                    {
                        if (isLargeRod && i == 0)
                        {
                            outofAreaRodPtCnt_row_top++;
                        }
                        else if (isLargeRod && i == (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1))
                        {
                            outofAreaRodPtCnt_row_bottom++;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y1);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y2);
                        }
                        else
                        {
                            if (isLargeRod && i == 0)
                            {
                                outofAreaRodPtCnt_row_top++;
                            }
                            else if (isLargeRod && i == (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1))
                            {
                                outofAreaRodPtCnt_row_bottom++;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                    }
                }
                foreach (double y_rod in ys_rod)
                {
                    ys.Add(y_rod);
                }
                // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                double radiusMargin = rodDistanceY * 0.01;
                // 境界上にロッドのある格子
                // ロッドの外
                for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                {
                    if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                    if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                    if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_rod += rodDistanceY * 0.5;
                            y_max_rod += rodDistanceY * 0.5;
                        }
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }

                // 境界上にロッドのない格子
                for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                {
                    if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                    if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                    if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == 0 && k == 0) continue;
                        if (i == (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1) && k == ndivForOneLattice) continue;
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_upper_rod = WaveguideWidth - i * rodDistanceY + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = WaveguideWidth - (i + 1) * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_upper_rod += rodDistanceY * 0.5;
                            y_max_lower_rod += rodDistanceY * 0.5;
                        }
                        bool isAddHalfRod_row_top = (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))));
                        if ((i != 0 || (i == 0 && isAddHalfRod_row_top))
                                && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }
                        if ((isShift180 || (!isShift180 && i != (rodCntHalf - 1)))
                            && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }

                        ys.Add(y_divpt);
                    }
                }

                // 欠陥部
                const int channelCnt = 2;
                System.Diagnostics.Debug.Assert(rodCntMiddle % 2 == 0);
                for (int channelIndex = 0; channelIndex < channelCnt; channelIndex++)
                {
                    for (int i = 0; i <= (defectRodCnt * ndivForOneLattice); i++)
                    {
                        if (channelIndex == 0)
                        {
                            if (!isShift180 && (i == 0 || i == (defectRodCnt * ndivForOneLattice))) continue;
                        }
                        else if (channelIndex == 1)
                        {
                            if (rodCntMiddle % 2 == 0)
                            {
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        double y_ofs = 0.0;

                        if (channelIndex == 1)
                        {
                            y_ofs = rodDistanceY * (defectRodCnt + rodCntMiddle);
                        }
                        double y_divpt = WaveguideWidth - rodDistanceY * rodCntHalf - i * (rodDistanceY / ndivForOneLattice) - y_ofs;
                        double y_min_upper_rod = WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) + 0.5 * rodDistanceY - rodRadius - radiusMargin - y_ofs;
                        double y_max_lower_rod = WaveguideWidth - rodDistanceY * rodCntHalf - 0.5 * rodDistanceY + rodRadius + radiusMargin - y_ofs;
                        if (isLargeRod)
                        {
                            y_divpt -= rodDistanceY * 0.5;
                            y_min_upper_rod -= rodDistanceY * 0.5;
                            y_max_lower_rod -= rodDistanceY * 0.5;
                        }
                        if (isLargeRod && isShift180)
                        {
                            // for isLargeRod == true
                            if (y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit)
                                    || y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit)
                                )
                            {
                                continue;
                            }
                        }
                        ys.Add(y_divpt);
                    }
                }

                // 昇順でソート
                double[] yAry = ys.ToArray();
                Array.Sort(yAry);
                ndivPlus = yAry.Length + 1;

                // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                bool isInRod = false;
                if (isLargeRod
                    && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                {
                    isInRod = true;
                }
                for (int i = 0; i < yAry.Length; i++)
                {
                    uint id_e = 1;
                    CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(0.0, yAry[i]));
                    uint id_v_add = resAddVertex.id_v_add;
                    uint id_e_add = resAddVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    if (isInRod)
                    {
                        id_e_rod_B1.Add(id_e_add);
                    }
                    bool contains = false;
                    foreach (double y_rod in ys_rod)
                    {
                        if (Math.Abs(y_rod - yAry[i]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {
                            contains = true;
                            break;
                        }
                    }
                    if (contains)
                    {
                        id_v_list_rod_B1.Add(id_v_add);

                        if (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            if ((id_v_list_rod_B1.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if ((id_v_list_rod_B1.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                        else
                        {
                            if (id_v_list_rod_B1.Count % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if (id_v_list_rod_B1.Count % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                    }
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                    {
                        if (i == (yAry.Length - 1))
                        {
                            System.Diagnostics.Debug.Assert(isInRod == true);
                            id_e_rod_B1.Add(id_e);
                        }
                    }
                }

                isInRod = false;
                if (isLargeRod
                    && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                {
                    isInRod = true;
                }
                for (int i = yAry.Length - 1; i >= 0; i--)
                {
                    uint id_e = 3;
                    CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(rodDistanceX * periodCnt, yAry[i]));
                    uint id_v_add = resAddVertex.id_v_add;
                    uint id_e_add = resAddVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    if (isInRod)
                    {
                        id_e_rod_B2.Add(id_e_add);
                    }
                    bool contains = false;
                    foreach (double y_rod in ys_rod)
                    {
                        if (Math.Abs(y_rod - yAry[i]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {
                            contains = true;
                            break;
                        }
                    }
                    if (contains)
                    {
                        id_v_list_rod_B2.Add(id_v_add);
                        if (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            if ((id_v_list_rod_B2.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if ((id_v_list_rod_B2.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                        else
                        {
                            if (id_v_list_rod_B2.Count % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if (id_v_list_rod_B2.Count % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                    }
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                    {
                        if (i == 0)
                        {
                            System.Diagnostics.Debug.Assert(isInRod == true);
                            id_e_rod_B2.Add(id_e);
                        }
                    }
                }

                int bRodCntHalf_Top = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                int bRodCntHalf_Bottom = 0;
                if (rodCntMiddle % 2 == 0)
                {
                    bRodCntHalf_Bottom = (int)((rodCntHalf + 1) / 2);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int bRodCntMiddle = (rodCntMiddle) / 2;
                if (!isLargeRod
                    || (isLargeRod &&
                           (isShift180 && (rodCntHalf % 2 == 0)) || (!isShift180 && (rodCntHalf % 2 == 1))
                       )
                    )
                {
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));
                }
                else
                {
                    // 未サポート
                    System.Diagnostics.Debug.Assert(false);
                    /*
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                     */
                }

                /////////////////////////////////////////////////////////////////////////////
                // ロッドを追加
                uint id_v_B1_top_rod_center = 1;
                //uint id_v_B1_bottom_rod_center = 2;
                uint id_v_B2_top_rod_center = 4;
                //uint id_v_B2_bottom_rod_center = 3;

                // 左右のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_rodQuarter = new List<uint>();
                IList<uint> id_v_list_F2_rodQuarter = new List<uint>();

                // ロッドを追加
                // 左のロッド
                for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                {
                    if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                    if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                    if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = 0;
                        if (i >= 0 && i < rodCntHalf)
                        {
                            i2 = bRodCntHalf_Top - 1 - (int)((rodCntHalf - 1 - i) / 2);
                        }
                        else if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                        {
                            i2 = bRodCntHalf_Top + bRodCntMiddle - 1 - (int)((rodCntHalf + defectRodCnt + rodCntMiddle - 1 - i) / 2);
                        }
                        else if (i >= (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) && i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle))
                        {
                            i2 = bRodCntHalf_Top + bRodCntMiddle + bRodCntHalf_Bottom - 1 - (int)((rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1 - i) / 2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        int ofs_index_left = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_left = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;
                        // 左のロッド
                        {
                            uint id_v0 = 0;
                            uint id_v1 = 0;
                            uint id_v2 = 0;
                            int index_v0 = (id_v_list_rod_B1.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            int index_v1 = (id_v_list_rod_B1.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            int index_v2 = (id_v_list_rod_B1.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            if (index_v2 > id_v_list_rod_B1.Count - 1)
                            {
                                isQuarterRod = true;
                                id_v0 = id_v_list_rod_B1[index_v0];
                                //id_v1 = id_v_list_rod_B1[index_v1];
                                id_v1 = id_v_B1_top_rod_center;
                                //id_v2 = id_v_list_rod_B1[work_id_v_list_rod_B.Count - 1];
                                id_v2 = id_v_list_F1_rodQuarter[0]; // 1つ飛ばしで参照;
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B1[index_v0];
                                id_v1 = id_v_list_rod_B1[index_v1];
                                id_v2 = id_v_list_rod_B1[index_v2];
                            }

                            double x0 = 0.0;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5;
                            }
                            uint lId = 0;
                            if (isQuarterRod)
                            {
                                // 1/4円を追加する
                                lId = WgCadUtil.AddExactlyQuarterRod(
                                    cad2d,
                                    baseLoopId,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    id_v2,
                                    id_v1,
                                    id_v0,
                                    0.0,
                                    true);
                            }
                            else
                            {
                                // 左のロッド
                                lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                            }
                            rodLoopIds.Add(lId);
                        }
                    }
                }
                // 右のロッド
                for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                {
                    if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                    if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                    if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = 0;
                        if (i >= 0 && i < rodCntHalf)
                        {
                            i2 = bRodCntHalf_Top - 1 - (int)((rodCntHalf - 1 - i) / 2);
                        }
                        else if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                        {
                            i2 = bRodCntHalf_Top + bRodCntMiddle - 1 - (int)((rodCntHalf + defectRodCnt + rodCntMiddle - 1 - i) / 2);
                        }
                        else if (i >= (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) && i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle))
                        {
                            i2 = bRodCntHalf_Top + bRodCntMiddle + bRodCntHalf_Bottom - 1 - (int)((rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1 - i) / 2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        int ofs_index_top = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_top = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;

                        // 右のロッド
                        {
                            uint id_v0 = 0;
                            uint id_v1 = 0;
                            uint id_v2 = 0;
                            int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            if (index_v0 < 0)
                            {
                                isQuarterRod = true;
                                //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                id_v0 = id_v_list_F1_rodQuarter[1];
                                //id_v1 = id_v_list_rod_B2[index_v1];
                                id_v1 = id_v_B2_top_rod_center;
                                id_v2 = id_v_list_rod_B2[index_v2];
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B2[index_v0];
                                id_v1 = id_v_list_rod_B2[index_v1];
                                id_v2 = id_v_list_rod_B2[index_v2];
                            }

                            double x0 = rodDistanceX * periodCnt;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5;
                            }
                            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                            uint lId = 0;
                            if (isQuarterRod)
                            {
                                // 1/4円を追加する
                                lId = WgCadUtil.AddExactlyQuarterRod(
                                    cad2d,
                                    baseLoopId,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    id_v2,
                                    id_v1,
                                    id_v0,
                                    270.0,
                                    true);
                            }
                            else
                            {
                                // 右のロッド
                                lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                            }
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                // 中央のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();

                // 中央のロッド
                for (int col = 1; col <= periodCnt * 2 - 1; col++)
                {
                    // 中央のロッド
                    for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle); i++)
                    {
                        if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                        if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部

                        if ((col % 2 == 1 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // 領域 + ロッド
                uint[] loopId_cad_list = new uint[1 + rodLoopIds.Count];
                int[] mediaIndex_list = new int[loopId_cad_list.Length];

                // 領域
                loopId_cad_list[0] = baseLoopId;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);

                // ロッド
                int offset = 1;
                rodLoopIds.ToArray().CopyTo(loopId_cad_list, offset);
                for (int i = offset; i < mediaIndex_list.Length; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 境界条件を設定する
            // 固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[2 + id_e_F1.Count + id_e_F2.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 4;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[2 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[2 + id_e_F1.Count + i] = id_e_F2[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId1 = 0;
            {
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 1;
                if (id_e_rod_B1.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndivPlus - 1) - (i - 1));
                    if (id_e_rod_B1.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId1,
                    ref EdgeDic);
            }

            // 開口条件2
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId2 = 0;
            {
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 3;
                if (id_e_rod_B2.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndivPlus - 1) * 2 - (i - 1));
                    if (id_e_rod_B2.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId2,
                    ref EdgeDic);
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            {
                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, FieldLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf))
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - (0.5 * rodDistanceY - rodRadius)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + (0.5 * rodDistanceY - rodRadius))) // dielectric rod
                        if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
                {
                    // チャンネル2
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt + rodCntMiddle) + 1.0 * rodDistanceY)) // air hole
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 7
0
        /// <summary>
        /// PC導波路 60°三角形格子 方向性結合器 (60°ベンド)
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            //int propModeCntToSolve = 3;
            int propModeCntToSolve = 2;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            // 高次モード入射
            //int incidentModeIndex = 1;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0.0;
            // 最大屈折率
            double maxEffN = 0.0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0;
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a air hole
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5;
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a air hole

            // 入出力導波路が同じ?
            //IsInoutWgSame = true; // 同じ
            //IsInoutWgSame = false; // 同じでない
            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false;
            //bool isShift180 = true;
            // ロッドの数(半分)
            //const int rodCntHalf = 3; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 3;
            System.Diagnostics.Debug.Assert(rodCntHalf % 2 == 1); // 奇数を指定(図面の都合上)
            // 欠陥ロッド数
            // for latticeTheta = 60 r = 0.30a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            double latticeTheta = 60.0;
            // ロッドの半径
            //double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            // ロッドの比誘電率
            //double rodEps = 3.40 * 3.40; // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.30a air hole
            const int ndivForOneLattice = 8;// 9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 3;
            const int rodCntDiscon = 3;
            // 結合部ロッド数
            const int rodCntMiddle = 2;
            // 最適形状?
            bool isOptBend = false;
            //bool isOptBend = true;
            // 結合長
            //const int rodCntCoupling = 4; // 7a for latticeTheta = 60 r = 0.30a air hole n = 3.40 (rodCntHalf == 3とき、4a + 2a<ベンド部> + 0.5a * 2<左右両端> = 7a)
            //const int rodCntCoupling = 2; // 5a for latticeTheta = 60 r = 0.30a air hole n = 3.40 (完全結合長に合わせた場合)
            //const int rodCntCoupling = 3;// 6a for latticeTheta = 60 r = 0.30a air hole n = 2.76
            const int rodCntCoupling = 3;
            // 入出力不連続部の距離
            const int rodCntDiscon_port1 = (rodCntDiscon + rodCntCoupling);  // 入力部は結合領域を含む
            const int rodCntDiscon_port3 = 3;

            // 格子の数
            const int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            //NormalizedFreq1 = 0.215;//0.210;
            //NormalizedFreq2 = 0.2401;// 0.2561;
            //FreqDelta = 0.00025; //0.0005;
            //GraphFreqInterval = 0.005;
            // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            NormalizedFreq1 = 0.267;
            NormalizedFreq2 = 0.2831;//0.2871;
            FreqDelta = 0.00025;// 0.0005;
            GraphFreqInterval = 0.004;

            //minEffN = 0.0;
            //maxEffN = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN_port2 = minWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            //maxEffN_port2 = maxWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;// 1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
                //isMagneticWall = true;
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
                incidentModeIndex = 0;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            const uint portCnt = 3;
            System.Diagnostics.Debug.Assert(Math.Abs(WaveguideWidth - WaveguideWidth) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            double disconLength1 = rodDistanceX * rodCntDiscon_port1;
            double disconLength3 = rodDistanceX * rodCntDiscon_port3;

            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            IList<uint> rodLoopIds_InputWg3 = new List<uint>();
            int ndivPlus_port1 = 0;
            int ndivPlus_port2 = 0;
            int ndivPlus_port3 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_rod_B5 = new List<uint>();
            IList<uint> id_e_rod_B6 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            IList<uint> id_e_F1_Bend = new List<uint>();

            // ベンド下側角
            double bendX1_0 = inputWgLength + disconLength1 + WaveguideWidth / Math.Sqrt(3.0);
            double bendY1_0 = 0.0;
            bendX1_0 -= latticeA * Math.Sqrt(3.0) / 4.0;
            bendY1_0 -= rodDistanceY / 4.0;
            if (rodCntMiddle % 2 == 0)
            {
                bendX1_0 -= rodDistanceX / 4.0;
                bendY1_0 -= rodDistanceY / 2.0;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
                /*
                if (!isShift180)
                {
                    bendX1_0 += rodDistanceX / 4.0;
                    bendY1_0 -= rodDistanceY / 2.0;
                }
                 */
            }
            double bendX1 = bendX1_0 + (0.0 - bendY1_0) / Math.Sqrt(3.0);
            double bendY1 = 0.0;
            // ベンド部と出力部の境界
            double bendX2 = bendX1_0 + WaveguideWidth / (2.0 * Math.Sqrt(3.0));
            double bendY2 = bendY1_0 + WaveguideWidth / 2.0;
            // 出力部内部境界の終点
            double port3_X2_B6 = bendX2 + disconLength3 / 2.0;
            double port3_Y2_B6 = bendY2 + disconLength3 * Math.Sqrt(3.0) / 2.0;
            // 出力部境界の終点
            double port3_X2_B5 = port3_X2_B6 + inputWgLength / 2.0;
            double port3_Y2_B5 = port3_Y2_B6 + inputWgLength * Math.Sqrt(3.0) / 2.0;
            // ベンド部上側角
            double bendX3_0 = inputWgLength + disconLength1;
            double bendY3_0 = WaveguideWidth;
            bendX3_0 -= latticeA * Math.Sqrt(3.0) / 4.0;
            bendY3_0 -= rodDistanceY / 4.0;
            if (rodCntMiddle % 2 == 0)
            {
                bendX3_0 -= rodDistanceX / 4.0;
                bendY3_0 -= rodDistanceY / 2.0;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }
            double bendX3 = bendX3_0 + (WaveguideWidth - bendY3_0) / Math.Sqrt(3.0);
            double bendY3 = WaveguideWidth;
            // 出力部内部境界の始点
            double port3_X1_B6 = bendX3_0 + disconLength3 / 2.0;
            double port3_Y1_B6 = bendY3_0 + disconLength3 * Math.Sqrt(3.0) / 2.0;
            // 出力部境界の始点
            double port3_X1_B5 = port3_X1_B6 + inputWgLength / 2.0;
            double port3_Y1_B5 = port3_Y1_B6 + inputWgLength * Math.Sqrt(3.0) / 2.0;

            // 導波路2
            double wg2_Y2 = WaveguideWidth - (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle) * rodDistanceY;
            double wg2_Y1 = wg2_Y2 + WaveguideWidth;
            double bendX1_wg2 = bendX1 + (wg2_Y1 - bendY1) / Math.Sqrt(3.0);
            // ポート2
            double port2_X = bendX1_wg2 + rodDistanceX * 0.25 + rodDistanceX * 0.5 + inputWgLength;
            double bendX4 = port2_X - inputWgLength - rodDistanceX * 0.5 - rodDistanceX * 0.25;

            System.Diagnostics.Debug.Assert(port3_Y2_B6 > wg2_Y1);
            // check
            {
                double[] pt1_port3_B5 = new double[] {port3_X1_B5, port3_Y1_B5};
                double[] pt2_port3_B5 = new double[] {port3_X2_B5, port3_Y2_B5};
                double distance_B5 = CVector2D.Distance2D(pt1_port3_B5, pt2_port3_B5);
                System.Diagnostics.Debug.Assert(Math.Abs(distance_B5 - WaveguideWidth) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
                double[] pt1_port3_B6 = new double[] { port3_X1_B6, port3_Y1_B6 };
                double[] pt2_port3_B6 = new double[] { port3_X2_B6, port3_Y2_B6 };
                double distance_B6 = CVector2D.Distance2D(pt1_port3_B6, pt2_port3_B6);
                System.Diagnostics.Debug.Assert(Math.Abs(distance_B6 - WaveguideWidth) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            }

            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, wg2_Y1)); // 頂点1
                    pts.Add(new CVector2D(0.0, wg2_Y2)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength, wg2_Y2)); // 頂点3
                    pts.Add(new CVector2D(port2_X - inputWgLength, wg2_Y2)); // 頂点4
                    pts.Add(new CVector2D(port2_X, wg2_Y2)); // 頂点5
                    pts.Add(new CVector2D(port2_X, wg2_Y1)); // 頂点6
                    pts.Add(new CVector2D(port2_X - inputWgLength, wg2_Y1)); // 頂点7
                    pts.Add(new CVector2D(bendX4, wg2_Y1)); // 頂点8
                    pts.Add(new CVector2D(port3_X2_B6, port3_Y2_B6)); // 頂点9
                    pts.Add(new CVector2D(port3_X2_B5, port3_Y2_B5)); // 頂点10
                    pts.Add(new CVector2D(port3_X1_B5, port3_Y1_B5)); // 頂点11
                    pts.Add(new CVector2D(port3_X1_B6, port3_Y1_B6)); // 頂点12
                    pts.Add(new CVector2D(bendX3, bendY3)); // 頂点13
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth));  // 頂点14
                    pts.Add(new CVector2D(inputWgLength, wg2_Y1)); // 頂点15
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 15).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(4, 7).id_e_add;
                uint eIdAdd3 = cad2d.ConnectVertex_Line(9, 12).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys_port1 = new List<double>();
                IList<double> ys_rod_port1 = new List<double>();
                IList<double> ys_port2 = new List<double>();
                IList<double> ys_rod_port2 = new List<double>();
                IList<double> xs_port3 = new List<double>();
                IList<double> xs_rod_port3 = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                IList<uint> id_v_list_rod_B5 = new List<uint>();
                IList<uint> id_v_list_rod_B6 = new List<uint>();

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    int cur_rodCntHalf = 0;
                    int cur_defectRodCnt = 0;
                    int cur_ndivForOneLattice = 0;
                    double cur_WaveguideWidth = 0.0;
                    double cur_rodDistanceY = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;
                    if (portIndex == 0)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port1;
                        ys_rod = ys_rod_port1;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 1)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port2;
                        ys_rod = ys_rod_port2;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 2)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = xs_port3;
                        ys_rod = xs_rod_port3;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }

                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    double radiusMargin = cur_rodDistanceY * 0.01;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }

                    // 境界上にロッドのない格子
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == 0 && k == 0) continue;
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == (cur_rodCntHalf - 1) && k == cur_ndivForOneLattice) continue;
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    // 欠陥部
                    for (int i = 0; i <= (cur_defectRodCnt * cur_ndivForOneLattice); i++)
                    {
                        if (!isShift180 && (i == 0 || i == (cur_defectRodCnt * cur_ndivForOneLattice))) continue;
                        double y_divpt = cur_rodDistanceY * (cur_rodCntHalf + cur_defectRodCnt) - i * (cur_rodDistanceY / cur_ndivForOneLattice);
                        ys.Add(y_divpt);
                    }

                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (portIndex == 0)
                    {
                        ndivPlus_port1 = cur_ndivPlus;
                    }
                    else if (portIndex == 1)
                    {
                        ndivPlus_port2 = cur_ndivPlus;
                    }
                    else if (portIndex == 2)
                    {
                        ndivPlus_port3 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    // 入力導波路 外側境界
                    // 入力導波路 内部側境界
                    // 出力導波路 外側境界
                    // 出力導波路 内部側境界
                    for (int boundaryIndex = 0; boundaryIndex < 2;  boundaryIndex++)
                    {
                        bool isInRod = false;
                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            double x_pt = 0.0;
                            double y_pt = 0.0;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (portIndex == 0 && boundaryIndex == 0)
                            {
                                // 入力導波路 外側境界
                                id_e = 1;
                                x_pt = 0.0;
                                y_pt = yAry[i] - (WaveguideWidth - wg2_Y1);
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B1;
                                work_id_v_list_rod_B = id_v_list_rod_B1;
                            }
                            else if (portIndex == 0 && boundaryIndex == 1)
                            {
                                // 入力導波路 内側境界
                                id_e = 16;
                                x_pt = inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i] - (WaveguideWidth - wg2_Y1);
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B2;
                                work_id_v_list_rod_B = id_v_list_rod_B2;
                            }
                            else if (portIndex == 1 && boundaryIndex == 0)
                            {
                                // 入力導波路 外側境界
                                id_e = 5;
                                x_pt = port2_X;
                                y_pt = yAry[yAry.Length - 1 - i] - (WaveguideWidth - wg2_Y1);
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (portIndex == 1 && boundaryIndex == 1)
                            {
                                // 入力導波路 内側境界
                                id_e = 17;
                                x_pt = port2_X - inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i] - (WaveguideWidth - wg2_Y1);
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else if (portIndex == 2 && boundaryIndex == 0)
                            {
                                // 出力導波路 外側境界
                                id_e = 10;
                                x_pt = port3_X1_B5 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port3_Y1_B5 - yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B5;
                                work_id_v_list_rod_B = id_v_list_rod_B5;
                            }
                            else if (portIndex == 2 && boundaryIndex == 1)
                            {
                                // 出力導波路 内側境界
                                id_e = 18;
                                x_pt = port3_X1_B6 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port3_Y1_B6 - yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B6;
                                work_id_v_list_rod_B = id_v_list_rod_B6;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y_pt));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                    }
                }
                int bRodCntHalf_port1 = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B5.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B6.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));

                // ロッドを追加
                /////////////////////////////////////////////////////////////
                // 入力導波路側ロッド
                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = wg2_Y1 - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = wg2_Y2 + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (colIndex == 1)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2外側
                        x_B = port2_X;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = wg2_Y1 - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = wg2_Y2 + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央のロッド (入力導波路 + 不連続部)
                int periodCntInputWg1 = 1;
                int periodCntBendX = (rodCntHalf * 2 + defectRodCnt) / 2;
                int rodCnt_BendY = rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle;
                int rodCnt_Wg2 = rodCntHalf * 2 + defectRodCnt;
                int periodCntX_port3 = (int)Math.Round(port3_X2_B6 / rodDistanceX);
                int periodCntX_BendX4 = (int)Math.Round(bendX4 / rodDistanceX);
                int periodCntX_port2 = (int)Math.Round(port2_X / rodDistanceX);
                int row_wg2_Y1 = (int)Math.Round((WaveguideWidth - wg2_Y1) / rodDistanceY);

                // ベンド最適化構造:ジグザグ
                //   r = 0.30a のとき
                // 小さいロッドの半径
                double rodRadius_Small_Zigzag = 0.0; // 小さいロッド
                //double rodRadius_Small_Zigzag = 0.14 * latticeA; // 小さいロッド
                //double rodRadius_Small_Zigzag = 0.12 * latticeA; // 小さいロッド
                double rodRadius_Big_Zigzag = rodRadius;//0.30 * latticeA; // 大きいロッド
                //double rodRadius_Big_Zigzag = 0.32 * latticeA; // 大きいロッド
                // 小さいロッドの周方向分割数
                int rodCircleDiv_Small_Zigzag = 12;// 12;
                int rodRadiusDiv_Small_Zigzag = 2; // 4;

                for (int col = 1; col <= (periodCntX_port3 * 2); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 中央のロッド
                    for (int i = 0; i < rodCnt_BendY; i++)
                    {
                        if (col >= 0 && col <= (periodCntInputWg1 * 2)
                            && (i >= 0 && i <= (rodCnt_BendY - rodCntHalf * 2 - defectRodCnt - 1))
                            )
                        {
                            continue;
                        }
                        if (col >= 0 && col < (periodCntInputWg1 * 2))
                        {
                            baseLoopId = 1;
                            inputWgNo = 1;
                        }
                        else
                        {
                            baseLoopId = 2;
                            inputWgNo = 0;
                        }

                        // 出力ポートとベンド部の境界判定
                        if (col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + 1))
                        {
                            int rowMin = (col - (periodCntInputWg1 + rodCntDiscon_port1 - 1) * 2) / 3;
                            if (i < rowMin)
                            {
                                continue;
                            }
                        }
                        // 下部の境界判定
                        if (col >= (periodCntX_BendX4 * 2))
                        {
                            int rowMax = row_wg2_Y1 - (col - (periodCntX_BendX4 * 2));
                            if (i > rowMax)
                            {
                                continue;
                            }
                        }
                        // ロッドの半径
                        double rr = rodRadius;
                        // ロッドの半径方向分割数
                        int nr = rodRadiusDiv;
                        // ロッドの周方向分割数
                        int nc = rodCircleDiv;
                        // ずらす距離
                        double ofs_x_rod = 0.0;
                        double ofs_y_rod = 0.0;

                        if (inputWgNo == 0)
                        {
                            // 分割数を調整
                            nr = 2;
                        }

                        // 欠陥(導波路2)
                        if (i >= (rodCnt_BendY - 1 - rodCntHalf - defectRodCnt + 1) && i <= (rodCnt_BendY - 1 - rodCntHalf))
                        {
                            continue;
                        }

                        if (!isOptBend)
                        {
                            // ベンド初期構造
                            // 欠陥(導波路1入力部)
                            if ((col >= (periodCntInputWg1 + rodCntDiscon) * 2 && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 - 1))
                                && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                continue;
                            }
                            // 欠陥(ベンド部入力側)
                            int colBend_port1 = (col - (periodCntInputWg1 + rodCntDiscon_port1) * 2);
                            int colBend_centerLine = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + periodCntBendX;
                            if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2))
                                && col <= (colBend_centerLine - 1)
                                && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                continue;
                            }
                            // 欠陥(ベンド部出力側)
                            if ((col >= (colBend_centerLine))
                                )
                            {
                                int colBend_port2 = col - colBend_centerLine;
                                if (i >= (rodCntHalf - colBend_port2) && i <= (rodCntHalf + defectRodCnt - 1 - colBend_port2))
                                {
                                    continue;
                                }
                            }
                        }

                        /*
                        // ベンド最適化構造:ベンド部に小さいロッドを3つ挿入
                        //   r = 0.30a, r = 0.29 のとき
                        // 小さいロッドの半径
                        //double rodRadius_Small = 0.14 * latticeA; // 小さいロッド3つ
                        //double rodRadius_Small = 0.1627 * latticeA; // ロッド2つ(中央のロッドがない)
                        double rodRadius_Small = 0.13 * latticeA; // ベンド中央にロッド1つ
                        // 小さいロッドの周方向分割数
                        int rodCircleDiv_Small = 12;// 12;
                        int rodRadiusDiv_Small = 2; // 4;
                        // 欠陥(入力部)
                        if ((col >= (periodCntInputWg1 + rodCntDiscon) * 2 && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 - 1))
                            && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                        {
                            continue;
                        }
                        // 欠陥(ベンド部入力側)
                        int colBend_port1 = (col - (periodCntInputWg1 + rodCntDiscon_port1) * 2);
                        int colBend_centerLine = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + periodCntBendX;
                        if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2))
                            && col <= (colBend_centerLine - 1)
                            && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                        {
                            continue; // ベンド中央にロッド1つ
                            //if (col == (colBend_centerLine - 2))
                            //{
                            //    rr = rodRadius_Small;
                            //    //nr = (int)Math.Ceiling(rodRadiusDiv * rr / rodRadius);
                            //    nr = rodRadiusDiv_Small;
                            //    nc = rodCircleDiv_Small;
                            //}
                            //else
                            //{
                            //    continue;
                            //}
                        }
                        // 欠陥(ベンド部出力側)
                        if ((col >= (colBend_centerLine))
                            )
                        {
                            int colBend_port2 = col - colBend_centerLine;
                            if (i >= (rodCntHalf - colBend_port2) && i <= (rodCntHalf + defectRodCnt - 1 - colBend_port2))
                            {
                                if (col == (colBend_centerLine)) // ベンド中央にロッド1つ
                                //if (col == (colBend_centerLine) || col == (colBend_centerLine + 1))  // rodRadius_Small = 0.14 * latticeA  小さいロッド3つ
                                //if (col == (colBend_centerLine + 1)) // ロッド2つ(中央のロッドがない)
                                {
                                    rr = rodRadius_Small;
                                    //nr = (int)Math.Ceiling(rodRadiusDiv * rr / rodRadius);
                                    nr = rodRadiusDiv_Small;
                                    nc = rodCircleDiv_Small;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                        }
                         */

                        if (isOptBend)
                        {
                            // ベンド最適形状:ジグザグ
                            // 欠陥(入力部)
                            if ((col >= (periodCntInputWg1 + rodCntDiscon) * 2 && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 - 1))
                                && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                if (col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 - 1))
                                {
                                    if (Math.Abs(rodRadius_Small_Zigzag) < Constants.PrecisionLowerLimit)
                                    {
                                        continue;
                                    }
                                    rr = rodRadius_Small_Zigzag;
                                    nr = rodRadiusDiv_Small_Zigzag;
                                    nc = rodCircleDiv_Small_Zigzag;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            // 欠陥(ベンド部入力側)
                            int colBend_port1 = (col - (periodCntInputWg1 + rodCntDiscon_port1) * 2);
                            int colBend_centerLine = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + periodCntBendX;
                            if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2))
                                && col <= (colBend_centerLine - 1)
                                && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                if (col == (colBend_centerLine - 2))
                                {
                                    if (Math.Abs(rodRadius_Small_Zigzag) < Constants.PrecisionLowerLimit)
                                    {
                                        continue;
                                    }
                                    rr = rodRadius_Small_Zigzag;
                                    nr = rodRadiusDiv_Small_Zigzag;
                                    nc = rodCircleDiv_Small_Zigzag;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                            // 欠陥(ベンド部出力側)
                            if ((col >= (colBend_centerLine))
                                )
                            {
                                int colBend_port2 = col - colBend_centerLine;
                                if (i >= (rodCntHalf - colBend_port2) && i <= (rodCntHalf + defectRodCnt - 1 - colBend_port2))
                                {
                                    if (col == (colBend_centerLine)) // ベンド中央
                                    {
                                    }
                                    else if (col == (colBend_centerLine + 1)) // 出力側ロッド
                                    {
                                        if (Math.Abs(rodRadius_Small_Zigzag) < Constants.PrecisionLowerLimit)
                                        {
                                            continue;
                                        }
                                        rr = rodRadius_Small_Zigzag;
                                        nr = rodRadiusDiv_Small_Zigzag;
                                        nc = rodCircleDiv_Small_Zigzag;
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }
                            }
                            // ベンド上側角
                            if ((col == (colBend_centerLine - 3) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt * 2 + rodCntMiddle + 1)))
                                || (col == (colBend_centerLine - 2) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt * 2 + rodCntMiddle + 2)))
                                || (col == colBend_centerLine && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt * 2 + rodCntMiddle + 2)))
                                )
                            {
                                rr = rodRadius_Big_Zigzag;
                            }
                            // ジグザグ中央
                            if (col == (colBend_centerLine - 1) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt * 2 + rodCntMiddle + 1)))
                            {
                                if (Math.Abs(rodRadius_Small_Zigzag) < Constants.PrecisionLowerLimit)
                                {
                                    continue;
                                }
                                rr = rodRadius_Small_Zigzag;
                                nr = rodRadiusDiv_Small_Zigzag;
                                nc = rodCircleDiv_Small_Zigzag;
                            }
                            // ベンド下側
                            if ((col == (colBend_centerLine - 3) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt + rodCntMiddle)))
                                || (col == (colBend_centerLine - 1) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt + rodCntMiddle)))
                                || (col == (colBend_centerLine) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt + rodCntMiddle + 1)))
                                || (col == (colBend_centerLine + 2) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt + rodCntMiddle + 1)))
                                || (col == (colBend_centerLine + 3) && i == (rodCnt_BendY - (rodCntHalf + defectRodCnt + rodCntMiddle + 2)))
                                )
                            {
                                rr = rodRadius_Big_Zigzag;
                            }
                        }

                        if ((col % 2 == 1 && (Math.Abs(i - (rodCnt_BendY - rodCnt_Wg2)) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(i - (rodCnt_BendY - rodCnt_Wg2)) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            //uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            x0 += ofs_x_rod;
                            y0 += ofs_y_rod;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, nc, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                        }
                    }
                }

                /////////////////////////////////////////////////////////////
                // 導波路2
                for (int col = (periodCntX_BendX4 * 2); col <= (periodCntX_port2 * 2 - 1); col++)
                {
                    if (col == ((periodCntX_port2 - periodCntInputWg1) * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= (periodCntX_port2 - periodCntInputWg1) * 2)
                    {
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }

                    for (int i = (rodCnt_BendY - rodCntHalf * 2 - defectRodCnt); i < rodCnt_BendY; i++)
                    {
                        double rr = rodRadius;
                        int nr = rodRadiusDiv;
                        if (inputWgNo == 0)
                        {
                            // 分割数を調整
                            nr = 2;
                        }

                        // 欠陥(導波路2)
                        if (i >= (rodCnt_BendY - 1 - rodCntHalf - defectRodCnt + 1) && i <= (rodCnt_BendY - 1 - rodCntHalf))
                        {
                            continue;
                        }

                        if ((col % 2 == 1 && (Math.Abs(i - (rodCnt_BendY - rodCnt_Wg2)) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(i - (rodCnt_BendY - rodCnt_Wg2)) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, rodCircleDiv, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                        }
                    }
                }

                /////////////////////////////////////////////////////////////
                // 出力導波路側ロッド
                // 上のロッドを追加
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 上のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x1_B = 0;
                    double y1_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 外側
                        x1_B = port3_X1_B5;
                        y1_B = port3_Y1_B5;
                        work_id_v_list_rod_B = id_v_list_rod_B5;
                        // 出力導波路領域
                        baseLoopId = 4;
                        inputWgNo = 3;
                    }
                    else if (colIndex == 1)
                    {
                        // 出力境界内側
                        x1_B = port3_X1_B6;
                        y1_B = port3_Y1_B6;
                        work_id_v_list_rod_B = id_v_list_rod_B6;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 上のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                                double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                double y0 = y1_B - y_proj / 2.0;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddExactlyHalfRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    (0.0 - 30.0),
                                    true);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 上のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double y_proj = WaveguideWidth - rodDistanceY * rodCntHalf + i * rodDistanceY + rodDistanceY * 0.5;
                                double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                double y0 = y1_B - y_proj / 2.0;
                                uint lId = WgCadUtil.AddExactlyHalfRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    (0.0 - 30.0),
                                    true);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 下のロッドを追加
                for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 下のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x1_B = 0;
                    double y1_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 内側
                        x1_B = port3_X1_B6;
                        y1_B = port3_Y1_B6;
                        work_id_v_list_rod_B = id_v_list_rod_B6;
                        // 出力導波路領域
                        baseLoopId = 4;
                        inputWgNo = 3;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 下のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                                double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                double y0 = y1_B - y_proj / 2.0;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddExactlyHalfRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    (180.0 - 30.0),
                                    true);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 下のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double y_proj = WaveguideWidth - rodDistanceY * rodCntHalf + i * rodDistanceY + rodDistanceY * 0.5;
                                double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                double y0 = y1_B - y_proj / 2.0;
                                uint lId = WgCadUtil.AddExactlyHalfRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    (180.0 - 30.0),
                                    true);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド (出力導波路)
                int periodCntInputWg2 = 1;
                int periodCntY = periodCntInputWg2 + rodCntDiscon_port3;

                // 中央のロッド(出力導波路)(左右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();

                // 中央のロッド (出力導波路)
                for (int col = 1; col <= (periodCntY * 2 - 2); col++)
                {
                    if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)

                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg2 * 2))
                    {
                        baseLoopId = 4;
                        inputWgNo = 3;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    double x1_B = 0.0;
                    double y1_B = 0.0;
                    x1_B = port3_X1_B5 - col * ((rodDistanceX * 0.5) / 2.0);
                    y1_B = port3_Y1_B5 - col * ((rodDistanceX * 0.5) * Math.Sqrt(3.0) / 2.0);

                    // 中央のロッド(出力導波路)
                    for (int i = 0; i <= (rodCntHalf * 2 + defectRodCnt); i++)
                    {
                        if (rodCntHalf == 5)
                        {
                            if (col < (periodCntY * 2 - 2))
                            {
                                if (i >= (rodCntHalf * 2 + defectRodCnt)) continue;
                            }
                        }
                        else
                        {
                            if (i >= (rodCntHalf * 2 + defectRodCnt)) continue;
                        }

                        double rr = rodRadius;
                        int nr = rodRadiusDiv;
                        if (inputWgNo == 0)
                        {
                            // 分割数を調整
                            nr = 2;
                        }
                        // 欠陥部
                        if (i == (rodCntHalf))
                        {
                            if (!isOptBend)
                            {
                                continue;
                            }
                            else
                            {
                                // ベンド最適形状:ジグザグ
                                if (col == (periodCntY * 2 - 2))
                                {
                                    if (Math.Abs(rodRadius_Small_Zigzag) < Constants.PrecisionLowerLimit)
                                    {
                                        continue;
                                    }
                                    rr = rodRadius_Small_Zigzag;
                                    nr = rodRadiusDiv_Small_Zigzag;
                                }
                                else
                                {
                                    continue;
                                }
                            }
                        }
                        if ((col % 2 == 1 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                            double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                            double y0 = y1_B - y_proj / 2.0;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, rodCircleDiv, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(ベンド部分)(左の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_Bend = new List<uint>();
                int rodCntY_F1_Bend = rodCnt_BendY - (rodCntHalf * 2 + defectRodCnt);
                for (int i = (rodCntY_F1_Bend - 1); i >= 0; i--)
                {
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 0);
                    if (isRodLattice)
                    {
                        uint id_e = 14;
                        double x0 = inputWgLength;
                        double y0 = WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                        double x_cross = inputWgLength;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_Bend.Add(id_v_add);
                            id_e_F1_Bend.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、左境界と接する半円)
                for (int i = 0; i < rodCntY_F1_Bend; i++)
                {
                    // 不連続領域
                    uint baseLoopId = 2;
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 0);
                    if (isRodLattice)
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(右半分)を追加
                            double x0 = inputWgLength;
                            double y0 = WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                            int row2 = (rodCntY_F1_Bend - 1 - i) / 2;
                            System.Diagnostics.Debug.Assert(row2 >= 0);
                            uint id_v0 = id_v_list_F1_Bend[row2 * 3 + 0];
                            uint id_v1 = id_v_list_F1_Bend[row2 * 3 + 1];
                            uint id_v2 = id_v_list_F1_Bend[row2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                90.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B5)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B6)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[4 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                loopId_cad_list[3] = 4;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 4] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[4 + rodLoopIds.Count];
                for (int i = 0; i < 4; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 4] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // ポート情報リスト作成
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[2].IncidentModeIndex = incidentModeIndex;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[12 + id_e_F1.Count + id_e_F2.Count + id_e_F1_Bend.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 6;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                eId_cad_list[6] = 9;
                eId_cad_list[7] = 11;
                eId_cad_list[8] = 12;
                eId_cad_list[9] = 13;
                eId_cad_list[10] = 14;
                eId_cad_list[11] = 15;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[12 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[12 + id_e_F1.Count + i] = id_e_F2[i];
                }
                for (int i = 0; i < id_e_F1_Bend.Count; i++)
                {
                    eId_cad_list[12 + id_e_F1.Count + id_e_F2.Count + i] = id_e_F1_Bend[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else if (portIndex == 2)
                {
                    ndivPlus = ndivPlus_port3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 5;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 10;
                    work_id_e_rod_B = id_e_rod_B5;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else if (portIndex == 2)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg3.Count];
                    loopId_cad_list[0] = 4;
                    for (int i = 0; i < rodLoopIds_InputWg3.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg3[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 2)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg3.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg3.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else if (portIndex == 2)
                {
                    ndivPlus = ndivPlus_port3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 16;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 17;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 18;
                    work_id_e_rod_B = id_e_rod_B6;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(18 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                if (portIndex == 0 || portIndex == 1)
                {
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else if (portIndex == 2)
                {
                    // Y軸から見ての回転角
                    double rotAngle = 60.0 * pi / 180.0;
                    double[] rotOrigin = new double[] { port3_X2_B5, port3_Y2_B5 };
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, rotAngle, rotOrigin, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (((portIndex == 0 || portIndex == 1) &&
                                (coord[1] >= (wg2_Y1 - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (wg2_Y1 - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            || (portIndex == 2 &&
                                (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            )
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 8
0
        /// <summary>
        /// 誘電体スラブ導波路グレーティング
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcId1"></param>
        /// <param name="FieldPortBcId2"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref uint FieldPortBcId1,
            ref uint FieldPortBcId2,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // メッシュの分割長さ
            double meshL = WaveguideWidth * 1.0 / 60.0;
            //double meshL = WaveguideWidth * 1.0 / 69.0;

            // 導波管不連続領域の長さ
            //double disconLength = 65.0 / 60.0 * WaveguideWidth;
            double disconLength = 40.0 / 60.0 * WaveguideWidth;

            // 誘電体スラブ導波路幅
            double slabWidth =WaveguideWidth / 30.0;
            // 誘電体スラブ比誘電率
            double coreEps = 2.402500;
            // グレーティング比誘電率
            double gratingEps = 2.102500;
            // グレーティングの数
            int gratingCnt = 8;  // 偶数とする
            // グレーティング1つの長さ
            double gratingOneLength = slabWidth;
            // グレーティングの全長
            double gratingAllLength = gratingOneLength * ((gratingCnt - 1) * 2 + 1);
            // グレーティング開始位置
            //double grating_X1 = 25.0 / 60.0 * WaveguideWidth;
            double grating_X1 = 5.0 / 60.0 * WaveguideWidth;
            double grating_X2 = grating_X1 + gratingAllLength;

            NormalizedFreq1 = 10.0;
            NormalizedFreq2 = 20.0;
            FreqDelta = 0.25;
            GraphFreqInterval = 2.0;

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            MediaInfo mediaVacumn = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 1.0, 0.0, 0.0 },
                   { 0.0, 1.0, 0.0 },
                   { 0.0, 0.0, 1.0 }
                }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { coreEps,  0.0,  0.0 },
                   {  0.0, coreEps,  0.0 },
                   {  0.0,  0.0, coreEps }
                }
            );
            MediaInfo mediaGrating = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { gratingEps,  0.0,  0.0 },
                   {  0.0, gratingEps,  0.0 },
                   {  0.0,  0.0, gratingEps }
                }
            );
            Medias.Add(mediaVacumn);
            Medias.Add(mediaCore);
            Medias.Add(mediaGrating);

            // 図面作成、メッシュ生成
            double coreY1 = (WaveguideWidth - slabWidth) * 0.5;
            double coreY2 = coreY1 + slabWidth;
            uint[] all_loopId_cad_list = new uint[3 + (2 * (gratingCnt - 1) + 1) + 1];
            for (int i = 0; i < all_loopId_cad_list.Length; i++)
            {
                all_loopId_cad_list[i] = (uint)(i + 1);
            }
            uint[] slab_loopId_cad_list = new uint[1 + (gratingCnt - 1) + 1];
            slab_loopId_cad_list[0] = 3;
            for (int i = 0; i < gratingCnt; i++)
            {
                slab_loopId_cad_list[1 + i] = (uint)(5 + i * 2);
            }
            uint[] grating_loopId_cad_list = new uint[gratingCnt];
            for (int i = 0; i < gratingCnt; i++)
            {
                grating_loopId_cad_list[i] = (uint)(4 + i * 2);
            }

            uint[] port1_eId_list = { 1, 6, 5 };
            uint port1_core_eId = 6;
            uint[] port2_eId_list = { 3, 8, 7 };
            uint port2_core_eId = 8;
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    // ループ1
                    IList<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(disconLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(disconLength, WaveguideWidth)); // 頂点4
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }

                // スラブ導波路と境界の交点
                uint[] parent_eId_list = {1, 3};
                double[] portX_list = {0.0, disconLength};
                IList<uint[]> slab_vIds_list = new List<uint[]>();
                for (int portIndex = 0; portIndex < (portCnt); portIndex++)
                {
                    uint parent_eId = parent_eId_list[portIndex];
                    double portX = portX_list[portIndex];

                    double workY1 = 0.0;
                    double workY2 = 0.0;
                    if (portIndex == 0)
                    {
                        workY1 = coreY1;
                        workY2 = coreY2;
                    }
                    else
                    {
                        workY1 = coreY2;
                        workY2 = coreY1;
                    }
                    uint vId1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY1)).id_v_add;
                    uint vId2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY2)).id_v_add;
                    uint[] work_vIds = new uint[2];
                    if (portIndex == 0)
                    {
                        work_vIds[0] = vId1;
                        work_vIds[1] = vId2;
                    }
                    else
                    {
                        work_vIds[0] = vId2;
                        work_vIds[1] = vId1;
                    }
                    slab_vIds_list.Add(work_vIds);
                }
                // スラブ導波路
                {
                    {
                        uint work_vId1 = slab_vIds_list[0][0];
                        uint work_vId2 = slab_vIds_list[1][0];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                    {
                        uint work_vId1 = slab_vIds_list[0][1];
                        uint work_vId2 = slab_vIds_list[1][1];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                }
                // グレーティング
                {
                    // 誘電体スラブの上下の辺
                    uint[] slabTopBottom_eIds = {9, 10};
                    double[] work_Ys = {coreY1, coreY2};
                    uint[][] work_vIds_list = new uint[2][];
                    // 上下の辺に頂点を追加
                    for (int edgeIndex = 0; edgeIndex < 2; edgeIndex++) // スラブの上下の辺
                    {
                        uint parent_eId = slabTopBottom_eIds[edgeIndex];
                        double workY = work_Ys[edgeIndex];
                        work_vIds_list[edgeIndex] = new uint[2 * gratingCnt];
                        for (int i = (2 * gratingCnt) - 1; i >= 0; i--)
                        {
                            double workX = grating_X1 + gratingOneLength * i;
                            uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY)).id_v_add;
                            work_vIds_list[edgeIndex][i] = vId;
                        }
                    }
                    // 上下の頂点を結ぶ
                    uint[] grating_eIds = new uint[(2 * gratingCnt)];
                    uint[] grating_lIds = new uint[(2 * gratingCnt)];
                    for (int i = 0; i < (2 * gratingCnt); i++)
                    {
                        uint work_vId1 = work_vIds_list[0][i];
                        uint work_vId2 = work_vIds_list[1][i];
                        CBRepSurface.CResConnectVertex res =cad2d.ConnectVertex_Line(work_vId1, work_vId2);
                        grating_eIds[i] = res.id_e_add;
                        grating_lIds[i] = res.id_l_add;
                    }
                    /*
                    // 分割数調整
                    for (int i = 0; i < (2 * gratingCnt); i++)
                    {
                        double workY = (coreY1 + coreY2) * 0.5;
                        double workX = grating_X1 + gratingOneLength * i;
                        uint parent_eId = grating_eIds[i];
                        uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY)).id_v_add;
                        System.Diagnostics.Debug.Assert(vId != 0);
                    }
                    for (int i = 0; i < (2 * gratingCnt - 1); i++)
                    {
                        double workY = (coreY1 + coreY2) * 0.5;
                        double workX = grating_X1 + gratingOneLength * i + gratingOneLength * 0.5;
                        uint parent_lId = grating_lIds[i];
                        uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_lId, new CVector2D(workX, workY)).id_v_add;
                        System.Diagnostics.Debug.Assert(vId != 0);
                    }
                     */
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // 誘電体スラブ導波路に色を付ける
                    {
                        uint[] work_lId_list = slab_loopId_cad_list;
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 1.0, 0.0, 1.0 });
                        }
                    }
                    {
                        uint[] work_lId_list = grating_loopId_cad_list;
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 0.0, 0.0, 1.0 });
                        }
                    }
                    // 境界の辺に色を付ける
                    {
                        uint[] work_eId_list = port1_eId_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.8, 0.0, 0.0 });
                        }
                    }
                    {
                        uint[] work_eId_list = port2_eId_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 0.0 });
                        }
                    }
                    // 境界の誘電体スラブの辺
                    cad2d.SetColor_Edge(port1_core_eId, new double[] { 1.0, 0.0, 0.0 });
                    cad2d.SetColor_Edge(port2_core_eId, new double[] { 1.0, 0.0, 0.0 });

                    // DEBUG
                    // 右側領域誘電体スラブ上下の辺
                    cad2d.SetColor_Edge(9, new double[] { 0.0, 0.0, 1.0 });
                    cad2d.SetColor_Edge(10, new double[] { 0.0, 0.0, 1.0 });

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list  = all_loopId_cad_list;
                int[] mediaIndex_list = new int[loopId_cad_list.Length];
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (slab_loopId_cad_list.Contains(loopId_cad_list[i]))
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    else if (grating_loopId_cad_list.Contains(loopId_cad_list[i]))
                    {
                        mediaIndex = Medias.IndexOf(mediaGrating);
                    }
                    mediaIndex_list[i] = mediaIndex;
                }

                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    uint loopId_cad = loopId_cad_list[i];
                    int mediaIndex = mediaIndex_list[i];
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, mediaIndex);
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = {2, 4};
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId1 = 0;
            FieldPortBcId2 = 0;
            uint[][] eId_cad_port_list = { port1_eId_list, port2_eId_list };
            uint[] core_eId_cad_list = { port1_core_eId, port2_core_eId };
            for (int portIndex = 0; portIndex < (portCnt); portIndex++) // ポート + 励振境界
            {
                uint[] eId_cad_port = eId_cad_port_list[portIndex];
                uint core_eId = core_eId_cad_list[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < eId_cad_port.Length; i++)
                {
                    uint eId_cad = eId_cad_port[i];
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (eId_cad == core_eId)
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex = Medias.IndexOf(mediaVacumn);
                    }
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                    {
                        wg2d.World.Edge edge = new wg2d.World.Edge();
                        edge.Set(eId, mediaIndex);
                        EdgeDic.Add(eId, edge);
                    }
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                if (portIndex == 0)
                {
                    FieldPortBcId1 = workFieldPortBcId;
                }
                else if (portIndex == 1)
                {
                    FieldPortBcId2 = workFieldPortBcId;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
            }

            return true;
        }
Exemplo n.º 9
0
        /// <summary>
        /// 誘電体スラブ導波路グレーティング
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="timeLoopCnt"></param>
        /// <param name="timeDelta"></param>
        /// <param name="gaussianT0"></param>
        /// <param name="gaussianTp"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcIdList"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            ref double WaveguideWidth,
            ref int timeLoopCnt,
            ref double timeDelta,
            ref double gaussianT0,
            ref double gaussianTp,
            ref double NormalizedFreqSrc,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double GraphFreqInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPortBcIdList,
            ref IList<uint> VIdRefList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            WaveguideWidth = 3.0e-3 * 30 * 4;

            // メッシュの分割長さ
            //double meshL = WaveguideWidth * 1.0 / 60.0;
            double meshL = WaveguideWidth * 1.0 / 65.0;
            double meshLForTimeDelta = meshL;

            // 導波管不連続領域の長さ
            double disconLength = 65.0 / 60.0 * WaveguideWidth;

            // 誘電体スラブ導波路幅
            double slabWidth =WaveguideWidth / 30.0;
            // 誘電体スラブ比誘電率
            double coreEps = 2.402500;
            // グレーティング比誘電率
            double gratingEps = 2.102500;
            // グレーティングの数
            int gratingCnt = 8;  // 偶数とする
            // グレーティング1つの長さ
            double gratingOneLength = slabWidth;
            // グレーティングの全長
            double gratingAllLength = gratingOneLength * ((gratingCnt - 1) * 2 + 1);
            // グレーティング開始位置
            double grating_X1 = 25.0 / 60.0 * WaveguideWidth;
            double grating_X2 = grating_X1 + gratingAllLength;

            // 形状設定で使用する単位長さ
            double unitLen = WaveguideWidth / 60.0;
            // 励振位置
            //double srcPosX = 10 * unitLen;
            double srcPosX = 9 * unitLen;
            // 観測点
            int port1OfsX = 5;
            int port2OfsX = 5;
            double port1PosX = srcPosX + port1OfsX * unitLen;
            double port1PosY = WaveguideWidth * 0.5;
            double port2PosX = disconLength - port2OfsX * unitLen;
            double port2PosY = WaveguideWidth * 0.5;
            System.Diagnostics.Debug.Assert(grating_X1 >= (port1PosX+  5.0 / 60.0 * WaveguideWidth));
            System.Diagnostics.Debug.Assert((grating_X2 + 4.0 / 60.0 * WaveguideWidth) <= port2PosX);

            // 時間領域
            //double courantNumber = 0.5;
            double courantNumber = 0.5;
            //timeLoopCnt = 3000;
            //timeLoopCnt = 1500;
            timeLoopCnt = 1000;

            // 時刻刻み
            //timeDelta = courantNumber * meshL / (c0 * Math.Sqrt(2.0));
            timeDelta = courantNumber * meshLForTimeDelta / (c0 * Math.Sqrt(2.0));

            // モード計算規格化周波数(搬送波規格化周波数)
            NormalizedFreqSrc = 12.0;

            /*
            // ガウシアンパルス
            gaussianT0 = 30 * timeDelta;
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0) * 4.0);
             */

            // 正弦波変調ガウシアンパルス
            // 波数
            double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
            // 波長
            double waveLengthSrc = 2.0 * pi / k0Src;
            // 周波数
            double freqSrc = c0 / waveLengthSrc;
            // 角周波数
            double omegaSrc = 2.0 * pi * freqSrc;
            // 搬送波の振動回数
            int nCycle = 5;
            //gaussianT0 = (1.0 / freqSrc) * nCycle / 2;
            //gaussianT0 = 0.5 * (1.0 / freqSrc) * nCycle / 2;
            gaussianT0 = 0.48 * (1.0 / freqSrc) * nCycle / 2;
            gaussianTp = gaussianT0 / (2.0 * Math.Sqrt(2.0 * Math.Log(2.0)));

            // 周波数領域
            NormalizedFreq1 = 10.0;
            NormalizedFreq2 = 20.0;
            GraphFreqInterval = 2.0;

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            MediaInfo mediaVacumn = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 1.0, 0.0, 0.0 },
                   { 0.0, 1.0, 0.0 },
                   { 0.0, 0.0, 1.0 }
                }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { coreEps,  0.0,  0.0 },
                   {  0.0, coreEps,  0.0 },
                   {  0.0,  0.0, coreEps }
                }
            );
            MediaInfo mediaGrating = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { gratingEps,  0.0,  0.0 },
                   {  0.0, gratingEps,  0.0 },
                   {  0.0,  0.0, gratingEps }
                }
            );
            Medias.Add(mediaVacumn);
            Medias.Add(mediaCore);
            Medias.Add(mediaGrating);

            // 図面作成、メッシュ生成
            double coreY1 = (WaveguideWidth - slabWidth) * 0.5;
            double coreY2 = coreY1 + slabWidth;
            int loopCnt_cad = 6 + (2 * (gratingCnt - 1) + 1) + 1;
            uint[] slab_loopId_cad_list = new uint[2 + (gratingCnt - 1) + 1];
            slab_loopId_cad_list[0] = 4;
            slab_loopId_cad_list[1] = 6;
            for (int i = 0; i < gratingCnt; i++)
            {
                slab_loopId_cad_list[2 + i] = (uint)(8 + i * 2);
            }
            uint[] grating_loopId_cad_list = new uint[gratingCnt];
            for (int i = 0; i < gratingCnt; i++)
            {
                grating_loopId_cad_list[i] = (uint)(7 + i * 2);
            }

            uint[] port1_eId_list = { 1, 9, 8 };
            uint port1_core_eId = 9;
            uint[] port2_eId_list = { 4, 11, 10 };
            uint port2_core_eId = 11;
            uint[] portSrc_eId_list = { 7, 13, 12 };
            uint portSrc_core_eId = 13;
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    // ループ1
                    IList<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(srcPosX, 0.0)); // 頂点3
                    pts.Add(new CVector2D(disconLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(disconLength, WaveguideWidth)); // 頂点5
                    pts.Add(new CVector2D(srcPosX, WaveguideWidth)); // 頂点6
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                    uint lId2 = cad2d.ConnectVertex_Line(3, 6).id_l_add;
                    System.Diagnostics.Debug.Assert(lId1 == 1);
                    System.Diagnostics.Debug.Assert(lId2 == 2);
                }
                {
                    uint parent_id_l_cad = 2;
                    // 観測点
                    cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port1PosX, port1PosY)); // 頂点7
                    cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port2PosX, port2PosY)); // 頂点8
                }

                // スラブ導波路と境界の交点
                uint[] parent_eId_list = {1, 4, 7};
                double[] portX_list = {0.0, disconLength, srcPosX};
                IList<uint[]> slab_vIds_list = new List<uint[]>();
                for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++)
                {
                    uint parent_eId = parent_eId_list[portIndex];
                    double portX = portX_list[portIndex];

                    double workY1 = 0.0;
                    double workY2 = 0.0;
                    if (portIndex == 0)
                    {
                        workY1 = coreY1;
                        workY2 = coreY2;
                    }
                    else
                    {
                        workY1 = coreY2;
                        workY2 = coreY1;
                    }
                    uint vId1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY1)).id_v_add;
                    uint vId2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY2)).id_v_add;
                    uint[] work_vIds = new uint[2];
                    if (portIndex == 0)
                    {
                        work_vIds[0] = vId1;
                        work_vIds[1] = vId2;
                    }
                    else
                    {
                        work_vIds[0] = vId2;
                        work_vIds[1] = vId1;
                    }
                    slab_vIds_list.Add(work_vIds);
                }
                // スラブ導波路
                {
                    // 励振面の左側領域
                    {
                        uint work_vId1 = slab_vIds_list[0][0];
                        uint work_vId2 = slab_vIds_list[2][0];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                    {
                        uint work_vId1 = slab_vIds_list[0][1];
                        uint work_vId2 = slab_vIds_list[2][1];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                    // 励振面の右側領域
                    {
                        uint work_vId1 = slab_vIds_list[2][0];
                        uint work_vId2 = slab_vIds_list[1][0];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                    {
                        uint work_vId1 = slab_vIds_list[2][1];
                        uint work_vId2 = slab_vIds_list[1][1];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                }
                // グレーティング
                {
                    // 励振面右側の誘電体スラブの上下の辺
                    uint[] slabTopBottom_eIds = {16, 17};
                    double[] work_Ys = {coreY1, coreY2};
                    uint[][] work_vIds_list = new uint[2][];
                    // 上下の辺に頂点を追加
                    for (int edgeIndex = 0; edgeIndex < 2; edgeIndex++) // スラブの上下の辺
                    {
                        uint parent_eId = slabTopBottom_eIds[edgeIndex];
                        double workY = work_Ys[edgeIndex];
                        work_vIds_list[edgeIndex] = new uint[2 * gratingCnt];
                        for (int i = (2 * gratingCnt) - 1; i >= 0; i--)
                        {
                            double workX = grating_X1 + gratingOneLength * i;
                            uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY)).id_v_add;
                            work_vIds_list[edgeIndex][i] = vId;
                        }
                    }
                    // 上下の頂点を結ぶ
                    uint[] grating_eIds = new uint[(2 * gratingCnt)];
                    uint[] grating_lIds = new uint[(2 * gratingCnt)];
                    for (int i = 0; i < (2 * gratingCnt); i++)
                    {
                        uint work_vId1 = work_vIds_list[0][i];
                        uint work_vId2 = work_vIds_list[1][i];
                        CBRepSurface.CResConnectVertex res =cad2d.ConnectVertex_Line(work_vId1, work_vId2);
                        grating_eIds[i] = res.id_e_add;
                        grating_lIds[i] = res.id_l_add;
                    }
                    /*
                    // 分割数調整
                    for (int i = 0; i < (2 * gratingCnt); i++)
                    {
                        double workY = (coreY1 + coreY2) * 0.5;
                        double workX = grating_X1 + gratingOneLength * i;
                        uint parent_eId = grating_eIds[i];
                        uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY)).id_v_add;
                        System.Diagnostics.Debug.Assert(vId != 0);
                    }
                    for (int i = 0; i < (2 * gratingCnt - 1); i++)
                    {
                        double workY = (coreY1 + coreY2) * 0.5;
                        double workX = grating_X1 + gratingOneLength * i + gratingOneLength * 0.5;
                        uint parent_lId = grating_lIds[i];
                        uint vId = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_lId, new CVector2D(workX, workY)).id_v_add;
                        System.Diagnostics.Debug.Assert(vId != 0);
                    }
                     */
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // 誘電体スラブ導波路に色を付ける
                    {
                        uint[] work_lId_list = slab_loopId_cad_list;
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 1.0, 0.0, 1.0 });
                        }
                    }
                    {
                        uint[] work_lId_list = grating_loopId_cad_list;
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 0.0, 0.0, 1.0 });
                        }
                    }
                    // 境界の辺に色を付ける
                    {
                        uint[] work_eId_list = port1_eId_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.8, 0.0, 0.0 });
                        }
                    }
                    {
                        uint[] work_eId_list = port2_eId_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 0.0 });
                        }
                    }
                    {
                        uint[] work_eId_list = portSrc_eId_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.0, 1.0, 0.0 });
                        }
                    }
                    // 境界の誘電体スラブの辺
                    cad2d.SetColor_Edge(port1_core_eId, new double[] { 1.0, 0.0, 0.0 });
                    cad2d.SetColor_Edge(port2_core_eId, new double[] { 1.0, 0.0, 0.0 });
                    cad2d.SetColor_Edge(portSrc_core_eId, new double[] { 1.0, 0.0, 0.0 });

                    // DEBUG
                    // 右側領域誘電体スラブ上下の辺
                    cad2d.SetColor_Edge(16, new double[] { 0.0, 0.0, 1.0 });
                    cad2d.SetColor_Edge(17, new double[] { 0.0, 0.0, 1.0 });

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list  = new uint[loopCnt_cad];
                for (int i = 0; i < loopCnt_cad; i++)
                {
                    loopId_cad_list[i] = (uint)(i + 1);
                }
                int[] mediaIndex_list = new int[loopId_cad_list.Length];
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (slab_loopId_cad_list.Contains(loopId_cad_list[i]))
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    else if (grating_loopId_cad_list.Contains(loopId_cad_list[i]))
                    {
                        mediaIndex = Medias.IndexOf(mediaGrating);
                    }
                    mediaIndex_list[i] = mediaIndex;
                }

                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    uint loopId_cad = loopId_cad_list[i];
                    int mediaIndex = mediaIndex_list[i];
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, mediaIndex);
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = {2, 3, 5, 6};
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcIdList.Clear();
            uint[][] eId_cad_port_list = { port1_eId_list, port2_eId_list, portSrc_eId_list };
            uint[] core_eId_cad_list = { port1_core_eId, port2_core_eId, portSrc_core_eId };
            for (int portIndex = 0; portIndex < (portCnt + 1); portIndex++) // ポート + 励振境界
            {
                uint[] eId_cad_port = eId_cad_port_list[portIndex];
                uint core_eId = core_eId_cad_list[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < eId_cad_port.Length; i++)
                {
                    uint eId_cad = eId_cad_port[i];
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (eId_cad == core_eId)
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex = Medias.IndexOf(mediaVacumn);
                    }
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                    {
                        wg2d.World.Edge edge = new wg2d.World.Edge();
                        edge.Set(eId, mediaIndex);
                        EdgeDic.Add(eId, edge);
                    }
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                FieldPortBcIdList.Add(workFieldPortBcId);
            }

            // 観測点
            VIdRefList.Clear();
            uint[] vId_cad_refPort = { 7, 8 };
            foreach (uint vId_cad in vId_cad_refPort)
            {
                uint vId = conv.GetIdEA_fromCad(vId_cad, CAD_ELEM_TYPE.VERTEX);
                VIdRefList.Add(vId);
            }

            return true;
        }
Exemplo n.º 10
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <returns></returns>
        private bool setNewProblem()
        {
            bool success = false;
            try
            {
                if( ProbNo == 0 )
                {
                    CMesher2D mesh2d = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.2) );
                        pts.Add( new CVector2D(0.5,0.2) );
                        pts.Add( new CVector2D(0.5,0.8) );
                        pts.Add( new CVector2D(1.0,0.8) );
                        pts.Add( new CVector2D(1.0,1.0) );
                        pts.Add( new CVector2D(0.0,1.0) );
                        cad2d.AddPolygon( pts );
                        cad2d.ConnectVertex_Line(6,3);
                        mesh2d = new CMesher2D(cad2d,0.05);
                        ////
                        using(CMesher2D msh_tmp = (CMesher2D)mesh2d.Clone())
                        {
                            mesh2d.Clear();
                            mesh2d.Dispose();
                            mesh2d = (CMesher2D)msh_tmp.Clone();
                        }
                    }
                    using(CSerializer fout = new CSerializer("hoge.txt", false))
                    {
                        // write file
                        mesh2d.Serialize(fout);
                    }
                    using(CSerializer fin = new CSerializer("hoge.txt", true))
                    {    // load file
                        mesh2d.Serialize(fin);
                    }
                    ////
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                    DrawerAry.InitTrans( Camera );
                    mesh2d.Clear();
                    mesh2d.Dispose();
                }
                else if( ProbNo == 1 )
                {
                    string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D mesh2d = new CMesher2D())
                        {
                            mesh2d.ReadFromFile_GiDMsh(mshfn);
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh2d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh2d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 2 )
                {
                    string mshfn = "../../../input_file/rect_quad.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D mesh2d = new CMesher2D())
                        {
                            mesh2d.ReadFromFile_GiDMsh(mshfn);
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh2d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh2d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 3 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.5) );
                        pts.Add( new CVector2D(0.5,0.5) );
                        pts.Add( new CVector2D(0.5,1.0) );
                        pts.Add( new CVector2D(0.0,1.0) );
                        cad2d.AddPolygon( pts );
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.1))
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            mesh3d.Extrude(mesh2d, 0.5, 0.1 );
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh3d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh3d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 4 )    // load mesh of GiD
                {
                    string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D mesh2d = new CMesher2D())
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            mesh2d.ReadFromFile_GiDMsh(mshfn);
                            mesh3d.Extrude(mesh2d, 5.0, 0.5 );
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 5 )
                {
                    string mshfn = "../../../input_file/cylinder_hex.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher3D mesh3d = new CMesher3D())
                        {
                            mesh3d.ReadFromFile_GiDMsh(mshfn);
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh3d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh3d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 6 )
                {
                    string mshfn = "../../../input_file/cylinder_tet.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher3D mesh3d = new CMesher3D())
                        {
                            mesh3d.ReadFromFile_GiDMsh(mshfn);
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh3d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh3d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 7 )
                {
                    string mshfn = "../../../input_file/rect_quad.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D mesh2d = new CMesher2D())
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            mesh2d.ReadFromFile_GiDMsh(mshfn);
                            mesh3d.Extrude(mesh2d, 5.0, 0.5 );
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh3D(mesh3d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 8 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        uint id_l = 0;
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            id_l = cad2d.AddPolygon( pts ).id_l_add;
                        }

                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.8,0.6) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.6,0.6) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.4,0.6) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.2,0.6) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.8,0.4) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.6,0.4) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.4,0.4) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.2,0.4) );
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.02))
                        {
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh2d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh2d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 9 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            cad2d.AddPolygon( pts );
                        }
                        cad2d.SetCurve_Arc(1,true, -0.5);
                        cad2d.SetCurve_Arc(2,false,-0.5);
                        cad2d.SetCurve_Arc(3,true, -0.5);
                        cad2d.SetCurve_Arc(4,false,-0.5);

                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.05))
                        {
                            using(CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                // write file
                                mesh2d.Serialize(fout);
                            }
                            using(CSerializer fin = new CSerializer("hoge.txt", true))
                            {    // load file
                                mesh2d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 10 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            uint id_l = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.2)).id_v_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.2)).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.8)).id_v_add;
                            uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.8)).id_v_add;
                            cad2d.ConnectVertex_Line(id_v1,id_v2);
                            cad2d.ConnectVertex_Line(id_v2,id_v3);
                            cad2d.ConnectVertex_Line(id_v3,id_v4);
                            cad2d.ConnectVertex_Line(id_v4,id_v1);
                        }

                        using(CMesher2D mesh2d = new CMesher2D())
                        {
                            mesh2d.AddIdLCad_CutMesh(1);    // cut mesh to loop whitch have id 1
                            mesh2d.SetMeshingMode_ElemLength(0.05);
                            mesh2d.Meshing(cad2d);

                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 11 )    // mesh with cut
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        uint id_l;
                        uint id_e1, id_e2, id_e3, id_e4, id_e5;
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(0.3,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            id_l = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.3,0.5) ).id_v_add;
                            id_e1 = cad2d.ConnectVertex_Line(2,id_v1).id_e_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.5) ).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.2) ).id_v_add;
                            uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.7,0.8) ).id_v_add;
                            uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5,0.5) ).id_v_add;
                            uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.9,0.5) ).id_v_add;
                            id_e2 = cad2d.ConnectVertex_Line(id_v2,id_v3).id_e_add;
                            id_e3 = cad2d.ConnectVertex_Line(id_v2,id_v4).id_e_add;
                            id_e4 = cad2d.ConnectVertex_Line(id_v2,id_v5).id_e_add;
                            id_e5 = cad2d.ConnectVertex_Line(id_v2,id_v6).id_e_add;
                        }
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.2))
                        {
                            IList<uint> aIdMsh_Inc = new List<uint>();
                            aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l,CAD_ELEM_TYPE.LOOP) );

                            IList<uint> aIdMshBar_Cut = new List<uint>();
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e1,CAD_ELEM_TYPE.EDGE) );
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e2,CAD_ELEM_TYPE.EDGE) );
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e3,CAD_ELEM_TYPE.EDGE) );
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e4,CAD_ELEM_TYPE.EDGE) );
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e5,CAD_ELEM_TYPE.EDGE) );
                            ////////////////
                            IList< IList<int> > aLnods = new List<IList<int>>();
                            IList<uint> mapVal2Co = new List<uint>();
                            mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc, aIdMshBar_Cut);

                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 12 )    // mesh with cut
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        uint id_l1, id_l2;
                        uint id_e3, id_e4;
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0, 0.0) );
                            pts.Add( new CVector2D(1.0, 0.0) );
                            pts.Add( new CVector2D(1.5, 0.0) );
                            pts.Add( new CVector2D(2.0, 0.0) );
                            pts.Add( new CVector2D(2.0, 1.0) );
                            pts.Add( new CVector2D(1.5, 1.0) );
                            pts.Add( new CVector2D(1.0, 1.0) );
                            pts.Add( new CVector2D(0.0, 1.0) );
                            uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l0, new CVector2D(0.5,0.5) ).id_v_add;
                            uint id_e1 = cad2d.ConnectVertex_Line(2,7).id_e_add;
                            uint id_e2 = cad2d.ConnectVertex_Line(3,6).id_e_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,id_e1, new CVector2D(1.0,0.5) ).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(0.5,0.0) ).id_v_add;
                            id_e3 = cad2d.ConnectVertex_Line(id_v1,id_v2).id_e_add;
                            id_e4 = cad2d.ConnectVertex_Line(id_v1,id_v3).id_e_add;
                            id_l1 = 1;
                            id_l2 = 2;
                        }
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.2))
                        {
                            IList<uint> aIdMsh_Inc = new List<uint>();
                            aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l1,CAD_ELEM_TYPE.LOOP) );
                            aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l2,CAD_ELEM_TYPE.LOOP) );

                            IList<uint> aIdMshBar_Cut = new List<uint>();
                            //aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e3,CAD_ELEM_TYPE.EDGE) );
                            aIdMshBar_Cut.Add( mesh2d.GetElemID_FromCadID(id_e4,CAD_ELEM_TYPE.EDGE) );
                            ////////////////
                            IList< IList<int> > aLnods = new List<IList<int>>();
                            IList<uint> mapVal2Co = new List<uint>();
                            mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc, aIdMshBar_Cut);

                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 13 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0, 0.0) );    // 1
                            pts.Add( new CVector2D(1.5, 0.0) );    // 2
                            pts.Add( new CVector2D(1.5, 0.4) );    // 3
                            pts.Add( new CVector2D(1.0, 0.4) );    // 4
                            pts.Add( new CVector2D(1.0, 0.5) );    // 5
                            pts.Add( new CVector2D(2.0, 0.5) );    // 6
                            pts.Add( new CVector2D(2.0, 1.0) );    // 7
                            pts.Add( new CVector2D(0.0, 1.0) );    // 8
                            pts.Add( new CVector2D(0.0, 0.5) );    // 9
                            uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_e1 = cad2d.ConnectVertex_Line(5,9).id_e_add;
                            cad2d.ShiftLayer_Loop(id_l0,true);
                            double[] col = new double[3] { 0.9, 0.4, 0.4 };
                            cad2d.SetColor_Loop(id_l0, col);
                            cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(1.3,0.5));
                        }
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.05))
                        {
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerMsh2D(mesh2d) );
                            DrawerAry.InitTrans( Camera );
                        }
                    }
                }
                else if( ProbNo == 14 )
                {
                    string svgfn = "../../../input_file/shape2d_0.svg";
                    if (File.Exists(svgfn))
                    {
                        CCadObj2D cad2d = null;
                        CCadSVG.ReadSVG_AddLoopCad(svgfn, out cad2d);
                        using (CMesher2D mesh2d = new CMesher2D())
                        {
                            mesh2d.SetMeshingMode_ElemSize(400);
                            mesh2d.AddIdLCad_CutMesh(1);
                            mesh2d.Meshing(cad2d);

                            DrawerAry.Clear();
                            DrawerAry.PushBack(new CDrawerMsh2D(mesh2d));
                            DrawerAry.InitTrans(Camera);
                        }
                        cad2d.Clear();
                        cad2d.Dispose();
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", svgfn);
                        MessageBox.Show(string.Format("SVGファイル:{0}がありません", svgfn));
                    }
                }
                success = true;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            DrawerGlUtility.SetProjectionTransform(Camera);
            Glut.glutPostRedisplay();
            ProbNo++;
            if (ProbNo == ProbCnt) ProbNo = 0;
            return success;
        }
Exemplo n.º 11
0
        /// <summary>
        /// フォトニック結晶導波路 直線
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="timeLoopCnt"></param>
        /// <param name="timeDelta"></param>
        /// <param name="gaussianT0"></param>
        /// <param name="gaussianTp"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPmlLoopIdList"></param>
        /// <param name="PmlStPosXList"></param>
        /// <param name="FieldPortSrcBcId"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            ref double WaveguideWidth,
            ref bool isPCWaveguide,
            ref double latticeA,
            ref int timeLoopCnt,
            ref double timeDelta,
            ref double gaussianT0,
            ref double gaussianTp,
            ref double NormalizedFreqSrc,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double GraphFreqInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPmlLoopIdList,
            ref IList<bool> IsPmlYDirectionList,
            ref IList<double> PmlStPosXList,
            ref IList<double> PmlLengthList,
            ref uint FieldPortSrcBcId,
            ref IList<uint> VIdRefList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            WaveguideWidth = 1.0e-3 * 240;
            isPCWaveguide = true;
            latticeA = 0.0;

            // フォトニック結晶導波路 直線
            // メッシュの分割長さ
            //double meshL = WaveguideWidth * 0.05;
            double meshL = WaveguideWidth * 0.02;
            //double meshL = WaveguideWidth * 0.03;

            /////////////////////////////////////////////
            // フォトニック導波路
            // ロッドの数(半分)
            const int rodCntHalf = 5;
            //const int rodCntHalf = 3;
            // 欠陥ロッド数
            const int defectRodCnt = 1;
            // 格子数
            const int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // 格子定数
            latticeA = WaveguideWidth / (double)latticeCnt;
            // 周期構造距離
            double periodicDistance = latticeA;
            // ロッドの半径
            double rodRadius = 0.18 * latticeA;
            // ロッドの比誘電率
            double rodEps = 3.4 * 3.4;
            // ロッドの円周分割数
            const int rodCircleDiv = 8;
            // ロッドの半径の分割数
            const int rodRadiusDiv = 1;
            /////////////////////////////////////////////

            // PMLの長さ
            //double pmlLength = 5 * periodicDistance;
            //double pmlLength = 10 * periodicDistance;
            double pmlLength = 6 * periodicDistance;
            // 導波管不連続領域の長さ
            double disconLength = 10 * periodicDistance;
            disconLength += 2.0 * pmlLength;

            // 励振位置
            //double srcPosX = pmlLength + 4.5 * periodicDistance;
            double srcPosX = pmlLength + 1.5 * periodicDistance;
            // 観測点
            double port1PosX = srcPosX + 1.5 * periodicDistance;
            double port1PosY = WaveguideWidth * 0.5;
            double port2PosX = disconLength - pmlLength - 1.0 * periodicDistance;
            double port2PosY = WaveguideWidth * 0.5;

            // 時間領域
            //double courantNumber = 0.5;
            double courantNumber = 0.5;
            //timeLoopCnt = 100000;
            timeLoopCnt = 3000;
            // 時刻刻み
            timeDelta = courantNumber * (WaveguideWidth * 0.02) / (c0 * Math.Sqrt(2.0));

            // モード計算規格化周波数(搬送波規格化周波数)
            // フォトニック結晶導波路の場合、a/λを規格化周波数とする
            //NormalizedFreqSrc = 0.400;
            NormalizedFreqSrc = 0.400;
            NormalizedFreqSrc *= (2.0 * WaveguideWidth) / latticeA;
            Console.WriteLine("NormalizedFreqSrc: {0}", NormalizedFreqSrc);

            // 周波数領域
            NormalizedFreq1 = 0.300;//0.302;
            NormalizedFreq2 = 0.440;//0.443;
            GraphFreqInterval = 0.02;
            NormalizedFreq1 *= (2.0 * WaveguideWidth) / latticeA;
            NormalizedFreq2 *= (2.0 * WaveguideWidth) / latticeA;
            GraphFreqInterval *= (2.0 * WaveguideWidth) / latticeA;

            /*
            // ガウシアンパルス
            //gaussianT0 = 30 * timeDelta;
            //gaussianT0 = 40 * timeDelta;
            gaussianT0 = 20 * timeDelta;
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0) * 4.0);
             */

            // 正弦波変調ガウシアンパルス
            // 波数
            double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
            // 波長
            double waveLengthSrc = 2.0 * pi / k0Src;
            // 周波数
            double freqSrc = c0 / waveLengthSrc;
            // 角周波数
            double omegaSrc = 2.0 * pi * freqSrc;
            // 搬送波のバンド幅
            double k0BandWidthSrc = (NormalizedFreq2 - NormalizedFreq1) *pi / WaveguideWidth; ;
            double waveLengthBandWidthSrc = 2.0 * pi / k0BandWidthSrc;
            double freqBandWidthSrc = c0 / waveLengthBandWidthSrc;
            gaussianT0 = (1.0 / freqBandWidthSrc);
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0));

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;

            // 媒質リスト作成
            {
                // TEモード
                claddingP = 1.0;
                claddingQ = 1.0;
                coreP = 1.0;
                coreQ = rodEps;
            }
            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // 全ループ数
            uint loopCnt_cad = 2 + portCnt;
            // ポート1のPML領域ループリスト
            uint[] port1_pml_loopIds_cad = { 1 };
            // ポート2のPML領域ループリスト
            uint[] port2_pml_loopIds_cad = { 4 };
            // PML開始位置X座標
            double[] pmlStPosX_list = { pmlLength, (disconLength - pmlLength) };
            // 観測点頂点ID
            uint[] portRef_vIds_cad = new uint[portCnt];
            // 励振面の辺ID
            uint[] eId_cad_src_list = new uint[1 + 3 * (2 * rodCntHalf)];
            uint[] core_eId_cad_src_list = new uint[2 * (2 * rodCntHalf)];
            eId_cad_src_list[0] = 12;
            for (int i = 0; i < 3 * (2 * rodCntHalf); i++)
            {
                eId_cad_src_list[1 + i] = (uint)(14 + (3 * (2 * rodCntHalf) - 1) - i);
            }
            for (int i = 0; i < (2 * rodCntHalf); i++)
            {
                uint eId1 = eId_cad_src_list[1 + i * 3];
                uint eId2 = eId_cad_src_list[1 + i * 3 + 1];
                uint eId3 = eId_cad_src_list[1 + i * 3 + 2];
                core_eId_cad_src_list[i * 2] = eId1;
                core_eId_cad_src_list[i * 2 + 1] = eId2;
            }
            // ロッドのループIDリスト
            IList<uint> rodLoopIds = new List<uint>();
            // ロッドのループIDリスト(PML領域)
            IList<uint> rodLoopIds_port1_pml = new List<uint>();
            IList<uint> rodLoopIds_port2_pml = new List<uint>();
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                IList<CVector2D> pts = new List<CVector2D>();
                pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                pts.Add(new CVector2D(pmlLength, 0.0)); // 頂点3
                pts.Add(new CVector2D(srcPosX, 0.0)); // 頂点4
                pts.Add(new CVector2D(disconLength - pmlLength, 0.0)); // 頂点5
                pts.Add(new CVector2D(disconLength, 0.0)); // 頂点6
                pts.Add(new CVector2D(disconLength, WaveguideWidth)); // 頂点7
                pts.Add(new CVector2D(disconLength - pmlLength, WaveguideWidth)); // 頂点8
                pts.Add(new CVector2D(srcPosX, WaveguideWidth)); // 頂点9
                pts.Add(new CVector2D(pmlLength, WaveguideWidth)); // 頂点10
                uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                uint lId2 = cad2d.ConnectVertex_Line(3, 10).id_l_add;
                uint lId3 = cad2d.ConnectVertex_Line(4, 9).id_l_add;
                uint lId4 = cad2d.ConnectVertex_Line(5, 8).id_l_add;
                // 観測点
                portRef_vIds_cad[0] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, lId3, new CVector2D(port1PosX, port1PosY)).id_v_add; // 頂点11
                portRef_vIds_cad[1] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, lId3, new CVector2D(port2PosX, port2PosY)).id_v_add; // 頂点12
                // check
                foreach (uint vId in portRef_vIds_cad)
                {
                    System.Diagnostics.Debug.Assert(vId != 0);
                }

                {
                    double workX = srcPosX;
                    IList<uint> work_vIds = new List<uint>();
                    IList<uint> work_vIds_center = new List<uint>();
                    for (int row = (rodCntHalf * 2 + defectRodCnt - 1); row >= 0; row--)
                    {
                        if (row >= (rodCntHalf) && row < (rodCntHalf + defectRodCnt))
                        {
                            // 欠陥部
                            continue;
                        }

                        uint parent_eId = eId_cad_src_list[0]; // 先頭の辺のID
                        double workY1 = row * latticeA + 0.5 * latticeA + rodRadius;
                        double workY2 = row * latticeA + 0.5 * latticeA - rodRadius;
                        uint vId1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY1)).id_v_add;
                        uint vId_center = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, (workY1 + workY2) * 0.5)).id_v_add;
                        uint vId2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(workX, workY2)).id_v_add;
                        System.Diagnostics.Debug.Assert(vId1 != 0);
                        System.Diagnostics.Debug.Assert(vId2 != 0);

                        work_vIds.Add(vId1);
                        work_vIds_center.Add(vId_center);
                        work_vIds.Add(vId2);
                    }
                    uint[] work_vIdAry = work_vIds.ToArray();
                    uint[] work_vIdAry_center = work_vIds_center.ToArray();
                    // 境界の右側半円
                    for (int row = (rodCntHalf * 2 + defectRodCnt - 1), vIndex = 0; row >= 0; row--)
                    {
                        if (row >= (rodCntHalf) && row < (rodCntHalf + defectRodCnt))
                        {
                            // 欠陥部
                            continue;
                        }
                        uint parent_lId = 3;
                        double workY1 = row * latticeA + 0.5 * latticeA - rodRadius * 0.5;
                        double workY2 = row * latticeA + 0.5 * latticeA + rodRadius * 0.5;
                        uint vId1 = work_vIdAry[vIndex * 2 + 1];
                        uint vId2 = work_vIdAry[vIndex * 2];
                        uint vId_center = work_vIds_center[vIndex];
                        uint lId = WgCadUtil.AddLeftRod(cad2d, parent_lId, vId1, vId_center, vId2, workX, (workY1 + workY2) * 0.5, rodRadius, rodCircleDiv, 1);
                        rodLoopIds.Add(lId);
                        vIndex++;
                    }
                    // 境界の左側半円
                    for (int row = (rodCntHalf * 2 + defectRodCnt - 1), vIndex = 0; row >= 0; row--)
                    {
                        if (row >= (rodCntHalf) && row < (rodCntHalf + defectRodCnt))
                        {
                            // 欠陥部
                            continue;
                        }
                        uint parent_lId = 2;
                        double workY1 = row * latticeA + 0.5 * latticeA - rodRadius * 0.5;
                        double workY2 = row * latticeA + 0.5 * latticeA + rodRadius * 0.5;
                        uint vId1 = work_vIdAry[vIndex * 2];
                        uint vId2 = work_vIdAry[vIndex * 2 + 1];
                        uint vId_center = work_vIds_center[vIndex];
                        uint lId = WgCadUtil.AddRightRod(cad2d, parent_lId, vId1, vId_center, vId2, workX, (workY1 + workY2) * 0.5, rodRadius, rodCircleDiv, 1);
                        rodLoopIds.Add(lId);
                        vIndex++;
                    }
                }

                //////////////////////////////////////////////////////////
                // ロッド追加
                int colCntX = (int)Math.Round(disconLength / periodicDistance);
                for (int col = 0; col < colCntX; col++)
                {
                    uint baseLoopId = 0;
                    double x1 = col * periodicDistance;
                    double x2 = (col + 1) * periodicDistance;
                    if (x1 < srcPosX && x2 > srcPosX)
                    {
                        continue;
                    }

                    for (int row = 0; row < (rodCntHalf * 2 + defectRodCnt); row++)
                    {
                        int pmlWgNo = 0;
                        if (x1 < (pmlLength - Constants.PrecisionLowerLimit))
                        {
                            pmlWgNo = 1;
                            baseLoopId = 1;
                        }
                        else if (x1 >= (pmlLength - Constants.PrecisionLowerLimit) && x1 < (srcPosX - Constants.PrecisionLowerLimit))
                        {
                            baseLoopId = 2;
                        }
                        else if (x1 >= (srcPosX - Constants.PrecisionLowerLimit) && x1 < (disconLength - pmlLength - Constants.PrecisionLowerLimit))
                        {
                            baseLoopId = 3;
                        }
                        else
                        {
                            pmlWgNo = 2;
                            baseLoopId = 4;
                        }
                        if (row >= (rodCntHalf) && row < (rodCntHalf + defectRodCnt)) continue; // 欠陥部
                        double x0 = col * periodicDistance + periodicDistance * 0.5;
                        double y0 = WaveguideWidth - row * latticeA - latticeA * 0.5;
                        uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                        rodLoopIds.Add(lId);
                        if (pmlWgNo == 1)
                        {
                            rodLoopIds_port1_pml.Add(lId);
                        }
                        else if (pmlWgNo == 2)
                        {
                            rodLoopIds_port2_pml.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // PML領域に色を付ける
                    uint[][] port_pml_loopIds_cad_list = { port1_pml_loopIds_cad, port2_pml_loopIds_cad };
                    for (int portIndex = 0; portIndex < portCnt; portIndex++)
                    {
                        uint[] work_lId_list = port_pml_loopIds_cad_list[portIndex];
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 0.5, 0.5, 0.5 });
                        }
                    }
                    // 誘電体ロッドに色を付ける
                    {
                        uint[] work_lId_list = rodLoopIds.ToArray();
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 1.0, 0.5, 0.0 });
                        }
                    }
                    // 境界の辺に色を付ける
                    {
                        uint[] work_eId_list = eId_cad_src_list;
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.8, 0.0, 0.0 });
                        }
                    }
                    // 境界の誘電体スラブの辺
                    {
                        uint[] work_port_core_eIds = core_eId_cad_src_list;
                        foreach (uint eId in work_port_core_eIds)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.0, 0.0, 1.0 });
                        }
                    }

                    /*
                    // DEBUG
                    {
                        uint[] work_eId_list = { 2, 3, 4, 5, 7, 8, 9, 10 };
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 1.0 });
                        }
                    }
                     */

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[loopCnt_cad + rodLoopIds.Count];
                for (int i = 0; i < loopCnt_cad; i++)
                {
                    loopId_cad_list[i] = (uint)(i + 1);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + loopCnt_cad] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[loopCnt_cad + rodLoopIds.Count];
                for (int i = 0; i < loopCnt_cad; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + loopCnt_cad] = Medias.IndexOf(mediaCore);
                }

                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    uint loopId_cad = loopId_cad_list[i];
                    int mediaIndex = mediaIndex_list[i];
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, mediaIndex);
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }

            // PML領域
            FieldPmlLoopIdList.Clear();
            IsPmlYDirectionList.Clear();
            PmlStPosXList.Clear();
            PmlLengthList.Clear();
            uint[][] loopId_cad_list_pml = new uint[portCnt][];
            // ポート1PML
            loopId_cad_list_pml[0] = new uint[port1_pml_loopIds_cad.Length + rodLoopIds_port1_pml.Count];
            port1_pml_loopIds_cad.CopyTo(loopId_cad_list_pml[0], 0);
            rodLoopIds_port1_pml.CopyTo(loopId_cad_list_pml[0], port1_pml_loopIds_cad.Length);
            // ポート2 PML
            loopId_cad_list_pml[1] = new uint[port2_pml_loopIds_cad.Length + rodLoopIds_port2_pml.Count];
            port2_pml_loopIds_cad.CopyTo(loopId_cad_list_pml[1], 0);
            rodLoopIds_port2_pml.CopyTo(loopId_cad_list_pml[1], port2_pml_loopIds_cad.Length);
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                uint[] loopId_cad_list = loopId_cad_list_pml[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint loopId_cad in loopId_cad_list)
                {
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                }
                uint workFieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
                FieldPmlLoopIdList.Add(workFieldLoopId);
                // Y方向PML?
                bool isPmlYDirection = false;
                IsPmlYDirectionList.Add(isPmlYDirection);
                // PML開始位置
                double pmlStPosX = pmlStPosX_list[portIndex];
                PmlStPosXList.Add(pmlStPosX);
                // PML長さ
                PmlLengthList.Add(pmlLength);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = { 2, 3, 4, 5, 7, 8, 9, 10 }; // PML終端磁気壁
                //uint[] eId_cad_list = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // PML終端電気壁
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortSrcBcId = 0;
            {
                // PMLを用いる場合は、励振面のみ
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_src_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                    {
                        wg2d.World.Edge edge = new wg2d.World.Edge();
                        int mediaIndex = Medias.IndexOf(mediaCladding);
                        if (core_eId_cad_src_list.Contains(eId_cad))
                        {
                            mediaIndex = Medias.IndexOf(mediaCore);
                        }
                        edge.Set(eId, mediaIndex);
                        EdgeDic.Add(eId, edge);
                    }
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                FieldPortSrcBcId = workFieldPortBcId;
            }

            // 観測点
            VIdRefList.Clear();
            uint[] vId_cad_refPort = portRef_vIds_cad;
            foreach (uint vId_cad in vId_cad_refPort)
            {
                uint vId = conv.GetIdEA_fromCad(vId_cad, CAD_ELEM_TYPE.VERTEX);
                VIdRefList.Add(vId);
            }

            return true;
        }
Exemplo n.º 12
0
        /// <summary>
        /// ロッド(半分)を追加する
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <returns></returns>
        public static uint AddHalfRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
                                      double startAngle, double additionalAngle = 0.0, bool isReverseAddVertex = false, uint id_v_st = uint.MaxValue, uint id_v_ed = uint.MaxValue)
        {
            System.Diagnostics.Debug.Assert(additionalAngle < 360.0 / rodCircleDiv);
            List <CVector2D> pts = new List <CVector2D>();

            System.Diagnostics.Debug.Assert((startAngle == 0.0) || (startAngle == 90.0) || (startAngle == 180.0) || (startAngle == 270.0));
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // メッシュ形状を整えるためにロッドの中心に頂点を追加
                uint id_v_center = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x0, y0)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_center != 0);
            }
            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    if (Math.Abs(additionalAngle) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit && (itheta == 0 || itheta == (rodCircleDiv / 2)))
                    {
                        continue;
                    }
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッドの分割数調整: ロッド1/4円から超えた部分
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = (startAngle + additionalAngle) * pi / 180.0;
                }
                else
                {
                    theta = (startAngle - additionalAngle) * pi / 180.0;
                }
                for (int k = 1; k < rodRadiusDiv; k++)
                {
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッドの分割数調整: ロッド1/4円から超えた部分
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = (startAngle - 180.0 - additionalAngle) * pi / 180.0;
                }
                else
                {
                    theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                }
                for (int k = 1; k < rodRadiusDiv; k++)
                {
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }

            uint retLoopId = 0;

            if (id_v_st != uint.MaxValue && id_v_ed != uint.MaxValue)
            {
                uint prev_id_v = id_v_st;

                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = (startAngle + additionalAngle) * pi / 180.0;
                    }
                    else
                    {
                        theta = (startAngle - additionalAngle) * pi / 180.0;
                    }
                    double x        = x0 + rodRadius * Math.Cos(theta);
                    double y        = y0 + rodRadius * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add;
                }

                // ロッド半円
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x        = x0 + rodRadius * Math.Cos(theta);
                    double y        = y0 + rodRadius * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add;
                }
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = (startAngle - 180.0 - additionalAngle) * pi / 180.0;
                    }
                    else
                    {
                        theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                    }
                    double x        = x0 + rodRadius * Math.Cos(theta);
                    double y        = y0 + rodRadius * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add; //!!!!!!!!!!!!!!!
                }
                uint last_id_v = id_v_ed;
                {
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                    uint id_e_add = resConnectVertex.id_e_add;
                    uint lId      = resConnectVertex.id_l_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    System.Diagnostics.Debug.Assert(lId != 0);
                    retLoopId = lId;
                }
            }
            else
            {
                System.Diagnostics.Debug.Assert(isReverseAddVertex == false); // 逆順未対応
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = (startAngle - additionalAngle) * pi / 180.0;
                    double x     = x0 + rodRadius * Math.Cos(theta);
                    double y     = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                // ロッド半円
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    double theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    double x     = x0 + rodRadius * Math.Cos(theta);
                    double y     = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                    double x     = x0 + rodRadius * Math.Cos(theta);
                    double y     = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                uint lId = cad2d.AddPolygon(pts, baseLoopId).id_l_add;
                retLoopId = lId;
            }
            return(retLoopId);
        }
Exemplo n.º 13
0
        /// <summary>
        /// PC欠陥導波路 2チャンネル
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="Beta1"></param>
        /// <param name="Beta2"></param>
        /// <param name="BetaDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinNormalizedFreq"></param>
        /// <param name="MaxNormalizedFreq"></param>
        /// <param name="GraphBetaInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="IsPCWaveguide"></param>
        /// <param name="latticeA"></param>
        /// <param name="periodicDistance"></param>
        /// <param name="PCWaveguidePorts"></param>
        /// <param name="CalcModeIndex"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcId1"></param>
        /// <param name="FieldPortBcId2"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double Beta1,
            ref double Beta2,
            ref double BetaDelta,
            ref double GraphFreqInterval,
            ref double MinNormalizedFreq,
            ref double MaxNormalizedFreq,
            ref double GraphBetaInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref bool IsPCWaveguide,
            ref double latticeA,
            ref double periodicDistance,
            ref IList<IList<uint>> PCWaveguidePorts,
            ref int CalcModeIndex,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref uint FieldPortBcId1,
            ref uint FieldPortBcId2,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // フォトニック結晶導波路(TEモード) 2チャンネル合分波
            //   問題2: 中央のロッド2本 偶モード
            //   問題-: 中央のロッド2本 奇モード
            //   問題-: 中央のロッド1本 奇モード
            //   問題-: 中央のロッド1本 偶モード
            //   Note: 中央のロッドが1本の場合、奇モードの方が基本モードになる
            IsPCWaveguide = true;
            // 基本モードを計算する
            CalcModeIndex = 0;
            // 高次モードを計算する
            //CalcModeIndex = 1;

            // ロッドの数(外側半分)
            const int rodCntHalf = 5;
            // ロッドの数(中央)
            //int rodCntMiddle = 1;
            int rodCntMiddle = 2;
            // 格子の数
            int latticeCnt = rodCntHalf * 2 + rodCntMiddle + 2;
            // 格子定数
            latticeA = WaveguideWidth / (double)latticeCnt;
            // 周期構造距離
            periodicDistance = latticeA;
            // ロッドの半径
            double rodRadius = 0.18 * latticeA;
            // ロッドの比誘電率
            double rodEps = 3.4 * 3.4;
            // 格子1辺の分割数
            //const int ndivForOneLattice = 4;
            const int ndivForOneLattice = 6;
            // 境界の総分割数
            int ndiv = latticeCnt * ndivForOneLattice;
            // ロッドの円周の分割数
            const int rodCircleDiv = 8;
            // ロッドの半径の分割数
            const int rodRadiusDiv = 1;
            // メッシュの長さ
            //double meshL = waveguideWidth * 0.1;
            double meshL = 1.05 * WaveguideWidth / ndiv;

            Beta1 = 0.0;
            Beta2 = 0.501 * (2.0 * pi / periodicDistance);
            BetaDelta = 0.02 * (2.0 * pi / periodicDistance);
            GraphBetaInterval = 0.1 * (2.0 * pi / periodicDistance);

            // フォトニック結晶導波路の場合、a/λを規格化周波数とする
            MinNormalizedFreq = 0.300;//0.302;
            MaxNormalizedFreq = 0.440;//0.443;
            GraphFreqInterval = 0.02;

            // 波のモード
            WaveModeDv = WgUtil.WaveModeDV.TE;

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (WaveModeDv == WgUtil.WaveModeDV.TM)
            {
                // TMモード
                claddingP = 1.0 / 1.0;
                claddingQ = 1.0;
                coreP = 1.0 / rodEps;
                coreQ = 1.0;
            }
            else
            {
                // TEモード
                claddingP = 1.0;
                claddingQ = 1.0;
                coreP = 1.0;
                coreQ = rodEps;
            }
            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // Cad
            uint baseLoopId = 0;
            IList<uint> rodLoopIds = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // ToDo: 周期境界1, 2上の分割が同じになるように設定する必要がある
                //
                // 領域を追加
                {
                    List<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));
                    pts.Add(new CVector2D(0.0, 0.0));
                    pts.Add(new CVector2D(latticeA, 0.0));
                    pts.Add(new CVector2D(latticeA, WaveguideWidth));
                    // 多角形追加
                    uint lId = cad2d.AddPolygon(pts).id_l_add;
                    baseLoopId = lId;
                }
                // 入出力導波路の周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 入力導波路
                {
                    uint id_e = 1;
                    double x1 = 0.0;
                    double y1 = WaveguideWidth;
                    double y2 = 0.0;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x1, y2);
                }
                // 出力導波路
                {
                    uint id_e = 3;
                    double x1 = latticeA;
                    double y1 = 0.0;
                    double y2 = WaveguideWidth;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndiv, x1, y1, x1, y2);
                }
                // ロッドを追加
                for (int i = 0; i < rodCntHalf; i++)
                {
                    double x0 = latticeA * 0.5;
                    double y0 = WaveguideWidth - i * latticeA - latticeA * 0.5;
                    uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }
                for (int i = 0; i < rodCntMiddle; i++)
                {
                    double x0 = latticeA * 0.5;
                    double y0 = WaveguideWidth * 0.5 + latticeA * rodCntMiddle * 0.5 - i * latticeA - latticeA * 0.5;
                    uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    double x0 = latticeA * 0.5;
                    double y0 = latticeA * rodCntHalf - i * latticeA - latticeA * 0.5;
                    uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }
                // 中央の2つのロッドとロッドの間のメッシュの対称性を改善する
                if (rodCntMiddle % 2 == 0) // 中央のロッドが偶数本のとき
                {
                    // 中央のロッドとロッドの間に頂点を追加
                    double x = latticeA * 0.5;
                    double y = WaveguideWidth * 0.5;
                    uint id_v_center = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_center != 0);
                }

                // 図面表示
                if (isCadShow)
                {
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // 領域 + ロッド
                uint[] loopId_cad_list = new uint[1 + rodLoopIds.Count];
                int[] mediaIndex_list = new int[loopId_cad_list.Length];

                // 領域
                loopId_cad_list[0] = baseLoopId;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);

                // ロッド
                int offset = 1;
                rodLoopIds.ToArray().CopyTo(loopId_cad_list, offset);
                for (int i = offset; i < mediaIndex_list.Length; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 境界条件を設定する
            // 固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if (WaveModeDv == WgUtil.WaveModeDV.TE)
            {
                uint[] eId_cad_list = { 2, 4 };
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId1 = 0;
            {
                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 1;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndiv - 1) - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                WgUtil.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId1,
                    ref EdgeDic);
            }

            // 開口条件2
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId2 = 0;
            {
                uint[] eId_cad_list = new uint[ndiv];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 3;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                for (int i = 1; i <= ndiv - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndiv - 1) * 2 - (i - 1));
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId2,
                    ref EdgeDic);
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            {
                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, FieldLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (coord[1] >= (WaveguideWidth - latticeA * (rodCntHalf + 1)) && coord[1] <= (WaveguideWidth - latticeA * (rodCntHalf)))
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
                {
                    // チャンネル2
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (coord[1] >= (latticeA * rodCntHalf) && coord[1] <= (latticeA * (rodCntHalf + 1)))
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 14
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <returns></returns>
        private bool setNewProblem()
        {
            bool success = false;
            try
            {
                if (ProbNo == 0 || ProbNo == 1)
                {
                    ////////////////
                    // 波源の頂点
                    uint id_v = 0;
                    // ワールド座標系のベースID
                    uint id_base = 0;
                    using (CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add(new CVector2D(0.0, 0.0));  // 頂点1
                        pts.Add(new CVector2D(2.0, 0.0));  // 頂点2
                        pts.Add(new CVector2D(2.0, 2.0));  // 頂点3
                        pts.Add(new CVector2D(0.0, 2.0));  // 頂点4
                        uint id_l = cad2d.AddPolygon(pts).id_l_add;
                        id_v = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5, 0.05)).id_v_add;
                        World.Clear();
                        id_base = World.AddMesh(new CMesher2D(cad2d, 0.04));
                    }
                    // CADのIDからワールド座標系のIDへ変換するコンバーターを取得
                    CIDConvEAMshCad conv = World.GetIDConverter(id_base);

                    // フィールドを作成する
                    //   図形の次元2次元、値、コーナー(要素の角頂点)
                    uint id_field_val = World.MakeField_FieldElemDim(
                        id_base,
                        2,
                        FIELD_TYPE.ZSCALAR,
                        FIELD_DERIVATION_TYPE.VALUE,
                        ELSEG_TYPE.CORNER);
                    //uint id_field_bc0 = World.GetPartialField(id_field_val,conv.GetIdEA_fromCad(2, 1));
                    uint id_field_bc1 = 0;
                    {
                        IList<uint> aEA = new List<uint>();
                        aEA.Add(conv.GetIdEA_fromCad(1, CAD_ELEM_TYPE.EDGE));
                        aEA.Add(conv.GetIdEA_fromCad(2, CAD_ELEM_TYPE.EDGE));
                        aEA.Add(conv.GetIdEA_fromCad(3, CAD_ELEM_TYPE.EDGE));
                        aEA.Add(conv.GetIdEA_fromCad(4, CAD_ELEM_TYPE.EDGE));
                        id_field_bc1 = World.GetPartialField(id_field_val, aEA);
                    }
                    CFieldValueSetter.SetFieldValue_Constant(id_field_bc1, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);

                    using (CZLinearSystem ls = new CZLinearSystem())
                    using (CZPreconditioner_ILU prec = new CZPreconditioner_ILU())
                    {
                        // 場のパターンをリニアシステムに追加する
                        ls.AddPattern_Field(id_field_val, World);

                        // 境界条件
                        //ls.SetFixedBoundaryCondition_Field(id_field_bc0,World);
                        //ls.SetFixedBoundaryCondition_Field(id_field_bc1,World);

                        // プリコンディショナ―フィルインあり
                        prec.SetFillInLevel(1);
                        // プリコンディショナ―にリニアシステムをセットする
                        prec.SetLinearSystem(ls);

                        // 波長
                        double wave_length = 0.4;

                        // 全体行列の作成
                        ls.InitializeMarge();

                        if (ProbNo == 0)
                        {
                            Console.WriteLine("///// DelFEM4NetFem.Eqn.CEqnHelmholtz");
                            // DelFEMのライブラリを使用
                            CEqnHelmholz.AddLinSys_Helmholtz(ls, wave_length, World, id_field_val);
                            CEqnHelmholz.AddLinSys_SommerfeltRadiationBC(ls, wave_length, World, id_field_bc1);
                        }
                        else
                        {
                            Console.WriteLine("///// CEqnHelmholtz_ForCSharp");
                            // C#で記述した関数を使用(TEST)
                            System.Diagnostics.Debug.Assert(ProbNo == 1);
                            CEqnHelmholtz_ForCSharp.AddLinSysHelmholtz(ls, wave_length, World, id_field_val);
                            CEqnHelmholtz_ForCSharp.AddLinSys_SommerfeltRadiationBC(ls, wave_length, World, id_field_bc1);
                        }
                        double res = ls.FinalizeMarge();

                        // リニアシステムのマトリクスの値をセットしてILU分解を行う
                        prec.SetValue(ls);

                        // 励振:波源を設定する
                        {
                            // 波源の頂点IDからワールド座標系の要素アレイIDを取得する
                            uint id_ea_v = conv.GetIdEA_fromCad(id_v, CAD_ELEM_TYPE.VERTEX);
                            Console.WriteLine(id_ea_v);
                            // 要素アレイを取得する
                            CElemAry ea = World.GetEA(id_ea_v);
                            // 要素セグメントを取得する
                            CElemAry.CElemSeg es = ea.GetSeg(1);  // セグメントID: 1
                            System.Diagnostics.Debug.Assert(ea.ElemType() == ELEM_TYPE.POINT);
                            // 最初の要素の節点番号を取り出す
                            uint[] noes = new uint[1];
                            es.GetNodes(0, noes); // 要素インデックス: 0
                            Console.WriteLine(noes[0]);

                            // 残差ベクトルのポインタを取得
                            using (CZVector_Blk_Ptr residualPtr = ls.GetResidualPtr(id_field_val, ELSEG_TYPE.CORNER, World))
                            {
                                // 節点番号noes[0]の0番目の自由度に値を加算する
                                residualPtr.AddValue(noes[0], 0, new Complex(1, 0));
                            }
                        }
                        Console.WriteLine("Residual : " + res);
                        {
                            double tol = 1.0e-6;
                            uint iter = 2000;
                            //CZSolverLsIter.Solve_CG(ref tol, ref iter, ls);
                            //CZSolverLsIter.Solve_PCG(ref tol, ref iter,ls, prec);
                            CZSolverLsIter.Solve_PCOCG(ref tol,ref iter,ls, prec);
                            //CZSolverLsIter.Solve_CGNR(ref tol,ref iter, ls);
                            //CZSolverLsIter.Solve_BiCGSTAB(ref tol,ref iter,ls);
                            //CZSolverLsIter.Solve_BiCGStabP(ref tol, ref iter,ls, prec);
                            Console.WriteLine(iter + " " + tol);
                        }
                        ls.UpdateValueOfField(id_field_val, World, FIELD_DERIVATION_TYPE.VALUE);
                    }

                    // 描画オブジェクトアレイの追加
                    DrawerAry.Clear();
                    DrawerAry.PushBack(new CDrawerFace(id_field_val, true, World, id_field_val, -0.05, 0.05));
                    //DrawerAry.PushBack( new CDrawerFaceContour(id_field_ val, World) );
                    DrawerAry.PushBack(new CDrawerEdge(id_field_val, true, World));
                    DrawerAry.InitTrans(Camera);
                }
                success = true;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            ProbNo++;
            if (ProbNo == ProbCnt) ProbNo = 0;
            return success;
        }
Exemplo n.º 15
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <returns></returns>
        private bool setNewProblem()
        {
            bool success = false;

            try
            {
                if (ProbNo == 0)
                {
                     // linear Solid stationary analysis
                    Id_field_disp_fix0 = 0;
                    Id_field_temp = 0;
                    Id_field_stress = 0;
                    Id_field_equiv_stress = 0;
                    ////////////////
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using (CCadObj2D cad2d = new CCadObj2D())
                    {
                        {
                            // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(5.0,0.0) );
                            pts.Add( new CVector2D(5.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            cad2d.AddPolygon( pts );
                        }
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.1) );
                        conv = World.GetIDConverter(id_base);
                    }

                    Solid.Clear();
                    Solid.UpdateDomain_Field(id_base, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // Setting Material Parameter
                    Solid.SetYoungPoisson(10.0,0.3,true);    // planter stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(4,CAD_ELEM_TYPE.EDGE),World);

                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc0,World);
                    FieldValueSetter.SetMathExp("sin(t*PI*2*0.1)", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    // Setting Visualiziation
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 1 )    // save stiffness matrix for the efficency of computation
                {
                    Solid.SetSaveStiffMat(true);
                }
                else if( ProbNo == 2 )    // non-stationary analysis
                {
                    Solid.SetSaveStiffMat(true);
                    Solid.SetStationary(false);
                }
                else if( ProbNo == 3 )    // set stiffer material
                {
                    Solid.SetYoungPoisson(50,0.3,true);
                }
                else if( ProbNo == 4 )    // set more stiffer material
                {
                    Solid.SetYoungPoisson(100,0.3,true);
                }
                else if( ProbNo == 5 )    // geometrical non-linear stationaly
                {
                    Solid.SetStationary(true);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 6 )    // geometrical non-linear non-stationary
                {
                    Solid.SetYoungPoisson(10,0.0,true);
                    Solid.SetStationary(false);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 7 )    // display equivalent stress field in deformedconfigulation
                {
                    Id_field_equiv_stress = World.MakeField_FieldElemDim(Id_field_disp, 2,
                        DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetStationary(true);
                    // set up visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_equiv_stress,false,World,Id_field_equiv_stress, 0,0.5) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // init view transformation
                }
                else if( ProbNo == 8 )    // display equivalent stress field in initial configulation
                {
                    // set up visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World,Id_field_equiv_stress, 0,0.5) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // init view transformation
                }
                else if( ProbNo == 9 )    // thermal-Solid analysis
                {
                    Id_field_equiv_stress = 0;
                    Id_field_stress = 0;
                    ////////////////
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using (CCadObj2D cad2d = new CCadObj2D())
                    {
                         {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(3.0,0.0) );
                            pts.Add( new CVector2D(3.0,1.0) );
                            pts.Add( new CVector2D(2.0,1.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            cad2d.AddPolygon( pts );
                        }
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.1) );
                        conv = World.GetIDConverter(id_base);
                    }
                    Solid.UpdateDomain_Field(id_base,World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // set material property
                    Solid.SetYoungPoisson(10.0,0.3,true);    // set planer stress
                    Solid.SetGeometricalNonlinear(false);    // geometricaly linear model
                    Solid.SetGravitation(0.0,-0.1);
                    Solid.SetTimeIntegrationParameter(Dt);    // set time setp

                    uint id_field_bc0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(6,CAD_ELEM_TYPE.EDGE),World);

                    // set temparature field
                    Id_field_temp = World.MakeField_FieldElemDim(Id_field_disp, 2,
                        DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.CORNER);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(Id_field_temp,World);
                    FieldValueSetter.SetMathExp("sin(6.28*y)*sin(x)*sin(t)", 0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    Solid.SetThermalStress(Id_field_temp);
                    Solid.ClearFixElemAry(3,World);

                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false, World, Id_field_temp, -1,1) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 10 )    // show contour in undeformed configuration
                {
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_temp,true, World, Id_field_temp, -1,1) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 11 )    // stop considering thermal-effect
                {
                    Solid.SetThermalStress(0);
                }
                else if( ProbNo == 12 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;        // get ID converter
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            uint id_l = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.2)).id_v_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.2)).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.7,0.8)).id_v_add;
                            uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l, new CVector2D(0.3,0.8)).id_v_add;
                            cad2d.ConnectVertex_Line(id_v1,id_v2);
                            cad2d.ConnectVertex_Line(id_v2,id_v3);
                            cad2d.ConnectVertex_Line(id_v3,id_v4);
                            cad2d.ConnectVertex_Line(id_v4,id_v1);
                        }
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.05) );
                        conv = World.GetIDConverter(id_base);        // get ID converter
                    }

                    Solid.SetDomain_FieldEA(id_base,conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.LOOP),World);
                    Solid.SetSaveStiffMat(true);
                    Solid.SetStationary(true);
                    Solid.SetTimeIntegrationParameter(Dt);    // set time step
                    Solid.SetYoungPoisson(2.5,0.3,true);    // planer stress
                    Solid.SetGeometricalNonlinear(false);    // set geometrical liner
                    Solid.SetGravitation(0.0,0.0);    // set gravitation

                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(3,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc2 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc1,World);
                    FieldValueSetter.SetMathExp("0.3*sin(1.5*t)", 0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.1*(cos(t)+1)", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    // set visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 13 )
                {
                    Solid.SetSaveStiffMat(true);
                }
                else if( ProbNo == 14 )
                {
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(false);
                }
                else if( ProbNo == 15 ){
                    Solid.SetStationary(true);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 16 ){
                    Solid.SetStationary(false);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 17 )    // hard and soft Solid are connected
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.0) );
                        pts.Add( new CVector2D(1.0,1.0) );
                        pts.Add( new CVector2D(0.0,1.0) );
                        cad2d.AddPolygon( pts );
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(0.5,0.0)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(0.5,1.0)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v1,id_v2);

                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.05) );
                        conv = World.GetIDConverter(id_base);  // get ID converter
                    }

                    Solid.SetDomain_FieldEA(id_base,conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.LOOP),World);
                    Solid.SetTimeIntegrationParameter(Dt);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);

                    Solid.SetYoungPoisson(3.0,0.3,true);
                    Solid.SetGeometricalNonlinear(false);    // set geometrically linear model
                    Solid.SetGravitation(0.0,0.0);

                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(3,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc2 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(5,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc1,World);
                    FieldValueSetter.SetMathExp("0.3*sin(1.5*t)",     0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.1*(cos(t)+1)+0.1", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    // set up visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    //DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.PushBack( new CDrawerEdge(id_base,true,World) );
                    DrawerAry.InitTrans(Camera);    // set view trnsformation
                }
                else if( ProbNo == 18 )
                {
                    Solid.SetSaveStiffMat(true);
                }
                else if( ProbNo == 19 )
                {
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(false);
                }
                else if( ProbNo == 20 )
                {
                    Solid.SetStationary(true);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 21 )
                {
                    Solid.SetStationary(false);
                    Solid.SetGeometricalNonlinear(true);
                }
                else if( ProbNo == 22 )    // 4 different type of Solid combined
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(2.0,0.0) );
                        pts.Add( new CVector2D(2.0,0.5) );
                        pts.Add( new CVector2D(0.0,0.5) );
                        cad2d.AddPolygon( pts );
                        uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(1.5,0.0)).id_v_add;
                        uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(1.0,0.0)).id_v_add;
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(0.5,0.0)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(0.5,0.5)).id_v_add;
                        uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(1.0,0.5)).id_v_add;
                        uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(1.5,0.5)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v1,id_v2);
                        cad2d.ConnectVertex_Line(id_v3,id_v4);
                        cad2d.ConnectVertex_Line(id_v5,id_v6);

                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.05) );
                        conv = World.GetIDConverter(id_base);  // get ID converter
                    }

                    Solid.UpdateDomain_Field(id_base,World);    // set domain of Solid analysis
                    Solid.SetTimeIntegrationParameter(Dt);    // set time step
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // set material property
                    Solid.SetYoungPoisson(1.0,0.3,true);
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,-0.0);

                    {    // St.Venant-Kirchhoff material
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.LOOP));
                        eqn.SetGeometricalNonlinear(true);
                        Solid.SetEquation(eqn);
                    }
                    {    // soft elastic material
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.LOOP));
                        eqn.SetYoungPoisson(0.1,0.3,true);
                        Solid.SetEquation(eqn);
                    }
                    uint Id_field_temp = World.MakeField_FieldElemAry(id_base, conv.GetIdEA_fromCad(3,CAD_ELEM_TYPE.LOOP),
                        DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.CORNER);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(Id_field_temp,World);
                    FieldValueSetter.SetMathExp("0.1*sin(3.14*4*y)*sin(2*t)", 0,FIELD_DERIVATION_TYPE.VALUE, World);
                    {    // linear elastic material concidering thrmal-Solid
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(3,CAD_ELEM_TYPE.LOOP));
                        eqn.SetThermalStress(Id_field_temp);
                        Solid.SetEquation(eqn);
                    }
                    {    // hard elastic material
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(4,CAD_ELEM_TYPE.LOOP));
                        eqn.SetYoungPoisson(10,0.3,true);
                        Solid.SetEquation(eqn);
                    }

                    Id_field_disp_fix0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.EDGE),World);

                    // set up visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    //DrawerAry.PushBack( new CDrawerEdge(id_base,false,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 23 )
                {
                    Solid.SetRho(0.0001);
                    Solid.SetStationary(false);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(Id_field_disp_fix0,World);
                    FieldValueSetter.SetMathExp("0.5*cos(2*t)", 1,FIELD_DERIVATION_TYPE.VALUE, World);
                }
                else if( ProbNo == 24 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(2.0,0.0) );
                        pts.Add( new CVector2D(2.0,1.0) );
                        pts.Add( new CVector2D(0.0,1.0) );
                        cad2d.AddPolygon( pts );
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,1, new CVector2D(1.0,0.0)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE,3, new CVector2D(1.0,1.0)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v1,id_v2);

                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.05) );
                        conv = World.GetIDConverter(id_base);  // ID converter
                    }
                    Solid.UpdateDomain_Field(id_base,World);    // set displacement field
                    Solid.SetTimeIntegrationParameter(Dt);    // set time step
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(false);
                    // set material property
                    Solid.SetYoungPoisson(1.0,0.3,true);    // planter stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,-0.0);
                    Solid.SetRho(0.001);

                    {    // soft elastic material
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.LOOP));
                        eqn.SetYoungPoisson(0.1,0.3,true);
                        Solid.SetEquation(eqn);
                    }
                    {    // hard elastic material
                        DelFEM4NetFem.Eqn.CEqn_Solid2D eqn = Solid.GetEquation(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.LOOP));
                        eqn.SetYoungPoisson(100000000,0.3,true);
                        Solid.SetEquation(eqn);
                    }

                    //Id_field_disp_fix0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,1),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(4,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc1,World);
                    FieldValueSetter.SetMathExp("0.3*sin(1.5*t)",     0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.1*(cos(t)+1)+0.1", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    // set up visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.InitTrans(Camera);    // initialize view transmation
                }
                else if( ProbNo == 25 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    uint id_base2 = 0;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        uint id_l;
                        uint id_e1,id_e2,id_e3,id_e4,id_e5;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(0.2,0.0) );
                            pts.Add( new CVector2D(1.0,0.0) );
                            pts.Add( new CVector2D(1.0,1.0) );
                            pts.Add( new CVector2D(0.0,1.0) );
                            id_l = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.2,0.5) ).id_v_add;
                            id_e1 = cad2d.ConnectVertex_Line(2,id_v1).id_e_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5,0.2) ).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5,0.5) ).id_v_add;
                            uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.5,0.8) ).id_v_add;
                            uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.8,0.5) ).id_v_add;
                            uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(0.3,0.5) ).id_v_add;
                            id_e2 = cad2d.ConnectVertex_Line(id_v2,id_v3).id_e_add;
                            id_e3 = cad2d.ConnectVertex_Line(id_v3,id_v4).id_e_add;
                            id_e4 = cad2d.ConnectVertex_Line(id_v3,id_v5).id_e_add;
                            id_e5 = cad2d.ConnectVertex_Line(id_v3,id_v6).id_e_add;
                        }
                        using(CMesher2D mesh2d = new CMesher2D(cad2d,0.1))
                        {
                            World.Clear();
                            id_base = World.AddMesh(mesh2d);
                            conv = World.GetIDConverter(id_base);  // get ID converter

                            {    // cut mesh
                                IList<uint> mapVal2Co = null;
                                IList< IList<int> > aLnods = null;
                                {
                                    IList<uint> aIdMsh_Inc = new List<uint>();
                                    aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l,CAD_ELEM_TYPE.LOOP) );
                                    IList<uint> aIdMshCut = new List<uint>();
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e1,CAD_ELEM_TYPE.EDGE) );
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e2,CAD_ELEM_TYPE.EDGE) );
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e3,CAD_ELEM_TYPE.EDGE) );
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e4,CAD_ELEM_TYPE.EDGE) );
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e5,CAD_ELEM_TYPE.EDGE) );
                                    mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc,aIdMshCut);
                                }
                                IList<uint> aIdEA_Inc = new List<uint>();
                                aIdEA_Inc.Add( conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.LOOP) );
                                id_base2 = World.SetCustomBaseField(id_base,aIdEA_Inc, aLnods, mapVal2Co);
                            }
                        } // mesh2d
                    } // cad2d

                    Solid.UpdateDomain_Field(id_base2, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // set material parameter
                    Solid.SetYoungPoisson(10.0,0.3,true);
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(3,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(5,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc0,World);
                    FieldValueSetter.SetMathExp("0.1*sin(t*PI*2*0.1)",    0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.1*(1-cos(t*PI*2*0.1))",1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    // set visualization
                    DrawerAry.Clear();
                    Id_field_disp = Solid.GetIdField_Disp();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set view transformation
                }
                else if( ProbNo == 26 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    uint id_base2 = 0;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        uint id_e;
                        uint id_l;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add( new CVector2D(0.0,0.0) );
                            pts.Add( new CVector2D(5.0,0.0) );
                            pts.Add( new CVector2D(5.0,2.0) );
                            pts.Add( new CVector2D(0.0,2.0) );
                            id_l = cad2d.AddPolygon( pts ).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 3, new CVector2D(2.5,2.0)).id_v_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l, new CVector2D(2.5,1.0)).id_v_add;
                            id_e = cad2d.ConnectVertex_Line(id_v1,id_v2).id_e_add;
                        }
                        using(CMesher2D mesh2d = new CMesher2D(cad2d,0.2))
                        {
                            World.Clear();
                            CurTime = 0;
                            id_base = World.AddMesh(mesh2d);
                            conv = World.GetIDConverter(id_base);
                            id_base2 = 0;
                            {    // cut mesh
                                IList<uint> mapVal2Co = new List<uint>();
                                IList< IList<int> > aLnods = new List<IList<int>>();
                                {
                                    IList<uint> aIdMsh_Inc = new List<uint>();
                                    aIdMsh_Inc.Add( mesh2d.GetElemID_FromCadID(id_l,CAD_ELEM_TYPE.LOOP) );
                                    IList<uint> aIdMshCut = new List<uint>();
                                    aIdMshCut.Add( mesh2d.GetElemID_FromCadID(id_e,CAD_ELEM_TYPE.EDGE) );
                                    mesh2d.GetClipedMesh(out aLnods, out mapVal2Co, aIdMsh_Inc,aIdMshCut);
                                }
                                IList<uint> aIdEA_Inc = new List<uint>();
                                aIdEA_Inc.Add( conv.GetIdEA_fromCad(id_l,CAD_ELEM_TYPE.LOOP) );
                                id_base2 = World.SetCustomBaseField(id_base,aIdEA_Inc, aLnods,mapVal2Co);
                            }
                        } // mesh2d
                    } // cad2d

                    Solid.UpdateDomain_Field(id_base2, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // set material parameter
                    Solid.SetYoungPoisson(10.0,0.3,true);    // set planer stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(4,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc0,World);
                    FieldValueSetter.SetMathExp("0.5*(1-cos(t*PI*2*0.1))", 0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.2*sin(t*PI*2*0.1)",     1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    Id_field_disp = Solid.GetIdField_Disp();
                    Id_field_equiv_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                        DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);

                    // set up visualization
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World,Id_field_equiv_stress) );
                    //DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // set transformation
                }
                else if( ProbNo == 27 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(3.0,0.0) );
                        pts.Add( new CVector2D(3.0,1.0) );
                        pts.Add( new CVector2D(0.0,1.0) );
                        cad2d.AddPolygon( pts );
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.3) );
                        conv = World.GetIDConverter(id_base);    // Get ID converter
                    }

                    Solid.Clear();
                    Solid.UpdateDomain_Field(id_base, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // Setting Material Parameter
                    Solid.SetYoungPoisson(2,0.3,true);    // planter stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(2,CAD_ELEM_TYPE.EDGE),World);
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(4,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc0,World);
                    FieldValueSetter.SetMathExp("0.5*sin(t*PI*2*0.1)",    0,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis
                    FieldValueSetter.SetMathExp("0.3*(1-cos(t*PI*2*0.1))",1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field y axis

                    Id_field_disp = Solid.GetIdField_Disp();
                    Id_field_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                        DelFEM4NetFem.Field.FIELD_TYPE.STSR2,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);
                    //Id_field_equiv_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                    //    DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                    //    DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                    //    DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);

                    // set up visualization
                    DrawerAry.Clear();
                    //DrawerAry.PushBack( new CDrawerFace(Id_field_equiv_stress,false,World,Id_field_equiv_stress, 0,0.5) );
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerVector(Id_field_stress,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // init view transformation
                }
                else if( ProbNo == 28 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(0.2,0.0) );
                        pts.Add( new CVector2D(0.2,0.5) );
                        pts.Add( new CVector2D(0.8,0.5) );
                        pts.Add( new CVector2D(0.8,0.0) );
                        pts.Add( new CVector2D(1.0,0.0) );
                        pts.Add( new CVector2D(1.0,0.7) );
                        pts.Add( new CVector2D(0.6,0.7) );
                        pts.Add( new CVector2D(0.4,0.7) );
                        pts.Add( new CVector2D(0.0,0.7) );
                        cad2d.AddPolygon( pts );
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.1) );
                        conv = World.GetIDConverter(id_base);    // Get ID converter
                    }

                    Solid.Clear();
                    Solid.UpdateDomain_Field(id_base, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // Setting Material Parameter
                    Solid.SetYoungPoisson(2,0.1,true);    // planter stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0;
                    {
                        IList<uint> aIdEA = new List<uint>();
                        aIdEA.Add(conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.EDGE));
                        aIdEA.Add(conv.GetIdEA_fromCad(5,CAD_ELEM_TYPE.EDGE));
                        id_field_bc0 = Solid.AddFixElemAry(aIdEA,World);
                    }
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(8,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc1,World);
                    FieldValueSetter.SetMathExp("-0.03*(1-cos(t*PI*2*0.1))", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis

                    Id_field_disp = Solid.GetIdField_Disp();
                    Id_field_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                        DelFEM4NetFem.Field.FIELD_TYPE.STSR2,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);
                    //Id_field_equiv_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                    //    DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                    //    DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                    //    DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);

                    // set up visualization
                    DrawerAry.Clear();
                    //DrawerAry.PushBack( new CDrawerFace(Id_field_equiv_stress,false,World,Id_field_equiv_stress, 0,0.5) );
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerVector(Id_field_stress,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // init view transformation
                }
                else if( ProbNo == 29 )
                {
                    uint id_base = 0;
                    CIDConvEAMshCad conv = null;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {    // define shape
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(0.0,0.0) );
                        pts.Add( new CVector2D(0.2,0.0) );
                        pts.Add( new CVector2D(0.2,0.5) );
                        pts.Add( new CVector2D(0.8,0.5) );
                        pts.Add( new CVector2D(0.8,0.3) );
                        pts.Add( new CVector2D(1.0,0.3) );
                        pts.Add( new CVector2D(1.0,0.7) );
                        pts.Add( new CVector2D(0.6,0.7) );
                        pts.Add( new CVector2D(0.4,0.7) );
                        pts.Add( new CVector2D(0.0,0.7) );
                        cad2d.AddPolygon( pts );
                        World.Clear();
                        id_base = World.AddMesh( new CMesher2D(cad2d,0.1) );
                        conv = World.GetIDConverter(id_base);    // Get ID converter
                    }

                    Solid.Clear();
                    Solid.UpdateDomain_Field(id_base, World);
                    Solid.SetSaveStiffMat(false);
                    Solid.SetStationary(true);
                    // Setting Material Parameter
                    Solid.SetYoungPoisson(2,0.1,true);    // planter stress
                    Solid.SetGeometricalNonlinear(false);
                    Solid.SetGravitation(0.0,0.0);
                    Solid.SetTimeIntegrationParameter(Dt,0.7);

                    uint id_field_bc0;
                    {
                        IList<uint> aIdEA = new List<uint>();
                        aIdEA.Add(conv.GetIdEA_fromCad(1,CAD_ELEM_TYPE.EDGE));
                        //aIdEA.Add(conv.GetIdEA_fromCad(5,CAD_ELEM_TYPE.EDGE));
                        id_field_bc0 = Solid.AddFixElemAry(aIdEA,World);
                    }
                    uint id_field_bc1 = Solid.AddFixElemAry(conv.GetIdEA_fromCad(8,CAD_ELEM_TYPE.EDGE),World);
                    if (FieldValueSetter != null)
                    {
                        FieldValueSetter.Clear();
                        FieldValueSetter.Dispose();
                    }
                    FieldValueSetter = new CFieldValueSetter(id_field_bc1,World);
                    FieldValueSetter.SetMathExp("-0.03*(1-cos(t*PI*2*0.1))", 1,FIELD_DERIVATION_TYPE.VALUE, World);    // oscilate bc1_field x axis

                    Id_field_disp = Solid.GetIdField_Disp();
                    Id_field_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                        DelFEM4NetFem.Field.FIELD_TYPE.STSR2,
                        DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                        DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);
                    //Id_field_equiv_stress = World.MakeField_FieldElemDim(Id_field_disp,2,
                    //    DelFEM4NetFem.Field.FIELD_TYPE.SCALAR,
                    //    DelFEM4NetFem.Field.FIELD_DERIVATION_TYPE.VALUE,
                    //    DelFEM4NetFem.Field.ELSEG_TYPE.BUBBLE);

                    // set up visualization
                    DrawerAry.Clear();
                    //DrawerAry.PushBack( new CDrawerFace(Id_field_equiv_stress,false,World,Id_field_equiv_stress, 0,0.5) );
                    DrawerAry.PushBack( new CDrawerFace(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerVector(Id_field_stress,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,false,World) );
                    DrawerAry.PushBack( new CDrawerEdge(Id_field_disp,true ,World) );
                    DrawerAry.InitTrans(Camera);    // init view transformation
                }
                success = true;

            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            ProbNo++;
            if (ProbNo == ProbCnt) ProbNo = 0;
            return success;
        }
Exemplo n.º 16
0
 ////////////////////////////////////////////////////////////////////////
 // 型
 ////////////////////////////////////////////////////////////////////////
 /// <summary>
 /// 境界を分割する
 /// </summary>
 /// <param name="cad2d"></param>
 /// <param name="id_e"></param>
 /// <param name="ndiv"></param>
 /// <param name="x1"></param>
 /// <param name="y1"></param>
 /// <param name="x2"></param>
 /// <param name="y2"></param>
 public static void DivideBoundary(CCadObj2D cad2d, uint id_e, int ndiv, double x1, double y1, double x2, double y2)
 {
     double signedWidthX = x2 - x1;
     double signedWidthY = y2 - y1;
     for (int i = ndiv - 1; i >= 1; i--)
     {
         double x = x1 + i * signedWidthX / ndiv;
         double y = y1 + i * signedWidthY / ndiv;
         CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x, y));
         uint id_v_add = resAddVertex.id_v_add;
         uint id_e_add = resAddVertex.id_e_add;
         System.Diagnostics.Debug.Assert(id_v_add != 0);
     }
 }
Exemplo n.º 17
0
        /// <summary>
        /// PC導波路 三角形格子 空洞共振器 (通過型)
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 入出力導波路が同じ?
            //IsInoutWgSame = false;// true;

            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            int propModeCntToSolve = 3;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            // 高次モード入射
            //int incidentModeIndex = 1;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0;
            // 最大屈折率
            double maxEffN = 0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0; // for latticeTheta = 45 r = 0.18a
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5; // for latticeTheta = 45 r = 0.18a
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a

            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false;
            //bool isShift180 = true;
            // ロッドの数(半分)
            //const int rodCntHalf = 3; // for latticeTheta = 60 r = 0.35a air hole
            const int rodCntHalf = 3;
            // 欠陥ロッド数
            const int defectRodCnt = 1;
            // 三角形格子の内角
            double latticeTheta = 60.0; // for latticeTheta = 60 r = 0.31a air hole
            // ロッドの半径
            //double rodRadiusRatio = 0.35; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_cavity == 1
            double rodRadiusRatio = 0.30952;// 0.31; // for latticeTheta = 60 r = 0.31a air hole defectRodCnt_cavity == 3
            // ロッドの比誘電率
            //double rodEps = 2.8 * 2.8; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_cavity == 1
            double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.31a air hole
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 7;//9; // for latticeTheta = 60 r = 0.35a air hole defectRodCnt_cavity == 1
            const int ndivForOneLattice = 7;
            // ロッド円周の分割数
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            const int rodRadiusDiv = 4;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 5; // defectRodCnt_cavity == 3
            const int rodCntDiscon = 5;
            // 入出力導波路の入力端からの長さ
            //const int rodCntX_Wg = 3; // defectRodCnt_cavity == 1
            //const int rodCntX_Wg = 2;//10; // defectRodCnt_cavity == 3
            const int rodCntX_Wg = 2;
            // 共振器の欠陥ロッド数
            //const int defectRodCnt_cavity = 1; // defectRodCnt_cavity == 1
            const int defectRodCnt_cavity = 3; // defectRodCnt_cavity == 3
            // 共振器と入力導波路の間のロッド数
            //const int spacingRodCnt = 1; // defectRodCnt_cavity == 1
            //const int spacingRodCnt = 3; // defectRodCnt_cavity == 3
            const int spacingRodCnt = 3;
            // 最適形状?
            //const bool isOpt = false;
            const bool isOpt = true;

            // 格子の数
            int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 導波路不連続領域の長さ
            double disconLength = rodDistanceX * rodCntDiscon;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit
                    || Math.Abs(latticeTheta - 30.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 60 r = 0.35a
                //NormalizedFreq1 = 0.275;
                //NormalizedFreq2 = 0.3201;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.005;

                // for latticeTheta = 60 r = 0.31a
                NormalizedFreq1 = 0.271;
                NormalizedFreq2 = 0.2771;
                FreqDelta = 0.0001;// 0.0002;
                GraphFreqInterval = 0.001;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            //minBeta = 0.0;
            //maxBeta = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;//1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // 入力導波路の長さ(ロッド数)
            const int rodCnt_inputWg = 1;
            // 共振器のY方向ロッド数
            const int rodCntY_cavity = 1;
            // 計算領域のX方向ロッド数
            int rodCntX = rodCnt_inputWg * 2 + rodCntDiscon + (rodCntDiscon - 1) + defectRodCnt_cavity;
            if (spacingRodCnt % 2 == 0)
            {
                rodCntX++;
            }
            // 計算領域のY方向ロッド数
            int rodCntY = rodCntHalf * 2 + defectRodCnt * 2 + spacingRodCnt * 2 + rodCntY_cavity;
            // 下端Y座標
            double bottomY = WaveguideWidth - rodCntY * rodDistanceY;
            // 右端X座標
            double port2_X = rodCntX * rodDistanceX;

            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            int ndivPlus = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            IList<uint> id_e_F1_cavity = new List<uint>();
            IList<uint> id_e_F2_cavity = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(inputWgLength, bottomY)); // 頂点4
                    pts.Add(new CVector2D(port2_X - inputWgLength, bottomY)); // 頂点5
                    pts.Add(new CVector2D(port2_X, bottomY)); // 頂点6
                    pts.Add(new CVector2D(port2_X, bottomY + WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(port2_X - inputWgLength, bottomY + WaveguideWidth)); // 頂点8
                    pts.Add(new CVector2D(port2_X - inputWgLength, WaveguideWidth)); // 頂点9
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点10
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 10).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(5, 8).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys = new List<double>();
                IList<double> ys_rod = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                // 境界上にロッドのある格子
                // 境界上のロッドの頂点
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY;
                    ys_rod.Add(y0);
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        ys_rod.Add(y1);
                        ys_rod.Add(y2);
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY;
                    ys_rod.Add(y0);
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        ys_rod.Add(y1);
                        ys_rod.Add(y2);
                    }
                }
                foreach (double y_rod in ys_rod)
                {
                    ys.Add(y_rod);
                }
                // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                double radiusMargin = rodDistanceY * 0.01;
                // 境界上にロッドのある格子
                // ロッドの外
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }

                // 境界上にロッドのない格子
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == 0 && k == 0) continue;
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        ys.Add(y_divpt);
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == (rodCntHalf - 1) && k == ndivForOneLattice) continue;
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        ys.Add(y_divpt);
                    }
                }
                // 欠陥部
                for (int i = 0; i <= (defectRodCnt * ndivForOneLattice); i++)
                {
                    if (!isShift180 && (i == 0 || i == (defectRodCnt * ndivForOneLattice))) continue;
                    double y_divpt = rodDistanceY * (rodCntHalf + defectRodCnt) - i * (rodDistanceY / ndivForOneLattice);
                    ys.Add(y_divpt);
                }

                // 昇順でソート
                double[] yAry = ys.ToArray();
                Array.Sort(yAry);
                ndivPlus = yAry.Length + 1;

                // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 入力導波路 外側境界
                // 入力導波路 内部側境界
                // 出力導波路 外側境界
                // 出力導波路 内部側境界
                for (int boundaryIndex = 0; boundaryIndex < 4; boundaryIndex++)
                {
                    bool isInRod = false;
                    for (int i = 0; i < yAry.Length; i++)
                    {
                        uint id_e = 0;
                        double x1 = 0.0;
                        double y_pt = 0.0;
                        IList<uint> work_id_e_rod_B = null;
                        IList<uint> work_id_v_list_rod_B = null;
                        int yAryIndex = 0;

                        if (boundaryIndex == 0)
                        {
                            // 入力導波路 外側境界
                            id_e = 1;
                            x1 = 0.0;
                            y_pt = yAry[i];
                            yAryIndex = i;
                            work_id_e_rod_B = id_e_rod_B1;
                            work_id_v_list_rod_B = id_v_list_rod_B1;
                        }
                        else if (boundaryIndex == 1)
                        {
                            // 入力導波路 内側境界
                            id_e = 11;
                            x1 = inputWgLength;
                            y_pt = yAry[yAry.Length - 1 - i];
                            yAryIndex = yAry.Length - 1 - i;
                            work_id_e_rod_B = id_e_rod_B2;
                            work_id_v_list_rod_B = id_v_list_rod_B2;
                        }
                        else if (boundaryIndex == 2)
                        {
                            // 出力導波路 外側境界
                            id_e = 6;
                            x1 = port2_X;
                            y_pt = yAry[yAry.Length - 1 - i] + bottomY;
                            yAryIndex = yAry.Length - 1 - i;
                            work_id_e_rod_B = id_e_rod_B3;
                            work_id_v_list_rod_B = id_v_list_rod_B3;
                        }
                        else if (boundaryIndex == 3)
                        {
                            // 出力導波路 内側境界
                            id_e = 12;
                            x1 = port2_X - inputWgLength;
                            y_pt = yAry[yAry.Length - 1 - i] + bottomY;
                            yAryIndex = yAry.Length - 1 - i;
                            work_id_e_rod_B = id_e_rod_B4;
                            work_id_v_list_rod_B = id_v_list_rod_B4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x1, y_pt));
                        uint id_v_add = resAddVertex.id_v_add;
                        uint id_e_add = resAddVertex.id_e_add;
                        System.Diagnostics.Debug.Assert(id_v_add != 0);
                        System.Diagnostics.Debug.Assert(id_e_add != 0);
                        if (isInRod)
                        {
                            work_id_e_rod_B.Add(id_e_add);
                        }
                        bool contains = false;
                        foreach (double y_rod in ys_rod)
                        {
                            if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                            {
                                contains = true;
                                break;
                            }
                        }
                        if (contains)
                        {
                            work_id_v_list_rod_B.Add(id_v_add);

                            if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                    }
                }

                int bRodCntHalf = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));

                /////////////////////////////////////////////////////////////////////////////
                // ロッドを追加

                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    double y_B = 0.0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        y_B = WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        y_B = WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else if (colIndex == 2)
                    {
                        // 出力境界 内側
                        x_B = port2_X - inputWgLength;
                        y_B = bottomY + WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = y_B - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = 0;
                                // 左のロッド
                                lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }

                                }
                                double x0 = x_B;
                                double y0 = (y_B - WaveguideWidth) + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = 0;
                                // 左のロッド
                                lId = WgCadUtil.AddLeftRod(
                                     cad2d,
                                     baseLoopId,
                                     work_id_v0,
                                     id_v1,
                                     work_id_v2,
                                     x0,
                                     y0,
                                     rodRadius,
                                     rodCircleDiv,
                                     rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0.0;
                    double y_B = 0.0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        y_B = WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (colIndex == 1)
                    {
                        // 出力境界 内側
                        x_B = port2_X - inputWgLength;
                        y_B = bottomY + WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (colIndex == 2)
                    {
                        // 出力境界 外側
                        x_B = port2_X;
                        y_B = bottomY + WaveguideWidth;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);

                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = y_B - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = 0;
                                // 右のロッド
                                lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        System.Diagnostics.Debug.Assert(false);
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = (y_B - WaveguideWidth) + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = 0;
                                // 右のロッド
                                lId = WgCadUtil.AddRightRod(
                                  cad2d,
                                  baseLoopId,
                                  id_v0,
                                  id_v1,
                                  id_v2,
                                  x0,
                                  y0,
                                  rodRadius,
                                  rodCircleDiv,
                                  rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央ロッド
                int periodCntInputWg1 = rodCnt_inputWg;
                int periodCntX = rodCntX;

                // 中央のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();

                // 中央のロッド
                for (int col = 1; col <= (periodCntX * 2 - 1); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntX - periodCntInputWg1) * 2) continue; // 出力導波路内部境界  (既にロッド追加済み)
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (col >= (periodCntInputWg1 * 2 + 1) && col < (periodCntX - periodCntInputWg1) * 2)
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (col >= ((periodCntX - periodCntInputWg1) * 2 + 1) && col < periodCntX * 2)
                    {
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 中央のロッド
                    int port2_stRodIndex = (rodCntY - (rodCntHalf * 2 + defectRodCnt));
                    for (int i = 0; i < rodCntY; i++)
                    {
                        double rr = rodRadius;
                        int nr = rodRadiusDiv;
                        if (inputWgNo == 0)
                        {
                            nr = 2; // 内部の分割数調整
                        }

                        // 入出力領域は導波路幅のみ
                        if (col < periodCntInputWg1 * 2)
                        {
                            if (i >= (rodCntHalf * 2 + defectRodCnt)) continue;
                        }
                        if (col >= (periodCntX * 2 - periodCntInputWg1 * 2))
                        {
                            if (i < port2_stRodIndex) continue;
                        }

                        // ロッドの位置のオフセット
                        double ofs_x_rod = 0.0;
                        double ofs_y_rod = 0.0;

                        // 導波路欠陥部
                        if (col <= (rodCntX_Wg * 2))
                        {
                            if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue;
                        }
                        if (col >= (periodCntX - rodCntX_Wg) * 2)
                        {
                            if (i >= (rodCntY - rodCntHalf - defectRodCnt) && i < (rodCntY - rodCntHalf)) continue;
                        }

                        // 共振器
                        int col_cavity_min = (periodCntInputWg1 * 2 + rodCntDiscon * 2);
                        int col_cavity_max = (periodCntInputWg1 * 2 + rodCntDiscon * 2 + defectRodCnt_cavity * 2 - 2);
                        if (spacingRodCnt % 2 == 0)
                        {
                            col_cavity_min++;
                            col_cavity_max++;
                        }
                        if (col >= col_cavity_min && col <= col_cavity_max)
                        {
                            if (i >= (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity)
                                && i <= (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - 1))
                            {
                                continue;
                            }
                        }
                        // 共振器の左右のロッドを外方向にずらす
                        if (isOpt)
                        {
                            if (defectRodCnt_cavity == 3)
                            {
                                // for defectRodCnt_cavity == 3
                                double ofs_ratio = 0.20;
                                if (i >= (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity)
                                    && i <= (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - 1))
                                {
                                    if (col == (col_cavity_min - 2))
                                    {
                                        ofs_x_rod = -ofs_ratio * latticeA;
                                    }
                                    else if (col == (col_cavity_max + 2))
                                    {
                                        ofs_x_rod = ofs_ratio * latticeA;
                                    }
                                }
                            }
                            else if (defectRodCnt_cavity == 1)
                            {
                                double rm = 0.25 * latticeA;
                                double ofsLen = (rodRadius - rm);
                                // for defectRodCnt_cavity == 1
                                // 左
                                if (col == (col_cavity_min - 2) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity))
                                {
                                    rr = rm;
                                    ofs_x_rod = -ofsLen;
                                }
                                // 左下
                                if (col == (col_cavity_min - 1) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity + 1))
                                {
                                    rr = rm;
                                    ofs_x_rod = -ofsLen * 1.0 / 2.0;
                                    ofs_y_rod = -ofsLen * Math.Sqrt(3.0) / 2.0;
                                }
                                // 右下
                                if (col == (col_cavity_min + 1) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity + 1))
                                {
                                    rr = rm;
                                    ofs_x_rod = ofsLen * 1.0 / 2.0;
                                    ofs_y_rod = -ofsLen * Math.Sqrt(3.0) / 2.0;
                                }
                                // 右
                                if (col == (col_cavity_min + 2) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity))
                                {
                                    rr = rm;
                                    ofs_x_rod = ofsLen;
                                }
                                // 右上
                                if (col == (col_cavity_min + 1) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity - 1))
                                {
                                    rr = rm;
                                    ofs_x_rod = ofsLen * 1.0 / 2.0;
                                    ofs_y_rod = ofsLen * Math.Sqrt(3.0) / 2.0;
                                }
                                // 左上
                                if (col == (col_cavity_min - 1) && i == (rodCntY - rodCntHalf - defectRodCnt - spacingRodCnt - rodCntY_cavity - 1))
                                {
                                    rr = rm;
                                    ofs_x_rod = -ofsLen * 1.0 / 2.0;
                                    ofs_y_rod = ofsLen * Math.Sqrt(3.0) / 2.0;
                                }
                            }
                        }

                        if ((col % 2 == 1 && (Math.Abs(rodCntY - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(rodCntY - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col + ofs_x_rod;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5 + ofs_y_rod;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, rodCircleDiv, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(空洞部分)(左の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_cavity = new List<uint>();
                int rodCntY_F1_cavity = rodCntY - (rodCntHalf * 2 + defectRodCnt);
                for (int i = (rodCntY_F1_cavity - 1); i >= 0; i--)
                {
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 0);
                    if (isRodLattice)
                    {
                        uint id_e = 3;
                        double x0 = inputWgLength;
                        double y0 = 0.0 - rodDistanceY * i - rodDistanceY * 0.5;
                        double x_cross = inputWgLength;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_cavity.Add(id_v_add);
                            id_e_F1_cavity.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、左境界と接する半円)
                for (int i = 0; i < rodCntY_F1_cavity; i++)
                {
                    // 不連続領域
                    uint baseLoopId = 2;
                    // 左の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 0);
                    if (isRodLattice)
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(右半分)を追加
                            double x0 = inputWgLength;
                            double y0 = 0.0 - rodDistanceY * i - rodDistanceY * 0.5;
                            int row2 = (rodCntY_F1_cavity - 1 - i) / 2;
                            System.Diagnostics.Debug.Assert(row2 >= 0);
                            uint id_v0 = id_v_list_F1_cavity[row2 * 3 + 0];
                            uint id_v1 = id_v_list_F1_cavity[row2 * 3 + 1];
                            uint id_v2 = id_v_list_F1_cavity[row2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                90.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }
                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(ベンド部分)(右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F2_cavity = new List<uint>();
                int rodCntY_F2_cavity = rodCntY - (rodCntHalf * 2 + defectRodCnt);
                for (int i = 0; i <= (rodCntY_F2_cavity - 1); i++)
                {
                    // 右の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 1);
                    if (isRodLattice)
                    {
                        uint id_e = 8;
                        double x0 = port2_X - inputWgLength;
                        double y0 = WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                        double x_cross = port2_X - inputWgLength;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_cavity.Add(id_v_add);
                            id_e_F2_cavity.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、右境界と接する半円)
                for (int i = (rodCntY_F2_cavity - 1); i >= 0; i--)
                {
                    // 不連続領域
                    uint baseLoopId = 2;
                    // 右の強制境界と交差するロッド
                    bool isRodLattice = false;
                    isRodLattice = (i % 2 == 1);
                    if (isRodLattice)
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(左半分)を追加
                            double x0 = port2_X - inputWgLength;
                            double y0 = WaveguideWidth - rodDistanceY * i - rodDistanceY * 0.5;
                            int row2 = i / 2;
                            System.Diagnostics.Debug.Assert(row2 >= 0);
                            uint id_v0 = id_v_list_F2_cavity[row2 * 3 + 0];
                            uint id_v1 = id_v_list_F2_cavity[row2 * 3 + 1];
                            uint id_v2 = id_v_list_F2_cavity[row2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                270.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[3 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 3] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[3 + rodLoopIds.Count];
                for (int i = 0; i < 3; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 3] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 2ポート情報リスト作成
            const uint portCnt = 2;
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                // 最小、最大波数ベクトル
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[8 + id_e_F1.Count + id_e_F2.Count + id_e_F1_cavity.Count + id_e_F2_cavity.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 5;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                eId_cad_list[6] = 9;
                eId_cad_list[7] = 10;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[8 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[8 + id_e_F1.Count + i] = id_e_F2[i];
                }
                for (int i = 0; i < id_e_F1_cavity.Count; i++)
                {
                    eId_cad_list[8 + id_e_F1.Count + id_e_F2.Count + i] = id_e_F1_cavity[i];
                }
                for (int i = 0; i < id_e_F2_cavity.Count; i++)
                {
                    eId_cad_list[8 + id_e_F1.Count + id_e_F2.Count + id_e_F1_cavity.Count + i] = id_e_F2_cavity[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 6;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 3 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 11;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 12;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 4 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                double ymax = WaveguideWidth;
                if (portIndex == 0)
                {
                    ymax = WaveguideWidth;
                }
                else if (portIndex == 1)
                {
                    ymax = bottomY + WaveguideWidth;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (coord[1] >= (ymax - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (ymax - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 18
0
        /// <summary>
        /// PC導波路 三角形格子 直線
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 入出力導波路が同じ?
            //IsInoutWgSame = false;// true;

            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            int propModeCntToSolve = 3;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            // 高次モード入射
            //int incidentModeIndex = 1;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0;
            // 最大屈折率
            double maxEffN = 0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0; // for latticeTheta = 45 r = 0.18a
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5; // for latticeTheta = 45 r = 0.18a
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a

            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false; // for latticeTheta = 30 r = 0.35a air hole
            //bool isShift180 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
            // ロッドの数(半分)
            //const int rodCntHalf = 5; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodCntHalf = 5; // for latticeTheta = 60 r = 0.30a air hole
            //const int rodCntHalf = 6; // for latticeTheta = 30 r = 0.30a air hole
            const int rodCntHalf = 3;// 5;
            // 欠陥ロッド数
            //const int defectRodCnt = 3; // for latticeTheta = 45 r = 0.18a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            //double latticeTheta = 45.0; // for latticeTheta = 45 r = 0.18a dielectric rod
            double latticeTheta = 60.0; // for latticeTheta = 60 r = 0.30a air hole
            //double latticeTheta = 30.0; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            // ロッドの半径
            //double rodRadiusRatio = 0.18;  // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole
            //double rodRadiusRatio = 0.35; // for latticeTheta = 60 r = 0.35a air hole
            //double rodRadiusRatio = 0.36; // for latticeTheta = 60 r = 0.36a air hole
            //double rodRadiusRatio = 0.29; // for latticeTheta = 60 r = 0.29a air hole
            //double rodRadiusRatio = 0.30; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            double rodRadiusRatio = 0.32;
            // ロッドの比誘電率
            //double rodEps = 3.4 * 3.4; // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodEps = 4.3 * 4.3; // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.30a air hole
            //double rodEps = 2.8 * 2.8; // for latticeTheta = 60 r = 0.35a air hole
            //double rodEps = 3.32 * 3.32; // for latticeTheta = 60 r = 0.36a air hole
            //double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.29a air hole
            //double rodEps = 3.4 * 3.4; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            double rodEps = 3.476 * 3.476;
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 7; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int ndivForOneLattice = 5; // for latticeTheta = 45 r = 0.18a dielectric rod rotEps = 4.3
            //const int ndivForOneLattice = 10; // for latticeTheta = 60 r = 0.30a air hole
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.35a air hole
            //const int ndivForOneLattice = 6; // for latticeTheta = 30 r = 0.35a air hole
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.36a air hole
            //const int ndivForOneLattice = 6; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            const int ndivForOneLattice = 8;// 9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 8; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 2; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 4;
            const int rodCntDiscon = 4;

            // ロッドが1格子を超える?
            //bool isLargeRod = (rodRadiusRatio >= 0.25);
            bool isLargeRod = (rodRadiusRatio >= 0.5 * Math.Sin(latticeTheta * pi / 180.0));
            // 格子の数
            int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            if (isLargeRod)
            {
                rodDistanceY = WaveguideWidth / (double)(latticeCnt - 1);
            }
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 導波路不連続領域の長さ
            double disconLength = rodDistanceX * rodCntDiscon;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            if (Math.Abs(latticeTheta - 45.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 3.6
                //  even 1st
                //NormalizedFreq1 = 0.320;//0.320;
                //NormalizedFreq2 = 0.3601;//0.380;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                //  odd
                //NormalizedFreq1 = 0.384;
                //NormalizedFreq2 = 0.432;
                //FreqDelta = 0.002;//0.001;
                //GraphFreqInterval = 0.01;
                //  even 2nd
                //NormalizedFreq1 = 0.420;
                //NormalizedFreq2 = 0.500;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 4.3
                NormalizedFreq1 = 0.260;
                NormalizedFreq2 = 0.3301;
                FreqDelta = 0.002;
                GraphFreqInterval = 0.01;
            }
            else if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit
                    || Math.Abs(latticeTheta - 30.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 60 r = 0.30a air hole
                //NormalizedFreq1 = 0.267; //0.270;
                //NormalizedFreq2 = 0.2871; //0.330;//0.3401;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004; //0.01;
                // for latticeTheta = 60 r = 0.35a air hole
                //NormalizedFreq1 = 0.294;//0.295;// 0.280;
                //NormalizedFreq2 = 0.315;//0.320;// 0.3301;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.002;// 0.010;
                // for latticeTheta = 60 r = 0.36a air hole
                //  wide-band
                //NormalizedFreq1 = 0.236;
                //NormalizedFreq2 = 0.3081;
                //FreqDelta = 0.0005;//0.001;
                //GraphFreqInterval = 0.010;
                // for latticeTheta = 60 r = 0.29a air hole
                //NormalizedFreq1 = 0.268;
                //NormalizedFreq2 = 0.2821;
                //FreqDelta = 0.0005;//0.001;
                //GraphFreqInterval = 0.002;
                // for latticeTheta = 30 r = 0.30a air hole n = 3.4
                //NormalizedFreq1 = 0.230;
                //NormalizedFreq2 = 0.256;//0.260;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004;

                NormalizedFreq1 = 0.215;
                NormalizedFreq2 = 0.2401;
                FreqDelta = 0.0005;
                GraphFreqInterval = 0.005;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            //minBeta = 0.0;
            //maxBeta = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;//1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            int ndivPlus = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(inputWgLength + disconLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(inputWgLength * 2 + disconLength, 0.0)); // 頂点5
                    pts.Add(new CVector2D(inputWgLength * 2 + disconLength, WaveguideWidth)); // 頂点6
                    pts.Add(new CVector2D(inputWgLength + disconLength, WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点8
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 8).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(4, 7).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys = new List<double>();
                IList<double> ys_rod = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                int outofAreaRodPtCnt_row_top = 0;
                int outofAreaRodPtCnt_row_bottom = 0;
                // 境界上にロッドのある格子
                // 境界上のロッドの頂点
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY;
                    if (isLargeRod)
                    {
                        y0 += 0.5 * rodDistanceY;
                    }
                    if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                    {
                        ys_rod.Add(y0);
                    }
                    else
                    {
                        if (isLargeRod && i == 0)
                        {
                            outofAreaRodPtCnt_row_top++;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y1);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y2);
                        }
                        else
                        {
                            if (isLargeRod && i == 0)
                            {
                                outofAreaRodPtCnt_row_top++;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY;
                    if (isLargeRod)
                    {
                        y0 -= 0.5 * rodDistanceY;
                    }
                    if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                    {
                        ys_rod.Add(y0);
                    }
                    else
                    {
                        if (isLargeRod && i == (rodCntHalf - 1))
                        {
                            outofAreaRodPtCnt_row_bottom++;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y1);
                        }
                        else
                        {
                            if (isLargeRod && i == (rodCntHalf - 1))
                            {
                                outofAreaRodPtCnt_row_bottom++;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                }
                foreach (double y_rod in ys_rod)
                {
                    ys.Add(y_rod);
                }
                // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                double radiusMargin = rodDistanceY * 0.01;
                // 境界上にロッドのある格子
                // ロッドの外
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_rod += rodDistanceY * 0.5;
                            y_max_rod += rodDistanceY * 0.5;
                        }
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt -= rodDistanceY * 0.5;
                            if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                            y_min_rod -= rodDistanceY * 0.5;
                            y_max_rod -= rodDistanceY * 0.5;
                        }
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }

                // 境界上にロッドのない格子
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == 0 && k == 0) continue;
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_upper_rod = WaveguideWidth - i * rodDistanceY + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = WaveguideWidth - (i + 1) * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_upper_rod += rodDistanceY * 0.5;
                            y_max_lower_rod += rodDistanceY * 0.5;
                        }
                        bool isAddHalfRod_row_top = (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))));
                        if ((i != 0 || (i == 0 && isAddHalfRod_row_top))
                                && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }
                        if ((isShift180 || (!isShift180 && i != (rodCntHalf - 1)))
                            && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }

                        ys.Add(y_divpt);
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == (rodCntHalf - 1) && k == ndivForOneLattice) continue;
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_upper_rod = rodDistanceY * rodCntHalf - i * rodDistanceY + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = rodDistanceY * rodCntHalf - (i + 1) * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt -= rodDistanceY * 0.5;
                            if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                            y_min_upper_rod -= rodDistanceY * 0.5;
                            y_max_lower_rod -= rodDistanceY * 0.5;
                        }
                        bool isAddHalfRod_row_bottom = (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))));
                        if ((isShift180 || (!isShift180 && i != 0))
                            && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }
                        if ((i != (rodCntHalf - 1) || (i == (rodCntHalf - 1) && isAddHalfRod_row_bottom))
                            && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }

                        ys.Add(y_divpt);
                    }
                }
                // 欠陥部
                for (int i = 0; i <= (defectRodCnt * ndivForOneLattice); i++)
                {
                    if (!isShift180 && (i == 0 || i == (defectRodCnt * ndivForOneLattice))) continue;
                    double y_divpt = rodDistanceY * (rodCntHalf + defectRodCnt) - i * (rodDistanceY / ndivForOneLattice);
                    double y_min_upper_rod = rodDistanceY * (rodCntHalf + defectRodCnt) + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                    double y_max_lower_rod = rodDistanceY * rodCntHalf - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                    if (isLargeRod)
                    {
                        y_divpt -= rodDistanceY * 0.5;
                        y_min_upper_rod -= rodDistanceY * 0.5;
                        y_max_lower_rod -= rodDistanceY * 0.5;
                    }
                    if (isLargeRod && isShift180)
                    {
                        // for isLargeRod == true
                        if (y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit)
                                || y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit)
                            )
                        {
                            continue;
                        }
                    }
                    ys.Add(y_divpt);
                }

                // 昇順でソート
                double[] yAry = ys.ToArray();
                Array.Sort(yAry);
                ndivPlus = yAry.Length + 1;

                // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                // 入力導波路 外側境界
                // 入力導波路 内部側境界
                // 出力導波路 外側境界
                // 出力導波路 内部側境界
                for (int boundaryIndex = 0; boundaryIndex < 4;  boundaryIndex++)
                {
                    bool isInRod = false;
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                    {
                        isInRod = true;
                    }

                    for (int i = 0; i < yAry.Length; i++)
                    {
                        uint id_e = 0;
                        double x1 = 0.0;
                        double y_pt = 0.0;
                        IList<uint> work_id_e_rod_B = null;
                        IList<uint> work_id_v_list_rod_B = null;
                        if (boundaryIndex == 0)
                        {
                            // 入力導波路 外側境界
                            id_e = 1;
                            x1 = 0.0;
                            y_pt = yAry[i];
                            work_id_e_rod_B = id_e_rod_B1;
                            work_id_v_list_rod_B = id_v_list_rod_B1;
                        }
                        else if (boundaryIndex == 1)
                        {
                            // 入力導波路 内側境界
                            id_e = 9;
                            x1 = inputWgLength;
                            y_pt = yAry[yAry.Length - 1 - i];
                            work_id_e_rod_B = id_e_rod_B2;
                            work_id_v_list_rod_B = id_v_list_rod_B2;
                        }
                        else if (boundaryIndex == 2)
                        {
                            // 出力導波路 外側境界
                            id_e = 5;
                            x1 = inputWgLength * 2 + disconLength;
                            y_pt = yAry[yAry.Length - 1 - i];
                            work_id_e_rod_B = id_e_rod_B3;
                            work_id_v_list_rod_B = id_v_list_rod_B3;
                        }
                        else if (boundaryIndex == 3)
                        {
                            // 出力導波路 内側境界
                            id_e = 10;
                            x1 = inputWgLength + disconLength;
                            y_pt = yAry[yAry.Length - 1 - i];
                            work_id_e_rod_B = id_e_rod_B4;
                            work_id_v_list_rod_B = id_v_list_rod_B4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x1, y_pt));
                        uint id_v_add = resAddVertex.id_v_add;
                        uint id_e_add = resAddVertex.id_e_add;
                        System.Diagnostics.Debug.Assert(id_v_add != 0);
                        System.Diagnostics.Debug.Assert(id_e_add != 0);
                        if (isInRod)
                        {
                            work_id_e_rod_B.Add(id_e_add);
                        }
                        bool contains = false;
                        foreach (double y_rod in ys_rod)
                        {
                            if (Math.Abs(y_rod - y_pt) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                            {
                                contains = true;
                                break;
                            }
                        }
                        if (contains)
                        {
                            work_id_v_list_rod_B.Add(id_v_add);

                            if (isLargeRod
                                && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                            {
                                if ((work_id_v_list_rod_B.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if ((work_id_v_list_rod_B.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                            else
                            {
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                        if (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            if (i == (yAry.Length - 1))
                            {
                                System.Diagnostics.Debug.Assert(isInRod == true);
                                work_id_e_rod_B.Add(id_e);
                            }
                        }
                    }
                }

                int bRodCntHalf = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                if (!isLargeRod
                    || (isLargeRod &&
                           (isShift180 && (rodCntHalf % 2 == 0)) || (!isShift180 && (rodCntHalf % 2 == 1))
                       )
                    )
                {
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                }
                else
                {
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                }

                /////////////////////////////////////////////////////////////////////////////
                // ロッドを追加
                uint id_e_F1_new_port1 = 0;
                uint id_e_F2_new_port1 = 0;
                uint id_e_F1_discon_new_port1 = 0;
                uint id_e_F2_discon_new_port1 = 0;
                uint id_e_F1_new_port2 = 0;
                uint id_e_F2_new_port2 = 0;
                uint id_e_F1_discon_new_port2 = 0;
                uint id_e_F2_discon_new_port2 = 0;
                uint id_v_B1_top_rod_center = 1;
                uint id_v_B1_bottom_rod_center = 2;
                uint id_v_B2_top_rod_center = 8;
                uint id_v_B2_bottom_rod_center = 3;
                uint id_v_B3_top_rod_center = 6;
                uint id_v_B3_bottom_rod_center = 5;
                uint id_v_B4_top_rod_center = 7;
                uint id_v_B4_bottom_rod_center = 4;

                // 左右のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_rodQuarter = new List<uint>();
                IList<uint> id_v_list_F2_rodQuarter = new List<uint>();

                for (int colIndex = 0; colIndex < 4; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 上の強制境界と交差する点
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 入力境界 外側
                            // 入力導波路領域
                            id_e_list[0] = 8;
                            id_e_list[1] = 8;
                        }
                        else if (colIndex == 1)
                        {
                            // 入力境界内側
                            // 不連続領域
                            id_e_list[0] = 8;
                            id_e_list[1] = 7;
                        }
                        else if (colIndex == 2)
                        {
                            // 出力境界内側
                            // 不連続領域
                            id_e_list[0] = 7;
                            id_e_list[1] = 6;
                        }
                        else if (colIndex == 3)
                        {
                            // 出力境界外側
                            // 出力導波路領域
                            id_e_list[0] = 6;
                            id_e_list[1] = 6;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = 0.0;
                        if (colIndex == 0 || colIndex == 1)
                        {
                            // 入力側
                            x0 = (rodDistanceX) * colIndex;
                        }
                        else if (colIndex == 2 || colIndex == 3)
                        {
                            // 出力側
                            x0 = inputWgLength + disconLength + (rodDistanceX) * (colIndex - 2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double y0 = WaveguideWidth;
                        double y_cross = WaveguideWidth;
                        double[] x_cross_list = new double[2];
                        x_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        x_cross_list[1] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double x_cross = x_cross_list[k];
                            if (colIndex == 0 || colIndex == 1)
                            {
                                if (x_cross <= (0.0 + Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else if (colIndex == 2 || colIndex == 3)
                            {
                                if (x_cross >= (inputWgLength * 2.0 + disconLength - Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_rodQuarter.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // 上側境界の中央部分の辺IDが新しくなる
                            if (colIndex == 0 && k == 1)
                            {
                                // 入力部
                                // 不変
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                // 不連続部
                                id_e_F1_new_port1 = id_e_add;
                            }
                            else if (colIndex == 1 && k == 1)
                            {
                                // 不連続部
                                //不変
                            }
                            else if (colIndex == 2 && k == 0)
                            {
                                // 不連続部(出力側)
                                id_e_F1_discon_new_port1 = id_e_add;
                                id_e_F1_discon_new_port2 = id_e_add;
                            }
                            else if (colIndex == 2 && k == 1)
                            {
                                // 不連続部(出力側)
                                // 不変
                            }
                            else if (colIndex == 3 && k == 0)
                            {
                                // 出力部
                                id_e_F1_new_port2 = id_e_add;
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                for (int colIndex = 3; colIndex >= 0; colIndex--) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 下の強制境界と交差するロッド
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 入力境界 外側
                            // 入力導波路領域
                            id_e_list[0] = 2;
                            id_e_list[1] = 2;
                        }
                        else if (colIndex == 1)
                        {
                            // 入力境界内側
                            // 不連続領域
                            id_e_list[0] = 3;
                            id_e_list[1] = 2;
                        }
                        else if (colIndex == 2)
                        {
                            // 出力境界内側
                            // 不連続領域
                            id_e_list[0] = 4;
                            id_e_list[1] = 3;
                        }
                        else if (colIndex == 3)
                        {
                            // 入力境界 外側
                            // 入力導波路領域
                            id_e_list[0] = 4;
                            id_e_list[1] = 4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = 0.0;
                        if (colIndex == 0 || colIndex == 1)
                        {
                            // 入力側
                            x0 = (rodDistanceX) * colIndex;
                        }
                        else if (colIndex == 2 || colIndex == 3)
                        {
                            // 出力側
                            x0 = inputWgLength + disconLength + (rodDistanceX) * (colIndex - 2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double y0 = 0.0;
                        double y_cross = 0.0;
                        double[] x_cross_list = new double[2];
                        x_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        x_cross_list[1] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double x_cross = x_cross_list[k];
                            if (colIndex == 0 || colIndex == 1)
                            {
                                if (x_cross <= (0.0 + Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else if (colIndex == 2 || colIndex == 3)
                            {
                                if (x_cross >= (inputWgLength * 2.0 + disconLength - Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_rodQuarter.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // 下側境界の中央部分の辺IDが新しくなる
                            //   Note:colInde == 3から追加されることに注意
                            if (colIndex == 0 && k == 0)
                            {
                                // 入力部
                                id_e_F2_new_port1 = id_e_add;
                            }
                            else if (colIndex == 0 && k == 1)
                            {
                                // 入力部
                                // 不変
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                // 不連続部
                                id_e_F2_discon_new_port1 = id_e_add;
                                id_e_F2_discon_new_port2 = id_e_add;
                            }
                            else if (colIndex == 2 && k == 1)
                            {
                                // 不連続部(出力側)
                                // 不変
                            }
                            else if (colIndex == 2 && k == 0)
                            {
                                // 不連続部(出力側)
                                id_e_F2_new_port2 = id_e_add;
                            }
                            else if (colIndex == 3 && k == 1)
                            {
                                // 出力部
                                // 不変
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    uint work_id_v_B_top_rod_center = 0;
                    uint work_id_v_B_bottom_rod_center = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        work_id_v_B_top_rod_center = id_v_B1_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B1_bottom_rod_center;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                       // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        work_id_v_B_top_rod_center = id_v_B2_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B2_bottom_rod_center;
                        isReverse = true;
                    }
                    else if (colIndex == 2)
                    {
                        // 出力境界 内側
                        x_B = inputWgLength + disconLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        work_id_v_B_top_rod_center = id_v_B4_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B4_bottom_rod_center;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            int ofs_index_left = 0;
                            if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                            {
                                ofs_index_left = -outofAreaRodPtCnt_row_top;
                            }
                            bool isQuarterRod = false;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                                    int index_v1 = (work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                                    int index_v2 = (work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_top_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1];
                                        id_v2 = id_v_list_F1_rodQuarter[0 + colIndex * 2]; // 1つ飛ばしで参照;
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_left;
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_left;
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_left;
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0];
                                        id_v0 = id_v_list_F1_rodQuarter[0 + colIndex * 2]; // 1つ飛ばしで参照
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_top_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                if (isLargeRod)
                                {
                                    y0 += rodDistanceY * 0.5;
                                }
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        work_id_v2,
                                        id_v1,
                                        work_id_v0,
                                        0.0,
                                        true);
                                }
                                else
                                {
                                    // 左のロッド
                                    lId = WgCadUtil.AddLeftRod(
                                        cad2d,
                                        baseLoopId,
                                        work_id_v0,
                                        id_v1,
                                        work_id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }

                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            int ofs_index_left = 0;
                            if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                            {
                                ofs_index_left = -outofAreaRodPtCnt_row_top;
                            }
                            bool isQuarterRod = false;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                        id_v0 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 1 - colIndex * 2]; // 1つ飛ばしで参照
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1]; // DEBUG
                                        id_v2 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 1 - colIndex * 2]; // 1つ飛ばしで参照
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }

                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                if (isLargeRod)
                                {
                                    y0 -= rodDistanceY * 0.5;
                                }
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        work_id_v2,
                                        id_v1,
                                        work_id_v0,
                                        90.0,
                                        true);
                                }
                                else
                                {
                                    // 左のロッド
                                    lId = WgCadUtil.AddLeftRod(
                                         cad2d,
                                         baseLoopId,
                                         work_id_v0,
                                         id_v1,
                                         work_id_v2,
                                         x0,
                                         y0,
                                         rodRadius,
                                         rodCircleDiv,
                                         rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    uint work_id_v_B_top_rod_center = 0;
                    uint work_id_v_B_bottom_rod_center = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        work_id_v_B_top_rod_center = id_v_B2_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B2_bottom_rod_center;
                    }
                    else if (colIndex == 1)
                    {
                        // 出力境界 内側
                        x_B = inputWgLength + disconLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        work_id_v_B_top_rod_center = id_v_B4_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B4_bottom_rod_center;
                    }
                    else if (colIndex == 2)
                    {
                        // 出力境界 外側
                        x_B = inputWgLength * 2.0 + disconLength;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        work_id_v_B_top_rod_center = id_v_B3_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B3_bottom_rod_center;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            int ofs_index_top = 0;
                            if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                            {
                                ofs_index_top = -outofAreaRodPtCnt_row_top;
                            }
                            bool isQuarterRod = false;

                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_top;
                                    int index_v1 = (work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_top;
                                    int index_v2 = (work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = id_v_B2_top_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1]; //DEBUG
                                        id_v2 = id_v_list_F1_rodQuarter[1 + colIndex * 2]; // 1つ飛ばしで参照;
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                        id_v0 = id_v_list_F1_rodQuarter[1 + colIndex * 2];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_top_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                if (isLargeRod)
                                {
                                    y0 += rodDistanceY * 0.5;
                                }
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v2,
                                        id_v1,
                                        id_v0,
                                        270.0,
                                        true);
                                }
                                else
                                {
                                    // 右のロッド
                                    lId = WgCadUtil.AddRightRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            int ofs_index_top = 0;
                            if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                            {
                                ofs_index_top = -outofAreaRodPtCnt_row_top;
                            }
                            bool isQuarterRod = false;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0]; //DEBUG
                                        id_v0 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 2 - colIndex * 2]; // 1つ飛ばしで参照
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                else
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1]; // DEBUG
                                        id_v2 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 2 - colIndex * 2]; // 1つ飛ばしで参照
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                if (isLargeRod)
                                {
                                    y0 -= rodDistanceY * 0.5;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v2,
                                        id_v1,
                                        id_v0,
                                        180.0,
                                        true);
                                }
                                else
                                {
                                    // 右のロッド
                                    lId = WgCadUtil.AddRightRod(
                                      cad2d,
                                      baseLoopId,
                                      id_v0,
                                      id_v1,
                                      id_v2,
                                      x0,
                                      y0,
                                      rodRadius,
                                      rodCircleDiv,
                                      rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央ロッド
                int periodCntInputWg1 = 1;
                int periodCntInputWg2 = 1;
                int periodCntX = periodCntInputWg1 + rodCntDiscon  + periodCntInputWg2;

                // 中央のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();
                for (int col = 1; col <= (periodCntX * 2 - 1); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntInputWg1 + rodCntDiscon) * 2) continue; // 出力導波路内部境界  (既にロッド追加済み)
                    if (col == (periodCntX * 2)) continue; // 出力導波路外側境界  (既にロッド追加済み)
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        inputWgNo = 1;
                    }
                    else if (col >= (periodCntInputWg1 * 2 + 1) && col < (periodCntInputWg1 + rodCntDiscon) * 2)
                    {
                        inputWgNo = 0;
                    }
                    else if (col >= ((periodCntInputWg1 + rodCntDiscon) * 2 + 1) && col < ((periodCntInputWg1 + rodCntDiscon + periodCntInputWg2) * 2))
                    {
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 上の強制境界と交差するロッド
                    if (isLargeRod
                           && ((col % 2 == 1 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 1 : 0)))
                               || (col % 2 == 0 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 0 : 1)))
                                )
                        )
                    {
                        uint id_e = 0;
                        if (inputWgNo == 1)
                        {
                            id_e = 8;
                            //if (!isShift180)
                            if (id_e_F1_new_port1 != 0)
                            {
                                id_e = id_e_F1_new_port1;
                            }
                        }
                        else if (inputWgNo == 0)
                        {
                            id_e = 7;
                            //if (!isShift180)
                            if (id_e_F1_discon_new_port1 != 0)
                            {
                                id_e = id_e_F1_discon_new_port1;
                            }
                        }
                        else if (inputWgNo == 2)
                        {
                            id_e = 6;
                            //if (!isShift180)
                            if (id_e_F1_new_port2 != 0)
                            {
                                id_e = id_e_F1_new_port2;
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = rodDistanceX * 0.5 * col;
                        double y0 = WaveguideWidth;
                        double y_cross = WaveguideWidth;
                        double[] x_cross_list = new double[3];
                        x_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        x_cross_list[1] = x0; // 中心
                        x_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        foreach (double x_cross in x_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                for (int col = (periodCntX * 2 - 1); col >= 1; col--)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntInputWg1 + rodCntDiscon) * 2) continue; // 出力導波路内部境界  (既にロッド追加済み)
                    if (col == (periodCntX * 2)) continue; // 出力導波路外側境界  (既にロッド追加済み)
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        inputWgNo = 1;
                    }
                    else if (col >= (periodCntInputWg1 * 2 + 1) && col < (periodCntInputWg1 + rodCntDiscon) * 2)
                    {
                        inputWgNo = 0;
                    }
                    else if (col >= ((periodCntInputWg1 + rodCntDiscon) * 2 + 1) && col < ((periodCntInputWg1 + rodCntDiscon + periodCntInputWg2) * 2))
                    {
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 下の強制境界と交差するロッド
                    if (isLargeRod
                           && ((col % 2 == 1 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 1 : 0)))
                              || (col % 2 == 0 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 0 : 1)))
                              )
                        )
                    {
                        uint id_e = 0;
                        if (inputWgNo == 1)
                        {
                            id_e = 2;
                            //if (!isShift180)
                            if (id_e_F2_new_port1 != 0)
                            {
                                id_e = id_e_F2_new_port1;
                            }
                        }
                        else if (inputWgNo == 0)
                        {
                            id_e = 3;
                            //if (!isShift180)
                            if (id_e_F2_discon_new_port1 != 0)
                            {
                                id_e = id_e_F2_discon_new_port1;
                            }
                        }
                        else if (inputWgNo == 2)
                        {
                            id_e = 4;
                            //if (!isShift180)
                            if (id_e_F2_new_port2 != 0)
                            {
                                id_e = id_e_F2_new_port2;
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = rodDistanceX * 0.5 * col;
                        double y0 = 0.0;
                        double y_cross = 0.0;
                        double[] x_cross_list = new double[3];
                        x_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        x_cross_list[1] = x0; // 中心
                        x_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        foreach (double x_cross in x_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // 中央のロッド
                for (int col = 1; col <= (periodCntX * 2 - 1); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntInputWg1 + rodCntDiscon) * 2) continue; // 出力導波路内部境界  (既にロッド追加済み)
                    if (col == (periodCntX * 2)) continue; // 出力導波路外側境界  (既にロッド追加済み)
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (col >= (periodCntInputWg1 * 2 + 1) && col < (periodCntInputWg1 + rodCntDiscon) * 2)
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (col >= ((periodCntInputWg1 + rodCntDiscon) * 2 + 1) && col < ((periodCntInputWg1 + rodCntDiscon + periodCntInputWg2) * 2))
                    {
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 中央のロッド
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (isLargeRod &&
                              ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                                || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                            )
                        {
                            if (i == 0)
                            {
                                {
                                    // 半円(下半分)を追加
                                    double x0 = rodDistanceX * 0.5 * col;
                                    double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                    if (isLargeRod)
                                    {
                                        y0 += rodDistanceY * 0.5; // for isLargeRod
                                    }
                                    int col2 = col / 2;
                                    if (isShift180 && (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 2;
                                    }
                                    else if (!isShift180 && (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 2;
                                    }
                                    uint id_v0 = id_v_list_F1[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F1[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F1[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        0.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (isLargeRod
                               && ((col % 2 == 1 && (i % 2 == (isShift180 ? 1 : 0)))
                                    || (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                               )
                        {
                            if (i == (rodCntHalf - 1))
                            {
                                {
                                    // 半円(上半分)を追加
                                    double x0 = rodDistanceX * 0.5 * col;
                                    double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                    if (isLargeRod)
                                    {
                                        y0 -= rodDistanceY * 0.5; // for isLargeRod
                                    }
                                    int col2 = (periodCntX * 2 - 1 - col) / 2;
                                    if (isShift180 && (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 1;
                                    }
                                    else if (!isShift180 && (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 1;
                                    }
                                    uint id_v0 = id_v_list_F2[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F2[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F2[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        180.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && (i % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 -= rodDistanceY * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[3 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 3] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[3 + rodLoopIds.Count];
                for (int i = 0; i < 3; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 3] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 2ポート情報リスト作成
            const uint portCnt = 2;
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                // 最小、最大波数ベクトル
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[6 + id_e_F1.Count + id_e_F2.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 6;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[6 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[6 + id_e_F1.Count + i] = id_e_F2[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 5;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus - 1) * 3 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 9;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 10;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus - 1) * 4 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf))
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - (0.5 * rodDistanceY - rodRadius)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + (0.5 * rodDistanceY - rodRadius))) // dielectric rod
                        if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 19
0
        /// <summary>
        /// 誘電体スラブ導波路
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="timeLoopCnt"></param>
        /// <param name="timeDelta"></param>
        /// <param name="gaussianT0"></param>
        /// <param name="gaussianTp"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPmlLoopIdList"></param>
        /// <param name="PmlStPosXList"></param>
        /// <param name="FieldPortSrcBcId"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            ref double WaveguideWidth,
            ref bool isPCWaveguide,
            ref double latticeA,
            ref int timeLoopCnt,
            ref double timeDelta,
            ref double gaussianT0,
            ref double gaussianTp,
            ref double NormalizedFreqSrc,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double GraphFreqInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPmlLoopIdList,
            ref IList<bool> IsPmlYDirectionList,
            ref IList<double> PmlStPosXList,
            ref IList<double> PmlLengthList,
            ref uint FieldPortSrcBcId,
            ref IList<uint> VIdRefList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            WaveguideWidth = 3.0e-3 * 30 * 4;

            // メッシュの分割長さ
            //double meshL = WaveguideWidth * 1.0 / 60.0;
            //double meshL = WaveguideWidth * 1.0 / 65.0; // メモリ不足
            double meshL = WaveguideWidth * 1.0 / 61.0;
            double meshLForTimeDelta = meshL;

            // 形状設定で使用する単位長さ
            double unitLen = WaveguideWidth / 60.0;
            // PMLの長さ
            double pmlLength = 10 * unitLen;
            //double pmlLength = 12 * unitLen;
            // 導波管不連続領域の長さ
            double disconLength = 25.0 / 60.0 * WaveguideWidth;
            disconLength += 2.0 * pmlLength;

            // 誘電体スラブ導波路幅
            double slabWidth =WaveguideWidth / 30.0;
            // 誘電体スラブ比誘電率
            double coreEps = 2.402500;

            // 励振位置
            //double srcPosX = pmlLength + 10 * unitLen;
            double srcPosX = pmlLength + 9 * unitLen;
            // 観測点
            int port1OfsX = 5;
            int port2OfsX = 5;
            double port1PosX = srcPosX + port1OfsX * unitLen;
            double port1PosY = WaveguideWidth * 0.5;
            double port2PosX = disconLength - pmlLength - port2OfsX * unitLen;
            double port2PosY = WaveguideWidth * 0.5;

            // 時間領域
            //double courantNumber = 0.5;
            double courantNumber = 0.5;
            //timeLoopCnt = 3000;
            timeLoopCnt = 1000;
            // 時刻刻み
            //timeDelta = courantNumber * meshL / (c0 * Math.Sqrt(2.0));
            timeDelta = courantNumber * meshLForTimeDelta / (c0 * Math.Sqrt(2.0));

            // モード計算規格化周波数(搬送波規格化周波数)
            NormalizedFreqSrc = 12.0;

            /*
            // ガウシアンパルス
            gaussianT0 = 30 * timeDelta;
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0) * 4.0);
             */

            // 正弦波変調ガウシアンパルス
            // 波数
            double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
            // 波長
            double waveLengthSrc = 2.0 * pi / k0Src;
            // 周波数
            double freqSrc = c0 / waveLengthSrc;
            // 角周波数
            double omegaSrc = 2.0 * pi * freqSrc;
            // 搬送波の振動回数
            int nCycle = 5;
            //gaussianT0 = (1.0 / freqSrc) * nCycle / 2;
            //gaussianT0 = 0.5 * (1.0 / freqSrc) * nCycle / 2;
            gaussianT0 = 0.48 * (1.0 / freqSrc) * nCycle / 2;

            gaussianTp = gaussianT0 / (2.0 * Math.Sqrt(2.0 * Math.Log(2.0)));

            // 周波数領域
            NormalizedFreq1 = 10.0;
            NormalizedFreq2 = 20.0;
            GraphFreqInterval = 2.0;

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            MediaInfo mediaVacumn = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 1.0, 0.0, 0.0 },
                   { 0.0, 1.0, 0.0 },
                   { 0.0, 0.0, 1.0 }
                }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { coreEps,  0.0,  0.0 },
                   {  0.0, coreEps,  0.0 },
                   {  0.0,  0.0, coreEps }
                }
            );
            Medias.Add(mediaVacumn);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            double coreY1 = (WaveguideWidth - slabWidth) * 0.5;
            double coreY2 = coreY1 + slabWidth;
            // 全ループ数
            uint loopCnt_cad = 12;
            uint[] slab_loopId_cad_list = {6, 8, 10, 12};
            // ポート1のPML領域ループリスト
            uint[] port1_pml_loopIds_cad = { 1, 5, 6 };
            // ポート2のPML領域ループリスト
            uint[] port2_pml_loopIds_cad = { 4, 11, 12 };
            // PML開始位置X座標
            double[] pmlStPosX_list = { pmlLength, (disconLength - pmlLength) };
            // 観測点頂点ID
            uint[] portRef_vIds_cad = new uint[portCnt];
            // ポート1Pml終端、ポート1、励振面、ポート2、ポート2PML終端
            uint[][] eId_cad_port_list = new uint[5][] {
                new uint[] { 1, 15, 14 },
                new uint[] { 11, 17, 16},
                new uint[] { 12, 19, 18},
                new uint[] { 13, 21, 20},
                new uint[] { 6, 23, 22},
            };
            uint[] eId_cad_core_list = { 15, 17, 19, 21, 23 };
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    // ループ1
                    IList<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(pmlLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(srcPosX, 0.0)); // 頂点4
                    pts.Add(new CVector2D(disconLength - pmlLength, 0.0)); // 頂点5
                    pts.Add(new CVector2D(disconLength, 0.0)); // 頂点6
                    pts.Add(new CVector2D(disconLength, WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(disconLength - pmlLength, WaveguideWidth)); // 頂点8
                    pts.Add(new CVector2D(srcPosX, WaveguideWidth)); // 頂点9
                    pts.Add(new CVector2D(pmlLength, WaveguideWidth)); // 頂点10
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                    uint lId2 = cad2d.ConnectVertex_Line(3, 10).id_l_add;
                    uint lId3 = cad2d.ConnectVertex_Line(4, 9).id_l_add;
                    uint lId4 = cad2d.ConnectVertex_Line(5, 8).id_l_add;
                }
                {
                    uint parent_id_l_cad = 3;
                    // 観測点
                    portRef_vIds_cad[0] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port1PosX, port1PosY)).id_v_add; // 頂点11
                    portRef_vIds_cad[1] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, parent_id_l_cad, new CVector2D(port2PosX, port2PosY)).id_v_add; // 頂点12
                    // check
                    foreach (uint vId in portRef_vIds_cad)
                    {
                        System.Diagnostics.Debug.Assert(vId != 0);
                    }
                }

                // スラブ導波路と境界の交点
                double[] portX_list = { 0.0, pmlLength, srcPosX, disconLength - pmlLength, disconLength };
                IList<uint[]> slab_vIds_list = new List<uint[]>();
                for (int portIndex = 0; portIndex < 5; portIndex++)
                {
                    uint parent_eId = eId_cad_port_list[portIndex][0];
                    double portX = portX_list[portIndex];

                    double workY1 = 0.0;
                    double workY2 = 0.0;
                    if (portIndex == 0)
                    {
                        workY1 = coreY1;
                        workY2 = coreY2;
                    }
                    else
                    {
                        workY1 = coreY2;
                        workY2 = coreY1;
                    }
                    uint vId1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY1)).id_v_add;
                    uint vId2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, parent_eId, new CVector2D(portX, workY2)).id_v_add;
                    uint[] work_vIds = new uint[2];
                    if (portIndex == 0)
                    {
                        work_vIds[0] = vId1;
                        work_vIds[1] = vId2;
                    }
                    else
                    {
                        work_vIds[0] = vId2;
                        work_vIds[1] = vId1;
                    }
                    slab_vIds_list.Add(work_vIds);
                }
                // スラブ導波路
                for (int portIndex = 0; portIndex < (5 - 1); portIndex++)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        uint work_vId1 = slab_vIds_list[portIndex][i];
                        uint work_vId2 = slab_vIds_list[(portIndex + 1)][i];
                        uint work_eId = cad2d.ConnectVertex_Line(work_vId1, work_vId2).id_e_add;
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // PML領域に色を付ける
                    uint[][] port_pml_loopIds_cad_list = { port1_pml_loopIds_cad, port2_pml_loopIds_cad };
                    for (int portIndex = 0; portIndex < portCnt; portIndex++)
                    {
                        uint[] work_lId_list = port_pml_loopIds_cad_list[portIndex];
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 0.5, 0.5, 0.5 });
                        }
                    }
                    // 誘電体スラブ導波路に色を付ける
                    {
                        uint[] work_lId_list = slab_loopId_cad_list;
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 1.0, 0.0, 1.0 });
                        }
                    }
                    // 境界の辺に色を付ける
                    double[][] work_color_B_list = new double[5][] {
                        new double[] { 0.0, 1.0, 0.0 },
                        new double[] { 0.0, 1.0, 0.0 },
                        new double[] { 1.0, 0.0, 0.0 },
                        new double[] { 1.0, 1.0, 0.0 },
                        new double[] { 1.0, 1.0, 0.0 },
                    };
                    for (int portIndex = 0; portIndex < 5; portIndex++)
                    {
                        uint[] work_eId_list = eId_cad_port_list[portIndex];
                        double[] work_color_B = work_color_B_list[portIndex];
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, work_color_B);
                        }
                    }

                    // 境界の誘電体スラブの辺
                    foreach (uint eId in eId_cad_core_list)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 0.0 });
                    }

                    // DEBUG
                    {
                        uint[] work_eId_list = { 2, 3, 4, 5, 7, 8, 9, 10 };
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 1.0 });
                        }
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list  = new uint[loopCnt_cad];
                for (int i = 0; i < loopCnt_cad; i++)
                {
                    loopId_cad_list[i] = (uint)(i + 1);
                }
                int[] mediaIndex_list = new int[loopId_cad_list.Length];
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (slab_loopId_cad_list.Contains(loopId_cad_list[i]))
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    mediaIndex_list[i] = mediaIndex;
                }

                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < loopId_cad_list.Length; i++)
                {
                    uint loopId_cad = loopId_cad_list[i];
                    int mediaIndex = mediaIndex_list[i];
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, mediaIndex);
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }
            // PML領域
            FieldPmlLoopIdList.Clear();
            IsPmlYDirectionList.Clear();
            PmlStPosXList.Clear();
            PmlLengthList.Clear();
            uint[][] loopId_cad_list_pml = { port1_pml_loopIds_cad, port2_pml_loopIds_cad };
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                uint[] loopId_cad_list = loopId_cad_list_pml[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint loopId_cad in loopId_cad_list)
                {
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                }
                uint workFieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
                FieldPmlLoopIdList.Add(workFieldLoopId);
                // Y方向PML?
                bool isPmlYDirection = false;
                IsPmlYDirectionList.Add(isPmlYDirection);
                // PML開始位置
                double pmlStPosX = pmlStPosX_list[portIndex];
                PmlStPosXList.Add(pmlStPosX);
                // PML長さ
                PmlLengthList.Add(pmlLength);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = { 2, 3, 4, 5, 7, 8, 9, 10 }; // PML終端磁気壁
                //uint[] eId_cad_list = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // PML終端電気壁
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortSrcBcId = 0;
            {
                uint portIndex = 2; // 励振面
                uint[] eId_cad_port = eId_cad_port_list[portIndex];
                uint core_eId = eId_cad_core_list[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                for (int i = 0; i < eId_cad_port.Length; i++)
                {
                    uint eId_cad = eId_cad_port[i];
                    int mediaIndex = Medias.IndexOf(mediaVacumn);
                    if (eId_cad == core_eId)
                    {
                        mediaIndex = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex = Medias.IndexOf(mediaVacumn);
                    }
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                    {
                        wg2d.World.Edge edge = new wg2d.World.Edge();
                        edge.Set(eId, mediaIndex);
                        EdgeDic.Add(eId, edge);
                    }
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                FieldPortSrcBcId = workFieldPortBcId;
            }

            // 観測点
            VIdRefList.Clear();
            uint[] vId_cad_refPort = portRef_vIds_cad;
            foreach (uint vId_cad in vId_cad_refPort)
            {
                uint vId = conv.GetIdEA_fromCad(vId_cad, CAD_ELEM_TYPE.VERTEX);
                VIdRefList.Add(vId);
            }

            return true;
        }
Exemplo n.º 20
0
        /// <summary>
        /// PC導波路 45°三角形格子 90°ベンド
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 問題09: 誘電体ロッド型45°三角形格子ベンド
            // 問題11: エアホール型60°-30°三角形格子ベンド
            const int probNoTri60 = 11;

            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            int propModeCntToSolve = 3;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            int incidentModeIndex_port2 = 0;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            double periodicDistance_port2 = 0;
            // 最小屈折率
            double minEffN = 0.0;
            double minEffN_port2 = 0.0;
            // 最大屈折率
            double maxEffN = 0.0;
            double maxEffN_port2 = 0.0;

            // 考慮する波数ベクトルの最小値
            double minWaveNum = 0.0;
            double minWaveNum_port2 = 0.0;
            // 考慮する波数ベクトルの最大値
            double maxWaveNum = 0.5;
            double maxWaveNum_port2 = 0.5;
            if (probNo == probNoTri60)
            {
                minWaveNum = 0.5; // for latticeTheta = 60 r = 0.35a air hole
                minWaveNum_port2 = 1.0; // for latticeTheta = 60 r = 0.35a air hole
                maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.35a air hole
                maxWaveNum_port2 = 1.5; // for latticeTheta = 60 r = 0.35a air hole
            }
            else
            {
                minWaveNum = 0.0; // for latticeTheta = 45 r = 0.18a
                minWaveNum_port2 = 0.0; // for latticeTheta = 45 r = 0.18a
                maxWaveNum = 0.5; // for latticeTheta = 45 r = 0.18a
                maxWaveNum_port2 = 0.5; // for latticeTheta = 45 r = 0.18a
            }

            // 入出力導波路が同じ?
            if (probNo == probNoTri60)
            {
                IsInoutWgSame = false; // for latticeTheta = 60
            }
            else
            {
                //IsInoutWgSame = true; // for latticeTheta = 45
            }
            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            bool isAirHole = false; // dielectric rod
            if (probNo == probNoTri60)
            {
                isAirHole = true; // air hole
            }
            else
            {
                isAirHole = false; // dielectric rod
            }
            // 周期を180°ずらす
            bool isShift180 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
            bool isShift180_port2 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
            if (probNo == probNoTri60)
            {
                isShift180 = false; // for latticeTheta = 60 r = 0.35a dielectric rod
                isShift180_port2 = false; // for latticeTheta = 30 r = 0.35a air hole
                System.Diagnostics.Debug.Assert(isShift180_port2 == false);
            }
            else
            {
                isShift180 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
                isShift180_port2 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
                System.Diagnostics.Debug.Assert(isShift180 == true && isShift180_port2 == true);
            }
            // Y方向周期をずらす
            bool isShiftY = false;
            if (probNo == probNoTri60)
            {
                isShiftY = true;
                //isShiftY = false;
            }
            else
            {
                isShiftY = false;
            }
            // ロッドの数(半分)
            //const int rodCntHalf = 5; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodCntHalf = 5; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 5;
            System.Diagnostics.Debug.Assert(rodCntHalf % 2 == 1); // 奇数を指定(図面の都合上)
            // 欠陥ロッド数
            int defectRodCnt = 1;
            int defectRodCnt_port2 = 1;
            if (probNo == probNoTri60)
            {
                // for latticeTheta = 60 r = 0.35a air hole
                defectRodCnt = 1;
                defectRodCnt_port2 = 1;
            }
            else
            {
                // for latticeTheta = 45 r = 0.18a dielectric rod
                // 3ロッド欠陥
                defectRodCnt = 3;
                defectRodCnt_port2 = 3;
            }
            // 三角形格子の内角
            double latticeTheta = 45.0; // for latticeTheta = 45 r = 0.18a dielectric rod
            if (probNo == probNoTri60)
            {
                latticeTheta = 60.0; // for latticeTheta = 60 r = 0.35a air hole
            }
            else
            {
                latticeTheta = 45.0; // for latticeTheta = 45 r = 0.18a dielectric rod
            }
            // ロッドの半径
            double rodRadiusRatio = 0.18;  // for latticeTheta = 45 r = 0.18a dielectric rod
            // ロッドの比誘電率
            double rodEps = 4.3 * 4.3; // for latticeTheta = 45 r = 0.18a dielectric rod
            // 1格子当たりの分割点の数
            int ndivForOneLattice = 5; // for latticeTheta = 45 r = 0.18a dielectric rod rotEps = 4.3
            if (probNo == probNoTri60)
            {
                // ロッドの半径
                rodRadiusRatio = 0.35; // for latticeTheta = 60 r = 0.35a air hole

                // ロッドの比誘電率
                rodEps = 2.8 * 2.8; // for latticeTheta = 60 r = 0.35a air hole

                // 1格子当たりの分割点の数
                //ndivForOneLattice = 10; // for latticeTheta = 60 r = 0.35a air hole
                ndivForOneLattice = 9;// 10;
            }
            else
            {
                // ロッドの半径
                rodRadiusRatio = 0.18;  // for latticeTheta = 45 r = 0.18a dielectric rod

                // ロッドの比誘電率
                //rodEps = 3.4 * 3.4; // for latticeTheta = 45 r = 0.18a dielectric rod
                rodEps = 4.3 * 4.3; // for latticeTheta = 45 r = 0.18a dielectric rod

                // 1格子当たりの分割点の数
                //ndivForOneLattice = 7; // for latticeTheta = 45 r = 0.18a dielectric rod
                //ndivForOneLattice = 5; // for latticeTheta = 45 r = 0.18a dielectric rod rotEps = 4.3
                ndivForOneLattice = 5;
            }
            // ロッド円周の分割数
            int rodCircleDiv = 8; // for latticeTheta = 45 r = 0.18a dielectric rod
            // ロッドの半径の分割数
            int rodRadiusDiv = 2; // for latticeTheta = 45 r = 0.18a dielectric rod
            if (probNo == probNoTri60)
            {
                // ロッド円周の分割数
                //rodCircleDiv = 12; // for latticeTheta = 60 r = 0.35a dielectric rod
                rodCircleDiv = 12;

                // ロッドの半径の分割数
                rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            }
            else
            {
                // ロッド円周の分割数
                rodCircleDiv = 8; // for latticeTheta = 45 r = 0.18a dielectric rod

                // ロッドの半径の分割数
                rodRadiusDiv = 2; // for latticeTheta = 45 r = 0.18a dielectric rod
            }
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 1;
            const int rodCntDiscon = 1;

            // 格子の数
            int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            periodicDistance_port2 = rodDistanceY * 2.0;

            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength1 = rodDistanceX;
            double inputWgLength2 = rodDistanceY * 2.0;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            if (Math.Abs(latticeTheta - 45.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 3.6
                //  even 1st
                //NormalizedFreq1 = 0.320;//0.320;
                //NormalizedFreq2 = 0.3601;//0.380;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                //  odd
                //NormalizedFreq1 = 0.384;
                //NormalizedFreq2 = 0.432;
                //FreqDelta = 0.002;//0.001;
                //GraphFreqInterval = 0.01;
                //  even 2nd
                //NormalizedFreq1 = 0.420;
                //NormalizedFreq2 = 0.500;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 4.3
                NormalizedFreq1 = 0.260;
                NormalizedFreq2 = 0.3301;
                FreqDelta = 0.002;
                GraphFreqInterval = 0.01;
            }
            else if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                System.Diagnostics.Debug.Assert(IsInoutWgSame == false);
                // for latticeTheta = 60 r = 0.35a air hole
                NormalizedFreq1 = 0.294;//0.295;// 0.280;
                NormalizedFreq2 = 0.315;//0.320;// 0.3301;
                FreqDelta = 0.001;//0.0005;// 0.001;
                GraphFreqInterval = 0.002;// 0.010;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            //minEffN = 0.0;
            //maxEffN = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN_port2 = minWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            //maxEffN_port2 = maxWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;// 1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
                minEffN_port2 = minEffN;
                maxEffN_port2 = maxEffN;
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
                minEffN_port2 = minEffN;
                maxEffN_port2 = maxEffN;
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
                incidentModeIndex = 0;
                incidentModeIndex_port2 = 0;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            const uint portCnt = 2;
            // ロッドが1格子を超える?
            //bool isLargeRod_port1 = (rodRadiusRatio >= 0.25);
            bool isLargeRod_port1 = (rodRadiusRatio >= 0.5 * Math.Sin(latticeTheta * pi / 180.0));
            System.Diagnostics.Debug.Assert(isLargeRod_port1 == false); // 入力側は45°60°のみ

            // 導波路2の三角形格子角度
            double latticeTheta_port2 = (180.0 - latticeTheta * 2.0) * 0.5;
            bool isLargeRod_port2 = (rodRadiusRatio >= 0.5 * Math.Sin(latticeTheta_port2 * pi / 180.0));
            // 導波路2のロッドの数(半分)
            int rodCntHalf_port2 = rodCntHalf;
            if (isLargeRod_port2)
            {
                rodCntHalf_port2 = (rodCntHalf + 1);
            }
            // 導波路2の格子数
            int latticeCnt_port2 = (rodCntHalf_port2 * 2 + defectRodCnt_port2);
            // 導波路2の幅
            double waveguideWidth2 = rodDistanceX * 0.5 * latticeCnt_port2;
            if (isLargeRod_port2)
            {
                waveguideWidth2 = rodDistanceX * 0.5 * (latticeCnt_port2 - 1);
            }
            // 導波路2の1格子当たりの分割数
            //int ndivForOneLattice_port2 = (int)Math.Round((double)ndivForOneLattice * ((rodDistanceX * 0.5) / rodDistanceY));
            int ndivForOneLattice_port2 = (int)Math.Ceiling((double)ndivForOneLattice * ((rodDistanceX * 0.5) / rodDistanceY));
            System.Diagnostics.Debug.WriteLine("isLargeRod_port2: {0}", isLargeRod_port2);
            System.Diagnostics.Debug.WriteLine("latticeTheta_port2: {0}", latticeTheta_port2);
            System.Diagnostics.Debug.WriteLine("rodCntHalf_port2: {0}", rodCntHalf_port2);
            System.Diagnostics.Debug.WriteLine("ndivForOneLattice_port2: {0}", ndivForOneLattice_port2);

            // 入出力不連続部の距離
            int rodCntDiscon_port1 = rodCntDiscon;
            int rodCntDiscon_port2 = rodCntDiscon;
            double disconLength1 = rodDistanceX * rodCntDiscon_port1;
            double disconLength2 = rodDistanceY * (2.0 * rodCntDiscon_port2);

            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            int ndivPlus_port1 = 0;
            int ndivPlus_port2 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            IList<uint> id_e_F2_Bend = new List<uint>();
            //uint id_v_B1_top_rod_center = 1;
            //uint id_v_B1_bottom_rod_center = 2;
            //uint id_v_B2_top_rod_center = 10;
            //uint id_v_B2_bottom_rod_center = 3;
            uint id_v_B3_top_rod_center = 7;
            uint id_v_B3_bottom_rod_center = 6;
            uint id_v_B4_top_rod_center = 8;
            uint id_v_B4_bottom_rod_center = 5;
            double port2_X = inputWgLength1 + disconLength1 - 0.25 * rodDistanceX + waveguideWidth2;
            double port2_Y = WaveguideWidth - 0.5 * rodDistanceY + disconLength2 + inputWgLength2;
            if (isLargeRod_port2)
            {
                if (defectRodCnt_port2 == 1 && isShiftY)
                {
                    // defectRodCnt_port2 == 1
                    if (isShift180)
                    {
                        port2_X += 0.25 * rodDistanceX;
                    }
                    else
                    {
                        port2_X += 0.75 * rodDistanceX;
                    }
                }
                else
                {
                    // defectRodCnt_port2 == 5
                    if (isShift180)
                    {
                        port2_Y -= rodDistanceY;
                        port2_X += 0.75 * rodDistanceX;
                    }
                    else
                    {
                        port2_Y -= rodDistanceY;
                        port2_X += 0.25 * rodDistanceX;
                    }
                }
            }
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength1, 0.0)); // 頂点3
                    pts.Add(new CVector2D(port2_X, 0.0)); // 頂点4
                    pts.Add(new CVector2D(port2_X, port2_Y - inputWgLength2)); // 頂点5
                    pts.Add(new CVector2D(port2_X, port2_Y)); // 頂点6
                    pts.Add(new CVector2D(port2_X - waveguideWidth2, port2_Y)); // 頂点7
                    pts.Add(new CVector2D(port2_X - waveguideWidth2, port2_Y - inputWgLength2)); // 頂点8
                    pts.Add(new CVector2D(port2_X - waveguideWidth2, WaveguideWidth)); // 頂点9
                    pts.Add(new CVector2D(inputWgLength1, WaveguideWidth)); // 頂点10
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 10).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(5, 8).id_e_add;
            ;
                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys_port1 = new List<double>();
                IList<double> ys_rod_port1 = new List<double>();
                IList<double> xs_port2 = new List<double>();
                IList<double> xs_rod_port2 = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                int outofAreaRodPtCnt_row_top_port1 = 0;
                int outofAreaRodPtCnt_row_bottom_port1 = 0;
                int outofAreaRodPtCnt_row_top_port2 = 0;
                int outofAreaRodPtCnt_row_bottom_port2 = 0;

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    bool cur_isShift180 = true;
                    bool cur_isLargeRod = false;
                    int cur_rodCntHalf = 0;
                    int cur_defectRodCnt = 0;
                    int cur_ndivForOneLattice = 0;
                    double cur_WaveguideWidth = 0.0;
                    double cur_rodDistanceY = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;
                    int cur_outofAreaRodPtCnt_row_top = 0;
                    int cur_outofAreaRodPtCnt_row_bottom = 0;
                    if (portIndex == 0)
                    {
                        cur_isShift180 = isShift180;
                        cur_isLargeRod = isLargeRod_port1;
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port1;
                        ys_rod = ys_rod_port1;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 1)
                    {
                        cur_isShift180 = isShift180_port2;
                        cur_isLargeRod = isLargeRod_port2;
                        cur_rodCntHalf = rodCntHalf_port2;
                        cur_defectRodCnt = defectRodCnt_port2;
                        cur_ndivForOneLattice = ndivForOneLattice_port2;
                        cur_WaveguideWidth = waveguideWidth2;
                        cur_rodDistanceY = rodDistanceX * 0.5;
                        ys = xs_port2;
                        ys_rod = xs_rod_port2;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (cur_isShift180 ? 1 : 0)) continue;
                        double y0 = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        System.Diagnostics.Debug.Assert(y0 >= 0 && y0 <= cur_WaveguideWidth);
                        if (cur_isLargeRod)
                        {
                            y0 += 0.5 * cur_rodDistanceY;
                        }
                        if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y0);
                        }
                        else
                        {
                            if (portIndex == 0 && cur_isLargeRod && i == 0)
                            {
                                outofAreaRodPtCnt_row_top_port1++;
                                cur_outofAreaRodPtCnt_row_top = outofAreaRodPtCnt_row_top_port1;
                            }
                            else if (portIndex == 1 && cur_isLargeRod && i == 0)
                            {
                                outofAreaRodPtCnt_row_top_port2++;
                                cur_outofAreaRodPtCnt_row_top = outofAreaRodPtCnt_row_top_port2;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            double y1 = y0 - k * rodRadius / rodRadiusDiv;
                            double y2 = y0 + k * rodRadius / rodRadiusDiv;
                            if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                            {
                                ys_rod.Add(y1);
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                            {
                                ys_rod.Add(y2);
                            }
                            else
                            {
                                if (portIndex == 0 && cur_isLargeRod && i == 0)
                                {
                                    outofAreaRodPtCnt_row_top_port1++;
                                    cur_outofAreaRodPtCnt_row_top = outofAreaRodPtCnt_row_top_port1;
                                }
                                else if (portIndex == 1 && cur_isLargeRod && i == 0)
                                {
                                    outofAreaRodPtCnt_row_top_port2++;
                                    cur_outofAreaRodPtCnt_row_top = outofAreaRodPtCnt_row_top_port2;
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (cur_isShift180 ? 1 : 0)) continue;
                        double y0 = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        if (cur_isLargeRod)
                        {
                            y0 -= 0.5 * cur_rodDistanceY;
                        }
                        if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y0);
                        }
                        else
                        {
                            if (portIndex == 0 && cur_isLargeRod && i == (cur_rodCntHalf - 1))
                            {
                                outofAreaRodPtCnt_row_bottom_port1++;
                                cur_outofAreaRodPtCnt_row_bottom = outofAreaRodPtCnt_row_bottom_port1;
                            }
                            else if (portIndex == 1 && cur_isLargeRod && i == (cur_rodCntHalf - 1))
                            {
                                outofAreaRodPtCnt_row_bottom_port2++;
                                cur_outofAreaRodPtCnt_row_bottom = outofAreaRodPtCnt_row_bottom_port2;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            double y1 = y0 - k * rodRadius / rodRadiusDiv;
                            double y2 = y0 + k * rodRadius / rodRadiusDiv;
                            if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                            {
                                ys_rod.Add(y1);
                            }
                            else
                            {
                                if (portIndex == 0 && cur_isLargeRod && i == (cur_rodCntHalf - 1))
                                {
                                    outofAreaRodPtCnt_row_bottom_port1++;
                                    cur_outofAreaRodPtCnt_row_bottom = outofAreaRodPtCnt_row_bottom_port1;
                                }
                                else if (portIndex == 1 && cur_isLargeRod && i == (cur_rodCntHalf - 1))
                                {
                                    outofAreaRodPtCnt_row_bottom_port2++;
                                    cur_outofAreaRodPtCnt_row_bottom = outofAreaRodPtCnt_row_bottom_port2;
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }
                            if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (cur_WaveguideWidth - Constants.PrecisionLowerLimit))
                            {
                                ys_rod.Add(y2);
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }
                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    //double radiusMargin = cur_rodDistanceY * 0.01;
                    double radiusMargin = cur_rodDistanceY * 0.012;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (cur_isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (cur_isLargeRod)
                            {
                                y_divpt += cur_rodDistanceY * 0.5;
                                if (y_divpt >= (cur_WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                                y_min_rod += cur_rodDistanceY * 0.5;
                                y_max_rod += cur_rodDistanceY * 0.5;
                            }
                            if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (cur_isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (cur_isLargeRod)
                            {
                                y_divpt -= cur_rodDistanceY * 0.5;
                                if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                                y_min_rod -= cur_rodDistanceY * 0.5;
                                y_max_rod -= cur_rodDistanceY * 0.5;
                            }
                            if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }

                    // 境界上にロッドのない格子
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (cur_isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == 0 && k == 0) continue;
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_upper_rod = cur_WaveguideWidth - i * cur_rodDistanceY + 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_lower_rod = cur_WaveguideWidth - (i + 1) * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (cur_isLargeRod)
                            {
                                y_divpt += cur_rodDistanceY * 0.5;
                                if (y_divpt >= (cur_WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                                y_min_upper_rod += cur_rodDistanceY * 0.5;
                                y_max_lower_rod += cur_rodDistanceY * 0.5;
                            }
                            bool isAddHalfRod_row_top = (cur_isLargeRod
                                && ((cur_isShift180 && (cur_rodCntHalf % 2 == 1)) || (!cur_isShift180 && (cur_rodCntHalf % 2 == 0))));
                            if ((i != 0 || (i == 0 && isAddHalfRod_row_top))
                                    && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                            {
                                continue;
                            }
                            if ((cur_isShift180 || (!cur_isShift180 && i != (cur_rodCntHalf - 1)))
                                && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                            {
                                continue;
                            }

                            ys.Add(y_divpt);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (cur_isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == (cur_rodCntHalf - 1) && k == cur_ndivForOneLattice) continue;
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_upper_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY + 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_lower_rod = cur_rodDistanceY * cur_rodCntHalf - (i + 1) * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (cur_isLargeRod)
                            {
                                y_divpt -= cur_rodDistanceY * 0.5;
                                if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                                y_min_upper_rod -= cur_rodDistanceY * 0.5;
                                y_max_lower_rod -= cur_rodDistanceY * 0.5;
                            }
                            bool isAddHalfRod_row_bottom = (cur_isLargeRod
                                && ((cur_isShift180 && (cur_rodCntHalf % 2 == 1)) || (!cur_isShift180 && (cur_rodCntHalf % 2 == 0))));
                            if ((cur_isShift180 || (!cur_isShift180 && i != 0))
                                && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                            {
                                continue;
                            }
                            if ((i != (cur_rodCntHalf - 1) || (i == (cur_rodCntHalf - 1) && isAddHalfRod_row_bottom))
                                && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                            {
                                continue;
                            }

                            ys.Add(y_divpt);
                        }
                    }
                    // 欠陥部
                    for (int i = 0; i <= (cur_defectRodCnt * cur_ndivForOneLattice); i++)
                    {
                        if (!cur_isShift180 && (i == 0 || i == (cur_defectRodCnt * cur_ndivForOneLattice))) continue;
                        double y_divpt = cur_rodDistanceY * (cur_rodCntHalf + cur_defectRodCnt) - i * (cur_rodDistanceY / cur_ndivForOneLattice);
                        double y_min_upper_rod = cur_rodDistanceY * (cur_rodCntHalf + cur_defectRodCnt) + 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = cur_rodDistanceY * cur_rodCntHalf - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                        if (cur_isLargeRod)
                        {
                            y_divpt -= cur_rodDistanceY * 0.5;
                            y_min_upper_rod -= cur_rodDistanceY * 0.5;
                            y_max_lower_rod -= cur_rodDistanceY * 0.5;
                        }
                        if (cur_isLargeRod && cur_isShift180)
                        {
                            // for isLargeRod == true
                            if (y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit)
                                    || y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit)
                                )
                            {
                                continue;
                            }
                        }
                        ys.Add(y_divpt);
                    }

                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (portIndex == 0)
                    {
                        ndivPlus_port1 = cur_ndivPlus;
                    }
                    else if (portIndex == 1)
                    {
                        ndivPlus_port2 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    // 入力導波路 外側境界
                    // 入力導波路 内部側境界
                    // 出力導波路 外側境界
                    // 出力導波路 内部側境界
                    for (int boundaryIndex = 0; boundaryIndex < 2; boundaryIndex++)
                    {
                        bool isInRod = false;
                        if (cur_isLargeRod
                            && ((cur_isShift180 && (cur_rodCntHalf % 2 == 1)) || (!cur_isShift180 && (cur_rodCntHalf % 2 == 0))))
                        {
                            isInRod = true;
                        }

                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            // 入力導波路
                            double x1 = 0.0;
                            double y_pt = 0.0;
                            // 出力導波路
                            double x_pt = 0.0;
                            double y1 = 0.0;
                            bool isYPeriodic = false;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (portIndex == 0 && boundaryIndex == 0)
                            {
                                // 入力導波路 外側境界
                                id_e = 1;
                                isYPeriodic = false;
                                x1 = 0.0;
                                y_pt = yAry[i];
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B1;
                                work_id_v_list_rod_B = id_v_list_rod_B1;
                            }
                            else if (portIndex == 0 && boundaryIndex == 1)
                            {
                                // 入力導波路 内側境界
                                id_e = 11;
                                isYPeriodic = false;
                                x1 = inputWgLength1;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B2;
                                work_id_v_list_rod_B = id_v_list_rod_B2;
                            }
                            else if (portIndex == 1 && boundaryIndex == 0)
                            {
                                // 出力導波路 外側境界
                                id_e = 6;
                                isYPeriodic = true;
                                //x_pt = port2_X - waveguideWidth2 + yAry[i] * (waveguideWidth2 / WaveguideWidth);
                                x_pt = port2_X - waveguideWidth2 + yAry[i];
                                yAryIndex = i;
                                y1 = port2_Y;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (portIndex == 1 && boundaryIndex == 1)
                            {
                                // 出力導波路 内側境界
                                id_e = 12;
                                isYPeriodic = true;
                                //x_pt = port2_X - waveguideWidth2 + yAry[i] * (waveguideWidth2 / WaveguideWidth);
                                x_pt = port2_X - waveguideWidth2 + yAry[i];
                                yAryIndex = i;
                                y1 = port2_Y - inputWgLength2;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            if (isYPeriodic)
                            {
                                resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y1));
                            }
                            else
                            {
                                resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x1, y_pt));
                            }
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);

                                if (cur_isLargeRod
                                    && ((cur_isShift180 && (cur_rodCntHalf % 2 == 1)) || (!cur_isShift180 && (cur_rodCntHalf % 2 == 0))))
                                {
                                    if ((work_id_v_list_rod_B.Count + cur_outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                                    {
                                        isInRod = true;
                                    }
                                    else if ((work_id_v_list_rod_B.Count + cur_outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                                    {
                                        isInRod = false;
                                    }
                                }
                                else
                                {
                                    if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                    {
                                        isInRod = true;
                                    }
                                    else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                    {
                                        isInRod = false;
                                    }
                                }
                            }
                            if (cur_isLargeRod
                                && ((cur_isShift180 && (cur_rodCntHalf % 2 == 1)) || (!cur_isShift180 && (cur_rodCntHalf % 2 == 0))))
                            {
                                if (i == (yAry.Length - 1))
                                {
                                    System.Diagnostics.Debug.Assert(isInRod == true);
                                    work_id_e_rod_B.Add(id_e);
                                }
                            }
                        }
                    }
                }

                int bRodCntHalf_port1 = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                int bRodCntHalf_port2 = (isShift180_port2 ? (int)((rodCntHalf_port2 + 1) / 2) : (int)((rodCntHalf_port2) / 2));
                if (!isLargeRod_port2
                    || (isLargeRod_port2 &&
                           (isShift180_port2 && (rodCntHalf_port2 % 2 == 0)) || (!isShift180_port2 && (rodCntHalf_port2 % 2 == 1))
                       )
                    )
                {
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1));
                }
                else
                {
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top_port2 == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom_port2 == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == (bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top_port2 - outofAreaRodPtCnt_row_bottom_port2));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == (bRodCntHalf_port2 * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top_port2 - outofAreaRodPtCnt_row_bottom_port2));
                }

                // ロッドを追加
                /////////////////////////////////////////////////////////////
                // 入力導波路側ロッド
                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength1;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top_port1 == 0); // 未対応
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom_port1 == 0); // 未対応
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top_port1 == 0); // 未対応
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom_port1 == 0); // 未対応
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }
                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength1;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央のロッド (入力導波路 + 不連続部)
                int periodCntInputWg1 = 1;
                //int periodCntBendX = latticeCnt / 2;
                int periodCntBendX = (rodCntHalf_port2 * 2 + defectRodCnt_port2) / 2;
                int periodCntX = periodCntInputWg1 + rodCntDiscon_port1 + periodCntBendX;
                for (int col = 1; col <= (periodCntX * 2); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (isLargeRod_port2)
                    {
                        if (defectRodCnt_port2 == 1 && isShiftY)
                        {
                            if (isShift180)
                            {
                                if (col >= (periodCntX * 2)) continue;
                            }
                        }
                        else
                        {
                            if (!isShift180)
                            {
                                if (col >= (periodCntX * 2)) continue;
                            }
                        }
                    }
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg1 * 2))
                    {
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }

                    // 中央のロッド
                    for (int i = 0; i < (rodCntHalf * 2 + defectRodCnt); i++)
                    {
                        double rr = rodRadius;
                        int nc = rodCircleDiv;
                        int nr = rodRadiusDiv;
                        if (isLargeRod_port1
                                && ((col % 2 == 1 && ((rodCntHalf * 2 + defectRodCnt - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                                    || (col % 2 == 0 && ((rodCntHalf * 2 + defectRodCnt - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                            )
                        {
                            if (i == 0)
                            {
                                continue;
                            }
                            if (i == ((rodCntHalf * 2 + defectRodCnt) - 1))
                            {
                                continue;
                            }
                        }

                        /*
                        //
                        // 直角コーナー
                        //
                        if ((col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                        {
                            continue;
                        }
                        if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2) && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1))
                            && (i >= 0 && i < rodCntHalf))
                        {
                            continue;
                        }
                         */

                        if (Math.Abs(latticeTheta - 45.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {

                            /*
                            //
                            // 角を取ったコーナー(コーナ部はW2) for latticeTheta = 45
                            //
                            // 入力側欠陥部
                            if ((col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 1)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                continue;
                            }
                            // 下側角
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 3)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 2)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 2)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 3)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 4)))
                            {
                                continue;
                            }
                            // 上側角
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 1)) && (i == (rodCntHalf - 1)))
                            {
                                continue;
                            }
                            // 出力側欠陥部
                            if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2) && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1))
                                && (i >= 0 && i < rodCntHalf))
                            {
                                continue;
                            }
                             */

                            //
                            // 角を取ったコーナー(コーナー部はW3) for latticeTheta = 45
                            //
                            // 入力側欠陥部
                            if ((col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 1)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                            {
                                continue;
                            }
                            // 下側角
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 3)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 2)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 2)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 3)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 4)))
                            {
                                continue;
                            }
                            // 上側角
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 1)) && (i == (rodCntHalf - 1)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 1)) && (i == (rodCntHalf - 3)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 2)) && (i == (rodCntHalf - 2)))
                            {
                                continue;
                            }
                            if ((col == ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 - 3)) && (i == (rodCntHalf - 1)))
                            {
                                continue;
                            }
                            // 出力側欠陥部
                            if ((col >= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2) && col <= ((periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1))
                                && (i >= 0 && i < rodCntHalf))
                            {
                                continue;
                            }

                        }
                        else  if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {
                            if (defectRodCnt_port2 == 1 && isShiftY)
                            {
                                //
                                // 結合コーナー  for latticeTheta = 60 defectCnt_port2 == 1
                                //
                                int defect_min_port2_col = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2;
                                int defect_max_port2_col = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2 - 1;
                                if (isShift180)
                                {
                                }
                                else
                                {
                                    defect_min_port2_col++;
                                    defect_max_port2_col++;
                                }
                                // 入力側欠陥部
                                if ((col <= (defect_min_port2_col - 2)) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                                {
                                    continue;
                                }
                                // 出力側欠陥部
                                if ((col >= defect_min_port2_col && col <= defect_max_port2_col)
                                    && (i >= 0 && i < rodCntHalf))
                                {
                                    continue;
                                }

                                // 出力導波路結合部のロッドを小さくする
                                if (col == (defect_min_port2_col - 1) && i == (rodCntHalf))
                                {
                                    rr = 0.16 * latticeA;
                                    nr = 2;
                                }
                            }
                            else
                            {
                                //
                                // 直角コーナー
                                //
                                int defect_min_port2_col = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + 1;
                                int defect_max_port2_col = (periodCntInputWg1 + rodCntDiscon_port1) * 2 + rodCntHalf_port2 + defectRodCnt_port2;
                                if (isShift180)
                                {
                                }
                                else
                                {
                                    defect_min_port2_col--;
                                    defect_max_port2_col--;
                                }
                                if ((col <= defect_max_port2_col) && (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1)))
                                {
                                    if (defectRodCnt_port2 == 1 && (col == (defect_min_port2_col - 2) && i == rodCntHalf))
                                    {
                                        // 出力導波路がCROWのときのベンド部共振器
                                    }
                                    else
                                    {
                                        continue;
                                    }
                                }
                                if ((col >= defect_min_port2_col && col <= defect_max_port2_col)
                                    && (i >= 0 && i < rodCntHalf))
                                {
                                    continue;
                                }
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        if ((col % 2 == 1 && ((rodCntHalf * 2 + defectRodCnt - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf * 2 + defectRodCnt - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, nc, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                /////////////////////////////////////////////////////////////
                // 出力導波路側ロッド
                uint id_e_F1_new_port2 = 0;
                uint id_e_F2_new_port2 = 0;
                uint id_e_F1_discon_new_port2 = 0;
                //uint id_e_F2_discon_new_port2 = 0;

                // 上下のロッド(出力導波路)(左右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_rodQuarter = new List<uint>();
                IList<uint> id_v_list_F2_rodQuarter = new List<uint>();
                for (int colIndex = 1; colIndex >= 0; colIndex--) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左の強制境界と交差する点
                    if (isLargeRod_port2
                        && (/*(isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) ||*/ (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 出力境界 外側
                            // 出力導波路領域
                            id_e_list[0] = 7;
                            id_e_list[1] = 7;
                        }
                        else if (colIndex == 1)
                        {
                            // 出力境界内側
                            // 不連続領域
                            id_e_list[0] = 8;
                            id_e_list[1] = 7;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = port2_X - waveguideWidth2;
                        double y0 = port2_Y - (rodDistanceY * 2.0) * colIndex;
                        double x_cross = port2_X - waveguideWidth2;
                        double[] y_cross_list = new double[2];
                        y_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0;
                        y_cross_list[1] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double y_cross = y_cross_list[k];
                            if (y_cross >= port2_Y)
                            {
                                continue;
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_rodQuarter.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // 左側境界の中央部分の辺IDが新しくなる
                            if (colIndex == 0 && k == 0)
                            {
                                // 出力部
                                id_e_F1_new_port2 = id_e_add;
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                // 不連続部
                                id_e_F1_discon_new_port2 = id_e_add;
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右の強制境界と交差するロッド
                    if (isLargeRod_port2
                        && (/*(isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) ||*/ (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 出力境界 外側
                            // 出力導波路領域
                            id_e_list[0] = 5;
                            id_e_list[1] = 5;
                        }
                        else if (colIndex == 1)
                        {
                            // 出力境界内側
                            // 不連続領域
                            id_e_list[0] = 5;
                            id_e_list[1] = 4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = port2_X;
                        double y0 = port2_Y - (rodDistanceY * 2.0) * colIndex;
                        double x_cross = port2_X;
                        double[] y_cross_list = new double[2];
                        y_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0;
                        y_cross_list[1] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double y_cross = y_cross_list[k];
                            if (y_cross >= port2_Y)
                            {
                                continue;
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_rodQuarter.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // 右側境界の中央部分の辺IDが新しくなる
                            if (colIndex == 0)
                            {
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                // 出力部
                                id_e_F2_new_port2 = id_e_add;
                            }
                            else if (colIndex == 1 && k == 1)
                            {
                                // 不連続部
                                // 変更なし
                                //id_e_F2_discon_new_port2 = id_e_add;
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // 上のロッドを追加
                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 上のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double y_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    uint work_id_v_B_top_rod_center = 0;
                    uint work_id_v_B_bottom_rod_center = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 外側
                        y_B = port2_Y;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        work_id_v_B_top_rod_center = id_v_B3_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B3_bottom_rod_center;
                    }
                    else if (colIndex == 1)
                    {
                        // 出力境界内側
                        y_B = port2_Y - inputWgLength2;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        work_id_v_B_top_rod_center = id_v_B4_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B4_bottom_rod_center;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port2 - 1 - (int)((rodCntHalf_port2 - 1 - i) / 2);
                            int ofs_index_top = 0;
                            if (isLargeRod_port2 && ((isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) || (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0))))
                            {
                                ofs_index_top = - outofAreaRodPtCnt_row_top_port2;
                            }
                            bool isQuarterRod = false;
                            // 上のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0];
                                        id_v0 = id_v_list_F1_rodQuarter[id_v_list_F1_rodQuarter.Count - 1 - colIndex * 2]; // 1つ飛ばしで参照
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_top_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = port2_X - waveguideWidth2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                double y0 = y_B;
                                if (isLargeRod_port2)
                                {
                                    x0 -= (rodDistanceX * 0.5) * 0.5;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v2,
                                        id_v1,
                                        id_v0,
                                        0.0,
                                        true);
                                }
                                else
                                {
                                    // 上のロッド
                                    lId = WgCadUtil.AddTopRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (i % 2 == (isShift180_port2 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            int ofs_index_top = 0;
                            if (isLargeRod_port2 && ((isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) || (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0))))
                            {
                                ofs_index_top = -outofAreaRodPtCnt_row_top_port2;
                            }
                            bool isQuarterRod = false;
                            // 上のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1]; // DEBUG
                                        id_v2 = id_v_list_F2_rodQuarter[0 + colIndex * 2]; // 1つ飛ばしで参照
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = port2_X - rodDistanceX * 0.5 * rodCntHalf_port2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                double y0 = y_B;
                                if (isLargeRod_port2)
                                {
                                    x0 += (rodDistanceX * 0.5) * 0.5;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v2,
                                        id_v1,
                                        id_v0,
                                        270.0,
                                        true);
                                }
                                else
                                {
                                    // 上のロッド
                                    lId = WgCadUtil.AddTopRod(
                                     cad2d,
                                     baseLoopId,
                                     id_v0,
                                     id_v1,
                                     id_v2,
                                     x0,
                                     y0,
                                     rodRadius,
                                     rodCircleDiv,
                                     rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 下のロッドを追加
                for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 下のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double y_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    uint work_id_v_B_top_rod_center = 0;
                    uint work_id_v_B_bottom_rod_center = 0;

                    if (colIndex == 0)
                    {
                        // 出力境界 内側
                        y_B = port2_Y - inputWgLength2;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        work_id_v_B_top_rod_center = id_v_B4_top_rod_center;
                        work_id_v_B_bottom_rod_center = id_v_B4_bottom_rod_center;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port2 - 1 - (int)((rodCntHalf_port2 - 1 - i) / 2);
                            int ofs_index_top = 0;
                            if (isLargeRod_port2 && ((isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) || (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0))))
                            {
                                ofs_index_top = -outofAreaRodPtCnt_row_top_port2;
                            }
                            bool isQuarterRod = false;
                            // 下のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                                    if (index_v0 < 0)
                                    {
                                        isQuarterRod = true;
                                        //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                        id_v0 = id_v_list_F1_rodQuarter[id_v_list_F1_rodQuarter.Count - 2 - colIndex * 2];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_top_rod_center;
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = port2_X - waveguideWidth2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                double y0 = y_B;
                                if (isLargeRod_port2)
                                {
                                    x0 -= (rodDistanceX * 0.5) * 0.5;
                                }
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        90.0,
                                        true);
                                }
                                else
                                {
                                    // 下のロッド
                                    lId = WgCadUtil.AddBottomRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (i % 2 == (isShift180_port2 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            int ofs_index_top = 0;
                            if (isLargeRod_port2 && ((isShift180_port2 && (rodCntHalf_port2 % 2 == 1)) || (!isShift180_port2 && (rodCntHalf_port2 % 2 == 0))))
                            {
                                ofs_index_top = -outofAreaRodPtCnt_row_top_port2;
                            }
                            bool isQuarterRod = false;
                            // 下のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                {
                                    int index_v0 = (work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v1 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                                    int index_v2 = (work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                                    if (index_v2 > work_id_v_list_rod_B.Count - 1)
                                    {
                                        isQuarterRod = true;
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        //id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v1 = work_id_v_B_bottom_rod_center;
                                        //id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1]; // DEBUG
                                        id_v2 = id_v_list_F2_rodQuarter[1 + colIndex * 2];
                                    }
                                    else
                                    {
                                        id_v0 = work_id_v_list_rod_B[index_v0];
                                        id_v1 = work_id_v_list_rod_B[index_v1];
                                        id_v2 = work_id_v_list_rod_B[index_v2];
                                    }
                                }
                                double x0 = port2_X - rodDistanceX * 0.5 * rodCntHalf_port2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                double y0 = y_B;
                                if (isLargeRod_port2)
                                {
                                    x0 += (rodDistanceX * 0.5) * 0.5;
                                }
                                uint lId = 0;
                                if (isQuarterRod)
                                {
                                    // 1/4円を追加する
                                    lId = WgCadUtil.AddExactlyQuarterRod(
                                        cad2d,
                                        baseLoopId,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        180.0,
                                        true);
                                }
                                else
                                {
                                    // 下のロッド
                                    lId = WgCadUtil.AddBottomRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv);
                                }
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド (出力導波路)
                int periodCntInputWg2 = 1;
                int periodCntY = periodCntInputWg2 + rodCntDiscon_port2;

                // 中央のロッド(出力導波路)(左右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();
                for (int col = (periodCntY * 2 - 1); col >= 1; col--)
                {
                    if (isLargeRod_port2)
                    {
                        if (col > (periodCntY * 2 - 2)) continue;
                    }
                    if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg2 * 2))
                    {
                        inputWgNo = 2;
                    }
                    else
                    {
                        inputWgNo = 0;
                    }

                    // 左の強制境界と交差するロッド
                    if (isLargeRod_port2
                           && ((col % 2 == 1 && ((rodCntHalf_port2 - 1 - 0) % 2 == (isShift180_port2 ? 1 : 0)))
                               || (col % 2 == 0 && ((rodCntHalf_port2 - 1 - 0) % 2 == (isShift180_port2 ? 0 : 1)))
                               )
                        )
                    {
                        uint id_e = 0;
                        if (inputWgNo == 0)
                        {
                            id_e = 8;
                            //if (!isShift180_port2)
                            if (id_e_F1_discon_new_port2 != 0)
                            {
                                id_e = id_e_F1_discon_new_port2;
                            }
                        }
                        else if (inputWgNo == 2)
                        {
                            id_e = 7;
                            //if (!isShift180_port2)
                            if (id_e_F1_new_port2 != 0)
                            {
                                id_e = id_e_F1_new_port2;
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = port2_X - waveguideWidth2;
                        double y0 = port2_Y - rodDistanceY * col;
                        double x_cross = port2_X - waveguideWidth2;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                for (int col = 1; col <= (periodCntY * 2 - 1); col++)
                {
                    if (isLargeRod_port2)
                    {
                        if (col > (periodCntY * 2 - 2)) continue;
                    }
                    if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg2 * 2))
                    {
                        inputWgNo = 2;
                    }
                    else
                    {
                        inputWgNo = 0;
                    }

                    // 右の強制境界と交差するロッド
                    if (isLargeRod_port2
                           && ((col % 2 == 1 && ((rodCntHalf_port2 - 1 - 0) % 2 == (isShift180_port2 ? 1 : 0)))
                               || (col % 2 == 0 && ((rodCntHalf_port2 - 1 - 0) % 2 == (isShift180_port2 ? 0 : 1)))
                               )
                        )
                    {
                        uint id_e = 0;
                        if (inputWgNo == 0)
                        {
                            id_e = 4;
                            //変更なし
                            ////if (!isShift180_port2)
                            //if (id_e_F2_discon_new_port2 != 0)
                            //{
                            //    id_e = id_e_F2_discon_new_port2;
                            //}
                        }
                        else if (inputWgNo == 2)
                        {
                            id_e = 5;
                            //if (!isShift180_port2)
                            if (id_e_F2_new_port2 != 0)
                            {
                                id_e = id_e_F2_new_port2;
                            }
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = port2_X;
                        double y0 = port2_Y - rodDistanceY * col;
                        double x_cross = port2_X;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // 中央のロッド (出力導波路)
                for (int col = 1; col <= (periodCntY * 2 - 1); col++)
                {
                    if (isLargeRod_port2)
                    {
                        if (defectRodCnt_port2 == 1 && isShiftY)
                        {
                            /*
                            if (isShift180)
                            {
                                if (col > (periodCntY * 2 - 2)) continue;
                            }
                             */
                        }
                        else
                        {
                            if (col > (periodCntY * 2 - 2)) continue;
                        }
                    }
                    if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    if (col >= 0 && col < (periodCntInputWg2 * 2))
                    {
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }

                    // 中央のロッド(出力導波路)
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (isLargeRod_port2
                               && ((col % 2 == 1 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 1 : 0)))
                                   || (col % 2 == 0 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 0 : 1))))
                            )
                        {
                            if (i == 0)
                            {
                                {
                                    // 左の強制境界と交差するロッド
                                    // 半円(右半分)を追加
                                    //double x0 = port2_X - waveguideWidth2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                    double x0 = port2_X - waveguideWidth2;
                                    double y0 = port2_Y - rodDistanceY * col;
                                    //if (isLargeRod_port2)
                                    //{
                                    //    x0 -= (rodDistanceX * 0.5) * 0.5; // for isLargeRod
                                    //}
                                    int col2 = (periodCntY * 2 - 1 - col) / 2;
                                    if (defectRodCnt_port2 == 1 && isShiftY)
                                    {
                                        // defectRodCnt_port2 == 1
                                        if (isShift180_port2)
                                        {
                                            col2 = col2 - 1;
                                        }
                                        else if (!isShift180_port2)
                                        {
                                        }
                                    }
                                    else
                                    {
                                        // defectRodCnt_port2 == 5
                                    }

                                    uint id_v0 = id_v_list_F1[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F1[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F1[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        90.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf_port2 - 1 - i) % 2 == (isShift180_port2 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = port2_X - waveguideWidth2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                            double y0 = port2_Y - rodDistanceY * col;
                            if (isLargeRod_port2)
                            {
                                x0 -= (rodDistanceX * 0.5) * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf_port2; i++)
                    {
                        if (isLargeRod_port2
                                && ((col % 2 == 1 && (i % 2 == (isShift180_port2 ? 1 : 0)))
                                    || (col % 2 == 0 && (i % 2 == (isShift180_port2 ? 0 : 1))))
                            )
                        {
                            if (i == (rodCntHalf_port2 - 1))
                            {
                                {
                                    // 右の強制境界と交差するロッド
                                    // 半円(左半分)を追加
                                    //double x0 = port2_X - rodDistanceX * 0.5 * rodCntHalf_port2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                                    double x0 = port2_X;
                                    double y0 = port2_Y - rodDistanceY * col;
                                    //if (isLargeRod_port2)
                                    //{
                                    //    x0 += (rodDistanceX * 0.5) * 0.5; // for isLargeRod
                                    //}
                                    int col2 = col / 2;
                                    if (defectRodCnt_port2 == 1 && isShiftY)
                                    {
                                        // defectRodCnt_port2 == 1
                                        if (isShift180_port2)
                                        {
                                            col2 = col2 - 1;
                                        }
                                        else if (!isShift180_port2)
                                        {
                                            col2 = col2 - 2;
                                        }
                                    }
                                    else
                                    {
                                        // defectRodCnt_port2 == 5
                                    }
                                    uint id_v0 = id_v_list_F2[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F2[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F2[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        270.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && (i % 2 == (isShift180_port2 ? 1 : 0)))
                            || (col % 2 == 0 && (i % 2 == (isShift180_port2 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = port2_X - rodDistanceX * 0.5 * rodCntHalf_port2 + i * rodDistanceX * 0.5 + rodDistanceX * 0.25;
                            double y0 = port2_Y - rodDistanceY * col;
                            if (isLargeRod_port2)
                            {
                                x0 += (rodDistanceX * 0.5) * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド(ベンド部分)(右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F2_Bend = new List<uint>();
                for (int col = (periodCntY * 2); col <= ((periodCntY * 2 + 1) + (rodCntHalf * 2 + defectRodCnt - 1)); col++) // 出力導波路から見てY方向はcolに相当
                {
                    if (!isLargeRod_port2)
                    {
                        continue;
                    }
                    if (defectRodCnt_port2 == 1 && isShiftY)
                    {
                    }
                    else
                    {
                        if (col >= ((periodCntY * 2 + 1) + (rodCntHalf * 2 + defectRodCnt - 1) - 2)) continue;
                    }
                    // 右の強制境界と交差するロッド
                    if (isLargeRod_port2
                            && ((col % 2 == 1 && ((rodCntHalf_port2 - 1) % 2 == (isShift180_port2 ? 1 : 0)))
                                || (col % 2 == 0 && ((rodCntHalf_port2 - 1) % 2 == (isShift180_port2 ? 0 : 1)))
                                )
                        )
                    {
                        uint id_e = 4;
                        //変更なし
                        ////if (!isShift180_port2)
                        //if (id_e_F2_discon_new_port2 != 0)
                        //{
                        //    id_e = id_e_F2_discon_new_port2;
                        //}
                        double x0 = port2_X;
                        double y0 = port2_Y - rodDistanceY * col;
                        double x_cross = port2_X;
                        double[] y_cross_list = new double[3];
                        y_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        y_cross_list[1] = y0; // 中心
                        y_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (x_cross - x0) * (x_cross - x0)) + y0; // 交点
                        foreach (double y_cross in y_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_Bend.Add(id_v_add);
                            id_e_F2_Bend.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                // 中央のロッド (ベンド、右境界と接する半円)
                for (int col = (periodCntY * 2); col <= ((periodCntY * 2 + 1) + (rodCntHalf * 2 + defectRodCnt - 1)); col++) // 出力導波路から見てY方向はcolに相当
                {
                    if (!isLargeRod_port2)
                    {
                        continue;
                    }
                    if (defectRodCnt_port2 == 1 && isShiftY)
                    {
                    }
                    else
                    {
                        if (col >= ((periodCntY * 2 + 1) + (rodCntHalf * 2 + defectRodCnt - 1) - 2)) continue;
                    }
                    // 不連続領域
                    uint baseLoopId = 2;

                    // i : (rodCntHalf_port2 - 1)
                    if (isLargeRod_port2
                            && ((col % 2 == 1 && ((rodCntHalf_port2 - 1) % 2 == (isShift180_port2 ? 1 : 0)))
                                || (col % 2 == 0 && ((rodCntHalf_port2 - 1) % 2 == (isShift180_port2 ? 0 : 1))))
                        )
                    {
                        {
                            // 右の強制境界と交差するロッド
                            // 半円(左半分)を追加
                            double x0 = port2_X;
                            double y0 = port2_Y - rodDistanceY * col;
                            int col2 = (col - (periodCntY * 2)) / 2;
                            System.Diagnostics.Debug.Assert(col2 >= 0);
                            uint id_v0 = id_v_list_F2_Bend[col2 * 3 + 0];
                            uint id_v1 = id_v_list_F2_Bend[col2 * 3 + 1];
                            uint id_v2 = id_v_list_F2_Bend[col2 * 3 + 2];
                            uint lId = WgCadUtil.AddExactlyHalfRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                270.0,
                                true);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[3 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 3] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[3 + rodLoopIds.Count];
                for (int i = 0; i < 3; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 3] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 2ポート情報リスト作成
            //const uint portCnt = 2;
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                //WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                if (portIndex == 0)
                {
                    WgPortInfoList[portIndex].PeriodicDistance = rodDistanceX;
                }
                else if (portIndex == 1)
                {
                    WgPortInfoList[portIndex].PeriodicDistance = rodDistanceY * 2.0;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (portIndex == 0)
                {
                    WgPortInfoList[portIndex].MinEffN = minEffN;
                    WgPortInfoList[portIndex].MaxEffN = maxEffN;
                    WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                    WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;
                }
                else if (portIndex == 1)
                {
                    WgPortInfoList[portIndex].MinEffN = minEffN_port2;
                    WgPortInfoList[portIndex].MaxEffN = maxEffN_port2;
                    WgPortInfoList[portIndex].MinWaveNum = minWaveNum_port2;
                    WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
            }
            if (incidentModeIndex_port2 != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex_port2: {0}", incidentModeIndex_port2);
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex_port2;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                //uint[] eId_cad_list = { 2, 3, 4, 5, 7, 8, 9, 10 };
                uint[] eId_cad_list = new uint[8 + id_e_F1.Count + id_e_F2.Count + id_e_F2_Bend.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 5;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                eId_cad_list[6] = 9;
                eId_cad_list[7] = 10;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[8 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[8 + id_e_F1.Count + i] = id_e_F2[i];
                }
                for (int i = 0; i < id_e_F2_Bend.Count; i++)
                {
                    eId_cad_list[8 + id_e_F1.Count + id_e_F2.Count + i] = id_e_F2_Bend[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 6;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        //eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) - (i - 1));
                        eId_cad_list[i] = (uint)(12 + (ndivPlus_port1 - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        //eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 3 - (i - 1));
                        eId_cad_list[i] = (uint)(12 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 11;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 12;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        //eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 2 - (i - 1));
                        eId_cad_list[i] = (uint)(12 + (ndivPlus_port1 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        //eId_cad_list[i] = (uint)(12 + (ndivPlus - 1) * 4 - (i - 1));
                        eId_cad_list[i] = (uint)(12 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf))
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - (0.5 * rodDistanceY - rodRadius)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + (0.5 * rodDistanceY - rodRadius))) // dielectric rod
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        if ((portIndex == 0 &&
                                (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            || (portIndex == 1 &&
                                (coord[0] >= ((port2_X - waveguideWidth2) + (0.5 * rodDistanceX) * (rodCntHalf_port2) - 1.0 * (0.5 * rodDistanceX))
                                  && coord[0] <= ((port2_X - waveguideWidth2) + (0.5 * rodDistanceX) * (rodCntHalf_port2 + defectRodCnt_port2) + 1.0 * (0.5 * rodDistanceX))))
                            )
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 21
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <param name="id_v0"></param>
        /// <param name="id_v1"></param>
        /// <param name="id_v2"></param>
        /// <param name="startAngle"></param>
        /// <param name="isReverseAddVertex"></param>
        /// <returns></returns>
        public static uint AddExactlyQuarterRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
                                                uint id_v0, uint id_v1, uint id_v2, double startAngle, bool isReverseAddVertex)
        {
            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);

            System.Diagnostics.Debug.Assert(Math.Abs(x0 - pt_center.x) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            System.Diagnostics.Debug.Assert(Math.Abs(y0 - pt_center.y) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            List <CVector2D> pts = new List <CVector2D>();

            System.Diagnostics.Debug.Assert((startAngle == 0.0) || (startAngle == 90.0) || (startAngle == 180.0) || (startAngle == 270.0));

            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 1; itheta < (rodCircleDiv / 4); itheta++)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x        = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y        = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            uint retLoopId = 0;
            uint prev_id_v = id_v0;

            // ロッド1/4円
            for (int itheta = 1; itheta < (rodCircleDiv / 4); itheta++)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                }
                else
                {
                    theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                }
                double x        = x0 + rodRadius * Math.Cos(theta);
                double y        = y0 + rodRadius * Math.Sin(theta);
                uint   id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_add != 0);
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                uint id_e_add = resConnectVertex.id_e_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                prev_id_v = id_v_add;
            }
            uint last_id_v = id_v2;

            {
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                uint id_e_add = resConnectVertex.id_e_add;
                uint lId      = resConnectVertex.id_l_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                System.Diagnostics.Debug.Assert(lId != 0);
                retLoopId = lId;
            }

            return(retLoopId);
        }
Exemplo n.º 22
0
        /// <summary>
        /// 導波管ベンド
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="timeLoopCnt"></param>
        /// <param name="timeDelta"></param>
        /// <param name="gaussianT0"></param>
        /// <param name="gaussianTp"></param>
        /// <param name="NormalizedFreqSrc"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPmlLoopIdList"></param>
        /// <param name="PmlStPosXList"></param>
        /// <param name="FieldPortSrcBcId"></param>
        /// <param name="VIdRefList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            ref double WaveguideWidth,
            ref bool isPCWaveguide,
            ref double latticeA,
            ref int timeLoopCnt,
            ref double timeDelta,
            ref double gaussianT0,
            ref double gaussianTp,
            ref double NormalizedFreqSrc,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double GraphFreqInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
             ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPmlLoopIdList,
            ref IList<bool> IsPmlYDirectionList,
            ref IList<double> PmlStPosXList,
            ref IList<double> PmlLengthList,
            ref uint FieldPortSrcBcId,
            ref IList<uint> VIdRefList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            WaveguideWidth = 3.0e-3 * 20 * 4;

            // 導波管ベンド
            // メッシュの分割長さ
            //double meshL = WaveguideWidth * 0.05;
            //double meshL = WaveguideWidth * 0.10;
            //double meshL = WaveguideWidth * 0.09;
            double meshL = WaveguideWidth * 0.04;

            // 入力部の長さ
            //double inputWGLength = 1.0 * WaveguideWidth;
            double inputWGLength = 2.0 * WaveguideWidth;
            // 形状設定で使用する単位長さ
            double unitLen = WaveguideWidth / 20.0;
            // PMLの長さ
            //double pmlLength = 10 * unitLen;
            double pmlLength = 12 * unitLen;

            // 励振位置
            double srcPosX = pmlLength + 5 * unitLen;
            // 観測点
            int port1OfsX = 5;
            int port2OfsY = 5;
            double port1PosX = srcPosX + port1OfsX * unitLen;
            double port1PosY = WaveguideWidth * 0.5;
            double port2PosX = pmlLength + inputWGLength + WaveguideWidth * 0.5;
            double port2PosY = -inputWGLength + port2OfsY * unitLen;

            // 時間領域
            //double courantNumber = 0.5;
            double courantNumber = 0.5;
            //timeLoopCnt = 3000;
            timeLoopCnt = 3000;
            // 時刻刻み
            timeDelta = courantNumber * meshL / (c0 * Math.Sqrt(2.0));

            // モード計算規格化周波数(搬送波規格化周波数)
            //NormalizedFreqSrc = 2.0;
            //NormalizedFreqSrc = 1.5; // ガウシアンパルス
            NormalizedFreqSrc = 2.0; // 正弦波変調ガウシアンパルス

            /*
            // ガウシアンパルス
            //gaussianT0 = 30 * timeDelta;
            //gaussianT0 = 40 * timeDelta;
            //gaussianT0 = 20 * timeDelta;
            gaussianT0 = 45 * timeDelta;
            gaussianTp = gaussianT0 / (Math.Sqrt(2.0) * 4.0);
             */

            // 正弦波変調ガウシアンパルス
            // 波数
            double k0Src = NormalizedFreqSrc * pi / WaveguideWidth;
            // 波長
            double waveLengthSrc = 2.0 * pi / k0Src;
            // 周波数
            double freqSrc = c0 / waveLengthSrc;
            // 角周波数
            double omegaSrc = 2.0 * pi * freqSrc;
            // 搬送波の振動回数
            int nCycle = 5;
            //gaussianT0 = (1.0 / freqSrc) * nCycle / 2;
            //gaussianT0 = 0.5 * (1.0 / freqSrc) * nCycle / 2;
            //gaussianT0 = 0.67 * (1.0 / freqSrc) * nCycle / 2;
            gaussianT0 = 0.65 * (1.0 / freqSrc) * nCycle / 2;
            gaussianTp = gaussianT0 / (2.0 * Math.Sqrt(2.0 * Math.Log(2.0)));

            // 周波数領域
            NormalizedFreq1 = 1.0;
            NormalizedFreq2 = 2.0;
            GraphFreqInterval = 0.2;

            // ポート数
            const int portCnt = 2;

            // 媒質リスト作成
            MediaInfo mediaVacumn = new MediaInfo
            (
                new double[3, 3]
                {
                   { 1.0/1.0, 0.0,     0.0     },
                   { 0.0,     1.0/1.0, 0.0     },
                   { 0.0,     0.0,     1.0/1.0 }
                },
                new double[3, 3]
                {
                   { 1.0, 0.0, 0.0 },
                   { 0.0, 1.0, 0.0 },
                   { 0.0, 0.0, 1.0 }
                }
            );
            Medias.Add(mediaVacumn);

            // 図面作成、メッシュ生成
            // 全ループ数
            uint loopCnt_cad = 2 + portCnt;
            // ポート1のPML領域ループリスト
            uint[] port1_pml_loopIds_cad = { 1 };
            // ポート2のPML領域ループリスト
            uint[] port2_pml_loopIds_cad = { 4 };
            // PML開始位置X座標
            double[] pmlStPosX_list = { pmlLength, -inputWGLength }; // ポート2はY方向PMLでY座標を格納
            // Y方向PML?
            bool[] isPmlYDirection_list = { false, true };
            // 観測点頂点ID
            uint[] portRef_vIds_cad = new uint[portCnt];
            // 励振面の辺ID
            uint eId_cad_src = 14;
            // ポート2
            double port2_X1 = pmlLength + inputWGLength;
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                IList<CVector2D> pts = new List<CVector2D>();
                pts.Add(new CVector2D(0.0, WaveguideWidth));  // 頂点1
                pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                pts.Add(new CVector2D(pmlLength, 0.0)); // 頂点3
                pts.Add(new CVector2D(srcPosX, 0.0)); // 頂点4
                pts.Add(new CVector2D(port2_X1, 0.0)); // 頂点5
                pts.Add(new CVector2D(port2_X1, -inputWGLength)); // 頂点6
                pts.Add(new CVector2D(port2_X1, -inputWGLength - pmlLength)); // 頂点7
                pts.Add(new CVector2D(port2_X1 + WaveguideWidth, -inputWGLength - pmlLength)); // 頂点8
                pts.Add(new CVector2D(port2_X1 + WaveguideWidth, -inputWGLength)); // 頂点9
                pts.Add(new CVector2D(port2_X1 + WaveguideWidth, WaveguideWidth)); // 頂点10
                pts.Add(new CVector2D(srcPosX, WaveguideWidth)); // 頂点11
                pts.Add(new CVector2D(pmlLength, WaveguideWidth)); // 頂点12
                uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                uint lId2 = cad2d.ConnectVertex_Line(3, 12).id_l_add;
                uint lId3 = cad2d.ConnectVertex_Line(4, 11).id_l_add;
                uint lId4 = cad2d.ConnectVertex_Line(6, 9).id_l_add;
                // 観測点
                portRef_vIds_cad[0] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, lId3, new CVector2D(port1PosX, port1PosY)).id_v_add; // 頂点13
                portRef_vIds_cad[1] = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, lId3, new CVector2D(port2PosX, port2PosY)).id_v_add; // 頂点14
                // check
                foreach (uint vId in portRef_vIds_cad)
                {
                    System.Diagnostics.Debug.Assert(vId != 0);
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // PML領域に色を付ける
                    uint[][] port_pml_loopIds_cad_list = { port1_pml_loopIds_cad, port2_pml_loopIds_cad };
                    for (int portIndex = 0; portIndex < portCnt; portIndex++)
                    {
                        uint[] work_lId_list = port_pml_loopIds_cad_list[portIndex];
                        foreach (uint lId in work_lId_list)
                        {
                            cad2d.SetColor_Loop(lId, new double[] { 0.5, 0.5, 0.5 });
                        }
                    }
                    // 境界の辺に色を付ける
                    {
                        uint[] work_eId_list = { eId_cad_src };
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 0.8, 0.0, 0.0 });
                        }
                    }
                    /*
                    // DEBUG
                    {
                        uint[] work_eId_list = {2, 3, 4, 5, 6, 8, 9, 10, 11, 12};
                        foreach (uint eId in work_eId_list)
                        {
                            cad2d.SetColor_Edge(eId, new double[] { 1.0, 1.0, 1.0 });
                        }
                    }
                     */

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }

                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */

                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list  = new uint[loopCnt_cad];
                for (int i = 0; i < loopCnt_cad; i++)
                {
                    loopId_cad_list[i] = (uint)(i + 1);
                }
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint loopId_cad in loopId_cad_list)
                {
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                    {
                        wg2d.World.Loop loop = new wg2d.World.Loop();
                        loop.Set(lId1, Medias.IndexOf(mediaVacumn));
                        LoopDic.Add(lId1, loop);
                    }
                }
                //System.Diagnostics.Debug.WriteLine("lId:" + lId1);
                FieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
            }
            // PML領域
            FieldPmlLoopIdList.Clear();
            IsPmlYDirectionList.Clear();
            PmlStPosXList.Clear();
            PmlLengthList.Clear();
            uint[][] loopId_cad_list_pml = { port1_pml_loopIds_cad, port2_pml_loopIds_cad };
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                uint[] loopId_cad_list = loopId_cad_list_pml[portIndex];
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint loopId_cad in loopId_cad_list)
                {
                    uint lId1 = conv.GetIdEA_fromCad(loopId_cad, CAD_ELEM_TYPE.LOOP);
                    aEA.Add(lId1);
                }
                uint workFieldLoopId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldLoopId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0);
                FieldPmlLoopIdList.Add(workFieldLoopId);
                // Y方向PML?
                bool isPmlYDirection = isPmlYDirection_list[portIndex];
                IsPmlYDirectionList.Add(isPmlYDirection);
                // PML開始位置
                double pmlStPosX = pmlStPosX_list[portIndex];
                PmlStPosXList.Add(pmlStPosX);
                // PML長さ
                PmlLengthList.Add(pmlLength);
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            {
                uint[] eId_cad_list = {2, 3, 4, 5, 6, 8, 9, 10, 11, 12}; // PML終端磁気壁
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                foreach (uint eId_cad in eId_cad_list)
                {
                    uint eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                    aEA.Add(eId);
                }
                // フィールドIDを取得
                FieldForceBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(FieldForceBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortSrcBcId = 0;
            {
                // PMLを用いる場合は、励振面のみ
                uint eId_cad = eId_cad_src;
                uint eId;
                // 要素アレイのリスト
                IList<uint> aEA = new List<uint>();
                eId = conv.GetIdEA_fromCad(eId_cad, CAD_ELEM_TYPE.EDGE);
                aEA.Add(eId);
                {
                    wg2d.World.Edge edge = new wg2d.World.Edge();
                    edge.Set(eId, Medias.IndexOf(mediaVacumn));
                    EdgeDic.Add(eId, edge);
                }
                uint workFieldPortBcId = World.GetPartialField(FieldValId, aEA);
                CFieldValueSetter.SetFieldValue_Constant(workFieldPortBcId, 0, FIELD_DERIVATION_TYPE.VALUE, World, 0); // 境界の界を0で設定
                FieldPortSrcBcId = workFieldPortBcId;
            }

            // 観測点
            VIdRefList.Clear();
            uint[] vId_cad_refPort = portRef_vIds_cad;
            foreach (uint vId_cad in vId_cad_refPort)
            {
                uint vId = conv.GetIdEA_fromCad(vId_cad, CAD_ELEM_TYPE.VERTEX);
                VIdRefList.Add(vId);
            }

            return true;
        }
Exemplo n.º 23
0
        /// <summary>
        /// PC導波路 60°三角形格子 方向性結合器 直線部
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            //int propModeCntToSolve = 3;
            int propModeCntToSolve = 2;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            //int incidentModeIndex = 0;
            // 高次モード入射
            int incidentModeIndex = 1; // 波数0.5~1.0の範囲ではeven super modeは高次モード
            // モード追跡する?
            //bool isModeTrace = true;
            bool isModeTrace = false;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0.0;
            // 最大屈折率
            double maxEffN = 0.0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0;
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a air hole
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5;
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a air hole

            // 入出力導波路が同じ?
            //IsInoutWgSame = true; // 同じ
            IsInoutWgSame = false; // 同じでない
            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false;
            //bool isShift180 = true;
            // ロッドの数(半分)
            //const int rodCntHalf = 3; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 3;
            System.Diagnostics.Debug.Assert(rodCntHalf % 2 == 1); // 奇数を指定(図面の都合上)
            // 欠陥ロッド数
            // for latticeTheta = 60 r = 0.30a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            double latticeTheta = 60.0;
            // ロッドの半径
            double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            //double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            // 入力側ロッド半径
            //double rodRadiusRatio_Middle_Input = 0.26;
            double rodRadiusRatio_Middle_Input = rodRadiusRatio;
            g_isPort1Rod_Small = Math.Abs(rodRadiusRatio - rodRadiusRatio_Middle_Input) >= Constants.PrecisionLowerLimit;
            // ロッドの比誘電率
            double rodEps = 3.40 * 3.40; // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            //double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.30a air hole
            const int ndivForOneLattice = 8;//9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;
            // 導波路不連続領域の長さ
            //const int rodCntDiscon = 3;
            const int rodCntDiscon = 0;//3;
            // 結合部ロッド数
            const int rodCntMiddle = 2;
            // 結合長
            //int rodCntCoupling = 4; // 7a for latticeTheta = 60 r = 0.30a air hole n = 3.40 (文献の構造 rodCntHalf == 3とき、4a + 2a<ベンド部> + 0.5a * 2<左右両端> = 7a)
            //int rodCntCoupling = 2; // 5a for latticeTheta = 60 r = 0.30a air hole n = 3.40 (完全結合長に合わせた場合)
            //int rodCntCoupling = 3;// 6a for latticeTheta = 60 r = 0.30a air hole n = 2.76 (文献の構造)
            int rodCntCoupling = 4;
            if (g_isPort1Rod_Small)
            {
                // 入力導波路の結合部をモード合成がうまくいくように変更した場合基準面を1周期ずらすので解析領域を1周期長くとる
                rodCntCoupling++;
            }
            // 入出力不連続部の距離
            int rodCntDiscon_port1 = (rodCntDiscon + rodCntCoupling);  // 入力部は結合領域を含む

            // 格子の数
            const int latticeCnt = rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 入力側ロッドの半径
            double rodRadius_Middle_Input = rodRadiusRatio_Middle_Input * latticeA;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            // 情報引渡し
            g_rodCntHalf = rodCntHalf;
            g_rodCntMiddle = rodCntMiddle;
            g_defectRodCnt = defectRodCnt;
            g_periodicDistance = periodicDistance;

            // for latticeTheta = 60 r = 0.30a air hole n = 3.40
            ////NormalizedFreq1 = 0.215;//0.210;
            ////NormalizedFreq2 = 0.2401;// 0.2561;
            NormalizedFreq1 = 0.215001;  // ポート2の固有モード計算失敗回避
            NormalizedFreq2 = 0.2401;
            FreqDelta = 0.00025; //0.0005;
            GraphFreqInterval = 0.005;
            // for latticeTheta = 60 r = 0.30a air hole n = 2.76
            ////NormalizedFreq1 = 0.267;
            ////NormalizedFreq2 = 0.2831;//0.2871;
            //NormalizedFreq1 = 0.267001;  // ポート2の固有モード計算失敗回避
            //NormalizedFreq2 = 0.2831;//0.2871;
            //FreqDelta = 0.00025;// 0.0005;
            //GraphFreqInterval = 0.004;

            //minEffN = 0.0;
            //maxEffN = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN_port2 = minWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            //maxEffN_port2 = maxWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;// 1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
                //isMagneticWall = true;
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
                incidentModeIndex = 0;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            const uint portCnt = 2;
            System.Diagnostics.Debug.Assert(Math.Abs(WaveguideWidth - WaveguideWidth) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            double disconLength1 = rodDistanceX * rodCntDiscon_port1;
            double disconLength2 = rodDistanceX * (rodCntDiscon + 1); // +1は元の問題に合わせるため
            double port2_X = inputWgLength * 2 + disconLength1 + disconLength2;

            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            int ndivPlus_port1 = 0;
            int ndivPlus_port2 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();

            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(0.0, WaveguideWidth)); // 頂点1
                    pts.Add(new CVector2D(0.0, 0.0)); // 頂点2
                    pts.Add(new CVector2D(inputWgLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(port2_X - inputWgLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(port2_X, 0.0)); // 頂点5
                    pts.Add(new CVector2D(port2_X, WaveguideWidth)); // 頂点6
                    pts.Add(new CVector2D(port2_X - inputWgLength, WaveguideWidth)); // 頂点7
                    pts.Add(new CVector2D(inputWgLength, WaveguideWidth)); // 頂点8
                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 8).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(4, 7).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys_port1 = new List<double>();
                IList<double> ys_rod_port1 = new List<double>();
                IList<double> ys_port2 = new List<double>();
                IList<double> ys_rod_port2 = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    int cur_rodCntHalf = 0;
                    int cur_defectRodCnt = 0;
                    int cur_rodCntMiddle = 0;
                    int cur_ndivForOneLattice = 0;
                    double cur_WaveguideWidth = 0.0;
                    double cur_rodDistanceY = 0.0;
                    double rr = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;
                    cur_rodCntHalf = rodCntHalf;
                    cur_defectRodCnt = defectRodCnt;
                    cur_rodCntMiddle = rodCntMiddle;
                    cur_ndivForOneLattice = ndivForOneLattice;
                    cur_WaveguideWidth = WaveguideWidth;
                    cur_rodDistanceY = rodDistanceY;
                    if (portIndex == 0)
                    {
                        ys = ys_port1;
                        ys_rod = ys_rod_port1;
                    }
                    else if (portIndex == 1)
                    {
                        ys = ys_port2;
                        ys_rod = ys_rod_port2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    System.Diagnostics.Debug.Assert(ys.Count == 0);
                    System.Diagnostics.Debug.Assert(ys_rod.Count == 0);

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    for (int i = 0; i < (cur_rodCntHalf * 2 + cur_defectRodCnt * 2 + cur_rodCntMiddle); i++)
                    {
                        if (i >= cur_rodCntHalf && i < (cur_rodCntHalf + cur_defectRodCnt)) continue; // 上側導波路部
                        if (i >= (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle) && i < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle + cur_defectRodCnt)) continue; // 下側導波路部
                        if (cur_rodCntMiddle % 2 == 0)
                        {
                            if (Math.Abs(cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        rr = rodRadius;
                        if (portIndex == 0)
                        {
                            if (i >= (cur_rodCntHalf + cur_defectRodCnt) && i < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle))
                            {
                                rr = rodRadius_Middle_Input;
                            }
                        }
                        double y0 = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rr / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rr / rodRadiusDiv);
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }
                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    double radiusMargin = cur_rodDistanceY * 0.01;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    for (int i = 0; i < (cur_rodCntHalf * 2 + cur_defectRodCnt * 2 + cur_rodCntMiddle); i++)
                    {
                        if (i >= cur_rodCntHalf && i < (cur_rodCntHalf + cur_defectRodCnt)) continue; // 上側導波路部
                        if (i >= (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle) && i < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle + cur_defectRodCnt)) continue; // 下側導波路部
                        if (cur_rodCntMiddle % 2 == 0)
                        {
                            if (Math.Abs(cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        rr = rodRadius;
                        if (portIndex == 0)
                        {
                            if (i >= (cur_rodCntHalf + cur_defectRodCnt) && i < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle))
                            {
                                rr = rodRadius_Middle_Input;
                            }
                        }
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rr - radiusMargin;
                            double y_max_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rr + radiusMargin;
                            if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }

                    // 境界上にロッドのない格子
                    for (int i = 0; i < (cur_rodCntHalf * 2 + cur_defectRodCnt * 2 + cur_rodCntMiddle); i++)
                    {
                        if (i >= cur_rodCntHalf && i < (cur_rodCntHalf + cur_defectRodCnt)) continue; // 上側導波路部
                        if (i >= (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle) && i < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle + cur_defectRodCnt)) continue; // 下側導波路部
                        if (cur_rodCntMiddle % 2 == 0)
                        {
                            if (Math.Abs(cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == 0 && k == 0) continue;
                            if (i == (cur_rodCntHalf * 2 + cur_defectRodCnt * 2 + cur_rodCntMiddle - 1) && k == cur_ndivForOneLattice) continue;
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            rr = rodRadius;
                            if (portIndex == 0)
                            {
                                if ((i - 1) >= (cur_rodCntHalf + cur_defectRodCnt) && (i - 1) < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle))
                                {
                                    rr = rodRadius_Middle_Input;
                                }
                            }
                            double y_min_upper_rod = cur_WaveguideWidth - i * cur_rodDistanceY + 0.5 * cur_rodDistanceY - rr - radiusMargin;
                            rr = rodRadius;
                            if (portIndex == 0)
                            {
                                if ((i + 1) >= (cur_rodCntHalf + cur_defectRodCnt) && (i + 1) < (cur_rodCntHalf + cur_defectRodCnt + cur_rodCntMiddle))
                                {
                                    rr = rodRadius_Middle_Input;
                                }
                            }
                            double y_max_lower_rod = cur_WaveguideWidth - (i + 1) * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rr + radiusMargin;
                            if ((isShift180 || (!isShift180 && i != (cur_rodCntHalf - 1)))
                                && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                            {
                                continue;
                            }

                            ys.Add(y_divpt);
                        }
                    }
                    // 欠陥部
                    const int channelCnt = 2;
                    System.Diagnostics.Debug.Assert(cur_rodCntMiddle % 2 == 0);
                    for (int channelIndex = 0; channelIndex < channelCnt; channelIndex++)
                    {
                        for (int i = 0; i <= (cur_defectRodCnt * cur_ndivForOneLattice); i++)
                        {
                            if (channelIndex == 0)
                            {
                                if (cur_rodCntMiddle % 2 == 0)
                                {
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }
                            else if (channelIndex == 1)
                            {
                                if (cur_rodCntMiddle % 2 == 0)
                                {
                                    if (!isShift180 && (i == 0 || i == (cur_defectRodCnt * cur_ndivForOneLattice))) continue;
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }
                            double y_ofs = 0.0;

                            if (channelIndex == 1)
                            {
                                y_ofs = cur_rodDistanceY * (cur_defectRodCnt + cur_rodCntMiddle);
                            }
                            double y_divpt = cur_WaveguideWidth - cur_rodDistanceY * cur_rodCntHalf - i * (cur_rodDistanceY / cur_ndivForOneLattice) - y_ofs;
                            ys.Add(y_divpt);
                        }
                    }

                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (portIndex == 0)
                    {
                        ndivPlus_port1 = cur_ndivPlus;
                    }
                    else if (portIndex == 1)
                    {
                        ndivPlus_port2 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    // 入力導波路 外側境界
                    // 入力導波路 内部側境界
                    // 出力導波路 外側境界
                    // 出力導波路 内部側境界
                    for (int boundaryIndex = 0; boundaryIndex < 2;  boundaryIndex++)
                    {
                        bool isInRod = false;
                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            double x_pt = 0.0;
                            double y_pt = 0.0;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (portIndex == 0 && boundaryIndex == 0)
                            {
                                // 入力導波路 外側境界
                                id_e = 1;
                                x_pt = 0.0;
                                y_pt = yAry[i];
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B1;
                                work_id_v_list_rod_B = id_v_list_rod_B1;
                            }
                            else if (portIndex == 0 && boundaryIndex == 1)
                            {
                                // 入力導波路 内側境界
                                id_e = 9;
                                x_pt = inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B2;
                                work_id_v_list_rod_B = id_v_list_rod_B2;
                            }
                            else if (portIndex == 1 && boundaryIndex == 0)
                            {
                                // 出力導波路 外側境界
                                id_e = 5;
                                x_pt = port2_X;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (portIndex == 1 && boundaryIndex == 1)
                            {
                                // 出力導波路 内側境界
                                id_e = 10;
                                x_pt = port2_X - inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y_pt));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                    }
                }

                int bRodCntHalf_Top = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                int bRodCntHalf_Bottom = 0;
                if (rodCntMiddle % 2 == 0)
                {
                    bRodCntHalf_Bottom = (int)((rodCntHalf + 1) / 2);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int bRodCntMiddle = (rodCntMiddle) / 2;
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == (bRodCntHalf_Top + bRodCntHalf_Bottom + bRodCntMiddle) * (rodRadiusDiv * 2 + 1));

                // ロッドを追加
                /////////////////////////////////////////////////////////////
                // 入力導波路側ロッド
                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    double rr = 0.0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = 0.0;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    int rodCntY = (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle);
                    for (int i = 0; i < rodCntY; i++)
                    {
                        {
                            // ポート1
                            if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                            if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                        }
                        rr = rodRadius;
                        if (colIndex == 0 || colIndex == 1)
                        {
                            if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                            {
                                rr = rodRadius_Middle_Input;
                            }
                        }
                        if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0))
                        {
                            int i2 = 0;
                            {
                                if (i >= 0 && i < rodCntHalf)
                                {
                                    i2 = bRodCntHalf_Top - 1 - (int)((rodCntHalf - 1 - i) / 2) + 1;
                                }
                                else if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                                {
                                    i2 = bRodCntHalf_Top + bRodCntMiddle - 1 - (int)((rodCntHalf + defectRodCnt + rodCntMiddle - 1 - i) / 2) + 1;
                                }
                                else if (i >= (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) && i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle))
                                {
                                    i2 = bRodCntHalf_Top + bRodCntMiddle + bRodCntHalf_Bottom - 1 - (int)((rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1 - i) / 2) ;
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rr,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }
                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    double rr = 0.0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (colIndex == 1)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2外側
                        x_B = port2_X;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    int rodCntY = (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle);
                    for (int i = 0; i < rodCntY; i++)
                    {
                        {
                            // ポート1
                            if (i >= rodCntHalf && i < (rodCntHalf + defectRodCnt)) continue; // 上側導波路部
                            if (i >= (rodCntHalf + defectRodCnt + rodCntMiddle) && i < (rodCntHalf + defectRodCnt + rodCntMiddle + defectRodCnt)) continue; // 下側導波路部
                        }
                        rr = rodRadius;
                        if (colIndex == 0)
                        {
                            if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                            {
                                rr = rodRadius_Middle_Input;
                            }
                        }
                        if (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0))
                        {
                            int i2 = 0;
                            {
                                if (i >= 0 && i < rodCntHalf)
                                {
                                    i2 = bRodCntHalf_Top - 1 - (int)((rodCntHalf - 1 - i) / 2) + 1;
                                }
                                else if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                                {
                                    i2 = bRodCntHalf_Top + bRodCntMiddle - 1 - (int)((rodCntHalf + defectRodCnt + rodCntMiddle - 1 - i) / 2) + 1;
                                }
                                else if (i >= (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) && i < (rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle))
                                {
                                    i2 = bRodCntHalf_Top + bRodCntMiddle + bRodCntHalf_Bottom - 1 - (int)((rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle - 1 - i) / 2);
                                }
                                else
                                {
                                    System.Diagnostics.Debug.Assert(false);
                                }
                            }

                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rr,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央のロッド (入力導波路 + 不連続部 + 出力導波路)
                int periodCntInputWg1 = 1;
                int rodCnt_Y = rodCntHalf * 2 + defectRodCnt * 2 + rodCntMiddle;
                int periodCntX_port2 = (int)Math.Round(port2_X / rodDistanceX);

                for (int col = 1; col <= (periodCntX_port2 * 2 - 1); col++)
                {
                    if (col == (periodCntInputWg1 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntX_port2 * 2 - periodCntInputWg1 * 2)) continue;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;
                    double rr = 0.0;

                    // 中央のロッド
                    for (int i = 0; i < rodCnt_Y; i++)
                    {
                        if (col >= 0 && col < (periodCntInputWg1 * 2))
                        {
                            baseLoopId = 1;
                            inputWgNo = 1;
                            rr = rodRadius;
                            if (i >= (rodCntHalf + defectRodCnt) && i < (rodCntHalf + defectRodCnt + rodCntMiddle))
                            {
                                rr = rodRadius_Middle_Input;
                            }
                        }
                        else if (col >= (periodCntInputWg1 * 2) && col < (periodCntX_port2 * 2 - periodCntInputWg1 * 2))
                        {
                            baseLoopId = 2;
                            inputWgNo = 0;
                            rr = rodRadius;
                        }
                        else if (col >= (periodCntX_port2 * 2 - periodCntInputWg1 * 2) && col <= (periodCntX_port2 * 2 - 1))
                        {
                            baseLoopId = 3;
                            inputWgNo = 2;
                            rr = rodRadius;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        // ロッドの半径
                        //double rr = rodRadius;
                        // ロッドの半径方向分割数
                        int nr = rodRadiusDiv;
                        // ロッドの周方向分割数
                        int nc = rodCircleDiv;
                        // ずらす距離
                        double ofs_x_rod = 0.0;
                        double ofs_y_rod = 0.0;

                        if (inputWgNo == 0)
                        {
                            // 分割数を調整
                            nr = 2;
                        }

                        // 欠陥(導波路2)
                        if (i >= (rodCnt_Y - 1 - rodCntHalf - defectRodCnt + 1) && i <= (rodCnt_Y - 1 - rodCntHalf))
                        {
                            continue;
                        }
                        // 欠陥(導波路1)
                        if (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1))
                        {
                            continue;
                        }

                        if ((col % 2 == 1 && (Math.Abs(i - (rodCnt_Y - (rodCntHalf * 2 + defectRodCnt))) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(i - rodCnt_Y - ((rodCntHalf * 2 + defectRodCnt))) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            //uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            x0 += ofs_x_rod;
                            y0 += ofs_y_rod;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, nc, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[3 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 3] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[3 + rodLoopIds.Count];
                for (int i = 0; i < 3; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 3] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // ポート情報リスト作成
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
            }
            if (!isModeTrace)
            {
                WgPortInfoList[0].IsModeTrace = isModeTrace;
                WgPortInfoList[1].IsModeTrace = isModeTrace;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[6 + id_e_F1.Count + id_e_F2.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 6;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[6 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[6 + id_e_F1.Count + i] = id_e_F2[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 5;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus_port1 - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 9;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 10;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus_port1 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(10 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                if (portIndex == 0 || portIndex == 1)
                {
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                {
                    {
                        // チャンネル1
                        IList<uint> portNodes = new List<uint>();
                        for (int i = 0; i < no_c_all.Length; i++)
                        {
                            // 座標からチャンネル(欠陥部)を判定する
                            double[] coord = coord_c_all[i];
                            if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                            {
                                portNodes.Add(no_c_all[i]);
                            }
                        }
                        wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                    }
                    {
                        // チャンネル2
                        IList<uint> portNodes = new List<uint>();
                        for (int i = 0; i < no_c_all.Length; i++)
                        {
                            // 座標からチャンネル(欠陥部)を判定する
                            double[] coord = coord_c_all[i];
                            if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt * 2 + rodCntMiddle) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt + rodCntMiddle) + 1.0 * rodDistanceY)) // air hole
                            {
                                portNodes.Add(no_c_all[i]);
                            }
                        }
                        wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                    }
                }
            }
            return true;
        }
Exemplo n.º 24
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <returns></returns>
        private bool setNewProblem()
        {
            bool success = false;

            try
            {
                if (ProbNo == 0)
                {
                    Id_base = 0;
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(-0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5, 0.5) );
                        pts.Add( new CVector2D(-0.5, 0.5) );
                        uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                        World.Clear();
                        Id_base = World.AddMesh( new CMesher2D(cad2d,0.02) );
                    }
                    Id_field_val = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.SCALAR);
                    System.Diagnostics.Debug.Assert( World.IsIdField(Id_field_val) );
                    clearFieldValueSetterAry(FieldValueSetterAry);
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                        fvs.SetMathExp("sin(10*sqrt(x^2+y^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                    DrawerAry.InitTrans( Camera );
                }
                else if( ProbNo == 1 )
                {
                    clearFieldValueSetterAry(FieldValueSetterAry);
                    CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                    fvs.SetMathExp("sin(2*PI*x-t)*sin(2*PI*y-t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                    FieldValueSetterAry.Add(fvs);
                }
                else if( ProbNo == 2 )
                {
                    string mshfn = "../../../input_file/rect_quad.msh";
                    //string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D msh2d = new CMesher2D())
                        {
                            msh2d.ReadFromFile_GiDMsh(mshfn);
                            World.Clear();
                            Id_base = World.AddMesh( msh2d );
                            Id_field_val = World.MakeField_FieldElemDim(Id_base,2,FIELD_TYPE.SCALAR);
                            clearFieldValueSetterAry(FieldValueSetterAry);
                            {
                                CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                                fvs.SetMathExp("sin(0.5*sqrt((x+1)^2+y^2)-0.1*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                                FieldValueSetterAry.Add(fvs);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                            DrawerAry.InitTrans( Camera);
                        }
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 3 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(-0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5, 0.5) );
                        pts.Add( new CVector2D(-0.5, 0.5) );
                        uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                        using(CMesher2D mesh2d = new CMesher2D(cad2d, 0.07))
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            mesh3d.Extrude(mesh2d, 1.0, 0.07);
                            World.Clear();
                            Id_base = World.AddMesh( mesh3d );
                        }
                    }
                    Id_field_val = World.MakeField_FieldElemDim(Id_base,2,FIELD_TYPE.SCALAR);
                    clearFieldValueSetterAry(FieldValueSetterAry);
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val,World);
                        fvs.SetMathExp("sin(10*sqrt(x^2+y^2+z^2)-PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE,World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                    DrawerAry.InitTrans( Camera );
                }
                else if( ProbNo == 4 )
                {
                    string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D mesh2d = new CMesher2D())
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            mesh2d.ReadFromFile_GiDMsh(mshfn);
                            mesh3d.Extrude(mesh2d, 5.0, 0.5);
                            World.Clear();
                            Id_base = World.AddMesh( mesh3d );
                        }
                        Id_field_val = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.SCALAR);
                        clearFieldValueSetterAry(FieldValueSetterAry);
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val,World);
                            fvs.SetMathExp("sin(1.0*sqrt(x^2+y^2+z^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                        DrawerAry.InitTrans( Camera );
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 5 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(-0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5, 0.5) );
                        pts.Add( new CVector2D(-0.5, 0.5) );
                        uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                        cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 1, new CVector2D(0.0, -0.5) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 3, new CVector2D(0.0,  0.5) );
                        cad2d.ConnectVertex_Line(5,6);
                        World.Clear();
                        Id_base = World.AddMesh( new CMesher2D(cad2d,0.02) );
                    }
                    CIDConvEAMshCad conv = World.GetIDConverter(Id_base);
                    Id_field_val = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.SCALAR);
                    System.Diagnostics.Debug.Assert( World.IsIdField(Id_field_val) );
                    {
                        uint id_field0 = World.GetPartialField(Id_field_val, conv.GetIdEA_fromCad(1, CAD_ELEM_TYPE.LOOP));
                        System.Diagnostics.Debug.Assert( World.IsIdField(id_field0) );
                        uint id_field1 = World.GetPartialField(Id_field_val, conv.GetIdEA_fromCad(2, CAD_ELEM_TYPE.LOOP));
                        System.Diagnostics.Debug.Assert( World.IsIdField(id_field1) );

                        clearFieldValueSetterAry(FieldValueSetterAry);
                        CFieldValueSetter fvs0 = new CFieldValueSetter(id_field0, World);
                        fvs0.SetMathExp("sin(10*sqrt((x+0.5)^2+y^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs0);
                        CFieldValueSetter fvs1 = new CFieldValueSetter(id_field1, World);
                        fvs1.SetMathExp("sin(10*sqrt((x-0.5)^2+y^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs1);
                    }
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                    DrawerAry.InitTrans( Camera );
                }
                else if( ProbNo == 6 )
                {
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(-0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5, 0.5) );
                        pts.Add( new CVector2D(-0.5, 0.5) );
                        cad2d.AddPolygon( pts );
                        cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 1, new CVector2D(0.0, -0.5) );
                        cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 3, new CVector2D(0.0,  0.5) );
                        cad2d.ConnectVertex_Line(5,6);
                        World.Clear();
                        Id_base = World.AddMesh( new CMesher2D(cad2d, 0.05) );
                    }
                    CIDConvEAMshCad conv = World.GetIDConverter(Id_base);
                    Id_field_val = World.MakeField_FieldElemAry(Id_base, conv.GetIdEA_fromCad(1, CAD_ELEM_TYPE.LOOP), FIELD_TYPE.SCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);
                    clearFieldValueSetterAry(FieldValueSetterAry);
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val,World);
                        fvs.SetMathExp("sin(10*sqrt((x+0.5)^2+y^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE,World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                    //DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World) );
                    DrawerAry.InitTrans( Camera );
                }
                else if( ProbNo == 7 )
                {
                    uint id_field_grad = World.MakeField_FieldElemDim(Id_field_val, 2, FIELD_TYPE.VECTOR2,FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.BUBBLE);
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(id_field_grad, World);
                        fvs.SetMathExp("0.1*sin(t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        fvs.SetMathExp("0.1*cos(t)", 1, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    DrawerAry.PushBack( new CDrawerVector(id_field_grad, World) );
                    DrawerAry.InitTrans( Camera );
                }
                else if( ProbNo == 8 )
                {
                    string mshfn = "../../../input_file/cylinder_tet.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher3D mesh3d = new CMesher3D())
                        {
                            mesh3d.ReadFromFile_GiDMsh(mshfn);
                            World.Clear();
                            Id_base = World.AddMesh( mesh3d );
                        }
                        Id_field_val = World.MakeField_FieldElemDim(Id_base, 3, FIELD_TYPE.SCALAR);
                        uint id_field_grad = World.MakeField_FieldElemDim(Id_field_val, 3, FIELD_TYPE.VECTOR3, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.BUBBLE);
                        clearFieldValueSetterAry(FieldValueSetterAry);
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val,World);
                            fvs.SetMathExp("sin(t+0.5*x)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(id_field_grad, World);
                            fvs.SetGradient(Id_field_val, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        DrawerAry.Clear();
                        //DrawerAry.PushBack( new CDrawerFaceContour(Id_field_val,World,-1.0,1.0) );
                        DrawerAry.PushBack( new CDrawerVector(id_field_grad,World) );
                        DrawerAry.PushBack( new CDrawerEdge(id_field_grad,true,World) );
                        DrawerAry.InitTrans( Camera );
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 9 )
                {
                    string mshfn = "../../../input_file/cylinder_hex.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher3D mesh3d = new CMesher3D())
                        {
                            mesh3d.ReadFromFile_GiDMsh(mshfn);
                            World.Clear();
                            Id_base = World.AddMesh( mesh3d );
                        }
                        Id_field_val = World.MakeField_FieldElemDim(Id_base, 3, FIELD_TYPE.SCALAR);
                        uint id_field_grad = World.MakeField_FieldElemDim(Id_field_val, 3, FIELD_TYPE.VECTOR3, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.BUBBLE);
                        clearFieldValueSetterAry(FieldValueSetterAry);
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                            fvs.SetMathExp("sin(t+0.5*x)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(id_field_grad, World);
                            fvs.SetGradient(Id_field_val, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack( new CDrawerVector(id_field_grad, World) );
                        DrawerAry.PushBack( new CDrawerEdge(id_field_grad,true, World) );
                        DrawerAry.InitTrans( Camera );
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 10 )
                {
                    //string mshfn = "../../../input_file/rect_quad.msh";
                    string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D msh2d = new CMesher2D())
                        {
                            msh2d.ReadFromFile_GiDMsh(mshfn);
                            World.Clear();
                            Id_base = World.AddMesh( msh2d );
                        }
                        Id_field_val = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.SCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.BUBBLE);
                        clearFieldValueSetterAry(FieldValueSetterAry);
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                            fvs.SetMathExp("sin(x+y-0.1*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack( new CDrawerFace(Id_field_val,true,World,Id_field_val,-1.0,1.0) );
                        DrawerAry.InitTrans(Camera);
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 11 )
                {
                    //string mshfn = "../../../input_file/rect_quad.msh";
                    string mshfn = "../../../input_file/hexa_tri.msh";
                    if (File.Exists(mshfn))
                    {
                        using(CMesher2D msh2d  = new CMesher2D())
                        using(CMesh3D_Extrude mesh3d = new CMesh3D_Extrude())
                        {
                            msh2d.ReadFromFile_GiDMsh(mshfn);
                            mesh3d.Extrude(msh2d, 5.0, 1);
                            World.Clear();
                            Id_base = World.AddMesh( mesh3d );
                        }
                        Id_field_val = World.MakeField_FieldElemDim(Id_base, 3, FIELD_TYPE.SCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.BUBBLE);
                        clearFieldValueSetterAry(FieldValueSetterAry);
                        {
                            CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                            fvs.SetMathExp("sin(0.5*sqrt(x^2+y^2+z^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                            FieldValueSetterAry.Add(fvs);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack( new CDrawerFace(Id_field_val,true,World, Id_field_val,-1.0,1.0) );
                        //DrawerAry.PushBack( new CDrawerFace(Id_field_val,true,World) );
                        DrawerAry.InitTrans(Camera);
                    }
                    else
                    {
                        Console.WriteLine("not exist:{0}", mshfn);
                        MessageBox.Show(string.Format("メッシュファイル:{0}がありません", mshfn));
                    }
                }
                else if( ProbNo == 12 )
                {
                    // scalar field and vector field
                    using(CCadObj2D cad2d = new CCadObj2D())
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add( new CVector2D(-0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5,-0.5) );
                        pts.Add( new CVector2D( 0.5, 0.5) );
                        pts.Add( new CVector2D(-0.5, 0.5) );
                        uint id_l0 = cad2d.AddPolygon( pts ).id_l_add;
                        World.Clear();
                        Id_base = World.AddMesh( new CMesher2D(cad2d, 0.1) );
                    }
                    Id_field_val = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.SCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER|ELSEG_TYPE.BUBBLE);
                    System.Diagnostics.Debug.Assert( World.IsIdField(Id_field_val) );
                    uint id_field_vec = World.MakeField_FieldElemDim(Id_base, 2, FIELD_TYPE.VECTOR2, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER|ELSEG_TYPE.BUBBLE);
                    System.Diagnostics.Debug.Assert( World.IsIdField(id_field_vec) );
                    clearFieldValueSetterAry(FieldValueSetterAry);
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(Id_field_val, World);
                        fvs.SetMathExp("sin(10*sqrt(x^2+y^2)-2*PI*t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    {
                        CFieldValueSetter fvs = new CFieldValueSetter(id_field_vec, World);
                        fvs.SetMathExp("0.05*sin(t)", 0, FIELD_DERIVATION_TYPE.VALUE, World);
                        fvs.SetMathExp("0.05*cos(t)", 1, FIELD_DERIVATION_TYPE.VALUE, World);
                        FieldValueSetterAry.Add(fvs);
                    }
                    DrawerAry.Clear();
                    DrawerAry.PushBack( new CDrawerFace(Id_field_val, true, World, Id_field_val, -1.0, 1.0) );
                    DrawerAry.PushBack( new CDrawerVector(id_field_vec, World) );
                    DrawerAry.InitTrans( Camera );
                }

                success = true;

            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            ProbNo++;
            if (ProbNo == ProbCnt) ProbNo = 0;
            return success;
        }
Exemplo n.º 25
0
        /// <summary>
        /// 半円(余剰角度なし)ロッドの追加
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="id_v0"></param>
        /// <param name="id_v1"></param>
        /// <param name="id_v2"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <param name="startAngle"></param>
        /// <param name="isReverseAddVertex"></param>
        /// <returns></returns>
        public static uint AddExactlyHalfRod(CCadObj2D cad2d, uint baseLoopId,
            uint id_v0, uint id_v1, uint id_v2,
            double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
            double startAngle, bool isReverseAddVertex)
        {
            uint retLoopId = 0;

            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
            System.Diagnostics.Debug.Assert(Math.Abs(x0 - pt_center.x) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            System.Diagnostics.Debug.Assert(Math.Abs(y0 - pt_center.y) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            // check
            //CVector2D pt0 = cad2d.GetVertexCoord(id_v0);
            //double x_pt0 = pt0.x;
            //double y_pt0 = pt0.y;
            //CVector2D pt2 = cad2d.GetVertexCoord(id_v2);
            //double x_pt2 = pt2.x;
            //double y_pt2 = pt2.y;

            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 1; itheta < (rodCircleDiv / 2); itheta++)
                {
                    double theta = 0.0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッド
            uint prev_id_v = id_v2;
            for (int itheta = 1; itheta < (rodCircleDiv / 2); itheta++)
            {
                double theta = 0.0;
                if (isReverseAddVertex)
                {
                    theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                }
                else
                {
                    theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                }
                double x = x0 + rodRadius * Math.Cos(theta);
                double y = y0 + rodRadius * Math.Sin(theta);
                uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_add != 0);
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                uint id_e_add = resConnectVertex.id_e_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                prev_id_v = id_v_add;
            }
            uint last_id_v = id_v0;
            {
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                uint id_e_add = resConnectVertex.id_e_add;
                uint lId = resConnectVertex.id_l_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                System.Diagnostics.Debug.Assert(lId != 0);
                retLoopId = lId;
            }
            return retLoopId;
        }
Exemplo n.º 26
0
        /// <summary>
        /// 三角形格子 PC欠陥導波路
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinBeta"></param>
        /// <param name="MaxBeta"></param>
        /// <param name="GraphBetaInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="IsPCWaveguide"></param>
        /// <param name="latticeA"></param>
        /// <param name="periodicDistance"></param>
        /// <param name="PCWaveguidePorts"></param>
        /// <param name="isSolveEigenItr"></param>
        /// <param name="CalcModeIndex"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcId1"></param>
        /// <param name="FieldPortBcId2"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinBeta,
            ref double MaxBeta,
            ref double GraphBetaInterval,
            ref double minEffN,
            ref double maxEffN,
            ref double minWaveNum,
            ref double maxWaveNum,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref bool IsPCWaveguide,
            ref double latticeA,
            ref double periodicDistance,
            ref IList<IList<uint>> PCWaveguidePorts,
            ref bool isSolveEigenItr,
            ref int CalcModeIndex,
            ref bool IsSVEA,
            ref bool IsModeTrace,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref uint FieldPortBcId1,
            ref uint FieldPortBcId2,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // PC導波路?
            IsPCWaveguide = true;
            // フォトニック結晶導波路(三角形格子)(TEモード)
            // 反復計算しないときfalseにする
            isSolveEigenItr = false;
            // 緩慢変化包絡線近似?
            //IsSVEA = true; // Φ = φ(x, y) exp(-jβx)と置く for latticeTheta = 45 r = 0.18a dielectric rod
            IsSVEA = false; // Φ(x, y)を直接解く for latticeTheta = 60 r = 0.30a air hole

            // 基本モードを計算する
            //CalcModeIndex = 0;
            // 高次モードを指定する
            //CalcModeIndex = 1;
            //CalcModeIndex = 0; // for latticeTheta = 60 r = 0.30a air hole  odd (upper beta side)
            //CalcModeIndex = 2; // for latticeTheta = 60 r = 0.30a air hole  odd (lower beta side)

            // 考慮する波数ベクトルの最小値
            minWaveNum = 0.0; // for latticeTheta = 45 r = 0.18a
            //minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a
            //minWaveNum = 1.0; // for latticeTheta = 30 r = 0.35a
            // 考慮する波数ベクトルの最大値
            maxWaveNum = 0.5; // for latticeTheta = 45 r = 0.18a
            //maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a
            //maxWaveNum = 1.5; // for latticeTheta = 30 r = 0.35a

            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false; // for latticeTheta = 30 r = 0.35a air hole
            //bool isShift180 = true; // for latticeTheta = 45 r = 0.18a dielectric rod
            // X方向周期の数
            //const int periodCnt = 1;
            const int periodCnt = 1;
            // ロッドの数(半分)
            //const int rodCntHalf = 5; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodCntHalf = 5; // for latticeTheta = 60 r = 0.30a air hole
            //const int rodCntHalf = 6; // for latticeTheta = 30 r = 0.35a air hole
            //const int rodCntHalf = 6; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            const int rodCntHalf = 5;
            // 欠陥ロッド数
            //const int defectRodCnt = 3; // for latticeTheta = 45 r = 0.18a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            //double latticeTheta = 45.0; // for latticeTheta = 45 r = 0.18a dielectric rod
            double latticeTheta = 60.0; // for latticeTheta = 60 r = 0.30a air hole
            //double latticeTheta = 30.0; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            // ロッドの半径
            //double rodRadiusRatio = 0.18;  // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodRadiusRatio = 0.30; // for latticeTheta = 60 r = 0.30a air hole
            //double rodRadiusRatio = 0.35; // for latticeTheta = 60 r = 0.35a air hole
            double rodRadiusRatio = 0.36; // for latticeTheta = 60 r = 0.36a air hole
            //double rodRadiusRatio = 0.30; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            // ロッドの比誘電率
            //double rodEps = 3.4 * 3.4; // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodEps = 4.3 * 4.3; // for latticeTheta = 45 r = 0.18a dielectric rod
            //double rodEps = 2.76 * 2.76; // for latticeTheta = 60 r = 0.30a air hole
            //double rodEps = 2.8 * 2.8; // for latticeTheta = 60 r = 0.35a air hole
            double rodEps = 3.32 * 3.32; // for latticeTheta = 60 r = 0.36a air hole
            //double rodEps = 3.4 * 3.4; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 7; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int ndivForOneLattice = 5; // for latticeTheta = 45 r = 0.18a dielectric rod rotEps = 4.3
            //const int ndivForOneLattice = 10; // for latticeTheta = 60 r = 0.30a air hole
            //const int ndivForOneLattice = 9; // for latticeTheta = 60 r = 0.35a air hole
            //const int ndivForOneLattice = 6; // for latticeTheta = 30 r = 0.35a air hole
            //const int ndivForOneLattice = 6; // for latticeTheta = 30 r = 0.30a air hole n = 3.4
            const int ndivForOneLattice = 9;
            // ロッド円周の分割数
            //const int rodCircleDiv = 8; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.30a
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 2; // for latticeTheta = 45 r = 0.18a dielectric rod
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.30a air hole
            const int rodRadiusDiv = 4;

            // ロッドが1格子を超える?
            //bool isLargeRod = (rodRadiusRatio >= 0.25);
            bool isLargeRod = (rodRadiusRatio >= 0.5 * Math.Sin(latticeTheta * pi / 180.0));
            // 格子の数
            int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            if (isLargeRod)
            {
                rodDistanceY = WaveguideWidth / (double)(latticeCnt - 1);
            }
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            // フォトニック結晶導波路の場合、a/λを規格化周波数とする
            if (Math.Abs(latticeTheta - 45.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 3.6
                //  even 1st
                //NormalizedFreq1 = 0.320;
                //NormalizedFreq2 = 0.380;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                //  odd
                //NormalizedFreq1 = 0.384;
                //NormalizedFreq2 = 0.432;
                //FreqDelta = 0.002;//0.001;
                //GraphFreqInterval = 0.01;
                //  even 2nd
                //NormalizedFreq1 = 0.420;
                //NormalizedFreq2 = 0.500;
                //FreqDelta = 0.002;
                //GraphFreqInterval = 0.01;
                // defectRodCnt = 1の場合
                //NormalizedFreq1 = 0.397;
                //NormalizedFreq2 = 0.4031;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.001;
                // for latticeTheta = 45 r = 0.18a dielectric rod  n = 4.3
                NormalizedFreq1 = 0.260;
                NormalizedFreq2 = 0.3301;
                FreqDelta = 0.002;
                GraphFreqInterval = 0.01;
            }
            else if (Math.Abs(latticeTheta - 60.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit
                    || Math.Abs(latticeTheta - 30.0) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // for latticeTheta = 60 r = 0.30a air hole
                //  even
                //NormalizedFreq1 = 0.267; //0.270;
                //NormalizedFreq2 = 0.2871; //0.330;//0.3401;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004; //0.01;
                //  odd upper side
                //NormalizedFreq1 = 0.290;
                //NormalizedFreq2 = 0.306;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004;
                //  odd lower side
                //NormalizedFreq1 = 0.290;
                //NormalizedFreq2 = 0.306;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004;
                // for latticeTheta = 60 r = 0.35a air hole
                // even
                //NormalizedFreq1 = 0.294;//0.295;// 0.280;
                //NormalizedFreq2 = 0.315;//0.320;// 0.3301;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004;
                // odd upper-side, lower-side
                //NormalizedFreq1 = 0.307;//0.300;
                //NormalizedFreq2 = 0.315;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.002;
                // for latticeTheta = 60 r = 0.36a air hole
                //  even wide-band
                NormalizedFreq1 = 0.236;
                NormalizedFreq2 = 0.3081;
                FreqDelta = 0.0005;//0.001;
                GraphFreqInterval = 0.010;
                // odd upper
                //NormalizedFreq1 = 0.266;
                //NormalizedFreq2 = 0.2771;
                //FreqDelta = 0.0005;//0.001;
                //GraphFreqInterval = 0.002;
                // odd lower
                //NormalizedFreq1 = 0.2720;
                //NormalizedFreq2 = 0.2771;
                //FreqDelta = 0.0005;//0.001;
                //GraphFreqInterval = 0.001;
                // for latticeTheta = 30 r = 0.30a air hole n = 3.4
                // even
                //NormalizedFreq1 = 0.230;
                //NormalizedFreq2 = 0.256;//0.260;
                //FreqDelta = 0.001;
                //GraphFreqInterval = 0.004;
            }
            else
            {
                System.Diagnostics.Debug.Assert(false);
            }

            MinBeta = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            MaxBeta = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA)) + 1.0e-6;
            MaxBeta = Math.Ceiling(MaxBeta * 10.0) / 10.0;
            GraphBetaInterval = 0.2;
            if (isAirHole)
            {
                minEffN = 0.0;//1.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0; // Math.Sqrt(rodEps);
            }

            // 波のモード
            //WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // Cad
            uint baseLoopId = 0;
            IList<uint> rodLoopIds = new List<uint>();
            int ndivPlus = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // ToDo: 周期境界1, 2上の分割が同じになるように設定する必要がある
                //
                // 領域を追加
                {
                    List<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(0.0, WaveguideWidth));
                    pts.Add(new CVector2D(0.0, 0.0));
                    pts.Add(new CVector2D(rodDistanceX * periodCnt, 0.0));
                    pts.Add(new CVector2D(rodDistanceX * periodCnt, WaveguideWidth));
                    // 多角形追加
                    uint lId = cad2d.AddPolygon(pts).id_l_add;
                    baseLoopId = lId;
                }
                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys = new List<double>();
                IList<double> ys_rod = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                int outofAreaRodPtCnt_row_top = 0;
                int outofAreaRodPtCnt_row_bottom = 0;
                // 境界上にロッドのある格子
                // 境界上のロッドの頂点
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY;
                    if (isLargeRod)
                    {
                        y0 += 0.5 * rodDistanceY;
                    }
                    if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                    {
                        ys_rod.Add(y0);
                    }
                    else
                    {
                        if (isLargeRod && i == 0)
                        {
                            outofAreaRodPtCnt_row_top++;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y1);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y2);
                        }
                        else
                        {
                            if (isLargeRod && i == 0)
                            {
                                outofAreaRodPtCnt_row_top++;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY;
                    if (isLargeRod)
                    {
                        y0 -= 0.5 * rodDistanceY;
                    }
                    if (y0 > (0.0 + Constants.PrecisionLowerLimit) && y0 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                    {
                        ys_rod.Add(y0);
                    }
                    else
                    {
                        if (isLargeRod && i == (rodCntHalf - 1))
                        {
                            outofAreaRodPtCnt_row_bottom++;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                    for (int k = 1; k <= rodRadiusDiv; k++)
                    {
                        double y1 = y0 - k * rodRadius / rodRadiusDiv;
                        double y2 = y0 + k * rodRadius / rodRadiusDiv;
                        if (y1 > (0.0 + Constants.PrecisionLowerLimit) && y1 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y1);
                        }
                        else
                        {
                            if (isLargeRod && i == (rodCntHalf - 1))
                            {
                                outofAreaRodPtCnt_row_bottom++;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        if (y2 > (0.0 + Constants.PrecisionLowerLimit) && y2 < (WaveguideWidth - Constants.PrecisionLowerLimit))
                        {
                            ys_rod.Add(y2);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                    }
                }
                foreach (double y_rod in ys_rod)
                {
                    ys.Add(y_rod);
                }
                // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                double radiusMargin = rodDistanceY * 0.01;
                // 境界上にロッドのある格子
                // ロッドの外
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = WaveguideWidth - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_rod += rodDistanceY * 0.5;
                            y_max_rod += rodDistanceY * 0.5;
                        }
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 1 : 0)) continue;
                    for (int k = 1; k <= (ndivForOneLattice - 1); k++)
                    {
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_rod = rodDistanceY * rodCntHalf - i * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt -= rodDistanceY * 0.5;
                            if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                            y_min_rod -= rodDistanceY * 0.5;
                            y_max_rod -= rodDistanceY * 0.5;
                        }
                        if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                        {
                            ys.Add(y_divpt);
                        }
                    }
                }

                // 境界上にロッドのない格子
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == 0 && k == 0) continue;
                        double y_divpt = WaveguideWidth - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_upper_rod = WaveguideWidth - i * rodDistanceY + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = WaveguideWidth - (i + 1) * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt += rodDistanceY * 0.5;
                            if (y_divpt >= (WaveguideWidth - Constants.PrecisionLowerLimit)) continue;
                            y_min_upper_rod += rodDistanceY * 0.5;
                            y_max_lower_rod += rodDistanceY * 0.5;
                        }
                        bool isAddHalfRod_row_top = (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))));
                        if ((i != 0 || (i == 0 && isAddHalfRod_row_top))
                                && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }
                        if ((isShift180 || (!isShift180 && i != (rodCntHalf - 1)))
                            && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }

                        ys.Add(y_divpt);
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 0 : 1)) continue;
                    for (int k = 0; k <= ndivForOneLattice; k++)
                    {
                        if (i == (rodCntHalf - 1) && k == ndivForOneLattice) continue;
                        double y_divpt = rodDistanceY * rodCntHalf - i * rodDistanceY - k * (rodDistanceY / ndivForOneLattice);
                        double y_min_upper_rod = rodDistanceY * rodCntHalf - i * rodDistanceY + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                        double y_max_lower_rod = rodDistanceY * rodCntHalf - (i + 1) * rodDistanceY - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                        if (isLargeRod)
                        {
                            y_divpt -= rodDistanceY * 0.5;
                            if (y_divpt <= (0.0 + Constants.PrecisionLowerLimit)) continue;
                            y_min_upper_rod -= rodDistanceY * 0.5;
                            y_max_lower_rod -= rodDistanceY * 0.5;
                        }
                        bool isAddHalfRod_row_bottom = (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))));
                        if ((isShift180 || (!isShift180 && i != 0))
                            && y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }
                        if ((i != (rodCntHalf - 1) || (i == (rodCntHalf - 1) && isAddHalfRod_row_bottom))
                            && y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit))
                        {
                            continue;
                        }

                        ys.Add(y_divpt);
                    }
                }
                // 欠陥部
                for (int i = 0; i <= (defectRodCnt * ndivForOneLattice); i++)
                {
                    if (!isShift180 && (i == 0 || i == (defectRodCnt * ndivForOneLattice))) continue;
                    double y_divpt = rodDistanceY * (rodCntHalf + defectRodCnt) - i * (rodDistanceY / ndivForOneLattice);
                    double y_min_upper_rod = rodDistanceY * (rodCntHalf + defectRodCnt) + 0.5 * rodDistanceY - rodRadius - radiusMargin;
                    double y_max_lower_rod = rodDistanceY * rodCntHalf - 0.5 * rodDistanceY + rodRadius + radiusMargin;
                    if (isLargeRod)
                    {
                        y_divpt -= rodDistanceY * 0.5;
                        y_min_upper_rod -= rodDistanceY * 0.5;
                        y_max_lower_rod -= rodDistanceY * 0.5;
                    }
                    if (isLargeRod && isShift180)
                    {
                        // for isLargeRod == true
                        if (y_divpt >= (y_min_upper_rod - Constants.PrecisionLowerLimit)
                                || y_divpt <= (y_max_lower_rod + Constants.PrecisionLowerLimit)
                            )
                        {
                            continue;
                        }
                    }
                    ys.Add(y_divpt);
                }

                // 昇順でソート
                double[] yAry = ys.ToArray();
                Array.Sort(yAry);
                ndivPlus = yAry.Length + 1;

                // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                bool isInRod = false;
                if (isLargeRod
                    && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                {
                    isInRod = true;
                }
                for (int i = 0; i < yAry.Length; i++)
                {
                    uint id_e = 1;
                    CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(0.0, yAry[i]));
                    uint id_v_add = resAddVertex.id_v_add;
                    uint id_e_add = resAddVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    if (isInRod)
                    {
                        id_e_rod_B1.Add(id_e_add);
                    }
                    bool contains = false;
                    foreach (double y_rod in ys_rod)
                    {
                        if (Math.Abs(y_rod - yAry[i]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {
                            contains = true;
                            break;
                        }
                    }
                    if (contains)
                    {
                        id_v_list_rod_B1.Add(id_v_add);

                        if (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            if ((id_v_list_rod_B1.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if ((id_v_list_rod_B1.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                        else
                        {
                            if (id_v_list_rod_B1.Count % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if (id_v_list_rod_B1.Count % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                    }
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                    {
                        if (i == (yAry.Length - 1))
                        {
                            System.Diagnostics.Debug.Assert(isInRod == true);
                            id_e_rod_B1.Add(id_e);
                        }
                    }
                }

                isInRod = false;
                if (isLargeRod
                    && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                {
                    isInRod = true;
                }
                for (int i = yAry.Length - 1; i >= 0; i--)
                {
                    uint id_e = 3;
                    CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(rodDistanceX * periodCnt, yAry[i]));
                    uint id_v_add = resAddVertex.id_v_add;
                    uint id_e_add = resAddVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    if (isInRod)
                    {
                        id_e_rod_B2.Add(id_e_add);
                    }
                    bool contains = false;
                    foreach (double y_rod in ys_rod)
                    {
                        if (Math.Abs(y_rod - yAry[i]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                        {
                            contains = true;
                            break;
                        }
                    }
                    if (contains)
                    {
                        id_v_list_rod_B2.Add(id_v_add);
                        if (isLargeRod
                            && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            if ((id_v_list_rod_B2.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if ((id_v_list_rod_B2.Count + outofAreaRodPtCnt_row_top) % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                        else
                        {
                            if (id_v_list_rod_B2.Count % (rodRadiusDiv * 2 + 1) == 1)
                            {
                                isInRod = true;
                            }
                            else if (id_v_list_rod_B2.Count % (rodRadiusDiv * 2 + 1) == 0)
                            {
                                isInRod = false;
                            }
                        }
                    }
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                    {
                        if (i == 0)
                        {
                            System.Diagnostics.Debug.Assert(isInRod == true);
                            id_e_rod_B2.Add(id_e);
                        }
                    }
                }

                int bRodCntHalf = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                if (!isLargeRod
                    || (isLargeRod &&
                           (isShift180 && (rodCntHalf % 2 == 0)) || (!isShift180 && (rodCntHalf % 2 == 1))
                       )
                    )
                {
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1));
                }
                else
                {
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_top == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(outofAreaRodPtCnt_row_bottom == (rodRadiusDiv + 1));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                    System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == (bRodCntHalf * 2 * (rodRadiusDiv * 2 + 1) - outofAreaRodPtCnt_row_top - outofAreaRodPtCnt_row_bottom));
                }

                /////////////////////////////////////////////////////////////////////////////
                // ロッドを追加
                uint id_e_F1_new_port1 = 0;
                uint id_e_F2_new_port1 = 0;
                uint id_v_B1_top_rod_center = 1;
                uint id_v_B1_bottom_rod_center = 2;
                uint id_v_B2_top_rod_center = 4;
                uint id_v_B2_bottom_rod_center = 3;

                // 左右のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1_rodQuarter = new List<uint>();
                IList<uint> id_v_list_F2_rodQuarter = new List<uint>();

                for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 上の強制境界と交差する点
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 入力境界 外側
                            // 入力導波路領域
                            id_e_list[0] = 4;
                            id_e_list[1] = 4;
                        }
                        else if (colIndex == 1)
                        {
                            // 入力境界内側
                            // 不連続領域
                            id_e_list[0] = 4;
                            id_e_list[1] = 4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = 0.0;
                        if (colIndex == 0 || colIndex == 1)
                        {
                            // 入力側
                            x0 = (rodDistanceX) * colIndex;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double y0 = WaveguideWidth;
                        double y_cross = WaveguideWidth;
                        double[] x_cross_list = new double[2];
                        x_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        x_cross_list[1] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double x_cross = x_cross_list[k];
                            if (colIndex == 0 || colIndex == 1)
                            {
                                if (x_cross <= (0.0 + Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                                if (x_cross >= (rodDistanceX * periodCnt - Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1_rodQuarter.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // 上側境界の中央部分の辺IDが新しくなる
                            if (colIndex == 0 && k == 1)
                            {
                                // 不変
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                id_e_F1_new_port1 = id_e_add;
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                for (int colIndex = 1; colIndex >= 0; colIndex--) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 下の強制境界と交差するロッド
                    if (isLargeRod
                        && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0)))
                           )
                    {
                        uint[] id_e_list = new uint[2];
                        if (colIndex == 0)
                        {
                            // 入力境界 外側
                            // 入力導波路領域
                            id_e_list[0] = 2;
                            id_e_list[1] = 2;
                        }
                        else if (colIndex == 1)
                        {
                            // 入力境界内側
                            // 不連続領域
                            id_e_list[0] = 2;
                            id_e_list[1] = 2;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double x0 = 0.0;
                        if (colIndex == 0 || colIndex == 1)
                        {
                            // 入力側
                            x0 = (rodDistanceX) * colIndex;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }
                        double y0 = 0.0;
                        double y_cross = 0.0;
                        double[] x_cross_list = new double[2];
                        x_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        x_cross_list[1] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0;
                        for (int k = 0; k < 2; k++)
                        {
                            uint id_e = id_e_list[k];
                            double x_cross = x_cross_list[k];
                            if (colIndex == 0 || colIndex == 1)
                            {
                                if (x_cross <= (0.0 + Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                                if (x_cross >= (rodDistanceX * periodCnt - Constants.PrecisionLowerLimit))
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2_rodQuarter.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // 下側境界の中央部分の辺IDが新しくなる
                            //   Note: colInde == 1から追加される
                            if (colIndex == 0 && k == 0)
                            {
                                id_e_F2_new_port1 = id_e_add;
                            }
                            else if (colIndex == 1 && k == 0)
                            {
                                // 不変
                            }
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // ロッドを追加
                // 左のロッド
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);
                        int ofs_index_left = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_left = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;
                        // 左のロッド
                        {
                            uint id_v0 = 0;
                            uint id_v1 = 0;
                            uint id_v2 = 0;
                            int index_v0 = (id_v_list_rod_B1.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            int index_v1 = (id_v_list_rod_B1.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            int index_v2 = (id_v_list_rod_B1.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)) - ofs_index_left;
                            if (index_v2 > id_v_list_rod_B1.Count - 1)
                            {
                                isQuarterRod = true;
                                id_v0 = id_v_list_rod_B1[index_v0];
                                //id_v1 = id_v_list_rod_B1[index_v1];
                                id_v1 = id_v_B1_top_rod_center;
                                //id_v2 = id_v_list_rod_B1[work_id_v_list_rod_B.Count - 1];
                                id_v2 = id_v_list_F1_rodQuarter[0]; // 1つ飛ばしで参照;
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B1[index_v0];
                                id_v1 = id_v_list_rod_B1[index_v1];
                                id_v2 = id_v_list_rod_B1[index_v2];
                            }

                            double x0 = 0.0;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5;
                            }
                            uint lId = 0;
                            if (isQuarterRod)
                            {
                                // 1/4円を追加する
                                lId = WgCadUtil.AddExactlyQuarterRod(
                                    cad2d,
                                    baseLoopId,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    id_v2,
                                    id_v1,
                                    id_v0,
                                    0.0,
                                    true);
                            }
                            else
                            {
                                // 左のロッド
                                lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                            }
                            rodLoopIds.Add(lId);
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = i / 2;
                        int ofs_index_left = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_left = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;
                        // 左のロッド
                        uint id_v0 = 0;
                        uint id_v1 = 0;
                        uint id_v2 = 0;
                        {
                            int index_v0 = (id_v_list_rod_B1.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1));
                            int index_v1 = (id_v_list_rod_B1.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1));
                            int index_v2 = (id_v_list_rod_B1.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1));
                            if (index_v0 < 0)
                            {
                                isQuarterRod = true;
                                //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                id_v0 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 1]; // 1つ飛ばしで参照
                                //id_v1 = id_v_list_rod_B1[index_v1];
                                id_v1 = id_v_B1_bottom_rod_center;
                                id_v2 = id_v_list_rod_B1[index_v2];
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B1[index_v0];
                                id_v1 = id_v_list_rod_B1[index_v1];
                                id_v2 = id_v_list_rod_B1[index_v2];
                            }
                        }

                        double x0 = 0.0;
                        double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                        if (isLargeRod)
                        {
                            y0 -= rodDistanceY * 0.5;
                        }
                        uint lId = 0;
                        if (isQuarterRod)
                        {
                            // 1/4円を追加する
                            lId = WgCadUtil.AddExactlyQuarterRod(
                                cad2d,
                                baseLoopId,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv,
                                id_v2,
                                id_v1,
                                id_v0,
                                90.0,
                                true);
                        }
                        else
                        {
                            // 左のロッド
                            lId = WgCadUtil.AddLeftRod(
                                cad2d,
                                baseLoopId,
                                id_v0,
                                id_v1,
                                id_v2,
                                x0,
                                y0,
                                rodRadius,
                                rodCircleDiv,
                                rodRadiusDiv);
                        }
                        rodLoopIds.Add(lId);
                    }
                }
                // 右のロッド
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = bRodCntHalf - 1 - (int)((rodCntHalf - 1 - i) / 2);
                        int ofs_index_top = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_top = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;

                        // 右のロッド
                        {
                            uint id_v0 = 0;
                            uint id_v1 = 0;
                            uint id_v2 = 0;
                            int index_v0 = (0 + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            int index_v1 = ((rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            int index_v2 = ((rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)) + ofs_index_top;
                            if (index_v0 < 0)
                            {
                                isQuarterRod = true;
                                //id_v0 = work_id_v_list_rod_B[0]; // DEBUG
                                id_v0 = id_v_list_F1_rodQuarter[1];
                                //id_v1 = id_v_list_rod_B2[index_v1];
                                id_v1 = id_v_B2_top_rod_center;
                                id_v2 = id_v_list_rod_B2[index_v2];
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B2[index_v0];
                                id_v1 = id_v_list_rod_B2[index_v1];
                                id_v2 = id_v_list_rod_B2[index_v2];
                            }

                            double x0 = rodDistanceX * periodCnt;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5;
                            }
                            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                            uint lId = 0;
                            if (isQuarterRod)
                            {
                                // 1/4円を追加する
                                lId = WgCadUtil.AddExactlyQuarterRod(
                                    cad2d,
                                    baseLoopId,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    id_v2,
                                    id_v1,
                                    id_v0,
                                    270.0,
                                    true);
                            }
                            else
                            {
                                // 右のロッド
                                lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                            }
                            rodLoopIds.Add(lId);
                        }
                    }
                }
                for (int i = 0; i < rodCntHalf; i++)
                {
                    if (i % 2 == (isShift180 ? 0 : 1))
                    {
                        int i2 = i / 2;
                        int ofs_index_top = 0;
                        if (isLargeRod && ((isShift180 && (rodCntHalf % 2 == 1)) || (!isShift180 && (rodCntHalf % 2 == 0))))
                        {
                            ofs_index_top = -outofAreaRodPtCnt_row_top;
                        }
                        bool isQuarterRod = false;
                        // 右のロッド
                        {
                            uint id_v0 = 0;
                            uint id_v1 = 0;
                            uint id_v2 = 0;
                            int index_v0 = (id_v_list_rod_B2.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1));
                            int index_v1 = (id_v_list_rod_B2.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1));
                            int index_v2 = (id_v_list_rod_B2.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1));
                            if (index_v2 > id_v_list_rod_B2.Count - 1)
                            {
                                isQuarterRod = true;
                                id_v0 = id_v_list_rod_B2[index_v0];
                                //id_v1 = id_v_list_rod_B2[index_v1];
                                id_v1 = id_v_B2_bottom_rod_center;
                                //id_v2 = id_v_list_rod_B2[id_v_list_rod_B2.Count - 1]; // DEBUG
                                id_v2 = id_v_list_F2_rodQuarter[id_v_list_F2_rodQuarter.Count - 2]; // 1つ飛ばしで参照
                            }
                            else
                            {
                                id_v0 = id_v_list_rod_B2[index_v0];
                                id_v1 = id_v_list_rod_B2[index_v1];
                                id_v2 = id_v_list_rod_B2[index_v2];
                            }

                            double x0 = rodDistanceX * periodCnt;
                            double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 -= rodDistanceY * 0.5;
                            }
                            uint lId = 0;
                            if (isQuarterRod)
                            {
                                // 1/4円を追加する
                                lId = WgCadUtil.AddExactlyQuarterRod(
                                    cad2d,
                                    baseLoopId,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv,
                                    id_v2,
                                    id_v1,
                                    id_v0,
                                    180.0,
                                    true);
                            }
                            else
                            {
                                // 右のロッド
                                lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                            }
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                // 中央のロッド(上下の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();
                for (int col = 1; col <= (periodCnt * 2 - 1); col++)
                {
                    // 上の強制境界と交差するロッド
                    if (isLargeRod
                            && ((col % 2 == 1 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 1 : 0)))
                               || (col % 2 == 0 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 0 : 1)))
                                )
                        )
                    {
                        uint id_e = 4;
                        //if (!isShift180)
                        if (id_e_F1_new_port1 != 0)
                        {
                            id_e = id_e_F1_new_port1;
                        }
                        double x0 = rodDistanceX * 0.5 * col;
                        double y0 = WaveguideWidth;
                        double y_cross = WaveguideWidth;
                        double[] x_cross_list = new double[3];
                        x_cross_list[0] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        x_cross_list[1] = x0; // 中心
                        x_cross_list[2] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        foreach (double x_cross in x_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F1.Add(id_v_add);
                            id_e_F1.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }
                for (int col = (periodCnt * 2 - 1); col >= 1; col--)
                {
                    // 下の強制境界と交差するロッド
                    if (isLargeRod
                           && ((col % 2 == 1 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 1 : 0)))
                              || (col % 2 == 0 && ((rodCntHalf - 1 - 0) % 2 == (isShift180 ? 0 : 1)))
                              )
                        )
                    {
                        uint id_e = 2;
                        //if (!isShift180)
                        if (id_e_F2_new_port1 != 0)
                        {
                            id_e = id_e_F2_new_port1;
                        }
                        double x0 = rodDistanceX * 0.5 * col;
                        double y0 = 0.0;
                        double y_cross = 0.0;
                        double[] x_cross_list = new double[3];
                        x_cross_list[0] = Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        x_cross_list[1] = x0; // 中心
                        x_cross_list[2] = -1.0 * Math.Sqrt(rodRadius * rodRadius - (y_cross - y0) * (y_cross - y0)) + x0; // 交点
                        foreach (double x_cross in x_cross_list)
                        {
                            CCadObj2D.CResAddVertex resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_cross, y_cross));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            id_v_list_F2.Add(id_v_add);
                            id_e_F2.Add(id_e_add);
                            // DEBUG
                            //cad2d.SetColor_Edge(id_e_add, new double[] { 1.0, 0.0, 0.0 });
                        }
                    }
                }

                // 中央のロッド
                for (int col = 1; col <= periodCnt * 2 - 1; col++)
                {
                    // 中央のロッド
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (isLargeRod &&
                              ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                                    || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                            )
                        {
                            if (i == 0)
                            {
                                {
                                    // 半円(下半分)を追加
                                    double x0 = rodDistanceX * 0.5 * col;
                                    double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                    if (isLargeRod)
                                    {
                                        y0 += rodDistanceY * 0.5; // for isLargeRod
                                    }
                                    int col2 = col / 2;
                                    if (isShift180 && (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 2;
                                    }
                                    else if (!isShift180 && (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 2;
                                    }
                                    uint id_v0 = id_v_list_F1[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F1[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F1[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        0.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 += rodDistanceY * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (isLargeRod
                                && ((col % 2 == 1 && (i % 2 == (isShift180 ? 1 : 0)))
                                    || (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                            )
                        {
                            if (i == (rodCntHalf - 1))
                            {
                                {
                                    // 半円(上半分)を追加
                                    double x0 = rodDistanceX * 0.5 * col;
                                    double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                    if (isLargeRod)
                                    {
                                        y0 -= rodDistanceY * 0.5; // for isLargeRod
                                    }
                                    int col2 = (periodCnt * 2 - 1 - col) / 2;
                                    if (isShift180 && (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 1;
                                    }
                                    else if (!isShift180 && (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                                    {
                                        col2 = col2 - 1;
                                    }
                                    uint id_v0 = id_v_list_F2[col2 * 3 + 0];
                                    uint id_v1 = id_v_list_F2[col2 * 3 + 1];
                                    uint id_v2 = id_v_list_F2[col2 * 3 + 2];
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        180.0,
                                        true);
                                    rodLoopIds.Add(lId);
                                }

                                continue;
                            }
                        }
                        if ((col % 2 == 1 && (i % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (i % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                            if (isLargeRod)
                            {
                                y0 -= rodDistanceY * 0.5; // for isLargeRod
                            }
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rodRadius, rodCircleDiv, rodRadiusDiv);
                            rodLoopIds.Add(lId);
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // 領域 + ロッド
                uint[] loopId_cad_list = new uint[1 + rodLoopIds.Count];
                int[] mediaIndex_list = new int[loopId_cad_list.Length];

                // 領域
                loopId_cad_list[0] = baseLoopId;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);

                // ロッド
                int offset = 1;
                rodLoopIds.ToArray().CopyTo(loopId_cad_list, offset);
                for (int i = offset; i < mediaIndex_list.Length; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 境界条件を設定する
            // 固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[2 + id_e_F1.Count + id_e_F2.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 4;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[2 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[2 + id_e_F1.Count + i] = id_e_F2[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件1
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId1 = 0;
            {
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 1;
                if (id_e_rod_B1.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndivPlus - 1) - (i - 1));
                    if (id_e_rod_B1.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId1,
                    ref EdgeDic);
            }

            // 開口条件2
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            FieldPortBcId2 = 0;
            {
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                eId_cad_list[0] = 3;
                if (id_e_rod_B2.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    eId_cad_list[i] = (uint)(4 + (ndivPlus - 1) * 2 - (i - 1));
                    if (id_e_rod_B2.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldPortBcId2,
                    ref EdgeDic);
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            {
                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                WgUtil.GetLoopCoordList(World, FieldLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf))
                        //if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - (0.5 * rodDistanceY - rodRadius)) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + (0.5 * rodDistanceY - rodRadius))) // dielectric rod
                        if (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY) && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)) // air hole
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 27
0
        /// <summary>
        /// ロッド(半分)を追加する
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <returns></returns>
        public static uint AddHalfRod(CCadObj2D cad2d, uint baseLoopId, double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
            double startAngle, double additionalAngle = 0.0, bool isReverseAddVertex = false, uint id_v_st = uint.MaxValue, uint id_v_ed = uint.MaxValue)
        {
            System.Diagnostics.Debug.Assert(additionalAngle < 360.0 / rodCircleDiv);
            List<CVector2D> pts = new List<CVector2D>();
            System.Diagnostics.Debug.Assert((startAngle == 0.0) || (startAngle == 90.0) || (startAngle == 180.0) || (startAngle == 270.0));
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                // メッシュ形状を整えるためにロッドの中心に頂点を追加
                uint id_v_center = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x0, y0)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_center != 0);
            }
            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    if (Math.Abs(additionalAngle) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit && (itheta == 0 || itheta == (rodCircleDiv / 2)))
                    {
                        continue;
                    }
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッドの分割数調整: ロッド1/4円から超えた部分
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = (startAngle + additionalAngle) * pi / 180.0;
                }
                else
                {
                    theta = (startAngle - additionalAngle) * pi / 180.0;
                }
                for (int k = 1; k < rodRadiusDiv; k++)
                {
                    double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            // ロッドの分割数調整: ロッド1/4円から超えた部分
            if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
            {
                double theta = 0;
                if (isReverseAddVertex)
                {
                    theta = (startAngle - 180.0 - additionalAngle) * pi / 180.0;
                }
                else
                {
                    theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                }
                for (int k = 1; k < rodRadiusDiv; k++)
                {
                    double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }

            uint retLoopId = 0;
            if (id_v_st != uint.MaxValue && id_v_ed != uint.MaxValue)
            {
                uint prev_id_v = id_v_st;

                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = (startAngle + additionalAngle) * pi / 180.0;
                    }
                    else
                    {
                        theta = (startAngle - additionalAngle) * pi / 180.0;
                    }
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add;
                }

                // ロッド半円
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = startAngle * pi / 180.0 - itheta * 2.0 * pi / rodCircleDiv;
                    }
                    else
                    {
                        theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    }
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add;
                }
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = 0;
                    if (isReverseAddVertex)
                    {
                        theta = (startAngle - 180.0 - additionalAngle) * pi / 180.0;
                    }
                    else
                    {
                        theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                    }
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                    uint id_e_add = resConnectVertex.id_e_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    prev_id_v = id_v_add; //!!!!!!!!!!!!!!!
                }
                uint last_id_v = id_v_ed;
                {
                    CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                    uint id_e_add = resConnectVertex.id_e_add;
                    uint lId = resConnectVertex.id_l_add;
                    System.Diagnostics.Debug.Assert(id_e_add != 0);
                    System.Diagnostics.Debug.Assert(lId != 0);
                    retLoopId = lId;
                }
            }
            else
            {
                System.Diagnostics.Debug.Assert(isReverseAddVertex == false); // 逆順未対応
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = (startAngle - additionalAngle) * pi / 180.0;
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                // ロッド半円
                for (int itheta = 0; itheta <= (rodCircleDiv / 2); itheta++)
                {
                    double theta = startAngle * pi / 180.0 + itheta * 2.0 * pi / rodCircleDiv;
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                // ロッド半円から超えた部分
                if (Math.Abs(additionalAngle) >= MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                {
                    double theta = (startAngle + 180.0 + additionalAngle) * pi / 180.0;
                    double x = x0 + rodRadius * Math.Cos(theta);
                    double y = y0 + rodRadius * Math.Sin(theta);
                    pts.Add(new CVector2D(x, y));
                }
                uint lId = cad2d.AddPolygon(pts, baseLoopId).id_l_add;
                retLoopId = lId;
            }
            return retLoopId;
        }
Exemplo n.º 28
0
        /// <summary>
        /// フォトニック結晶 三角形格子(斜め領域) 上下に半円ロッド
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="periodicDistanceY"></param>
        /// <param name="isTriLattice"></param>
        /// <param name="calcBetaCnt"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinNormalizedFreq"></param>
        /// <param name="MaxNormalizedFreq"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="latticeA"></param>
        /// <param name="periodicDistanceX"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="FieldPortBcIds"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double periodicDistanceY,
            ref bool isTriLattice,
            ref int calcBetaCnt,
            ref double GraphFreqInterval,
            ref double MinNormalizedFreq,
            ref double MaxNormalizedFreq,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref double latticeA,
            ref double periodicDistanceX,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<uint> FieldPortBcIds,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // フォトニック結晶 三角形格子(斜め領域)
            isTriLattice = true; // 三角形格子

            // 空孔?
            //bool isAirHole = false;
            bool isAirHole = true;
            // 三角形格子の内角
            double latticeTheta = 60.0;
            // 格子定数
            latticeA = periodicDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistanceX = periodicDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // X方向オフセット
            double ofsX = periodicDistanceX * 0.5;
            // ロッドの半径
            double rodRadius = 0.30 * latticeA;
            // ロッドの比誘電率
            double rodEps = 2.76 * 2.76;
            // 格子1辺の分割数
            const int ndivForOneLattice = 12;
            // ロッドの円周分割数
            const int rodCircleDiv = 16;// 12;
            // ロッドの半径の分割数
            const int rodRadiusDiv = 5;// 4;
            // メッシュの長さ
            //double meshL = 1.05 * periodicDistanceY / ndivForOneLattice;
            double meshL = 1.05 * (periodicDistanceY / Math.Sin(latticeTheta * pi / 180.0)) / ndivForOneLattice;

            MinNormalizedFreq = 0.000;
            MaxNormalizedFreq = 1.000;
            GraphFreqInterval = 0.10;

            // 波のモード
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            // Cad
            uint baseLoopId = 0;
            IList<uint> rodLoopIds = new List<uint>();
            int ndivPlus_B1 = 0;
            int ndivPlus_B3 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                // 領域を追加
                {
                    List<CVector2D> pts = new List<CVector2D>();
                    pts.Add(new CVector2D(ofsX, periodicDistanceY));
                    pts.Add(new CVector2D(0.0, 0.0));
                    pts.Add(new CVector2D(periodicDistanceX, 0.0));
                    pts.Add(new CVector2D(ofsX + periodicDistanceX, periodicDistanceY));
                    // 多角形追加
                    uint lId = cad2d.AddPolygon(pts).id_l_add;
                    baseLoopId = lId;
                }
                // 周期構造境界上の頂点を追加
                //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                ndivPlus_B1 = ndivForOneLattice;
                // 境界1:左
                {
                    uint id_e = 1;
                    double x1 = ofsX;
                    double y1 = periodicDistanceY;
                    double x2 = 0.0;
                    double y2 = 0.0;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndivPlus_B1, x1, y1, x2, y2);
                }
                // 境界2:右
                {
                    uint id_e = 3;
                    double x1 = periodicDistanceX;
                    double y1 = 0.0;
                    double x2 = periodicDistanceX + ofsX;
                    double y2 = periodicDistanceY;
                    WgCadUtil.DivideBoundary(cad2d, id_e, ndivPlus_B1, x1, y1, x2, y2);
                }
                IList<double> xs_B3 = new List<double>();
                IList<double> xs_rod_B3 = new List<double>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                for (int axisIndex = 1; axisIndex < 2; axisIndex++) // X方向、Y方向の意味
                {
                    int cur_ndivForOneLattice = 0;
                    double cur_periodicDistanceY = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;

                    if (axisIndex == 1)
                    {
                        // Y方向周期(境界3、境界4)
                        cur_ndivForOneLattice = (int)Math.Ceiling((double)ndivForOneLattice * (periodicDistanceX / periodicDistanceY));
                        cur_periodicDistanceY = periodicDistanceX;
                        ys = xs_B3;
                        ys_rod = xs_rod_B3;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    {
                        double y0 = 0.5 * cur_periodicDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            double y1 = y0 - k * rodRadius / rodRadiusDiv;
                            double y2 = y0 + k * rodRadius / rodRadiusDiv;
                            ys_rod.Add(y1);
                            ys_rod.Add(y2);
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }
                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    double radiusMargin = cur_periodicDistanceY * 0.01;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    {
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_periodicDistanceY - k * (cur_periodicDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = 0.5 * cur_periodicDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = 0.5 * cur_periodicDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < (y_min_rod - Constants.PrecisionLowerLimit) || y_divpt > (y_max_rod + Constants.PrecisionLowerLimit))
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }
                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (axisIndex == 1)
                    {
                        ndivPlus_B3 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    for (int boundaryIndex = 0; boundaryIndex < 2;  boundaryIndex++)
                    {
                        bool isInRod = false;
                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            double x_pt = 0.0;
                            double y_pt = 0.0;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (axisIndex == 1 && boundaryIndex == 0)
                            {
                                // 境界3:下側
                                id_e = 2;
                                x_pt = yAry[yAry.Length - 1 - i];
                                y_pt = 0.0;
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (axisIndex == 1 && boundaryIndex == 1)
                            {
                                // 境界4:上側
                                id_e = 4;
                                x_pt = yAry[i] + ofsX;
                                y_pt = periodicDistanceY;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y_pt));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                    }
                }
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == (rodRadiusDiv * 2 + 1));

                // 下のロッド
                {
                    uint id_v0 = 0;
                    uint id_v1 = 0;
                    uint id_v2 = 0;
                    {
                        int index_v0 = rodRadiusDiv * 2;
                        int index_v1 = rodRadiusDiv;
                        int index_v2 = 0;
                        id_v0 = id_v_list_rod_B3[index_v0];
                        id_v1 = id_v_list_rod_B3[index_v1];
                        id_v2 = id_v_list_rod_B3[index_v2];
                    }
                    double x0 = periodicDistanceX * 0.5;
                    double y0 = 0.0;
                    uint lId = 0;
                    // 下のロッド
                    lId = WgCadUtil.AddBottomRod(
                        cad2d,
                        baseLoopId,
                        id_v0,
                        id_v1,
                        id_v2,
                        x0,
                        y0,
                        rodRadius,
                        rodCircleDiv,
                        rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }
                // 上のロッド
                {
                    uint id_v0 = 0;
                    uint id_v1 = 0;
                    uint id_v2 = 0;
                    {
                        int index_v0 = 0;
                        int index_v1 = rodRadiusDiv;
                        int index_v2 = rodRadiusDiv * 2;
                        id_v0 = id_v_list_rod_B4[index_v0];
                        id_v1 = id_v_list_rod_B4[index_v1];
                        id_v2 = id_v_list_rod_B4[index_v2];
                    }
                    double x0 = periodicDistanceX * 0.5 + ofsX;
                    double y0 = periodicDistanceY;
                    uint lId = 0;
                    // 上のロッド
                    lId = WgCadUtil.AddTopRod(
                        cad2d,
                        baseLoopId,
                        id_v0,
                        id_v1,
                        id_v2,
                        x0,
                        y0,
                        rodRadius,
                        rodCircleDiv,
                        rodRadiusDiv);
                    rodLoopIds.Add(lId);
                }

                // 図面表示
                //isCadShow = true;
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }

                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                 // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // 領域 + ロッド
                uint[] loopId_cad_list = new uint[1 + rodLoopIds.Count];
                int[] mediaIndex_list = new int[loopId_cad_list.Length];

                // 領域
                loopId_cad_list[0] = baseLoopId;
                mediaIndex_list[0] = Medias.IndexOf(mediaCladding);

                // ロッド
                int offset = 1;
                rodLoopIds.ToArray().CopyTo(loopId_cad_list, offset);
                for (int i = offset; i < mediaIndex_list.Length; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                }
                WgUtil.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // 境界条件を設定する
            // 固定境界条件(強制境界)
            FieldForceBcId = 0; // なし

            for (int boundaryIndex = 0; boundaryIndex < 4; boundaryIndex++)
            {
                int cur_ndivPlus = 0;
                if (boundaryIndex == 0)
                {
                    // 開口条件1
                    cur_ndivPlus = ndivPlus_B1;
                }
                else if (boundaryIndex == 1)
                {
                    cur_ndivPlus = ndivPlus_B1;
                }
                else if (boundaryIndex == 2)
                {
                    cur_ndivPlus = ndivPlus_B3;
                }
                else if (boundaryIndex == 3)
                {
                    cur_ndivPlus = ndivPlus_B3;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[cur_ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;
                if (boundaryIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (boundaryIndex == 1)
                {
                    eId_cad_list[0] = 3;
                    work_id_e_rod_B = id_e_rod_B2;
                }
                else if (boundaryIndex == 2)
                {
                    eId_cad_list[0] = 2;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else if (boundaryIndex == 3)
                {
                    eId_cad_list[0] = 4;
                    work_id_e_rod_B = id_e_rod_B4;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= cur_ndivPlus - 1; i++)
                {
                    if (boundaryIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndivPlus_B1 - 1) - (i - 1));
                    }
                    else if (boundaryIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndivPlus_B1 - 1) * 2 - (i - 1));
                    }
                    else if (boundaryIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndivPlus_B1 - 1) * 2 + (ndivPlus_B3 - 1) - (i - 1));
                    }
                    else if (boundaryIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(4 + (ndivPlus_B1 - 1) * 2 + (ndivPlus_B3 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint cur_fieldPortBcId = 0;
                WgUtilForPeriodicEigenBetaSpecified.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out cur_fieldPortBcId,
                    ref EdgeDic);
                FieldPortBcIds.Add(cur_fieldPortBcId);
            }

            return true;
        }
Exemplo n.º 29
0
        /// <summary>
        /// ロッド1/4円を追加する
        /// </summary>
        /// <param name="cad2d"></param>
        /// <param name="baseLoopId"></param>
        /// <param name="x0"></param>
        /// <param name="y0"></param>
        /// <param name="rodRadius"></param>
        /// <param name="rodCircleDiv"></param>
        /// <param name="rodRadiusDiv"></param>
        /// <returns></returns>
        public static uint AddQuarterRod(CCadObj2D cad2d, uint baseLoopId,
            uint id_v0, uint id_v1, uint id_v2,
            double x0, double y0, double rodRadius, int rodCircleDiv, int rodRadiusDiv,
            double startAngle, double endAngle, bool isReverseAddVertex = false)
        {
            CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
            System.Diagnostics.Debug.Assert(Math.Abs(x0 - pt_center.x) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            System.Diagnostics.Debug.Assert(Math.Abs(y0 - pt_center.y) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            List<CVector2D> pts = new List<CVector2D>();

            // ロッドの分割数調整
            for (int k = 1; k < rodRadiusDiv; k++)
            {
                for (int itheta = 0; itheta <= rodCircleDiv; itheta++)
                {
                    double workAngle = 0.0;
                    if (isReverseAddVertex)
                    {
                        workAngle = 360.0 - itheta * 360.0 / rodCircleDiv;
                        if (workAngle <= endAngle || workAngle >= startAngle)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        workAngle = itheta * 360.0 / rodCircleDiv;
                        if (workAngle <= startAngle || workAngle >= endAngle)
                        {
                            continue;
                        }
                    }
                    double theta = workAngle * pi / 180.0;
                    double x = x0 + (k * rodRadius / rodRadiusDiv) * Math.Cos(theta);
                    double y = y0 + (k * rodRadius / rodRadiusDiv) * Math.Sin(theta);
                    uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                    System.Diagnostics.Debug.Assert(id_v_add != 0);
                }
            }
            uint retLoopId = 0;
            uint prev_id_v = id_v0;

            // ロッド1/4円
            for (int itheta = 0; itheta <= rodCircleDiv; itheta++)
            {
                double workAngle = 0.0;
                if (isReverseAddVertex)
                {
                    workAngle = 360.0 - itheta * 360.0 / rodCircleDiv;
                    if (workAngle <= endAngle || workAngle >= startAngle)
                    {
                        continue;
                    }
                }
                else
                {
                    workAngle = itheta * 360.0 / rodCircleDiv;
                    if (workAngle <= startAngle || workAngle >= endAngle)
                    {
                        continue;
                    }
                }

                double theta = workAngle * pi / 180.0;
                double x = x0 + rodRadius * Math.Cos(theta);
                double y = y0 + rodRadius * Math.Sin(theta);
                uint id_v_add = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, baseLoopId, new CVector2D(x, y)).id_v_add;
                System.Diagnostics.Debug.Assert(id_v_add != 0);
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, id_v_add);
                uint id_e_add = resConnectVertex.id_e_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                prev_id_v = id_v_add;
            }
            uint last_id_v = id_v2;
            {
                CBRepSurface.CResConnectVertex resConnectVertex = cad2d.ConnectVertex_Line(prev_id_v, last_id_v);
                uint id_e_add = resConnectVertex.id_e_add;
                uint lId = resConnectVertex.id_l_add;
                System.Diagnostics.Debug.Assert(id_e_add != 0);
                System.Diagnostics.Debug.Assert(lId != 0);
                retLoopId = lId;
            }

            return retLoopId;
        }
Exemplo n.º 30
0
        /// <summary>
        /// PC導波路 60°三角形格子 Wavelength division demultiplexer(2 ladder)
        /// </summary>
        /// <param name="probNo"></param>
        /// <param name="WaveguideWidth"></param>
        /// <param name="NormalizedFreq1"></param>
        /// <param name="NormalizedFreq2"></param>
        /// <param name="FreqDelta"></param>
        /// <param name="GraphFreqInterval"></param>
        /// <param name="MinSParameter"></param>
        /// <param name="MaxSParameter"></param>
        /// <param name="GraphSParameterInterval"></param>
        /// <param name="WaveModeDv"></param>
        /// <param name="World"></param>
        /// <param name="FieldValId"></param>
        /// <param name="FieldLoopId"></param>
        /// <param name="FieldForceBcId"></param>
        /// <param name="WgPortInfoList"></param>
        /// <param name="Medias"></param>
        /// <param name="LoopDic"></param>
        /// <param name="EdgeDic"></param>
        /// <param name="IsInoutWgSame"></param>
        /// <param name="isCadShow"></param>
        /// <param name="CadDrawerAry"></param>
        /// <param name="Camera"></param>
        /// <returns></returns>
        public static bool SetProblem(
            int probNo,
            double WaveguideWidth,
            ref double NormalizedFreq1,
            ref double NormalizedFreq2,
            ref double FreqDelta,
            ref double GraphFreqInterval,
            ref double MinSParameter,
            ref double MaxSParameter,
            ref double GraphSParameterInterval,
            ref WgUtil.WaveModeDV WaveModeDv,
            ref CFieldWorld World,
            ref uint FieldValId,
            ref uint FieldLoopId,
            ref uint FieldForceBcId,
            ref IList<WgUtilForPeriodicEigenExt.WgPortInfo> WgPortInfoList,
            ref IList<MediaInfo> Medias,
            ref Dictionary<uint, wg2d.World.Loop> LoopDic,
            ref Dictionary<uint, wg2d.World.Edge> EdgeDic,
            ref bool IsInoutWgSame,
            ref bool isCadShow,
            ref CDrawerArray CadDrawerAry,
            ref CCamera Camera
            )
        {
            // 固有値を反復で解く?
            //bool isSolveEigenItr = true; //単一モードのとき反復で解く
            bool isSolveEigenItr = false; // 反復で解かない
            // 解く伝搬モードの数
            //int propModeCntToSolve = 1;
            //int propModeCntToSolve = 3;
            int propModeCntToSolve = 2;
            // 緩慢変化包絡線近似?
            //bool isSVEA = true;  // Φ = φexp(-jβx)と置く
            bool isSVEA = false; // Φを直接解く

            // 入射モードインデックス
            // 基本モード入射
            int incidentModeIndex = 0;
            // 高次モード入射
            //int incidentModeIndex = 1;

            // 格子定数
            double latticeA = 0;
            // 周期構造距離
            double periodicDistance = 0;
            // 最小屈折率
            double minEffN = 0.0;
            // 最大屈折率
            double maxEffN = 0.0;

            // 考慮する波数ベクトルの最小値
            //double minWaveNum = 0.0;
            double minWaveNum = 0.5; // for latticeTheta = 60 r = 0.30a air hole
            // 考慮する波数ベクトルの最大値
            //double maxWaveNum = 0.5;
            double maxWaveNum = 1.0; // for latticeTheta = 60 r = 0.30a air hole

            // 入出力導波路が同じ?
            //IsInoutWgSame = true; // 同じ
            //IsInoutWgSame = false; // 同じでない
            // 磁気壁を使用する?
            bool isMagneticWall = false; // 電気壁を使用する
            //bool isMagneticWall = true; // 磁気壁を使用する
            // 空孔?
            //bool isAirHole = false; // dielectric rod
            bool isAirHole = true; // air hole
            // 周期を180°ずらす
            bool isShift180 = false;
            //bool isShift180 = true;
            // ロッドの数(半分)
            //const int rodCntHalf = 3; // for latticeTheta = 60 r = 0.30a air hole
            const int rodCntHalf = 3;
            System.Diagnostics.Debug.Assert(rodCntHalf % 2 == 1); // 奇数を指定(図面の都合上)
            // 欠陥ロッド数
            // for latticeTheta = 60 r = 0.30a dielectric rod
            const int defectRodCnt = 1;
            // 三角形格子の内角
            double latticeTheta = 60.0;
            // ロッドの半径
            double rodRadiusRatio = 0.32; // for latticeTheta = 60 r = 0.32a air hole n = 3.476
            // ロッドの比誘電率
            double rodEps = 3.476 * 3.476; // for latticeTheta = 60 r = 0.32a air hole n = 3.476
            // 1格子当たりの分割点の数
            //const int ndivForOneLattice = 8; // for latticeTheta = 60 r = 0.32a air hole
            const int ndivForOneLattice = 7;// 6;// 8;
            // ロッド円周の分割数
            //const int rodCircleDiv = 12; // for latticeTheta = 60 r = 0.32a air hole
            const int rodCircleDiv = 12;
            // ロッドの半径の分割数
            //const int rodRadiusDiv = 4; // for latticeTheta = 60 r = 0.32a air hole
            const int rodRadiusDiv = 4;
            // 入出力不連続部の距離
            const int rodCntDiscon_port1 = 0;
            const int rodCntDiscon_1st_ladder = 1;
            const int rodCntDiscon_2nd_ladder = 3;// 5;
            const int rodCntDiscon_port3 = 5;

            // 格子の数
            const int latticeCnt = rodCntHalf * 2 + defectRodCnt;
            // ロッド間の距離(Y方向)
            double rodDistanceY = WaveguideWidth / (double)latticeCnt;
            // 格子定数
            latticeA = rodDistanceY / Math.Sin(latticeTheta * pi / 180.0);
            // ロッド間の距離(X方向)
            double rodDistanceX = rodDistanceY * 2.0 / Math.Tan(latticeTheta * pi / 180.0);
            // 周期構造距離
            periodicDistance = rodDistanceX;
            // ロッドの半径
            double rodRadius = rodRadiusRatio * latticeA;
            // 入出力導波路の周期構造部分の長さ
            double inputWgLength = rodDistanceX;
            // メッシュのサイズ
            double meshL = 1.05 * WaveguideWidth / (latticeCnt * ndivForOneLattice);

            // for latticeTheta = 60 r = 0.32a air hole n = 3.476
            NormalizedFreq1 = 0.215;
            NormalizedFreq2 = 0.2401;
            FreqDelta = 0.0005;
            GraphFreqInterval = 0.005;

            //minEffN = 0.0;
            //maxEffN = 0.5 * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN = minWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //maxEffN = maxWaveNum * 1.0 / (NormalizedFreq1 * (periodicDistance / latticeA));
            //minEffN_port2 = minWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            //maxEffN_port2 = maxWaveNum_port2 * 1.0 / (NormalizedFreq1 * (periodicDistance_port2 / latticeA));
            if (isAirHole)
            {
                minEffN = 0.0;// 1.0;//0.0;
                maxEffN = Math.Sqrt(rodEps);
            }
            else
            {
                minEffN = 0.0;
                maxEffN = 1.0;//Math.Sqrt(rodEps);
            }

            MinSParameter = 0.0;
            MaxSParameter = 1.0;
            GraphSParameterInterval = 0.2;

            // 波のモード
            //WaveModeDv = WaveModeDV.TE; // dielectric rod
            if (isAirHole)
            {
                WaveModeDv = WgUtil.WaveModeDV.TM; // air hole
                //isMagneticWall = true;
            }
            else
            {
                WaveModeDv = WgUtil.WaveModeDV.TE; // dielectric rod
                isMagneticWall = false;
                incidentModeIndex = 0;
            }

            // 媒質リスト作成
            double claddingP = 1.0;
            double claddingQ = 1.0;
            double coreP = 1.0;
            double coreQ = 1.0;
            if (isAirHole)
            {
                // 誘電体基盤 + 空孔(air hole)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / rodEps;
                    claddingQ = 1.0;
                    coreP = 1.0 / 1.0;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = rodEps;
                    coreP = 1.0;
                    coreQ = 1.0;
                }
            }
            else
            {
                // 誘電体ロッド(dielectric rod)
                if (WaveModeDv == WgUtil.WaveModeDV.TM)
                {
                    // TMモード
                    claddingP = 1.0 / 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0 / rodEps;
                    coreQ = 1.0;
                }
                else
                {
                    // TEモード
                    claddingP = 1.0;
                    claddingQ = 1.0;
                    coreP = 1.0;
                    coreQ = rodEps;
                }
            }

            MediaInfo mediaCladding = new MediaInfo
            (
                new double[3, 3]
                        {
                           { claddingP,       0.0,       0.0 },
                           {       0.0, claddingP,       0.0 },
                           {       0.0,       0.0, claddingP }
                        },
                new double[3, 3]
                        {
                           { claddingQ,       0.0,       0.0 },
                           {       0.0, claddingQ,       0.0 },
                           {       0.0,       0.0, claddingQ }
                        }
            );
            MediaInfo mediaCore = new MediaInfo
            (
                new double[3, 3]
                        {
                           { coreP,   0.0,   0.0 },
                           {   0.0, coreP,   0.0 },
                           {   0.0,   0.0, coreP }
                        },
                new double[3, 3]
                        {
                           { coreQ,   0.0,   0.0 },
                           {   0.0, coreQ,   0.0 },
                           {   0.0,   0.0, coreQ }
                        }
            );
            Medias.Add(mediaCladding);
            Medias.Add(mediaCore);

            // 図面作成、メッシュ生成
            const uint portCnt = 4;
            System.Diagnostics.Debug.Assert(Math.Abs(WaveguideWidth - WaveguideWidth) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit);
            double disconLength1 = rodDistanceX * rodCntDiscon_port1;
            double disconLength2_1 = rodDistanceX * rodCntDiscon_1st_ladder;
            double disconLength2_2 = rodDistanceX * rodCntDiscon_2nd_ladder;
            double disconLength3 = rodDistanceX * rodCntDiscon_port3;

            // Cad
            IList<uint> rodLoopIds = new List<uint>();
            IList<uint> rodLoopIds_InputWg1 = new List<uint>();
            IList<uint> rodLoopIds_InputWg2 = new List<uint>();
            IList<uint> rodLoopIds_InputWg3 = new List<uint>();
            IList<uint> rodLoopIds_InputWg4 = new List<uint>();
            int ndivPlus_port1 = 0;
            int ndivPlus_port2 = 0;
            int ndivPlus_port3 = 0;
            int ndivPlus_port4 = 0;
            IList<uint> id_e_rod_B1 = new List<uint>();
            IList<uint> id_e_rod_B2 = new List<uint>();
            IList<uint> id_e_rod_B3 = new List<uint>();
            IList<uint> id_e_rod_B4 = new List<uint>();
            IList<uint> id_e_rod_B5 = new List<uint>();
            IList<uint> id_e_rod_B6 = new List<uint>();
            IList<uint> id_e_rod_B7 = new List<uint>();
            IList<uint> id_e_rod_B8 = new List<uint>();
            IList<uint> id_e_F1 = new List<uint>();
            IList<uint> id_e_F2 = new List<uint>();

            //  ポート3ベンド
            double bendX2_0 = inputWgLength + disconLength1 + WaveguideWidth * 2.0 / Math.Sqrt(3.0);
            double bendY2_0 = WaveguideWidth;
            bendX2_0 += latticeA * Math.Sqrt(3.0) / 4.0;
            bendY2_0 -= rodDistanceY / 4.0;
            bendX2_0 += rodDistanceX / 4.0;
            bendY2_0 -= rodDistanceY / 2.0;
            double bendX2 = bendX2_0 + (bendY2_0 - WaveguideWidth) / Math.Sqrt(3.0);
            double bendY2 = WaveguideWidth;
            double bendX1 = bendX2 - WaveguideWidth * 2.0 / Math.Sqrt(3.0);
            double bendY1 = WaveguideWidth;
            // ポート3出力部内部境界の終点
            double port3_X2_B6 = bendX2_0 - disconLength3 / 2.0;
            double port3_Y2_B6 = bendY2_0 + disconLength3 * Math.Sqrt(3.0) / 2.0;
            // ポート3出力部境界の終点
            double port3_X2_B5 = port3_X2_B6 - inputWgLength / 2.0;
            double port3_Y2_B5 = port3_Y2_B6 + inputWgLength * Math.Sqrt(3.0) / 2.0;
            // ポート3出力部境界の始点
            double port3_X1_B5 = port3_X2_B5 - WaveguideWidth * Math.Sqrt(3.0) / 2.0;
            double port3_Y1_B5 = port3_Y2_B5 - WaveguideWidth / 2.0;
            // ポート3出力部内部境界の始点
            double port3_X1_B6 = port3_X2_B6 - WaveguideWidth * Math.Sqrt(3.0) / 2.0;
            double port3_Y1_B6 = port3_Y2_B6 - WaveguideWidth / 2.0;

            //  ポート4ベンド
            double bendX4_0 = inputWgLength + disconLength1 + disconLength2_1 + WaveguideWidth * 2.0 / Math.Sqrt(3.0) * 2.0;
            double bendY4_0 = WaveguideWidth;
            bendX4_0 += latticeA * Math.Sqrt(3.0) / 4.0;
            bendY4_0 -= rodDistanceY / 4.0;
            bendX4_0 += rodDistanceX / 4.0;
            bendY4_0 -= rodDistanceY / 2.0;
            double bendX4 = bendX4_0 + (bendY4_0 - WaveguideWidth) / Math.Sqrt(3.0);
            double bendY4 = WaveguideWidth;
            double bendX3 = bendX4 - WaveguideWidth * 2.0 / Math.Sqrt(3.0);
            double bendY3 = WaveguideWidth;

            // ポート4出力部内部境界の終点
            double port4_X2_B8 = bendX4_0 - disconLength3 / 2.0;
            double port4_Y2_B8 = bendY4_0 + disconLength3 * Math.Sqrt(3.0) / 2.0;
            // ポート3出力部境界の終点
            double port4_X2_B7 = port4_X2_B8 - inputWgLength / 2.0;
            double port4_Y2_B7 = port4_Y2_B8 + inputWgLength * Math.Sqrt(3.0) / 2.0;
            // ポート3出力部境界の始点
            double port4_X1_B7 = port4_X2_B7 - WaveguideWidth * Math.Sqrt(3.0) / 2.0;
            double port4_Y1_B7 = port4_Y2_B7 - WaveguideWidth / 2.0;
            // ポート3出力部内部境界の始点
            double port4_X1_B8 = port4_X2_B8 - WaveguideWidth * Math.Sqrt(3.0) / 2.0;
            double port4_Y1_B8 = port4_Y2_B8 - WaveguideWidth / 2.0;

            // ポート2
            double port2_X = (int)(bendX4 / rodDistanceX) * rodDistanceX + disconLength2_2 + rodDistanceX * 0.5 + inputWgLength;

            // ポート1
            double port1_X = -0.5 * rodDistanceX;

            // ワールド座標系
            uint baseId = 0;
            CIDConvEAMshCad conv = null;
            using (CCadObj2D cad2d = new CCadObj2D())
            {
                //------------------------------------------------------------------
                // 図面作成
                //------------------------------------------------------------------
                {
                    IList<CVector2D> pts = new List<CVector2D>();
                    // 領域追加
                    pts.Add(new CVector2D(port1_X,WaveguideWidth)); // 頂点1
                    pts.Add(new CVector2D(port1_X, 0.0)); // 頂点2
                    pts.Add(new CVector2D(port1_X + inputWgLength, 0.0)); // 頂点3
                    pts.Add(new CVector2D(port2_X - inputWgLength, 0.0)); // 頂点4
                    pts.Add(new CVector2D(port2_X, 0.0)); // 頂点5
                    pts.Add(new CVector2D(port2_X, WaveguideWidth)); // 頂点6
                    pts.Add(new CVector2D(port2_X - inputWgLength, WaveguideWidth)); // 頂点7

                    pts.Add(new CVector2D(bendX4, WaveguideWidth)); // 頂点8
                    pts.Add(new CVector2D(port4_X2_B8, port4_Y2_B8)); // 頂点9
                    pts.Add(new CVector2D(port4_X2_B7, port4_Y2_B7)); // 頂点10
                    pts.Add(new CVector2D(port4_X1_B7, port4_Y1_B7)); // 頂点11
                    pts.Add(new CVector2D(port4_X1_B8, port4_Y1_B8)); // 頂点12
                    pts.Add(new CVector2D(bendX3, bendY3)); // 頂点13

                    pts.Add(new CVector2D(bendX2, WaveguideWidth)); // 頂点14
                    pts.Add(new CVector2D(port3_X2_B6, port3_Y2_B6)); // 頂点15
                    pts.Add(new CVector2D(port3_X2_B5, port3_Y2_B5)); // 頂点16
                    pts.Add(new CVector2D(port3_X1_B5, port3_Y1_B5)); // 頂点17
                    pts.Add(new CVector2D(port3_X1_B6, port3_Y1_B6)); // 頂点18
                    pts.Add(new CVector2D(bendX1, bendY1)); // 頂点19

                    pts.Add(new CVector2D(port1_X + inputWgLength, WaveguideWidth));  // 頂点20

                    uint lId1 = cad2d.AddPolygon(pts).id_l_add;
                }
                // 入出力領域を分離
                uint eIdAdd1 = cad2d.ConnectVertex_Line(3, 20).id_e_add;
                uint eIdAdd2 = cad2d.ConnectVertex_Line(4, 7).id_e_add;
                uint eIdAdd3 = cad2d.ConnectVertex_Line(15, 18).id_e_add;
                uint eIdAdd4 = cad2d.ConnectVertex_Line(9, 12).id_e_add;

                // 入出力導波路の周期構造境界上の頂点を追加
                IList<double> ys_port1 = new List<double>();
                IList<double> ys_rod_port1 = new List<double>();
                IList<double> ys_port2 = new List<double>();
                IList<double> ys_rod_port2 = new List<double>();
                IList<double> xs_port3 = new List<double>();
                IList<double> xs_rod_port3 = new List<double>();
                IList<double> xs_port4 = new List<double>();
                IList<double> xs_rod_port4 = new List<double>();
                IList<uint> id_v_list_rod_B1 = new List<uint>();
                IList<uint> id_v_list_rod_B2 = new List<uint>();
                IList<uint> id_v_list_rod_B3 = new List<uint>();
                IList<uint> id_v_list_rod_B4 = new List<uint>();
                IList<uint> id_v_list_rod_B5 = new List<uint>();
                IList<uint> id_v_list_rod_B6 = new List<uint>();
                IList<uint> id_v_list_rod_B7 = new List<uint>();
                IList<uint> id_v_list_rod_B8 = new List<uint>();

                for (int portIndex = 0; portIndex < portCnt; portIndex++)
                {
                    int cur_rodCntHalf = 0;
                    int cur_defectRodCnt = 0;
                    int cur_ndivForOneLattice = 0;
                    double cur_WaveguideWidth = 0.0;
                    double cur_rodDistanceY = 0.0;
                    IList<double> ys = null;
                    IList<double> ys_rod = null;
                    if (portIndex == 0)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port1;
                        ys_rod = ys_rod_port1;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 1)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = ys_port2;
                        ys_rod = ys_rod_port2;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 2)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = xs_port3;
                        ys_rod = xs_rod_port3;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else if (portIndex == 3)
                    {
                        cur_rodCntHalf = rodCntHalf;
                        cur_defectRodCnt = defectRodCnt;
                        cur_ndivForOneLattice = ndivForOneLattice;
                        cur_WaveguideWidth = WaveguideWidth;
                        cur_rodDistanceY = rodDistanceY;
                        ys = xs_port4;
                        ys_rod = xs_rod_port4;
                        System.Diagnostics.Debug.Assert(ys.Count == 0);
                        System.Diagnostics.Debug.Assert(ys_rod.Count == 0);
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // 境界上にロッドのある格子
                    // 境界上のロッドの頂点
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        double y0 = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY;
                        ys_rod.Add(y0);
                        for (int k = 1; k <= rodRadiusDiv; k++)
                        {
                            ys_rod.Add(y0 - k * rodRadius / rodRadiusDiv);
                            ys_rod.Add(y0 + k * rodRadius / rodRadiusDiv);
                        }
                    }
                    foreach (double y_rod in ys_rod)
                    {
                        ys.Add(y_rod);
                    }

                    // 境界上のロッドの外の頂点はロッドから少し離さないとロッドの追加で失敗するのでマージンをとる
                    double radiusMargin = cur_rodDistanceY * 0.01;
                    // 境界上にロッドのある格子
                    // ロッドの外
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_WaveguideWidth - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 1 : 0)) continue;
                        for (int k = 1; k <= (cur_ndivForOneLattice - 1); k++)
                        {
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            double y_min_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY - rodRadius - radiusMargin;
                            double y_max_rod = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - 0.5 * cur_rodDistanceY + rodRadius + radiusMargin;
                            if (y_divpt < y_min_rod || y_divpt > y_max_rod)
                            {
                                ys.Add(y_divpt);
                            }
                        }
                    }

                    // 境界上にロッドのない格子
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if ((cur_rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == 0 && k == 0) continue;
                            double y_divpt = cur_WaveguideWidth - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    for (int i = 0; i < cur_rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1)) continue;
                        for (int k = 0; k <= cur_ndivForOneLattice; k++)
                        {
                            if (i == (cur_rodCntHalf - 1) && k == cur_ndivForOneLattice) continue;
                            double y_divpt = cur_rodDistanceY * cur_rodCntHalf - i * cur_rodDistanceY - k * (cur_rodDistanceY / cur_ndivForOneLattice);
                            ys.Add(y_divpt);
                        }
                    }
                    // 欠陥部
                    for (int i = 0; i <= (cur_defectRodCnt * cur_ndivForOneLattice); i++)
                    {
                        if (!isShift180 && (i == 0 || i == (cur_defectRodCnt * cur_ndivForOneLattice))) continue;
                        double y_divpt = cur_rodDistanceY * (cur_rodCntHalf + cur_defectRodCnt) - i * (cur_rodDistanceY / cur_ndivForOneLattice);
                        ys.Add(y_divpt);
                    }

                    // 昇順でソート
                    double[] yAry = ys.ToArray();
                    Array.Sort(yAry);
                    int cur_ndivPlus = 0;
                    cur_ndivPlus = yAry.Length + 1;
                    if (portIndex == 0)
                    {
                        ndivPlus_port1 = cur_ndivPlus;
                    }
                    else if (portIndex == 1)
                    {
                        ndivPlus_port2 = cur_ndivPlus;
                    }
                    else if (portIndex == 2)
                    {
                        ndivPlus_port3 = cur_ndivPlus;
                    }
                    else if (portIndex == 3)
                    {
                        ndivPlus_port4 = cur_ndivPlus;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    // yAryは昇順なので、yAryの並びの順に追加すると境界1上を逆方向に移動することになる
                    //  逆から追加しているのは、頂点によって新たに生成される辺に頂点を追加しないようにするため
                    // 入力導波路 外側境界
                    // 入力導波路 内部側境界
                    // 出力導波路 外側境界
                    // 出力導波路 内部側境界
                    for (int boundaryIndex = 0; boundaryIndex < 2;  boundaryIndex++)
                    {
                        bool isInRod = false;
                        for (int i = 0; i < yAry.Length; i++)
                        {
                            uint id_e = 0;
                            double x_pt = 0.0;
                            double y_pt = 0.0;

                            IList<uint> work_id_e_rod_B = null;
                            IList<uint> work_id_v_list_rod_B = null;
                            int yAryIndex = 0;
                            if (portIndex == 0 && boundaryIndex == 0)
                            {
                                // ポート1導波路 外側境界
                                id_e = 1;
                                x_pt = port1_X;
                                y_pt = yAry[i];
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B1;
                                work_id_v_list_rod_B = id_v_list_rod_B1;
                            }
                            else if (portIndex == 0 && boundaryIndex == 1)
                            {
                                // ポート1導波路 内側境界
                                id_e = 21;
                                x_pt = port1_X + inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B2;
                                work_id_v_list_rod_B = id_v_list_rod_B2;
                            }
                            else if (portIndex == 1 && boundaryIndex == 0)
                            {
                                // ポート2導波路 外側境界
                                id_e = 5;
                                x_pt = port2_X;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B3;
                                work_id_v_list_rod_B = id_v_list_rod_B3;
                            }
                            else if (portIndex == 1 && boundaryIndex == 1)
                            {
                                // ポート2導波路 内側境界
                                id_e = 22;
                                x_pt = port2_X - inputWgLength;
                                y_pt = yAry[yAry.Length - 1 - i];
                                yAryIndex = yAry.Length - 1 - i;
                                work_id_e_rod_B = id_e_rod_B4;
                                work_id_v_list_rod_B = id_v_list_rod_B4;
                            }
                            else if (portIndex == 2 && boundaryIndex == 0)
                            {
                                // ポート3導波路 外側境界
                                id_e = 16;
                                x_pt = port3_X1_B5 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port3_Y1_B5 + yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B5;
                                work_id_v_list_rod_B = id_v_list_rod_B5;
                            }
                            else if (portIndex == 2 && boundaryIndex == 1)
                            {
                                // ポート3導波路 内側境界
                                id_e = 23;
                                x_pt = port3_X1_B6 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port3_Y1_B6 + yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B6;
                                work_id_v_list_rod_B = id_v_list_rod_B6;
                            }
                            else if (portIndex == 3 && boundaryIndex == 0)
                            {
                                // ポート4導波路 外側境界
                                id_e = 10;
                                x_pt = port4_X1_B7 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port4_Y1_B7 + yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B7;
                                work_id_v_list_rod_B = id_v_list_rod_B7;
                            }
                            else if (portIndex == 3 && boundaryIndex == 1)
                            {
                                // ポート4導波路 内側境界
                                id_e = 24;
                                x_pt = port4_X1_B8 + yAry[i] * Math.Sqrt(3.0) / 2.0;
                                y_pt = port4_Y1_B8 + yAry[i] / 2.0;
                                yAryIndex = i;
                                work_id_e_rod_B = id_e_rod_B8;
                                work_id_v_list_rod_B = id_v_list_rod_B8;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }

                            CCadObj2D.CResAddVertex resAddVertex = null;
                            resAddVertex = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e, new CVector2D(x_pt, y_pt));
                            uint id_v_add = resAddVertex.id_v_add;
                            uint id_e_add = resAddVertex.id_e_add;
                            System.Diagnostics.Debug.Assert(id_v_add != 0);
                            System.Diagnostics.Debug.Assert(id_e_add != 0);
                            if (isInRod)
                            {
                                work_id_e_rod_B.Add(id_e_add);
                            }
                            bool contains = false;
                            foreach (double y_rod in ys_rod)
                            {
                                if (Math.Abs(y_rod - yAry[yAryIndex]) < MyUtilLib.Matrix.Constants.PrecisionLowerLimit)
                                {
                                    contains = true;
                                    break;
                                }
                            }
                            if (contains)
                            {
                                work_id_v_list_rod_B.Add(id_v_add);
                                if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 1)
                                {
                                    isInRod = true;
                                }
                                else if (work_id_v_list_rod_B.Count % (rodRadiusDiv * 2 + 1) == 0)
                                {
                                    isInRod = false;
                                }
                            }
                        }
                    }
                }
                int bRodCntHalf_port1 = (isShift180 ? (int)((rodCntHalf + 1) / 2) : (int)((rodCntHalf) / 2));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B1.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B2.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B3.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B4.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B5.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B6.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B7.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));
                System.Diagnostics.Debug.Assert(id_v_list_rod_B8.Count == bRodCntHalf_port1 * 2 * (rodRadiusDiv * 2 + 1));

                // ロッドを追加
                /////////////////////////////////////////////////////////////
                // 入力導波路側ロッド
                // 左のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 左のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 始点、終点が逆?
                    bool isReverse = false;
                    if (colIndex == 0)
                    {
                        // 入力境界 外側
                        x_B = port1_X;
                        work_id_v_list_rod_B = id_v_list_rod_B1;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                        isReverse = false;
                    }
                    else if (colIndex == 1)
                    {
                        // 入力境界 内側
                        x_B = port1_X + inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                        isReverse = true;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                        isReverse = true;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 左のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = 0.0 + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint work_id_v0 = id_v0;
                                uint work_id_v2 = id_v2;
                                if (isReverse)
                                {
                                    work_id_v0 = id_v2;
                                    work_id_v2 = id_v0;
                                }
                                uint lId = WgCadUtil.AddLeftRod(
                                    cad2d,
                                    baseLoopId,
                                    work_id_v0,
                                    id_v1,
                                    work_id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 右のロッドを追加
                for (int colIndex = 0; colIndex < 3; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                {
                    // 右のロッド
                    IList<uint> work_id_v_list_rod_B = null;
                    double x_B = 0;
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    if (colIndex == 0)
                    {
                        // 入力境界 内側
                        x_B = port1_X + inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B2;
                        // 入力導波路領域
                        baseLoopId = 1;
                        inputWgNo = 1;
                    }
                    else if (colIndex == 1)
                    {
                        // ポート2内側
                        x_B = port2_X - inputWgLength;
                        work_id_v_list_rod_B = id_v_list_rod_B4;
                        // 不連続領域
                        baseLoopId = 2;
                        inputWgNo = 0;
                    }
                    else if (colIndex == 2)
                    {
                        // ポート2外側
                        x_B = port2_X;
                        work_id_v_list_rod_B = id_v_list_rod_B3;
                        // 出力導波路領域
                        baseLoopId = 3;
                        inputWgNo = 2;
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }

                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                                CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                    for (int i = 0; i < rodCntHalf; i++)
                    {
                        if (i % 2 == (isShift180 ? 0 : 1))
                        {
                            int i2 = i / 2;
                            // 右のロッド
                            {
                                uint id_v0 = 0;
                                uint id_v1 = 0;
                                uint id_v2 = 0;
                                if (work_id_v_list_rod_B == id_v_list_rod_B1)
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv * 2 + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - (rodRadiusDiv + 1) - i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 - 1 - i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                else
                                {
                                    id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                    id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                }
                                double x0 = x_B;
                                double y0 = 0.0 + rodDistanceY * rodCntHalf - i * rodDistanceY - rodDistanceY * 0.5;
                                uint lId = WgCadUtil.AddRightRod(
                                    cad2d,
                                    baseLoopId,
                                    id_v0,
                                    id_v1,
                                    id_v2,
                                    x0,
                                    y0,
                                    rodRadius,
                                    rodCircleDiv,
                                    rodRadiusDiv);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                            }
                        }
                    }
                }

                // 中央のロッド (入力導波路 + 不連続部)
                int periodCntInputWg1 = 1;
                int rodCnt_BendY = rodCntHalf * 2 + defectRodCnt;
                int periodCntX_BendX1 = (int)Math.Round(bendX1 / rodDistanceX);
                int periodCntX_BendX2 = (int)Math.Round(bendX2 / rodDistanceX);
                int periodCntX_BendX3 = (int)Math.Round(bendX3 / rodDistanceX);
                int periodCntX_BendX4 = (int)Math.Round(bendX4 / rodDistanceX);
                int periodCntX_port2 = (int)Math.Ceiling(port2_X / rodDistanceX) - 1;

                for (int col = -1; col <= (periodCntX_port2 * 2); col++)
                {
                    if (col == 1) continue; // 入力導波路内部境界 (既にロッド追加済み)
                    if (col == (periodCntX_port2 * 2 - 1)) continue; // ポート2導波路内部境界
                    uint baseLoopId = 0;
                    int inputWgNo = 0;

                    // 中央のロッド
                    for (int i = 0; i < rodCnt_BendY; i++)
                    {
                        if (col <= (periodCntInputWg1 * 2)
                            && (i >= (rodCntHalf * 2 + defectRodCnt))
                            )
                        {
                            continue;
                        }
                        if (col >= -1 && col <= 1)
                        {
                            baseLoopId = 1;
                            inputWgNo = 1;
                        }
                        else if (col >= (periodCntX_port2 * 2 - 1))
                        {
                            baseLoopId = 3;
                            inputWgNo = 2;
                        }
                        else
                        {
                            baseLoopId = 2;
                            inputWgNo = 0;
                        }

                        // ロッドの半径
                        double rr = rodRadius;
                        // ロッドの半径方向分割数
                        int nr = rodRadiusDiv;
                        // ロッドの周方向分割数
                        int nc = rodCircleDiv;
                        // ずらす距離
                        double ofs_x_rod = 0.0;
                        double ofs_y_rod = 0.0;

                        if (inputWgNo == 0)
                        {
                            // 分割数を調整
                            nr = 2;
                        }

                        // 導波路1欠陥部
                        if (i >= rodCntHalf && i <= (rodCntHalf + defectRodCnt - 1))
                        {
                            continue;
                        }

                        // ベンド部上下のエアホール
                        double r1 = 0.206 * latticeA;
                        double r2 = 0.294 * latticeA;
                        // 遮断導波路のエアホール
                        double rb_1st = 0.375 * latticeA;
                        double rb_2nd = 0.400 * latticeA;

                        // ベンド部 1段目 ポート3
                        int colBend_1st = col - (periodCntX_BendX1 * 2 + (rodCntHalf + 1) * 2);
                        // ベンド部 2段目 ポート4
                        int colBend_2nd = col - (periodCntX_BendX3 * 2 + (rodCntHalf + 1) * 2);

                        // ポート3ベンド部
                        if (colBend_1st >= 0 && colBend_1st <= (rodCntHalf - 2)
                            && i == colBend_1st)
                        {
                            continue;
                        }
                        else if (colBend_1st == (rodCntHalf - 1)
                            && i == (rodCntHalf - 1))
                        {
                            // ポート3出力結合部
                            rr = r1;
                        }
                        else if (colBend_1st == (rodCntHalf - 1)
                            && i == (rodCntHalf + defectRodCnt))
                        {
                            // ポート3出力結合部の向かい側
                            rr = r2;
                        }
                        // 遮断導波路部(1段目)
                        if (colBend_1st >= (rodCntHalf) && colBend_2nd <= (rodCntHalf - 1))
                        {
                            if (i == (rodCntHalf - 1) || i == (rodCntHalf + defectRodCnt))
                            {
                                rr = rb_1st;
                            }
                        }

                        // ポート4ベンド部
                        if (colBend_2nd >= 0 && colBend_2nd <= (rodCntHalf - 2)
                            && i == colBend_2nd)
                        {
                            continue;
                        }
                        else if (colBend_2nd == (rodCntHalf - 1)
                            && i == (rodCntHalf - 1))
                        {
                            // ポート3出力結合部
                            rr = r1;
                        }
                        else if (colBend_2nd == (rodCntHalf - 1)
                            && i == (rodCntHalf + defectRodCnt))
                        {
                            // ポート3出力結合部の向かい側
                            rr = r2;
                        }
                        // 遮断導波路部(2段目)
                        if (colBend_2nd >= (rodCntHalf) && col <= (periodCntX_port2 * 2 - 4))
                        {
                            if (i == (rodCntHalf - 1) || i == (rodCntHalf + defectRodCnt))
                            {
                                rr = rb_2nd;
                            }
                        }

                        if ((col % 2 == 1 && (Math.Abs(i - rodCnt_BendY) % 2 == (isShift180 ? 1 : 0)))
                            || (col % 2 == 0 && (Math.Abs(i - rodCnt_BendY) % 2 == (isShift180 ? 0 : 1))))
                        {
                            // 中央ロッド
                            double x0 = rodDistanceX * 0.5 * col;
                            double y0 = WaveguideWidth - i * rodDistanceY - rodDistanceY * 0.5;
                            x0 += ofs_x_rod;
                            y0 += ofs_y_rod;
                            uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, nc, nr);
                            rodLoopIds.Add(lId);
                            if (inputWgNo == 1)
                            {
                                rodLoopIds_InputWg1.Add(lId);
                            }
                            else if (inputWgNo == 2)
                            {
                                rodLoopIds_InputWg2.Add(lId);
                            }
                            else if (inputWgNo == 3)
                            {
                                rodLoopIds_InputWg3.Add(lId);
                            }
                        }
                    }
                }

                /////////////////////////////////////////////////////////////
                // 出力導波路側ロッド
                for (int portIndex = 2; portIndex <= 3; portIndex++)
                {
                    // 上のロッドを追加
                    for (int colIndex = 0; colIndex < 2; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                    {
                        // 上のロッド
                        IList<uint> work_id_v_list_rod_B = null;
                        double x1_B = 0;
                        double y1_B = 0;
                        uint baseLoopId = 0;
                        int inputWgNo = 0;

                        if (portIndex == 2 && colIndex == 0)
                        {
                            // 出力境界 外側
                            x1_B = port3_X1_B5;
                            y1_B = port3_Y1_B5;
                            work_id_v_list_rod_B = id_v_list_rod_B5;
                            // 出力導波路領域
                            baseLoopId = 4;
                            inputWgNo = 3;
                        }
                        else if (portIndex == 2 && colIndex == 1)
                        {
                            // 出力境界内側
                            x1_B = port3_X1_B6;
                            y1_B = port3_Y1_B6;
                            work_id_v_list_rod_B = id_v_list_rod_B6;
                            // 不連続領域
                            baseLoopId = 2;
                            inputWgNo = 0;
                        }
                        else if (portIndex == 3 && colIndex == 0)
                        {
                            // 出力境界 外側
                            x1_B = port4_X1_B7;
                            y1_B = port4_Y1_B7;
                            work_id_v_list_rod_B = id_v_list_rod_B7;
                            // 出力導波路領域
                            baseLoopId = 5;
                            inputWgNo = 4;
                        }
                        else if (portIndex == 3 && colIndex == 1)
                        {
                            // 出力境界内側
                            x1_B = port4_X1_B8;
                            y1_B = port4_Y1_B8;
                            work_id_v_list_rod_B = id_v_list_rod_B8;
                            // 不連続領域
                            baseLoopId = 2;
                            inputWgNo = 0;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        for (int i = 0; i < rodCntHalf; i++)
                        {
                            if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                            {
                                int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                                // 上のロッド
                                {
                                    uint id_v0 = 0;
                                    uint id_v1 = 0;
                                    uint id_v2 = 0;
                                    {
                                        id_v0 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v2 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    }
                                    double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                                    double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                    double y0 = y1_B + y_proj / 2.0;
                                    double startAngle = (0.0 + 30.0);

                                    CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        startAngle,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                    else if (inputWgNo == 3)
                                    {
                                        rodLoopIds_InputWg3.Add(lId);
                                    }
                                    else if (inputWgNo == 4)
                                    {
                                        rodLoopIds_InputWg4.Add(lId);
                                    }
                                }
                            }
                        }
                        for (int i = 0; i < rodCntHalf; i++)
                        {
                            if (i % 2 == (isShift180 ? 0 : 1))
                            {
                                int i2 = i / 2;
                                // 上のロッド
                                {
                                    uint id_v0 = 0;
                                    uint id_v1 = 0;
                                    uint id_v2 = 0;
                                    {
                                        id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                    }
                                    double y_proj = WaveguideWidth - rodDistanceY * rodCntHalf + i * rodDistanceY + rodDistanceY * 0.5;
                                    double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                    double y0 = y1_B + y_proj / 2.0;
                                    double startAngle = (0.0 + 30.0);
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        startAngle,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                    else if (inputWgNo == 3)
                                    {
                                        rodLoopIds_InputWg3.Add(lId);
                                    }
                                    else if (inputWgNo == 4)
                                    {
                                        rodLoopIds_InputWg4.Add(lId);
                                    }
                                }
                            }
                        }
                    }

                    // 下のロッドを追加
                    for (int colIndex = 0; colIndex < 1; colIndex++) // このcolIndexは特に図面上のカラムを指すわけではない(ループ変数)
                    {
                        // 下のロッド
                        IList<uint> work_id_v_list_rod_B = null;
                        double x1_B = 0;
                        double y1_B = 0;
                        uint baseLoopId = 0;
                        int inputWgNo = 0;

                        if (portIndex == 2 && colIndex == 0)
                        {
                            // 出力境界 内側
                            x1_B = port3_X1_B6;
                            y1_B = port3_Y1_B6;
                            work_id_v_list_rod_B = id_v_list_rod_B6;
                            // 出力導波路領域
                            baseLoopId = 4;
                            inputWgNo = 3;
                        }
                        else if (portIndex == 3 && colIndex == 0)
                        {
                            // 出力境界 内側
                            x1_B = port4_X1_B8;
                            y1_B = port4_Y1_B8;
                            work_id_v_list_rod_B = id_v_list_rod_B8;
                            // 出力導波路領域
                            baseLoopId = 5;
                            inputWgNo = 4;
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        for (int i = 0; i < rodCntHalf; i++)
                        {
                            if ((rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))
                            {
                                int i2 = bRodCntHalf_port1 - 1 - (int)((rodCntHalf - 1 - i) / 2);
                                // 下のロッド
                                {
                                    uint id_v0 = 0;
                                    uint id_v1 = 0;
                                    uint id_v2 = 0;
                                    {
                                        id_v0 = work_id_v_list_rod_B[(rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v1 = work_id_v_list_rod_B[(rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v2 = work_id_v_list_rod_B[0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    }
                                    double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                                    double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                    double y0 = y1_B + y_proj / 2.0;
                                    double startAngle = (180.0 + 30.0);
                                    CVector2D pt_center = cad2d.GetVertexCoord(id_v1);
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        startAngle,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                    else if (inputWgNo == 3)
                                    {
                                        rodLoopIds_InputWg3.Add(lId);
                                    }
                                    else if (inputWgNo == 4)
                                    {
                                        rodLoopIds_InputWg4.Add(lId);
                                    }
                                }
                            }
                        }
                        for (int i = 0; i < rodCntHalf; i++)
                        {
                            if (i % 2 == (isShift180 ? 0 : 1))
                            {
                                int i2 = i / 2;
                                // 下のロッド
                                {
                                    uint id_v0 = 0;
                                    uint id_v1 = 0;
                                    uint id_v2 = 0;
                                    {
                                        id_v0 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv * 2) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v1 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + (rodRadiusDiv) + i2 * (rodRadiusDiv * 2 + 1)];
                                        id_v2 = work_id_v_list_rod_B[work_id_v_list_rod_B.Count / 2 + 0 + i2 * (rodRadiusDiv * 2 + 1)];
                                    }
                                    double y_proj = WaveguideWidth - rodDistanceY * rodCntHalf + i * rodDistanceY + rodDistanceY * 0.5;
                                    double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                    double y0 = y1_B + y_proj / 2.0;
                                    double startAngle = (180.0 + 30.0);
                                    uint lId = WgCadUtil.AddExactlyHalfRod(
                                        cad2d,
                                        baseLoopId,
                                        id_v0,
                                        id_v1,
                                        id_v2,
                                        x0,
                                        y0,
                                        rodRadius,
                                        rodCircleDiv,
                                        rodRadiusDiv,
                                        startAngle,
                                        true);
                                    rodLoopIds.Add(lId);
                                    if (inputWgNo == 1)
                                    {
                                        rodLoopIds_InputWg1.Add(lId);
                                    }
                                    else if (inputWgNo == 2)
                                    {
                                        rodLoopIds_InputWg2.Add(lId);
                                    }
                                    else if (inputWgNo == 3)
                                    {
                                        rodLoopIds_InputWg3.Add(lId);
                                    }
                                    else if (inputWgNo == 4)
                                    {
                                        rodLoopIds_InputWg4.Add(lId);
                                    }
                                }
                            }
                        }
                    }
                }

                ////////////////////////////////////////////////////////////////////////////////////////////////////
                // 中央のロッド (出力導波路)
                int periodCntInputWg2 = 1;
                int periodCntY = periodCntInputWg2 + rodCntDiscon_port3;
                int periodCntY_Short = periodCntY - (rodCntHalf * 2 + defectRodCnt) / 2 - 1;

                // 中央のロッド(出力導波路)(左右の強制境界と交差する円)と境界の交点
                IList<uint> id_v_list_F1 = new List<uint>();
                IList<uint> id_v_list_F2 = new List<uint>();

                // 中央のロッド (出力導波路)
                for (int portIndex = 2; portIndex <= 3; portIndex++)
                {
                    for (int col = 1; col <= (periodCntY * 2 - 2); col++)
                    {
                        if (col == (periodCntInputWg2 * 2)) continue; // 入力導波路内部境界 (既にロッド追加済み)

                        uint baseLoopId = 0;
                        int inputWgNo = 0;
                        if (col >= 0 && col < (periodCntInputWg2 * 2))
                        {
                            if (portIndex == 2)
                            {
                                baseLoopId = 4;
                                inputWgNo = 3;
                            }
                            else if (portIndex == 3)
                            {
                                baseLoopId = 5;
                                inputWgNo = 4;
                            }
                            else
                            {
                                System.Diagnostics.Debug.Assert(false);
                            }
                        }
                        else
                        {
                            baseLoopId = 2;
                            inputWgNo = 0;
                        }
                        double x1_B = 0.0;
                        double y1_B = 0.0;
                        if (portIndex == 2)
                        {
                            x1_B = port3_X1_B5 + col * ((rodDistanceX * 0.5) / 2.0);
                            y1_B = port3_Y1_B5 - col * ((rodDistanceX * 0.5) * Math.Sqrt(3.0) / 2.0);
                        }
                        else if (portIndex == 3)
                        {
                            x1_B = port4_X1_B7 + col * ((rodDistanceX * 0.5) / 2.0);
                            y1_B = port4_Y1_B7 - col * ((rodDistanceX * 0.5) * Math.Sqrt(3.0) / 2.0);
                        }
                        else
                        {
                            System.Diagnostics.Debug.Assert(false);
                        }

                        // 中央のロッド(出力導波路)
                        for (int i = 0; i <= (rodCntHalf * 2 + defectRodCnt); i++)
                        {
                            if (col >= (periodCntY_Short * 2))
                            {
                                int workCol = col - (periodCntY_Short * 2);
                                if (i < workCol)
                                {
                                    continue;
                                }
                            }

                            // 欠陥部
                            if (i >= (rodCntHalf * 2 + defectRodCnt)) continue;

                            double rr = rodRadius;
                            int nr = rodRadiusDiv;
                            if (inputWgNo == 0)
                            {
                                // 分割数を調整
                                nr = 2;
                            }
                            // 欠陥部
                            if (i == (rodCntHalf))
                            {
                                continue;
                            }
                            if ((col % 2 == 1 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 1 : 0)))
                                || (col % 2 == 0 && (Math.Abs(rodCntHalf - 1 - i) % 2 == (isShift180 ? 0 : 1))))
                            {
                                // 中央ロッド
                                double y_proj = i * rodDistanceY + rodDistanceY * 0.5;
                                double x0 = x1_B + y_proj * Math.Sqrt(3.0) / 2.0;
                                double y0 = y1_B + y_proj / 2.0;
                                uint lId = WgCadUtil.AddRod(cad2d, baseLoopId, x0, y0, rr, rodCircleDiv, nr);
                                rodLoopIds.Add(lId);
                                if (inputWgNo == 1)
                                {
                                    rodLoopIds_InputWg1.Add(lId);
                                }
                                else if (inputWgNo == 2)
                                {
                                    rodLoopIds_InputWg2.Add(lId);
                                }
                                else if (inputWgNo == 3)
                                {
                                    rodLoopIds_InputWg3.Add(lId);
                                }
                                else if (inputWgNo == 4)
                                {
                                    rodLoopIds_InputWg4.Add(lId);
                                }
                            }
                        }
                    }
                }

                //isCadShow = true;
                // 図面表示
                if (isCadShow)
                {
                    // check
                    // ロッドを色付けする
                    foreach (uint lIdRod in rodLoopIds)
                    {
                        cad2d.SetColor_Loop(lIdRod, new double[] { 0.0, 0.0, 1.0 });
                    }
                    // 境界上のロッドの辺に色を付ける
                    foreach (uint eId in id_e_rod_B1)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B2)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B3)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B4)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B5)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B6)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B7)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    foreach (uint eId in id_e_rod_B8)
                    {
                        cad2d.SetColor_Edge(eId, new double[] { 1.0, 0.0, 1.0 });
                    }
                    CadDrawerAry.Clear();
                    CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                    CadDrawerAry.InitTrans(Camera);
                    return true;
                }
                /*
                // 図面表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */
                /*
                // メッシュ表示
                isCadShow = true;
                CadDrawerAry.Clear();
                CadDrawerAry.PushBack(new CDrawerMsh2D(new CMesher2D(cad2d, meshL)));
                CadDrawerAry.InitTrans(Camera);
                return true;
                 */

                //------------------------------------------------------------------
                // メッシュ作成
                //------------------------------------------------------------------
                // メッシュを作成し、ワールド座標系にセットする
                World.Clear();
                using (CMesher2D mesher2d = new CMesher2D(cad2d, meshL))
                {
                    baseId = World.AddMesh(mesher2d);
                    conv = World.GetIDConverter(baseId);
                }
            }
            // 界の値を扱うバッファ?を生成する。
            // フィールド値IDが返却される。
            //    要素の次元: 2次元 界: 複素数スカラー 微分タイプ: 値 要素セグメント: 角節点
            FieldValId = World.MakeField_FieldElemDim(baseId, 2,
                FIELD_TYPE.ZSCALAR, FIELD_DERIVATION_TYPE.VALUE, ELSEG_TYPE.CORNER);

            // 領域
            //   ワールド座標系のループIDを取得
            //   媒質をループ単位で指定する
            FieldLoopId = 0;
            {
                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = new uint[5 + rodLoopIds.Count];
                loopId_cad_list[0] = 1;
                loopId_cad_list[1] = 2;
                loopId_cad_list[2] = 3;
                loopId_cad_list[3] = 4;
                loopId_cad_list[4] = 5;
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    loopId_cad_list[i + 5] = rodLoopIds[i];
                }
                int[] mediaIndex_list = new int[5 + rodLoopIds.Count];
                for (int i = 0; i < 5; i++)
                {
                    mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 0; i < rodLoopIds.Count; i++)
                {
                    mediaIndex_list[i + 5] = Medias.IndexOf(mediaCore);
                }
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out FieldLoopId,
                    ref LoopDic);
            }

            // ポート情報リスト作成
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgPortInfoList.Add(new WgUtilForPeriodicEigenExt.WgPortInfo());
                System.Diagnostics.Debug.Assert(WgPortInfoList.Count == (portIndex + 1));
                WgPortInfoList[portIndex].LatticeA = latticeA;
                WgPortInfoList[portIndex].PeriodicDistance = periodicDistance;
                WgPortInfoList[portIndex].MinEffN = minEffN;
                WgPortInfoList[portIndex].MaxEffN = maxEffN;
                WgPortInfoList[portIndex].MinWaveNum = minWaveNum;
                WgPortInfoList[portIndex].MaxWaveNum = maxWaveNum;

                // 緩慢変化包絡線近似?
                WgPortInfoList[portIndex].IsSVEA = isSVEA;
                // 固有値問題を反復で解く?
                WgPortInfoList[portIndex].IsSolveEigenItr = isSolveEigenItr;
                // 伝搬モードの数
                WgPortInfoList[portIndex].PropModeCntToSolve = propModeCntToSolve;
            }
            // 入射ポートの設定
            //   ポート1を入射ポートとする
            WgPortInfoList[0].IsIncidentPort = true;
            // 入射インデックスの設定
            if (incidentModeIndex != 0)
            {
                System.Diagnostics.Debug.WriteLine("IncidentModeIndex: {0}", incidentModeIndex);
                WgPortInfoList[0].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[1].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[2].IncidentModeIndex = incidentModeIndex;
                WgPortInfoList[3].IncidentModeIndex = incidentModeIndex;
            }

            // 境界条件を設定する
            //   固定境界条件(強制境界)
            //   ワールド座標系の辺IDを取得
            //   媒質は指定しない
            FieldForceBcId = 0;
            if ((WaveModeDv == WgUtil.WaveModeDV.TE && !isMagneticWall)  // TEモードで電気壁
                || (WaveModeDv == WgUtil.WaveModeDV.TM && isMagneticWall) // TMモードで磁気壁
                )
            {
                uint[] eId_cad_list = new uint[16 + id_e_F1.Count + id_e_F2.Count];
                eId_cad_list[0] = 2;
                eId_cad_list[1] = 3;
                eId_cad_list[2] = 4;
                eId_cad_list[3] = 6;
                eId_cad_list[4] = 7;
                eId_cad_list[5] = 8;
                eId_cad_list[6] = 9;
                eId_cad_list[7] = 11;
                eId_cad_list[8] = 12;
                eId_cad_list[9] = 13;
                eId_cad_list[10] = 14;
                eId_cad_list[11] = 15;
                eId_cad_list[12] = 17;
                eId_cad_list[13] = 18;
                eId_cad_list[14] = 19;
                eId_cad_list[15] = 20;
                for (int i = 0; i < id_e_F1.Count; i++)
                {
                    eId_cad_list[16 + i] = id_e_F1[i];
                }
                for (int i = 0; i < id_e_F2.Count; i++)
                {
                    eId_cad_list[16 + id_e_F1.Count + i] = id_e_F2[i];
                }
                Dictionary<uint, Edge> dummyEdgeDic = null;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    null,
                    FieldValId,
                    out FieldForceBcId,
                    ref dummyEdgeDic);
            }
            // 開口条件
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldPortBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else if (portIndex == 2)
                {
                    ndivPlus = ndivPlus_port3;
                }
                else if (portIndex == 3)
                {
                    ndivPlus = ndivPlus_port4;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 1;
                    work_id_e_rod_B = id_e_rod_B1;
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 5;
                    work_id_e_rod_B = id_e_rod_B3;
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 16;
                    work_id_e_rod_B = id_e_rod_B5;
                }
                else if (portIndex == 3)
                {
                    eId_cad_list[0] = 10;
                    work_id_e_rod_B = id_e_rod_B7;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                }
                else
                {
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) - (i - 1));
                    }
                    else if (portIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) * 2 + (ndivPlus_port4 - 1) - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                Dictionary<uint, Edge> workEdgeDic = new Dictionary<uint, Edge>();
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref workEdgeDic);
                wgPortInfo1.FieldPortBcId = fieldPortBcId;
                foreach (var pair in workEdgeDic)
                {
                    EdgeDic.Add(pair.Key, pair.Value);
                    wgPortInfo1.InputWgEdgeDic.Add(pair.Key, pair.Value);
                }
            }

            ////////////////////////////////////////////////////////////////////////////////////////////////////////
            // 周期構造入出力導波路1
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgLoopId = 0;

                // ワールド座標系のループIDを取得
                uint[] loopId_cad_list = null;
                if (portIndex == 0)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg1.Count];
                    loopId_cad_list[0] = 1;
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg1[i];
                    }
                }
                else if (portIndex == 1)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg2.Count];
                    loopId_cad_list[0] = 3;
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg2[i];
                    }
                }
                else if (portIndex == 2)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg3.Count];
                    loopId_cad_list[0] = 4;
                    for (int i = 0; i < rodLoopIds_InputWg3.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg3[i];
                    }
                }
                else if (portIndex == 3)
                {
                    loopId_cad_list = new uint[1 + rodLoopIds_InputWg4.Count];
                    loopId_cad_list[0] = 5;
                    for (int i = 0; i < rodLoopIds_InputWg4.Count; i++)
                    {
                        loopId_cad_list[i + 1] = rodLoopIds_InputWg4[i];
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                int[] mediaIndex_list = null;
                if (portIndex == 0)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg1.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg1.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 1)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg2.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg2.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 2)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg3.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg3.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else if (portIndex == 3)
                {
                    mediaIndex_list = new int[1 + rodLoopIds_InputWg4.Count];
                    mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    for (int i = 0; i < rodLoopIds_InputWg4.Count; i++)
                    {
                        mediaIndex_list[i + 1] = Medias.IndexOf(mediaCore);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }

                uint fieldInputWgLoopId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Loop(
                    conv,
                    World,
                    loopId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldInputWgLoopId,
                    ref wgPortInfo1.InputWgLoopDic);
                wgPortInfo1.FieldInputWgLoopId = fieldInputWgLoopId;
            }
            // 周期構造境界
            //    周期構造境界は2つあり、1つは入出力ポート境界を使用。ここで指定するのは、内部側の境界)
            //   ワールド座標系の辺IDを取得
            //   辺単位で媒質を指定する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.FieldInputWgBcId = 0;

                int ndivPlus = 0;
                if (portIndex == 0)
                {
                    ndivPlus = ndivPlus_port1;
                }
                else if (portIndex == 1)
                {
                    ndivPlus = ndivPlus_port2;
                }
                else if (portIndex == 2)
                {
                    ndivPlus = ndivPlus_port3;
                }
                else if (portIndex == 3)
                {
                    ndivPlus = ndivPlus_port4;
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                uint[] eId_cad_list = new uint[ndivPlus];
                int[] mediaIndex_list = new int[eId_cad_list.Length];
                IList<uint> work_id_e_rod_B = null;

                if (portIndex == 0)
                {
                    eId_cad_list[0] = 21;
                    work_id_e_rod_B = id_e_rod_B2;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 1)
                {
                    eId_cad_list[0] = 22;
                    work_id_e_rod_B = id_e_rod_B4;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 2)
                {
                    eId_cad_list[0] = 23;
                    work_id_e_rod_B = id_e_rod_B6;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else if (portIndex == 3)
                {
                    eId_cad_list[0] = 24;
                    work_id_e_rod_B = id_e_rod_B8;
                    if (work_id_e_rod_B.Contains(eId_cad_list[0]))
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[0] = Medias.IndexOf(mediaCladding);
                    }
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                for (int i = 1; i <= ndivPlus - 1; i++)
                {
                    if (portIndex == 0)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 1)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 2)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) * 2 - (i - 1));
                    }
                    else if (portIndex == 3)
                    {
                        eId_cad_list[i] = (uint)(24 + (ndivPlus_port1 - 1) * 2 + (ndivPlus_port2 - 1) * 2 + (ndivPlus_port3 - 1) * 2 + (ndivPlus_port4 - 1) * 2 - (i - 1));
                    }
                    else
                    {
                        System.Diagnostics.Debug.Assert(false);
                    }
                    if (work_id_e_rod_B.Contains(eId_cad_list[i]))
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCore);
                    }
                    else
                    {
                        mediaIndex_list[i] = Medias.IndexOf(mediaCladding);
                    }
                }
                uint fieldPortBcId = 0;
                WgUtilForPeriodicEigen.GetPartialField_Edge(
                    conv,
                    World,
                    eId_cad_list,
                    mediaIndex_list,
                    FieldValId,
                    out fieldPortBcId,
                    ref wgPortInfo1.InputWgEdgeDic);
                wgPortInfo1.FieldInputWgBcId = fieldPortBcId;
            }
            // フォトニック結晶導波路チャンネル上節点を取得する
            for (int portIndex = 0; portIndex < portCnt; portIndex++)
            {
                WgUtilForPeriodicEigenExt.WgPortInfo wgPortInfo1 = WgPortInfoList[portIndex];
                wgPortInfo1.IsPCWaveguide = true;

                uint[] no_c_all = null;
                Dictionary<uint, uint> to_no_loop = null;
                double[][] coord_c_all = null;
                if (portIndex == 0 || portIndex == 1)
                {
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else if (portIndex == 2)
                {
                    // Y軸から見ての回転角
                    double rotAngle = 120.0 * pi / 180.0;
                    double[] rotOrigin = new double[] { port3_X2_B5, port3_Y2_B5 };
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, rotAngle, rotOrigin, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else if (portIndex == 3)
                {
                    // Y軸から見ての回転角
                    double rotAngle = 120.0 * pi / 180.0;
                    double[] rotOrigin = new double[] { port4_X2_B7, port4_Y2_B7 };
                    WgUtil.GetLoopCoordList(World, wgPortInfo1.FieldInputWgLoopId, rotAngle, rotOrigin, out no_c_all, out to_no_loop, out coord_c_all);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(false);
                }
                {
                    // チャンネル1
                    IList<uint> portNodes = new List<uint>();
                    for (int i = 0; i < no_c_all.Length; i++)
                    {
                        // 座標からチャンネル(欠陥部)を判定する
                        double[] coord = coord_c_all[i];
                        if (((portIndex == 0 || portIndex == 1) &&
                                (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            || ((portIndex == 2 || portIndex == 3) &&
                                (coord[1] >= (WaveguideWidth - rodDistanceY * (rodCntHalf + defectRodCnt) - 1.0 * rodDistanceY)
                                  && coord[1] <= (WaveguideWidth - rodDistanceY * rodCntHalf + 1.0 * rodDistanceY)))
                            )
                        {
                            portNodes.Add(no_c_all[i]);
                        }
                    }
                    wgPortInfo1.PCWaveguidePorts.Add(portNodes);
                }
            }
            return true;
        }
Exemplo n.º 31
0
        /// <summary>
        /// 問題を設定する
        /// </summary>
        /// <returns></returns>
        private bool setNewProblem()
        {
            bool success = false;
            try
            {
                using (CCadObj2D cad2d = new CCadObj2D())
                {
                    if (ProbNo == 0)
                    {
                        IList<CVector2D> pts = new List<CVector2D>();
                        pts.Add(new CVector2D(0.0, 0.0));
                        pts.Add(new CVector2D(1.0, 0.0));
                        pts.Add(new CVector2D(1.0, 1.0));
                        pts.Add(new CVector2D(0.0, 1.0));
                        uint id_l0 = cad2d.AddPolygon(pts, 0).id_l_add;
                        uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.5)).id_v_add;
                        uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.8)).id_v_add;
                        uint id_v7 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.8, 0.5)).id_v_add;
                        uint id_v8 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.2)).id_v_add;
                        uint id_v9 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.2, 0.5)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v5, id_v6);
                        cad2d.ConnectVertex_Line(id_v5, id_v7);
                        cad2d.ConnectVertex_Line(id_v5, id_v8);
                        cad2d.ConnectVertex_Line(id_v5, id_v9);

                        using (CCadObj2D cad2dtmp = cad2d.Clone()) // コピーのテスト
                        {
                            // export to the file
                            using (CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                cad2dtmp.Serialize(fout);
                            }
                        }
                        // import form the file
                        cad2d.Clear();
                        using (CSerializer fin = new CSerializer("hoge.txt", true))
                        {
                            cad2d.Serialize(fin);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 1)
                    {
                        CCadObj2D.CResAddPolygon res;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(2.0, 1.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(1.0, 2.0));
                            pts.Add(new CVector2D(0.0, 2.0));
                            res = cad2d.AddPolygon(pts);
                        }
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, res.aIdE[1]);
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, res.aIdE[2]);
                        cad2d.RemoveElement(CAD_ELEM_TYPE.VERTEX, res.aIdV[2]);
                        uint id_e_new = cad2d.ConnectVertex_Line(res.aIdE[3], res.aIdE[1]).id_e_add;
                        CCadObj2D.CResAddVertex res0 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e_new, new CVector2D(1, 0.4));
                        CCadObj2D.CResAddVertex res1 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e_new, new CVector2D(1, 0.6));
                        CCadObj2D.CResAddVertex res2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, res.aIdE[5], new CVector2D(0, 0.4));
                        CCadObj2D.CResAddVertex res3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, res.aIdE[5], new CVector2D(0, 0.6));
                        cad2d.ConnectVertex_Line(res0.id_v_add, res2.id_v_add);
                        cad2d.ConnectVertex_Line(res1.id_v_add, res3.id_v_add);
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, res1.id_e_add);
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, res3.id_e_add);
                        using (CCadObj2D cad2dtmp = cad2d.Clone()) // コピーのテスト
                        {
                            // export to the file
                            using (CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                cad2dtmp.Serialize(fout);
                            }
                        }
                        // import form the file
                        cad2d.Clear();
                        using (CSerializer fin = new CSerializer("hoge.txt", true))
                        {
                            cad2d.Serialize(fin);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 2)
                    {
                        uint id_l0;
                        {    // Make model
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.4));
                            pts.Add(new CVector2D(0.0, 0.4));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        //cad2d.SetCurve_Arc(1,true,-0.2);
                        //cad2d.SetCurve_Arc(2,true, -0.5);
                        cad2d.SetCurve_Arc(3, false, 0);
                        //cad2d.SetCurve_Arc(4,true, -0.5);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 3)
                    {
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(0, 0)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(1, 0)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v1, id_v2);
                        uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(1, 1)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v2, id_v3);
                        uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(0, 1)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v4, id_v3);
                        uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 2, new CVector2D(1, 0.5)).id_v_add;
                        uint id_v7 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(0.5, 0.5)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v5, id_v7);
                        uint id_v6 = cad2d.AddVertex(CAD_ELEM_TYPE.NOT_SET, 0, new CVector2D(1.5, 0.5)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v5, id_v6);
                        cad2d.ConnectVertex_Line(id_v4, id_v1);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 4)
                    {
                        uint id_l0;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        //uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP,id_l0,new CVector2D(0.5,0.5));
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.2)).id_v_add;
                        uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.8, 0.5)).id_v_add;
                        uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.8)).id_v_add;
                        uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.2, 0.5)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v2, id_v3);
                        cad2d.ConnectVertex_Line(id_v3, id_v4);
                        cad2d.ConnectVertex_Line(id_v4, id_v5);
                        uint id_e1 = cad2d.ConnectVertex_Line(id_v5, id_v2).id_e_add;
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, id_e1);
                        cad2d.ConnectVertex_Line(id_v5, id_v2);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 5)
                    {
                        uint id_l0;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 6)
                    {
                        uint id_l0;
                        {    // define initial loop
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.3, 0.1));
                            pts.Add(new CVector2D(0.9, 0.1));
                            pts.Add(new CVector2D(0.9, 0.7));
                            cad2d.AddPolygon(pts, id_l0);
                        }
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.1, 0.9));
                            pts.Add(new CVector2D(0.7, 0.9));
                            pts.Add(new CVector2D(0.1, 0.3));
                            cad2d.AddPolygon(pts, id_l0);
                        }
                        uint id_e0 = cad2d.ConnectVertex_Line(1, 3).id_e_add;
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, id_e0);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 7)
                    {
                        uint id_l0;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.9, 0.7)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.9, 0.1)).id_v_add;
                        uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.3, 0.1)).id_v_add;
                        cad2d.ConnectVertex_Line(id_v1, id_v2);
                        cad2d.ConnectVertex_Line(id_v2, id_v3);
                        cad2d.ConnectVertex_Line(id_v3, id_v1);
                        {
                            uint id_e0 = cad2d.ConnectVertex_Line(id_v2, 2).id_e_add;
                            cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, id_e0);
                        }
                        {
                            uint id_e0 = cad2d.ConnectVertex_Line(2, id_v2).id_e_add;
                            cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, id_e0);
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 8)
                    {
                        uint id_e3, id_e4;
                        {
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));    // 1
                            pts.Add(new CVector2D(1.0, 0.0));    // 2
                            pts.Add(new CVector2D(1.5, 0.0));    // 3
                            pts.Add(new CVector2D(2.0, 0.0));    // 4
                            pts.Add(new CVector2D(2.0, 1.0));    // 5
                            pts.Add(new CVector2D(1.5, 1.0));    // 6
                            pts.Add(new CVector2D(1.0, 1.0));    // 7
                            pts.Add(new CVector2D(0.0, 1.0));    // 8
                            uint id_l0 = cad2d.AddPolygon(pts).id_l_add;
                            uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.5)).id_v_add;
                            uint id_e1 = cad2d.ConnectVertex_Line(2, 7).id_e_add;
                            uint id_e2 = cad2d.ConnectVertex_Line(3, 6).id_e_add;
                            uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e1, new CVector2D(1.0, 0.5)).id_v_add;
                            uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, 1, new CVector2D(0.5, 0.0)).id_v_add;
                            id_e3 = cad2d.ConnectVertex_Line(id_v1, id_v2).id_e_add;
                            id_e4 = cad2d.ConnectVertex_Line(id_v1, id_v3).id_e_add;
                        }
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 9)
                    {
                        uint id_l0;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.2, 0.7)).id_v_add;
                        uint id_v2 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.2, 0.3)).id_v_add;
                        uint id_e0 = cad2d.ConnectVertex_Line(id_v1, id_v2).id_e_add;
                        uint id_v3 = cad2d.AddVertex(CAD_ELEM_TYPE.EDGE, id_e0, new CVector2D(0.2, 0.5)).id_v_add;
                        uint id_v4 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.5, 0.5)).id_v_add;
                        uint id_v5 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, id_l0, new CVector2D(0.7, 0.5)).id_v_add;
                        uint id_e1 = cad2d.ConnectVertex_Line(id_v3, id_v4).id_e_add;
                        uint id_e2 = cad2d.ConnectVertex_Line(id_v4, id_v5).id_e_add;
                        cad2d.RemoveElement(CAD_ELEM_TYPE.EDGE, id_e1);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 10)
                    {
                        uint id_l0;
                        {    // define shape
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            id_l0 = cad2d.AddPolygon(pts).id_l_add;
                        }
                        uint id_v1 = cad2d.AddVertex(CAD_ELEM_TYPE.LOOP, 0, new CVector2D(1.1, 0)).id_v_add;
                        cad2d.RemoveElement(CAD_ELEM_TYPE.VERTEX, id_v1);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 11)
                    {
                        {    // define initial loop
                            IList<CVector2D> pts = new List<CVector2D>();
                            pts.Add(new CVector2D(0.0, 0.0));
                            pts.Add(new CVector2D(1.0, 0.0));
                            pts.Add(new CVector2D(1.0, 1.0));
                            pts.Add(new CVector2D(0.0, 1.0));
                            pts.Add(new CVector2D(0.0, 0.5));
                            cad2d.AddPolygon(pts);
                        }
                        /*
                        {
                            IList<CVector2D> aRelCo = new List<CVector2D>();
                            aRelCo.Add(new CVector2D(0.25, -0.1));
                            aRelCo.Add(new CVector2D(0.5, -0.0));
                            aRelCo.Add(new CVector2D(0.75, -0.1));
                            cad2d.SetCurve_Polyline(1, aRelCo);
                        }
                        cad2d.SetCurve_Arc(2, true, -1);
                        {
                            IList<CVector2D> aRelCo = new List<CVector2D>();
                            aRelCo.Add(new CVector2D(+0.01, 0.35));
                            aRelCo.Add(new CVector2D(-0.05, 0.25));
                            aRelCo.Add(new CVector2D(+0.01, 0.15));
                            cad2d.SetCurve_Polyline(5, aRelCo);
                        }
                         */
                        cad2d.RemoveElement(CAD_ELEM_TYPE.VERTEX, 1);  // removing this point marges 2 polylines
                        cad2d.SetCurve_Bezier(3, 0.2, +0.5, 0.8, -0.5);
                        //cad2d.SetCurve_Bezier(4, 0.0,-1.0, 0.3,+1.0);
                        //cad2d.SetCurve_Bezier(5, 0.0,-1.0, 0.3,-1.0);
                        Console.WriteLine("area : {0}", cad2d.GetArea_Loop(1));
                        cad2d.WriteToFile_dxf("hoge.dxf", 1);
                        DrawerAry.Clear();
                        DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                        DrawerAry.InitTrans(Camera);
                    }
                    else if (ProbNo == 12)
                    {
                        string svgfname = "../../../input_file/shape2d_0.svg";
                        CCadObj2D cad2dtmp = null;
                        if (File.Exists(svgfname))
                        {
                            DelFEM4NetCad.CCadSVG.ReadSVG_AddLoopCad(svgfname, out cad2dtmp);
                            // export to the file
                            using (CSerializer fout = new CSerializer("hoge.txt", false))
                            {
                                cad2dtmp.Serialize(fout);
                            }
                            cad2dtmp.Dispose();
                            // import form the file
                            cad2d.Clear();
                            using (CSerializer fin = new CSerializer("hoge.txt", true))
                            {
                                cad2d.Serialize(fin);
                            }
                            DrawerAry.Clear();
                            DrawerAry.PushBack(new CDrawer_Cad2D(cad2d));
                            DrawerAry.InitTrans(Camera);
                        }
                        else
                        {
                            MessageBox.Show("SVGファイルがありません");
                        }
                    }
                } // using cad2d
                success = true;
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception.Message + " " + exception.StackTrace);
            }

            Gl.glMatrixMode(Gl.GL_PROJECTION);
            Gl.glLoadIdentity();
            DrawerGlUtility.SetProjectionTransform(Camera);
            Glut.glutPostRedisplay();
            ProbNo++;
            if (ProbNo == ProbCnt) ProbNo = 0;
            return success;
        }